对于虚拟机来说, 如果指定1G内存,以slot为单位,进行mmap虚拟内存映射申请,申请之后memset进行物理内存申请,从而占用物理内存。对于宿主机来说mmap申请宿主机虚拟内存为连续的,进行memset初始化发生缺页中断从而申请物理内存,这些宿主机物理内存未必是连续的。对于虚拟机来说,虚拟机物理内存当然是连续的,所以可以让虚拟机物理内存虚拟对应与宿主机虚拟内存。
注意:
1.slot不是物理上的内存槽,而是把物理上内存按照相应逻辑进行分隔,例如显卡内存范围可以称为一个slot, bios内存范围可以称之为另一个slot等等。
2.转换后,知道宿主机虚拟地址后,当然VMM可以读写客户机的内存。宿主机虚拟地址实际是宿主机进程虚拟地址,属于用户空间。
如下图所示:
| |~ ~ ~ ~
~ ~ ~ ~
| |
hva?---> | |<----gfn
| | (slotn)base_hva-->| |<----base_gfn
~ ~ ~ ~
~ ~ ~ ~
| |
| | (slot0)
| |
备注:
左侧为宿主机虚拟内存,右侧为客户机物理内存
hva=base_hva+(gfn-base_gfn)*PAGE_SIZE
unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
{
struct kvm_memory_slot *slot;
(1) gfn = unalias_gfn_instantiation(kvm, gfn);
(2) slot = gfn_to_memslot_unaliased(kvm, gfn);
(3) if (!slot || slot->flags & KVM_MEMSLOT_INVALID)
(4) return bad_hva();
(5) return (slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE);
}
EXPORT_SYMBOL_GPL(gfn_to_hva);
上面已经谈到1G内存,虚拟机以slot方式分隔,命名为alias一些内存slot,这一些slot内存一般对应于显卡内存等。对于这些slot内存(称之为alias)需要重新映射到其他的slot内存, 客户机物理页框转换为宿主机虚拟地址只针对其他的slot内存(非alias)内存slot。
语句(1)判断如果客户机物理页框在命名为alias内存slot,需要以映射后的页框计算,否则gfn不变
语句(2)根据客户机物理页框查找属于那个slot
语句 (5)进行客户机物理页框到宿主机虚拟地址转换