base_hva-->| |
~ ~ ~ ~
~ ~ ~ ~
| |
| | (slot0)
| |
备注:
左侧为宿主机虚拟内存,右侧为客户机物理内存
基于上图,客户机物理页框如何转换为宿主机物理地址(gfn---->hva)
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)进行客户机物理页框到宿主机虚拟地址转换