了解x2APIC的虚拟APIC页面

时间:2017-12-23 07:57:56

标签: linux x86 virtual-machine virtualization apic

我正在编写VMM,我正在尝试支持在VMX非root模式下运行的来宾操作系统对x2APIC寄存器的虚拟访问。

我想首先做一些简单的事情,比如从客户操作系统中读取本地APIC ID。我已尝试在我的VMM中添加对此的支持,但我读到的值似乎不正确。

不幸的是,我似乎无法在网上找到有关虚拟APIC页面的大量信息。我已经阅读了英特尔手册(APIC虚拟化和虚拟中断)的第29章,这就是我正在做的事情:

  1. 在基于二级处理器的VM执行控件中,我将以下位设置为1 :(我在下面设置了第9位,因为我最终想支持发布的IPI)

    1. SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE(第4位)
    2. SECONDARY_EXEC_APIC_REGISTER_VIRT(第8位)
    3. SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY(第9位)
  2. 在MSR位图中,我禁用0x802的截取,这是本地APIC ID寄存器。

  3. 在我的来宾操作系统中,我使用rdmsr来阅读0x802

  4. 我在两个固定到不同内核的线程上执行第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偏移量对我有意义:当与0x8020x2进行AND运算时,MSR地址0xFF将为0x2 0x20当左移4位时{1}}。如果您通过其内存映射寄存器访问xAPIC,则0x20是物理APIC页面内的偏移量。然后读取8个字节(即64位),因此低32位是x2APIC的本地APIC ID。

1 个答案:

答案 0 :(得分:1)

我能够在@prl的帮助下解决这个问题。我必须自己为每个核心分配一个虚拟APIC页面,然后使用其相关核心的本地APIC ID单独初始化每个页面。

然后我将页面的物理地址添加到VMCS(在Linux内核中定义了一个名为VIRTUAL_APIC_PAGE_ADDR的常量,其中包含VMCS中的偏移量)。我没有意识到我必须初始化页面,因为它没有自动完成。

编辑:我在Linux上实现了一个有效的虚拟化系统,支持x2APIC虚拟化和发布中断处理,并在this document中写了这两个主题。该文档应该相当简单,并且包含指向我的实现的链接。