Index: /trunk/include/VBox/iom.h
===================================================================
--- /trunk/include/VBox/iom.h	(revision 19992)
+++ /trunk/include/VBox/iom.h	(revision 19993)
@@ -213,4 +213,5 @@
 VMMDECL(int)  IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue);
 VMMDECL(int)  IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue);
+VMMDECL(int)  IOMMMIOPhysHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault);
 VMMDECL(int)  IOMInterpretCheckPortIOAccess(PVM pVM, PCPUMCTXCORE pCtxCore, RTIOPORT Port, unsigned cb);
 VMMDECL(int)  IOMMMIOMapMMIO2Page(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysRemapped, uint64_t fPageFlags);
Index: /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 19992)
+++ /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 19993)
@@ -1043,9 +1043,8 @@
  * @param   uErrorCode  CPU Error code.
  * @param   pCtxCore    Trap register frame.
- * @param   pvFault     The fault address (cr2).
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
  * @param   pvUser      Pointer to the MMIO ring-3 range entry.
  */
-VMMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
+int iomMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault, void *pvUser)
 {
     /* Take the IOM lock before performing any MMIO. */
@@ -1058,6 +1057,6 @@
 
     STAM_PROFILE_START(&pVM->iom.s.StatRZMMIOHandler, a);
-    Log(("IOMMMIOHandler: GCPhys=%RGp uErr=%#x pvFault=%RGv rip=%RGv\n",
-         GCPhysFault, (uint32_t)uErrorCode, pvFault, (RTGCPTR)pCtxCore->rip));
+    Log(("iomMMIOHandler: GCPhys=%RGp uErr=%#x pvFault=%RGv rip=%RGv\n",
+         GCPhysFault, (uint32_t)uErrorCode, (RTGCPTR)pCtxCore->rip));
 
     PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser;
@@ -1244,4 +1243,35 @@
 }
 
+/**
+ * \#PF Handler callback for MMIO ranges.
+ *
+ * @returns VBox status code (appropriate for GC return).
+ * @param   pVM         VM Handle.
+ * @param   uErrorCode  CPU Error code.
+ * @param   pCtxCore    Trap register frame.
+ * @param   pvFault     The fault address (cr2).
+ * @param   GCPhysFault The GC physical address corresponding to pvFault.
+ * @param   pvUser      Pointer to the MMIO ring-3 range entry.
+ */
+VMMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
+{
+    LogFlow(("IOMMMIOHandler: GCPhys=%RGp uErr=%#x pvFault=%RGv rip=%RGv\n",
+             GCPhysFault, (uint32_t)uErrorCode, pvFault, (RTGCPTR)pCtxCore->rip));
+    return iomMMIOHandler(pVM, uErrorCode, pCtxCore, GCPhysFault, pvUser);
+}
+
+/**
+ * Physical access handler for MMIO ranges.
+ *
+ * @returns VBox status code (appropriate for GC return).
+ * @param   pVM         VM Handle.
+ * @param   uErrorCode  CPU Error code.
+ * @param   pCtxCore    Trap register frame.
+ * @param   GCPhysFault The GC physical address.
+ */
+VMMDECL(int) IOMMMIOPhysHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault)
+{
+    return iomMMIOHandler(pVM, uErrorCode, pCtxCore, GCPhysFault, iomMMIOGetRange(&pVM->iom.s, GCPhysFault));
+}
 
 #ifdef IN_RING3
Index: /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 19992)
+++ /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 19993)
@@ -2929,9 +2929,10 @@
         {
             errCode |= X86_TRAP_PF_P;
-
+        }
 #if 0
+        else {
             /* Shortcut for APIC TPR reads and writes; 32 bits guests only */
             if (    (GCPhys & 0xfff) == 0x080
-                &&  GCPhys > 0x1000000  /* to skip VGA frame buffer accesses */
+                &&  GCPhys > 0x1000000   /* to skip VGA frame buffer accesses */
                 &&  !CPUMIsGuestInLongModeEx(pCtx)
                 &&  (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC))
@@ -2939,14 +2940,19 @@
                 RTGCPHYS GCPhysApicBase;
                 PDMApicGetBase(pVM, &GCPhysApicBase);   /* @todo cache this */
+                GCPhysApicBase &= PAGE_BASE_GC_MASK;
                 if (GCPhys == GCPhysApicBase + 0x80)
                 {
+                    Log(("Enable VT-x virtual APIC access filtering\n"));
                     pVCpu->hwaccm.s.vmx.proc_ctls2 |= VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC;
-                    rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS2, val);
+                    rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS2, pVCpu->hwaccm.s.vmx.proc_ctls2);
+                    AssertRC(rc);
+
+                    rc = IOMMMIOMapMMIOHCPage(pVM, GCPhysApicBase, pVM->hwaccm.s.vmx.pAPICPhys, X86_PTE_RW | X86_PTE_P);
                     AssertRC(rc);
                 }
             }
-#endif
-        }
-        LogFlow(("EPT Page fault %x at %RGp error code %x\n", (uint32_t)exitQualification, GCPhys, errCode));
+        }
+#endif
+        Log(("EPT Page fault %x at %RGp error code %x\n", (uint32_t)exitQualification, GCPhys, errCode));
 
         /* GCPhys contains the guest physical address of the page fault. */
@@ -3409,6 +3415,7 @@
     {
         LogFlow(("VMX_EXIT_APIC_ACCESS\n"));
-
-        switch(VMX_EXIT_QUALIFICATION_APIC_ACCESS_TYPE(exitQualification))
+        unsigned uAccessType = VMX_EXIT_QUALIFICATION_APIC_ACCESS_TYPE(exitQualification);
+
+        switch(uAccessType)
         {
         case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
@@ -3420,5 +3427,8 @@
 
             Log(("Apic access at %RGp\n", GCPhys));
-            rc = VINF_EM_RAW_EMULATE_INSTR;
+            rc = IOMMMIOPhysHandler(pVM, (uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ) ? 0 : X86_TRAP_PF_RW, CPUMCTX2CORE(pCtx), GCPhys);
+            if (rc == VINF_SUCCESS)
+                goto ResumeExecution;   /* rip already updated */
+
             break;
         }
