【问题标题】:How is the first instruction of VirtualMachine is fetched (in KVM-QEMU)VirtualMachine 的第一条指令是如何获取的(在 KVM-QEMU 中)
【发布时间】:2016-11-26 11:08:21
【问题描述】:

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

【问题讨论】:

  • 这个问题是不是太傻了,还是答案很直接,没人愿意回答?
  • 嗨@wangt13,你还在寻找这个问题的答案吗?如果是这样,我可以尝试用 QEMU 来解释它,以及 QEMU 和 KVM 是如何尝试做这个活动的。
  • @Arnabjyoti,如果你能分享你的答案,我将不胜感激。

标签: x86 virtualization


【解决方案1】:

我将在 QEMU 的上下文中解释这一点,以及启用 KVM 加速器时 QEMU 是如何运行的。

您可能知道,在 kvm 下,虚拟机是通过打开设备节点 /dev/kvm 来创建的。来宾将拥有自己的内存,并且通常与创建它的用户空间进程分开。所以基本上 kvm 被构造为一个相当典型的 Linux 字符设备——你使用ioctl()s 来创建、运行、修改参数、分配内存以及读写虚拟机的 VCPU 寄存器。因此,初始设置将通过各种ioctl()s 完成,这些ioctl()s 将设置 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寄存器,而第二个函数将设置初始段寄存器值。

访客页表将植根于 CR3 寄存器。这个页表是如何工作的?

为此,你需要记住,KVM 中的 mmu 只占了一级虚拟化(guest virtual -> guest physical),而不占第二级(guest physical ->主机物理)。初始 RIP 将考虑虚拟地址 - 它将被适当地转换为来宾中的物理地址。但是,要将这个客户物理地址转换为主机物理地址,您需要有一个单独的页表。这是一个影子页表,将与原始页表(将客户虚拟 -> 客户物理转换)结合使用以执行整个转换。

需要同步访客页表影子页表的状态,这有时会成为一个问题.每当来宾将写入其页表时,也需要对影子页表执行相应的更改。

【讨论】:

  • 非常感谢您的详细解答。如果我的理解有误,请纠正我。启动VM(第一条指令,一般为实模式),KVM需要设置VM内存,将启动代码放入VM的内存中,然后将EIP/RIP设置到第一条指令的地址,最后调用vmlaunch启动虚拟机。
  • @Wangt13,是的,从高层来看,你是对的。但中间还有很多事情发生。
猜你喜欢
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 2019-05-15
  • 2018-01-19
相关资源
最近更新 更多