首页 文章

如何获取VirtualMachine的第一条指令(在KVM-QEMU中)

提问于
浏览
0

我是SO和X86 VMX的新手 . 我正在学习X86上的KVM-QEMU,我想知道有关如何获取VM的第一条指令的详细信息,以便VM可以开始运行 . 有一些KVM API用于配置和注册一组内存作为VM的物理内存,然后将guest_RIP设置为AAA(例如) . 我不知道何时调用VMLaunch(使用正确配置的VMCS),CPU如何在VMCS中从该RIP获取指令,是通过某些地址转换过程,因此guest_CR3应正确设置为指向HOST为客人分配的内存?谢谢

1 回答

  • 0

    我将在QEMU的背景下解释这一点,以及启用KVM加速器时QEMU的运行方式 .

    您可能知道,在kvm下,通过打开设备节点 /dev/kvm 来创建虚拟机 . guest虚拟机将拥有自己的内存,通常与创建它的用户空间进程分开 . 所以kvm基本上是一个相当典型的Linux字符设备 - 你使用 ioctl() 来创建,运行,修改参数,分配内存以及读写虚拟机的VCPU寄存器 . 因此,初始设置将通过各种 ioctl() 来完成,这将设置KVM以供进一步使用 .

    就QEMU代码而言,所有执行(无论是KVM还是非KVM)都从以下开始:

    vl.c start of everything

    KVM架构的初始化通过以下功能发生 - (从 CPUID 收集CPU标志并设置频率等)

    kvm_arch_init_vcpu

    完成所有初始化功能后,函数 do_kvm_cpu_synchronize_post_init 将尝试根据主机CPU状态同步VCPU寄存器的初始值 . 它调用另一个函数 kvm_arch_put_registers 并将VCPU设置为 dirty . 为什么VCPU设置为脏?只有这样,后续函数才会实际初始化VCPU寄存器的值 .

    此函数 kvm_arch_put_registers 是获取VMCS寄存器的所有初始值的关键 . 如果你看到它的身体,你会发现正在发生的事情: -

    kvm_arch_put_registers

    特别关注函数 kvm_getput_regskvm_put_sregs - 第一个函数将设置 GPRsEFLAGS 以及 EIP/RIP 寄存器的初始值,而第二个函数将设置初始段寄存器值 .

    guest page table 将根植于 CR3 寄存器 . 这个页面表如何工作?

    为此,您需要记住KVM中的 mmu 仅占一级虚拟化(来宾虚拟 - >来宾物理),但不考虑第二级(来宾物理 - >主机物理) . 初始RIP将考虑虚拟地址 - 它将被适当地转换为来宾中的物理地址 . 但是,要将此guest虚拟机物理地址转换为主机物理地址,您需要具有单独的页表 . 这是 shadow page table ,将与 original page table (转换来宾虚拟 - >来宾物理)一起使用以执行整个翻译 .

    需要 synchronizing guest page tableshadow page table 的状态,这有时往往是一个问题 . 只要guest虚拟机将写入其页表,就需要在影子页表上执行相应的更改 .

相关问题