Linux公社论坛

 找回密码
 注册
查看: 74|回复: 0

[其他] 虚拟化:gva、gpa、hva、hpa转化

[复制链接]

0

主题

0

听众

1

积分

新手上路

Rank: 1

glowing 发表于 2020-2-11 11:12:17 |显示全部楼层
gva -> gpa和hva -> hpa转化较为简单,分别去查guest和host页表即可。

gpa -> hva:

由于我所接触的虚拟化方式是采用qemu-kvm的方式。kvm负责cpu和内存的虚拟化,qemu负责io的虚拟化,且gpa->hva都是由qemu维护的,提供给kvm管理借口。具体代码实现见:
  1. kvm_pfn_t __gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn,
  2.                    bool atomic, bool *async, bool write_fault,
  3.                    bool *writable)
  4. {
  5.     unsigned long addr = __gfn_to_hva_many(slot, gfn, NULL, write_fault);

  6.     if (addr == KVM_HVA_ERR_RO_BAD)
  7.         return KVM_PFN_ERR_RO_FAULT;

  8.     if (kvm_is_error_hva(addr))
  9.         return KVM_PFN_NOSLOT;

  10.     /* Do not map writable pfn in the readonly memslot. */
  11.     if (writable && memslot_is_readonly(slot)) {
  12.         *writable = false;
  13.         writable = NULL;
  14.     }   

  15.     return hva_to_pfn(addr, atomic, async, write_fault,
  16.               writable);
  17. }
复制代码
里面的第一句话就是完成gpa->hva的转化:__gfn_to_hva_many

  1. static unsigned long __gfn_to_hva_many(struct kvm_memory_slot *slot, gfn_t gfn,
  2.                        gfn_t *nr_pages, bool write)
  3. {
  4.     if (!slot || slot->flags & KVM_MEMSLOT_INVALID)
  5.         return KVM_HVA_ERR_BAD;

  6.     if (memslot_is_readonly(slot) && write)
  7.         return KVM_HVA_ERR_RO_BAD;

  8.     if (nr_pages)
  9.         *nr_pages = slot->npages - (gfn - slot->base_gfn);

  10.     return __gfn_to_hva_memslot(slot, gfn);
  11. }
复制代码
三个if是进行条件判断,最核心的就是return语句:__gfn_to_hva_memslot

  1. static inline unsigned long
  2. __gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn)
  3. {
  4.     return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE;
  5. }
复制代码
这里有必要讲一下kvm_memory_slot结构体:
  1. struct kvm_memory_slot {
  2.     gfn_t base_gfn;    //当前slot的起始地址对应的gpa
  3.     unsigned long npages;
  4.     unsigned long *dirty_bitmap;
  5.     struct kvm_arch_memory_slot arch;
  6.     unsigned long userspace_addr;     //hva   
  7.     u32 flags;
  8.     short id;
  9. };
复制代码
所以(gfn - slot->base_gfn) * PAGE_SIZE就是gpa在当前slot中的地址偏移,加上其实地址对应的hva,既得当前gpa对应的hva。(当前gpa与起始gpa的差  等于  当前hva与起始hva的差   /*每个slot地址连续*/)

注:关于qemu内存管理的详细解释请参考下面的网址:

http://oenhan.com/qemu-memory-struct

https://www.cnblogs.com/ck1020/p/6729224.html


[注:转自本人的博客]
您需要登录后才可以回帖 登录 | 注册

关注Linux公社官方微信,免费领取邀请码。

手机版|Linux公社(LinuxIDC.com)旗下网站【www.linuxidc.net】

GMT+8, 2020-2-24 07:35 , Processed in 0.041003 second(s), 13 queries , Wincache On.

Powered by Discuz! X 3.2

© 2010-2016 Comsenz Inc.

回顶部