我正在编写一个 VMM,并且我正在尝试支持在 VMX 非 root 模式下运行的来宾操作系统对 x2APIC 寄存器的虚拟访问。
我想从做一些简单的事情开始,例如从客户操作系统中读取本地 APIC ID。我尝试在我的 VMM 中添加对此的支持,但我读取的值似乎不正确。
不幸的是,我似乎无法在网上找到很多关于虚拟 APIC 页面的信息。我已经阅读了英特尔手册的第 29 章(APIC 虚拟化和虚拟中断),这就是我正在做的事情:
在基于辅助处理器的 VM 执行控件中,我将以下位设置为 1:(我在下面设置位 9,因为我最终想要支持发布的 IPI)
SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE
(第 4 位)SECONDARY_EXEC_APIC_REGISTER_VIRT
(第 8 位)SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY
(位 9)
在 MSR 位图中,我禁用了对 的拦截
0x802
,这是本地 APIC ID 寄存器。在我的来宾操作系统中,我
rdmsr
用来阅读0x802
.
我在固定到不同内核的两个线程上执行第 3 步。他们都2621447225
从寄存器中读取值。这似乎是不正确的,因为线程被固定到不同的内核,因此应该读取不同的本地 APIC ID(而且数量2621447225
非常大)。我做错了什么?
以下是一些附加信息供您参考:
在英特尔手册的第 29.5 节(虚拟化基于 MSR 的 APIC 访问)中,它说:
If “APIC-register virtualization” is 1 and ECX contains a value in the range 800H–8FFH, the instruction reads the 8 bytes from offset X on the virtual-APIC page into EDX:EAX, where X = (ECX & FFH) « 4. This occurs even if the local APIC is not in x2APIC mode (no general-protection fault occurs because the local APIC is not in x2APIC mode).
偏移量对X
我来说很有意义:MSR 地址0x802
将0x2
在与 进行与运算时变为0xFF
,并且在左移 4 位时变为。如果您通过其内存映射寄存器访问 xAPIC,则它是物理 APIC 页面内的偏移量。然后读取 8 个字节(即 64 位),因此低 32 位是 x2APIC 的本地 APIC ID。0x2
0x20
0x20