我正在开发一个项目,我需要将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
?)
答案 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
是插槽的大小。
现在要执行翻译,您必须:
KVMSlot
元素列表中。列表的头部存储在 KVMMemoryListener
中。要找到它,您可以检查访客实际地址是否在 start_addr
和 start_addr + memory_size
之间。offset = gpa - start_addr
) 中的偏移量hva = ram + offset
。当然,来宾物理地址和主机虚拟地址中的偏移量是相同的,这就是您可以使用它的原因。最后,您可以使用 QEMU Monitor 的函数 gpa2hva
检查翻译是否正确。