Index: /trunk/include/VBox/vmm/cpumctx.h
===================================================================
--- /trunk/include/VBox/vmm/cpumctx.h	(revision 72414)
+++ /trunk/include/VBox/vmm/cpumctx.h	(revision 72415)
@@ -877,4 +877,8 @@
 #define CPUMCTX_EXTRN_OTHER_MSRS                UINT64_C(0x0000008000000000)
 
+/** Mask of all the MSRs. */
+#define CPUMCTX_EXTRN_ALL_MSRS                  (  CPUMCTX_EXTRN_EFER | CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS \
+                                                 | CPUMCTX_EXTRN_SYSENTER_MSRS | CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS)
+
 /** Mask of bits the keepers can use for state tracking. */
 #define CPUMCTX_EXTRN_KEEPER_STATE_MASK         UINT64_C(0xffff000000000000)
Index: /trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h	(revision 72414)
+++ /trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h	(revision 72415)
@@ -2311,58 +2311,79 @@
     {
         /*
-         * Handle writes.
+         * Get all the MSR state.  Since we're getting EFER, we also need to
+         * get CR0, CR4 and CR3.
          */
-        if (pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE)
-        {
-            rcStrict = CPUMSetGuestMsr(pVCpu, pMsg->MsrNumber, RT_MAKE_U64((uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx));
-            Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n",
-                  pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
-                  pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
-            if (rcStrict == VINF_SUCCESS)
+        nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
+        rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, pGVCpu, pCtx,
+                                                       CPUMCTX_EXTRN_ALL_MSRS | CPUMCTX_EXTRN_CR0
+                                                     | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4,
+                                                     "MSRs");
+        if (rcStrict == VINF_SUCCESS)
+        {
+
+            /*
+             * Handle writes.
+             */
+            if (pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE)
             {
-                nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
-                nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header);
-                return VINF_SUCCESS;
+                rcStrict = CPUMSetGuestMsr(pVCpu, pMsg->MsrNumber, RT_MAKE_U64((uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx));
+                Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n",
+                      pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
+                      pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
+                if (rcStrict == VINF_SUCCESS)
+                {
+                    nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
+                    nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header);
+                    return VINF_SUCCESS;
+                }
+# ifndef IN_RING3
+                /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */
+                if (rcStrict == VERR_CPUM_RAISE_GP_0)
+                    rcStrict = VINF_CPUM_R3_MSR_WRITE;
+                return rcStrict;
+# else
+                LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n",
+                        pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
+                        pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
+# endif
             }
+            /*
+             * Handle reads.
+             */
+            else
+            {
+                uint64_t uValue = 0;
+                rcStrict = CPUMQueryGuestMsr(pVCpu, pMsg->MsrNumber, &uValue);
+                Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
+                      pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
+                      pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
+                if (rcStrict == VINF_SUCCESS)
+                {
+                    nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
+                    pCtx->rax = (uint32_t)uValue;
+                    pCtx->rdx = uValue >> 32;
+                    pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX);
+                    nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header);
+                    return VINF_SUCCESS;
+                }
 # ifndef IN_RING3
-            /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */
-            if (rcStrict == VERR_CPUM_RAISE_GP_0)
-                rcStrict = VINF_CPUM_R3_MSR_WRITE;
+                /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */
+                if (rcStrict == VERR_CPUM_RAISE_GP_0)
+                    rcStrict = VINF_CPUM_R3_MSR_READ;
+                return rcStrict;
+# else
+                LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
+                        pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
+                        pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
+# endif
+            }
+        }
+        else
+        {
+            LogRel(("MsrExit/%u: %04x:%08RX64/%s: %sMSR %08x -> %Rrc - msr state import\n",
+                    pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
+                    pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE ? "WR" : "RD",
+                    pMsg->MsrNumber, VBOXSTRICTRC_VAL(rcStrict) ));
             return rcStrict;
-# else
-            LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n",
-                    pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
-                    pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
-# endif
-        }
-        /*
-         * Handle reads.
-         */
-        else
-        {
-            uint64_t uValue = 0;
-            rcStrict = CPUMQueryGuestMsr(pVCpu, pMsg->MsrNumber, &uValue);
-            Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
-                  pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
-                  pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
-            if (rcStrict == VINF_SUCCESS)
-            {
-                nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
-                pCtx->rax = (uint32_t)uValue;
-                pCtx->rdx = uValue >> 32;
-                pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX);
-                nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header);
-                return VINF_SUCCESS;
-            }
-# ifndef IN_RING3
-            /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */
-            if (rcStrict == VERR_CPUM_RAISE_GP_0)
-                rcStrict = VINF_CPUM_R3_MSR_READ;
-            return rcStrict;
-# else
-            LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
-                    pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
-                    pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
-# endif
         }
     }
@@ -2379,5 +2400,5 @@
      * If we get down here, we're supposed to #GP(0).
      */
-    rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "NMI");
+    rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "MSR");
     if (rcStrict == VINF_SUCCESS)
     {
@@ -2413,60 +2434,78 @@
     {
         /*
-         * Handle writes.
+         * Get all the MSR state.  Since we're getting EFER, we also need to
+         * get CR0, CR4 and CR3.
          */
-        if (pExit->MsrAccess.AccessInfo.IsWrite)
-        {
-            rcStrict = CPUMSetGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber,
-                                       RT_MAKE_U64((uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx));
-            Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n",
-                  pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
-                  pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
-            if (rcStrict == VINF_SUCCESS)
+        nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
+        rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx,
+                                                       CPUMCTX_EXTRN_ALL_MSRS | CPUMCTX_EXTRN_CR0
+                                                     | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4,
+                                                     "MSRs");
+        if (rcStrict == VINF_SUCCESS)
+        {
+            /*
+             * Handle writes.
+             */
+            if (pExit->MsrAccess.AccessInfo.IsWrite)
             {
-                nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
-                nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
-                return VINF_SUCCESS;
+                rcStrict = CPUMSetGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber,
+                                           RT_MAKE_U64((uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx));
+                Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
+                      pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->MsrAccess.MsrNumber,
+                      (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
+                if (rcStrict == VINF_SUCCESS)
+                {
+                    nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
+                    return VINF_SUCCESS;
+                }
+                LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n", pVCpu->idCpu,
+                        pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
+                        pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx,
+                        VBOXSTRICTRC_VAL(rcStrict) ));
             }
-            LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n",
+            /*
+             * Handle reads.
+             */
+            else
+            {
+                uint64_t uValue = 0;
+                rcStrict = CPUMQueryGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber, &uValue);
+                Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", pVCpu->idCpu,
+                      pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
+                      pExit->MsrAccess.MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
+                if (rcStrict == VINF_SUCCESS)
+                {
+                    pCtx->rax = (uint32_t)uValue;
+                    pCtx->rdx = uValue >> 32;
+                    pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX);
+                    nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
+                    return VINF_SUCCESS;
+                }
+                LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
+                        pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->MsrAccess.MsrNumber,
+                        uValue, VBOXSTRICTRC_VAL(rcStrict) ));
+            }
+        }
+        else
+        {
+            LogRel(("MsrExit/%u: %04x:%08RX64/%s: %sMSR %08x -> %Rrc - msr state import\n",
                     pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
-                    pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
-        }
-        /*
-         * Handle reads.
-         */
-        else
-        {
-            uint64_t uValue = 0;
-            rcStrict = CPUMQueryGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber, &uValue);
-            Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
-                  pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
-                  pExit->MsrAccess.MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
-            if (rcStrict == VINF_SUCCESS)
-            {
-                nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
-                pCtx->rax = (uint32_t)uValue;
-                pCtx->rdx = uValue >> 32;
-                pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX);
-                nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
-                return VINF_SUCCESS;
-            }
-            LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
-                    pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
-                    pExit->MsrAccess.MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
+                    pExit->MsrAccess.AccessInfo.IsWrite ? "WR" : "RD", pExit->MsrAccess.MsrNumber, VBOXSTRICTRC_VAL(rcStrict) ));
+            return rcStrict;
         }
     }
     else if (pExit->MsrAccess.AccessInfo.IsWrite)
-        Log4(("MsrExit/%u: %04x:%08RX64/%s: CPL %u -> #GP(0); WRMSR %08x, %08x:%08x\n",
-              pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
-              pExit->VpContext.ExecutionState.Cpl, pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx ));
+        Log4(("MsrExit/%u: %04x:%08RX64/%s: CPL %u -> #GP(0); WRMSR %08x, %08x:%08x\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
+              pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpContext.ExecutionState.Cpl,
+              pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx ));
     else
-        Log4(("MsrExit/%u: %04x:%08RX64/%s: CPL %u -> #GP(0); RDMSR %08x\n",
-              pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
-              pExit->VpContext.ExecutionState.Cpl, pExit->MsrAccess.MsrNumber));
+        Log4(("MsrExit/%u: %04x:%08RX64/%s: CPL %u -> #GP(0); RDMSR %08x\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
+              pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpContext.ExecutionState.Cpl,
+              pExit->MsrAccess.MsrNumber));
 
     /*
      * If we get down here, we're supposed to #GP(0).
      */
-    rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "NMI");
+    rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "MSR");
     if (rcStrict == VINF_SUCCESS)
     {
Index: /trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp	(revision 72414)
+++ /trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp	(revision 72415)
@@ -2432,6 +2432,18 @@
  *
  *
- * - Need to figure out how to emulate X2APIC (AMD Ryzen), doesn't work with
- *   debian 9.0/64.
+ * - The IA32_APIC_BASE register does not work right:
+ *
+ *      - Attempts by the guest to clear bit 11 (EN) are ignored, both the
+ *        guest and the VMM reads back the old value.
+ *
+ *      - Attempts to modify the base address (bits NN:12) seems to be ignored
+ *        in the same way.
+ *
+ *      - The VMM can modify both the base address as well as the the EN and
+ *        BSP bits, however this is useless if we cannot intercept the WRMSR.
+ *
+ *      - Attempts by the guest to set the EXTD bit (X2APIC) result in #GP(0),
+ *        while the VMM ends up with with ERROR_HV_INVALID_PARAMETER.  Seems
+ *        there is no way to support X2APIC.
  *
  *
