Index: trunk/src/VBox/VMM/EM.cpp
===================================================================
--- trunk/src/VBox/VMM/EM.cpp	(revision 9064)
+++ trunk/src/VBox/VMM/EM.cpp	(revision 9069)
@@ -209,4 +209,8 @@
     STAM_REG_USED(pVM, &pStats->StatGCXAdd,                 STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/XAdd",      STAMUNIT_OCCURENCES,    "The number of times XADD was successfully interpreted.");
     STAM_REG_USED(pVM, &pStats->StatHCXAdd,                 STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/XAdd",      STAMUNIT_OCCURENCES,    "The number of times XADD was successfully interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatHCRdmsr,                STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Rdmsr",      STAMUNIT_OCCURENCES,   "The number of times RDMSR was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatGCRdmsr,                STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Rdmsr",      STAMUNIT_OCCURENCES,   "The number of times RDMSR was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatHCWrmsr,                STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Wrmsr",      STAMUNIT_OCCURENCES,   "The number of times WRMSR was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatGCWrmsr,                STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Wrmsr",      STAMUNIT_OCCURENCES,   "The number of times WRMSR was not interpreted.");
 
     STAM_REG(pVM, &pStats->StatGCInterpretFailed,           STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed",            STAMUNIT_OCCURENCES,    "The number of times an instruction was not interpreted.");
@@ -251,4 +255,8 @@
     STAM_REG_USED(pVM, &pStats->StatGCFailedRdtsc,          STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Rdtsc",      STAMUNIT_OCCURENCES,    "The number of times RDTSC was not interpreted.");
     STAM_REG_USED(pVM, &pStats->StatHCFailedRdtsc,          STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Rdtsc",      STAMUNIT_OCCURENCES,    "The number of times RDTSC was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatGCFailedRdmsr,          STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Rdmsr",      STAMUNIT_OCCURENCES,    "The number of times RDMSR was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatHCFailedRdmsr,          STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Rdmsr",      STAMUNIT_OCCURENCES,    "The number of times RDMSR was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatGCFailedWrmsr,          STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Wrmsr",      STAMUNIT_OCCURENCES,    "The number of times WRMSR was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatHCFailedWrmsr,          STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Wrmsr",      STAMUNIT_OCCURENCES,    "The number of times WRMSR was not interpreted.");
 
     STAM_REG_USED(pVM, &pStats->StatGCFailedMisc,           STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Misc",       STAMUNIT_OCCURENCES,    "The number of times some misc instruction was encountered.");
Index: trunk/src/VBox/VMM/EMInternal.h
===================================================================
--- trunk/src/VBox/VMM/EMInternal.h	(revision 9064)
+++ trunk/src/VBox/VMM/EMInternal.h	(revision 9069)
@@ -141,4 +141,8 @@
     STAMCOUNTER             StatGCClts;
     STAMCOUNTER             StatHCClts;
+    STAMCOUNTER             StatHCRdmsr;
+    STAMCOUNTER             StatHCWrmsr;
+    STAMCOUNTER             StatGCRdmsr;
+    STAMCOUNTER             StatGCWrmsr;
 
     STAMCOUNTER             StatGCInterpretFailed;
@@ -183,4 +187,8 @@
     STAMCOUNTER             StatGCFailedMWait;
     STAMCOUNTER             StatHCFailedMWait;
+    STAMCOUNTER             StatHCFailedRdmsr;
+    STAMCOUNTER             StatHCFailedWrmsr;
+    STAMCOUNTER             StatGCFailedRdmsr;
+    STAMCOUNTER             StatGCFailedWrmsr;
 
     STAMCOUNTER             StatGCFailedAdd;
Index: trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 9064)
+++ trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 9069)
@@ -37,4 +37,5 @@
 #include <VBox/hwaccm.h>
 #include <VBox/tm.h>
+#include <VBox/pdmapi.h>
 
 #include <VBox/param.h>
@@ -2042,4 +2043,204 @@
 }
 
+/**
+ * Interpret RDMSR
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ * @param   pRegFrame   The register frame.
+ *
+ */
+EMDECL(int) EMInterpretRdmsr(PVM pVM, PCPUMCTXCORE pRegFrame)
+{
+    uint32_t u32Dummy, u32Features, cpl;
+    uint64_t val;
+    CPUMCTX *pCtx;
+    int      rc;
+
+    rc = CPUMQueryGuestCtxPtr(pVM, &pCtx);
+    AssertRC(rc);
+
+    /* Get the current privilege level. */
+    cpl = CPUMGetGuestCPL(pVM, pRegFrame);
+    if (cpl != 0)
+        return VERR_EM_INTERPRETER; /* supervisor only */
+
+    CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
+    if (!(u32Features & X86_CPUID_FEATURE_EDX_MSR))
+        return VERR_EM_INTERPRETER; /* not supported */
+
+    switch (pRegFrame->ecx)
+    {
+    case MSR_IA32_APICBASE:
+        rc = PDMApicGetBase(pVM, &val);
+        AssertRC(rc);
+        break;
+
+    case MSR_IA32_CR_PAT:
+        val = pCtx->msrPAT;
+        break;
+
+    case MSR_IA32_SYSENTER_CS:
+        val = pCtx->SysEnter.cs;
+        break;
+
+    case MSR_IA32_SYSENTER_EIP:
+        val = pCtx->SysEnter.eip;
+        break;
+
+    case MSR_IA32_SYSENTER_ESP:
+        val = pCtx->SysEnter.esp;
+        break;
+
+    case MSR_K6_EFER:
+        val = pCtx->msrEFER;
+        break;
+
+    case MSR_K8_SF_MASK:
+        val = pCtx->msrSFMASK;
+        break;
+
+    case MSR_K6_STAR:
+        val = pCtx->msrSTAR;
+        break;
+
+    case MSR_K8_LSTAR:
+        val = pCtx->msrLSTAR;
+        break;
+
+    case MSR_K8_CSTAR:
+        val = pCtx->msrCSTAR;
+        break;
+
+    case MSR_K8_FS_BASE:
+        val = pCtx->msrFSBASE;
+        break;
+
+    case MSR_K8_GS_BASE:
+        val = pCtx->msrGSBASE;
+        break;
+
+    case MSR_K8_KERNEL_GS_BASE:
+        val = pCtx->msrKERNELGSBASE;
+        break;
+
+    default:
+        /* We should actually trigger a #GP here, but don't as that might cause more trouble. */
+        val = 0;
+        break;
+    }
+    Log(("EMInterpretRdmsr %x -> val=%VX64\n", pRegFrame->ecx, val));
+    pRegFrame->eax = (uint32_t) val;
+    pRegFrame->edx = (uint32_t) (val >> 32ULL);
+    return VINF_SUCCESS;
+}
+
+/**
+ * RDMSR Emulation.
+ */
+static int emInterpretRdmsr(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
+{
+    return EMInterpretRdmsr(pVM, pRegFrame);
+}
+
+/**
+ * Interpret WRMSR
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ * @param   pRegFrame   The register frame.
+ *
+ */
+EMDECL(int) EMInterpretWrmsr(PVM pVM, PCPUMCTXCORE pRegFrame)
+{
+    uint32_t u32Dummy, u32Features, cpl;
+    uint64_t val;
+    CPUMCTX *pCtx;
+    int      rc;
+
+    rc = CPUMQueryGuestCtxPtr(pVM, &pCtx);
+    AssertRC(rc);
+
+    /* Get the current privilege level. */
+    cpl = CPUMGetGuestCPL(pVM, pRegFrame);
+    if (cpl != 0)
+        return VERR_EM_INTERPRETER; /* supervisor only */
+
+    CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
+    if (!(u32Features & X86_CPUID_FEATURE_EDX_MSR))
+        return VERR_EM_INTERPRETER; /* not supported */
+
+    val = (uint64_t)pRegFrame->eax | ((uint64_t)pRegFrame->edx << 32ULL);
+    Log(("EMInterpretWrmsr %x val=%VX64\n", pRegFrame->ecx, val));
+    switch (pRegFrame->ecx)
+    {
+    case MSR_IA32_APICBASE:
+        rc = PDMApicSetBase(pVM, val);
+        AssertRC(rc);
+        break;
+
+    case MSR_IA32_CR_PAT:
+        pCtx->msrPAT = val;
+        break;
+
+    case MSR_IA32_SYSENTER_CS:
+        pCtx->SysEnter.cs = val;
+        break;
+
+    case MSR_IA32_SYSENTER_EIP:
+        pCtx->SysEnter.eip = val;
+        break;
+
+    case MSR_IA32_SYSENTER_ESP:
+        pCtx->SysEnter.esp = val;
+        break;
+
+    case MSR_K6_EFER:
+        AssertFailed();
+        pCtx->msrEFER = val;
+        break;
+
+    case MSR_K8_SF_MASK:
+        pCtx->msrSFMASK = val;
+        break;
+
+    case MSR_K6_STAR:
+        pCtx->msrSTAR = val;
+        break;
+
+    case MSR_K8_LSTAR:
+        pCtx->msrLSTAR = val;
+        break;
+
+    case MSR_K8_CSTAR:
+        pCtx->msrCSTAR = val;
+        break;
+
+    case MSR_K8_FS_BASE:
+        pCtx->msrFSBASE = val;
+        break;
+
+    case MSR_K8_GS_BASE:
+        pCtx->msrGSBASE = val;
+        break;
+
+    case MSR_K8_KERNEL_GS_BASE:
+        pCtx->msrKERNELGSBASE = val;
+        break;
+
+    default:
+        /* We should actually trigger a #GP here, but don't as that might cause more trouble. */
+        break;
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * WRMSR Emulation.
+ */
+static int emInterpretWrmsr(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
+{
+    return EMInterpretWrmsr(pVM, pRegFrame);
+}
 
 /**
@@ -2145,4 +2346,8 @@
         INTERPRET_CASE(OP_MONITOR, Monitor);
         INTERPRET_CASE(OP_MWAIT, MWait);
+#ifdef VBOX_WITH_MSR_EMULATION
+        INTERPRET_CASE(OP_RDMSR, Rdmsr);
+        INTERPRET_CASE(OP_WRMSR, Wrmsr);
+#endif
         INTERPRET_CASE_EX_PARAM3(OP_ADD,Add, AddSub, EMEmulateAdd);
         INTERPRET_CASE_EX_PARAM3(OP_SUB,Sub, AddSub, EMEmulateSub);
