Qemu-KVM:将访客物理地址转换为主机虚拟/主机物理地址

时间:2017-01-25 20:18:23

标签: qemu kvm

我正在开发一个项目,我需要将qemu-guest物理地址转换为托管虚拟/物理地址。

我正在使用VMI(虚拟机内省)来反省qemu进程(KVM VM)并读取存储在virtio环缓冲区描述符中的客户物理地址。因此,我正在寻找一种简单的方法将qemu物理地址转换为主机端的主机虚拟地址。 (即,从qemu过程中提取尽可能少的信息)。

我在网上看到,在以前的版本中,qemu将物理RAM库存储在变量phys_ram_base中,以便可以按如下方式获取主机虚拟地址:

host_virtual = phys_ram_base + guest_physical_address

在较新版本的qemu中是否可以这样(例如,我如何获得qemu物理基地址 - 前phys_ram_base?)

1 个答案:

答案 0 :(得分:0)

我不得不解决同样的问题,我想出了以下解决方案。

当使用带有 -enable-kvm 选项的 QEMU 时,内存通过 KVM_SET_USER_MEMORY_REGION ioctl 分配给来宾。基本上,QEMU 准备了一个 kvm_userspace_memory_region 结构,其中来宾的物理地址与主机虚拟地址相关联,然后发出 ioctl。现在,事实证明 KVMSlot 结构与 KVM API 提供的结构(几乎)是 1:1 的。 QEMU 存储所有信息,以便在那里执行从客户物理地址到主机虚拟地址的转换。

KVMSlot 结构体定义如下:

    typedef struct KVMSlot
    {
        hwaddr start_addr;
        ram_addr_t memory_size;
        void *ram;
        int slot;
        int flags;
        int old_flags;
        /* Dirty bitmap cache for the slot */
        unsigned long *dirty_bmap;
    } KVMSlot;

start_addr 是对应于所考虑插槽的开始位置的物理地址,ram 是其对应的主机虚拟地址,然后 memory_size 是插槽的大小。

现在要执行翻译,您必须:

  1. 找到正确的插槽。可以分配许多插槽,它们保存在 KVMSlot 元素列表中。列表的头部存储在 KVMMemoryListener 中。要找到它,您可以检查访客实际地址是否在 start_addrstart_addr + memory_size 之间。
  2. 计算您的访客物理地址在插槽 (offset = gpa - start_addr) 中的偏移量
  3. 计算转换后的主机虚拟地址,如 hva = ram + offset。当然,来宾物理地址和主机虚拟地址中的偏移量是相同的,这就是您可以使用它的原因。

最后,您可以使用 QEMU Monitor 的函数 gpa2hva 检查翻译是否正确。