我正在编写一个VMM,并且我试图通过运行在VMX非根模式下的来宾操作系统来支持对x2APIC寄存器的虚拟访问。
首先,我想做一些简单的事情,比如从来宾操作系统中读取本地APIC ID。我尝试在我的VMM中添加对此的支持,但是我读到的值似乎是不正确的。
不幸的是,我似乎在网上找不到很多关于虚拟APIC页面的信息。我已经阅读了Intel手册第29章(APIC虚拟化和虚拟中断),下面是我正在做的工作:
1. `SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE` (bit 4)
2. `SECONDARY_EXEC_APIC_REGISTER_VIRT` (bit 8)
3. `SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY` (bit 9)
0x802的截取,这是本地的APIC寄存器。rdmsr读取0x802。我在两个线程上执行步骤3,这些线程被固定在不同的核心上。他们都从寄存器中读取值2621447225 。这似乎是不正确的,因为线程被固定在不同的核心上,因此应该读取不同的本地APIC (并且数字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在0xFF时和0xFF中将是0x2,当左移4位时0x2将变成0x20。0x20是物理APIC页面中的偏移量,如果您是通过xAPIC内存映射寄存器访问它的话。然后读取8个字节(即64位),因此较低的32位是x2APIC的本地APIC。
发布于 2017-12-24 07:41:27
我能够在@prl的帮助下解决这个问题。我必须为每个核心自己分配一个虚拟的APIC页面,然后用其相关的核心的本地APIC ID单独初始化每个页面。
然后,我将页面的物理地址添加到VMCS (在Linux内核中定义了一个名为VIRTUAL_APIC_PAGE_ADDR的常量,它包含VMCS中的偏移量)。我没有意识到我必须初始化这个页面,因为它不是自动完成的。
编辑:I在Linux上实现了一个支持x2APIC虚拟化的工作虚拟化系统,并发布了中断处理,并在本文件中写了这两个主题。该文档应该相当简单,它包含一个指向我的实现的链接。
https://stackoverflow.com/questions/47950831
复制相似问题