Index: /trunk/include/VBox/vmm/apic.h
===================================================================
--- /trunk/include/VBox/vmm/apic.h	(revision 60645)
+++ /trunk/include/VBox/vmm/apic.h	(revision 60646)
@@ -926,5 +926,5 @@
  */
 VMMR3_INT_DECL(void)        APICR3InitIpi(PVMCPU pVCpu);
-VMMR3_INT_DECL(void)        APICR3Reset(PVMCPU pVCpu);
+VMMR3_INT_DECL(void)        APICR3Reset(PVMCPU pVCpu, bool fResetApicBaseMsr);
 /** @} */
 #endif /* IN_RING3 */
Index: /trunk/src/VBox/VMM/VMMAll/APICAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/APICAll.cpp	(revision 60645)
+++ /trunk/src/VBox/VMM/VMMAll/APICAll.cpp	(revision 60646)
@@ -373,5 +373,5 @@
  * @param   uApicBaseMsr        The APIC Base MSR value.
  */
-static APICMODE apicGetMode(uint64_t uApicBaseMsr)
+APICMODE apicGetMode(uint64_t uApicBaseMsr)
 {
     uint32_t const uMode   = MSR_APICBASE_GET_MODE(uApicBaseMsr);
@@ -1970,4 +1970,7 @@
 {
     Assert(pVCpu);
+    NOREF(pDevIns);
+
+#ifdef IN_RING3
     PAPICCPU pApicCpu   = VMCPU_TO_APICCPU(pVCpu);
     PAPIC    pApic      = VM_TO_APIC(pVCpu->CTX_SUFF(pVM));
@@ -1976,10 +1979,6 @@
     uint64_t uBaseMsr   = pApicCpu->uApicBaseMsr;
 
-    /** @todo probably go back to ring-3 for all cases regardless of
-     *        fRZEnabled. Writing this MSR is not something guests
-     *        typically do often, and therefore is not performance
-     *        critical. We'll have better diagnostics in ring-3. */
-    if (!pApic->fRZEnabled)
-        return VINF_CPUM_R3_MSR_WRITE;
+    Log4(("APIC%u: ApicSetBaseMsr: u64BaseMsr=%#RX64 enmNewMode=%s enmOldMode=%s\n", pVCpu->idCpu, u64BaseMsr,
+          apicGetModeName(enmNewMode), apicGetModeName(enmOldMode)));
 
     /*
@@ -1993,11 +1992,7 @@
     if (MSR_APICBASE_GET_PHYSADDR(uBaseMsr) != XAPIC_APICBASE_PHYSADDR)
     {
-#ifdef IN_RING3
         LogRelMax(5, ("APIC%u: Attempt to relocate base to %#RGp, unsupported -> #GP(0)\n", pVCpu->idCpu,
                       MSR_APICBASE_GET_PHYSADDR(uBaseMsr)));
         return VERR_CPUM_RAISE_GP_0;
-#else
-        return VINF_CPUM_R3_MSR_WRITE;
-#endif
     }
 
@@ -2014,5 +2009,4 @@
             case APICMODE_DISABLED:
             {
-#ifdef IN_RING3
                 /*
                  * The APIC state needs to be reset (especially the APIC ID as x2APIC APIC ID bit layout
@@ -2021,10 +2015,7 @@
                  * See Intel spec. 10.4.3 "Enabling or Disabling the Local APIC".
                  */
-                APICR3Reset(pVCpu);
+                APICR3Reset(pVCpu, false /* fResetApicBaseMsr */);
                 uBaseMsr &= ~(MSR_APICBASE_XAPIC_ENABLE_BIT | MSR_APICBASE_X2APIC_ENABLE_BIT);
                 Log4(("APIC%u: Switched mode to disabled\n", pVCpu->idCpu));
-#else
-                return VINF_CPUM_R3_MSR_WRITE;
-#endif
                 break;
             }
@@ -2044,5 +2035,5 @@
             case APICMODE_X2APIC:
             {
-                uBaseMsr |= MSR_APICBASE_X2APIC_ENABLE_BIT;
+                uBaseMsr |= MSR_APICBASE_XAPIC_ENABLE_BIT | MSR_APICBASE_X2APIC_ENABLE_BIT;
 
                 /*
@@ -2078,4 +2069,7 @@
     ASMAtomicWriteU64(&pApicCpu->uApicBaseMsr, uBaseMsr);
     return VINF_SUCCESS;
+#else  /* !IN_RING3 */
+    return VINF_CPUM_R3_MSR_WRITE;
+#endif /* IN_RING3 */
 }
 
@@ -2195,4 +2189,10 @@
             switch (enmDeliveryMode)
             {
+                case XAPICDELIVERYMODE_INIT:
+                {
+                    /** @todo won't work in R0/RC because callers don't care about rcRZ. */
+                    AssertMsgFailed(("INIT through LINT0/LINT1 is not yet supported\n"));
+                    /* fallthru */
+                }
                 case XAPICDELIVERYMODE_FIXED:
                 {
@@ -2208,5 +2208,4 @@
                 case XAPICDELIVERYMODE_SMI:
                 case XAPICDELIVERYMODE_NMI:
-                case XAPICDELIVERYMODE_INIT:    /** @todo won't work in R0/RC because callers don't care about rcRZ. */
                 {
                     VMCPUSET DestCpuSet;
@@ -2221,5 +2220,6 @@
                 case XAPICDELIVERYMODE_EXTINT:
                 {
-                    Log4(("APIC%u: APICLocalInterrupt: External interrupt. u8Pin=%u u8Level=%u\n", pVCpu->idCpu, u8Pin, u8Level));
+                    Log4(("APIC%u: APICLocalInterrupt: %s ExtINT through LINT%u\n", pVCpu->idCpu,
+                          u8Level ? "Raising" : "Lowering", u8Pin));
                     if (u8Level)
                         APICSetInterruptFF(pVCpu, PDMAPICIRQ_EXTINT);
@@ -2244,11 +2244,21 @@
     else
     {
-        /* The APIC is disabled, pass it through the CPU. */
-        LogFlow(("APIC%u: APICLocalInterrupt: APIC hardware-disabled, passing interrupt to CPU. u8Pin=%u u8Level=%u\n",
-                 pVCpu->idCpu, u8Pin, u8Level));
-        if (u8Level)
-            APICSetInterruptFF(pVCpu, PDMAPICIRQ_EXTINT);
+        /* The APIC is hardware disabled. The CPU behaves as though there is no on-chip APIC. */
+        if (u8Pin == 0)
+        {
+            /* LINT0 behaves as an external interrupt pin. */
+            Log4(("APIC%u: APICLocalInterrupt: APIC hardware-disabled, %s ExtINT through LINT0\n", pVCpu->idCpu,
+                  u8Level ? "raising" : "lowering"));
+            if (u8Level)
+                APICSetInterruptFF(pVCpu, PDMAPICIRQ_EXTINT);
+            else
+                APICClearInterruptFF(pVCpu, PDMAPICIRQ_EXTINT);
+        }
         else
-            APICClearInterruptFF(pVCpu, PDMAPICIRQ_EXTINT);
+        {
+            /* LINT1 behaves as NMI. */
+            Log4(("APIC%u: APICLocalInterrupt: APIC hardware-disabled, raising NMI through LINT1\n", pVCpu->idCpu));
+            APICSetInterruptFF(pVCpu, PDMAPICIRQ_NMI);
+        }
     }
 
Index: /trunk/src/VBox/VMM/VMMR3/APIC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/APIC.cpp	(revision 60645)
+++ /trunk/src/VBox/VMM/VMMR3/APIC.cpp	(revision 60646)
@@ -253,7 +253,8 @@
  * reset.
  *
- * @param   pVCpu           The cross context virtual CPU structure.
- */
-VMMR3_INT_DECL(void) APICR3Reset(PVMCPU pVCpu)
+ * @param   pVCpu               The cross context virtual CPU structure.
+ * @param   fResetApicBaseMsr   Whether to reset the APIC base MSR.
+ */
+VMMR3_INT_DECL(void) APICR3Reset(PVMCPU pVCpu, bool fResetApicBaseMsr)
 {
     VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu);
@@ -291,5 +292,6 @@
     /** @todo It isn't clear in the spec. where exactly the default base address
      *        is (re)initialized, atm we do it here in Reset. */
-    apicR3ResetBaseMsr(pVCpu);
+    if (fResetApicBaseMsr)
+        apicR3ResetBaseMsr(pVCpu);
 
     /*
@@ -373,8 +375,13 @@
     PCXAPICPAGE  pXApicPage  = VMCPU_TO_CXAPICPAGE(pVCpu);
     PCX2APICPAGE pX2ApicPage = VMCPU_TO_CX2APICPAGE(pVCpu);
+
+    uint64_t const uBaseMsr  = pApicCpu->uApicBaseMsr;
+    APICMODE const enmMode   = apicGetMode(uBaseMsr);
     bool const   fX2ApicMode = XAPIC_IN_X2APIC_MODE(pVCpu);
 
-    pHlp->pfnPrintf(pHlp, "VCPU[%u] APIC at %#RGp\n", pVCpu->idCpu, MSR_APICBASE_GET_PHYSADDR(pApicCpu->uApicBaseMsr));
-    pHlp->pfnPrintf(pHlp, "  Mode                          = %s\n", fX2ApicMode ? "x2Apic" : "xApic");
+    pHlp->pfnPrintf(pHlp, "VCPU[%u] APIC:\n", pVCpu->idCpu);
+    pHlp->pfnPrintf(pHlp, "  APIC Base MSR                 = %#RX64 (Addr=%#RX64)\n", uBaseMsr,
+                    MSR_APICBASE_GET_PHYSADDR(uBaseMsr));
+    pHlp->pfnPrintf(pHlp, "  Mode                          = %#x (%s)\n", enmMode, apicGetModeName(enmMode));
     if (fX2ApicMode)
     {
@@ -386,5 +393,5 @@
     pHlp->pfnPrintf(pHlp, "  Version                       = %#x\n",      pXApicPage->version.all.u32Version);
     pHlp->pfnPrintf(pHlp, "    APIC Version                = %#x\n",      pXApicPage->version.u.u8Version);
-    pHlp->pfnPrintf(pHlp, "    Max LVT entries             = %u\n",       pXApicPage->version.u.u8MaxLvtEntry);
+    pHlp->pfnPrintf(pHlp, "    Max LVT entry index (0..N)  = %u\n",       pXApicPage->version.u.u8MaxLvtEntry);
     pHlp->pfnPrintf(pHlp, "    EOI Broadcast supression    = %RTbool\n",  pXApicPage->version.u.fEoiBroadcastSupression);
     if (!fX2ApicMode)
@@ -929,5 +936,5 @@
             TMTimerStop(pApicCpu->pTimerR3);
 
-        APICR3Reset(pVCpuDest);
+        APICR3Reset(pVCpuDest, true /* fResetApicBaseMsr */);
 
         /* Clear the interrupt pending force flag. */
@@ -1070,5 +1077,5 @@
         if (fNeedsGCMapping)
         {
-            pApic->pvApicPibRC == NIL_RTRCPTR;
+            pApic->pvApicPibRC = NIL_RTRCPTR;
             int rc = MMR3HyperMapHCPhys(pVM, (void *)pApic->pvApicPibR3, NIL_RTR0PTR, pApic->HCPhysApicPib, pApic->cbApicPib,
                                         "APIC PIB", (PRTGCPTR)&pApic->pvApicPibRC);
@@ -1127,5 +1134,5 @@
 
                 /* Associate the per-VCPU PIB pointers to the per-VM PIB mapping. */
-                size_t const offApicPib    = idCpu * sizeof(APICPIB);
+                uint32_t const offApicPib  = idCpu * sizeof(APICPIB);
                 pApicCpu->pvApicPibR0      = (RTR0PTR)((RTR0UINTPTR)pApic->pvApicPibR0 + offApicPib);
                 pApicCpu->pvApicPibR3      = (RTR3PTR)((RTR3UINTPTR)pApic->pvApicPibR3 + offApicPib);
@@ -1135,5 +1142,5 @@
                 /* Initialize the virtual-APIC state. */
                 memset((void *)pApicCpu->pvApicPageR3, 0, pApicCpu->cbApicPage);
-                APICR3Reset(pVCpu);
+                APICR3Reset(pVCpu, true /* fResetApicBaseMsr */);
 
 #ifdef DEBUG_ramshankar
Index: /trunk/src/VBox/VMM/include/APICInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/APICInternal.h	(revision 60645)
+++ /trunk/src/VBox/VMM/include/APICInternal.h	(revision 60646)
@@ -629,4 +629,5 @@
 const char             *apicGetTimerModeName(XAPICTIMERMODE enmTimerMode);
 void                    apicHintTimerFreq(PAPICCPU pApicCpu, uint32_t uInitialCount, uint8_t uTimerShift);
+APICMODE                apicGetMode(uint64_t uApicBaseMsr);
 
 VMMDECL(uint64_t)       APICGetBaseMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu);
