title: Understanding the virtual APIC page for x2APIC
body: <p>I am writing a VMM, and I'm trying to support virtual accesses to the x2APIC's registers by a guest OS running in VMX non-root mode.</p>
  
  <p>I want to start off by doing something simple, such as reading the local APIC ID from within the guest OS. I've tried adding support for this in my VMM, but the value I read seems to be incorrect.</p>
  
  <p>Unfortunately, I can't seem to find a lot of information online about the virtual APIC page. I've read through chapter 29 of the Intel manual (APIC Virtualization and Virtual Interrupts), and here's what I'm doing:</p>
  
  <ol>
  <li><p>In the secondary processor-based VM-execution controls, I set the following bits to 1: (I'm setting bit 9 below since I ultimately want to support posted IPIs)</p>
  
  <ol>
  <li><code>SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE</code> (bit 4) </li>
  <li><code>SECONDARY_EXEC_APIC_REGISTER_VIRT</code> (bit 8) </li>
  <li><code>SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY</code> (bit 9)</li>
  </ol></li>
  <li><p>In the MSR bitmap, I disable intercepts for <code>0x802</code>, which is the local APIC ID register.</p></li>
  <li><p>In my guest OS, I use <code>rdmsr</code> to read <code>0x802</code>.</p></li>
  </ol>
  
  <p><strong>I perform step 3 on two threads that are pinned to different cores. They both read the value <code>2621447225</code> from the register. This seems incorrect since the threads are pinned to different cores and should therefore read different local APIC IDs (and the number <code>2621447225</code> is really big).</strong> What am I doing incorrectly?</p>
  
  <p>Here's some additional information for your reference:</p>
  
  <p>In section 29.5 (Virtualizing MSR-based APIC Accesses) of the Intel manual, it says:</p>
  
  <p><code>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 &amp; 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).</code></p>
  
  <p>The <code>X</code> offset makes sense to me: the MSR address <code>0x802</code> will be <code>0x2</code> when AND'd with <code>0xFF</code>, and <code>0x2</code> will become <code>0x20</code> when left-shifted 4 bits. <code>0x20</code> is the offset within the physical APIC's page if you were accessing an xAPIC through its memory-mapped registers. 8 bytes (i.e. 64 bits) are then read, so the lower 32 bits are the local APIC ID for x2APIC.</p>