Index: /trunk/src/VBox/VMM/VMMR3/VMMTests.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VMMTests.cpp	(revision 49140)
+++ /trunk/src/VBox/VMM/VMMR3/VMMTests.cpp	(revision 49141)
@@ -618,2 +618,119 @@
 }
 
+
+#ifdef VBOX_WITH_RAW_MODE
+
+/**
+ * Used by VMMDoBruteForceMsrs to dump the CPUID info of the host CPU as a
+ * prefix to the MSR report.
+ */
+static DECLCALLBACK(void) vmmDoPrintfVToStream(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list va)
+{
+    PRTSTREAM pOutStrm = ((PRTSTREAM *)pHlp)[-1];
+    RTStrmPrintfV(pOutStrm, pszFormat, va);
+}
+
+/**
+ * Used by VMMDoBruteForceMsrs to dump the CPUID info of the host CPU as a
+ * prefix to the MSR report.
+ */
+static DECLCALLBACK(void) vmmDoPrintfToStream(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    vmmDoPrintfVToStream(pHlp, pszFormat, va);
+    va_end(va);
+}
+
+#endif
+
+
+/**
+ * Uses raw-mode to query all possible MSRs on the real hardware.
+ *
+ * This generates a msr-report.txt file (appending, no overwriting) as well as
+ * writing the values and process to stdout.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ */
+VMMDECL(int) VMMDoBruteForceMsrs(PVM pVM)
+{
+#ifdef VBOX_WITH_RAW_MODE
+    RTRCPTR RCPtrEP;
+    int rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "VMMRCTestReadMsrs", &RCPtrEP);
+    if (RT_SUCCESS(rc))
+    {
+        RTPrintf("VMM: VMMRCTestReadMsrs=%RRv\n", RCPtrEP);
+        PRTSTREAM pOutStrm;
+        rc = RTStrmOpen("msr-report.txt", "a", &pOutStrm);
+        if (RT_SUCCESS(rc))
+        {
+            /* Header */
+            struct
+            {
+                PRTSTREAM   pOutStrm;
+                DBGFINFOHLP Hlp;
+            } MyHlp = { pOutStrm, { vmmDoPrintfToStream, vmmDoPrintfVToStream } };
+            DBGFR3Info(pVM->pUVM, "cpuid", "verbose", &MyHlp.Hlp);
+            RTStrmPrintf(pOutStrm, "\n");
+
+            /*
+             * The MSRs.
+             */
+            uint32_t const      cMsrsPerCall = 1024;
+            uint32_t            cbResults = cMsrsPerCall * sizeof(VMMTESTMSRENTRY);
+            PVMMTESTMSRENTRY    paResults;
+            rc = MMHyperAlloc(pVM, cbResults, 0, MM_TAG_VMM, (void **)&paResults);
+            if (RT_SUCCESS(rc))
+            {
+                RTRCPTR  RCPtrResults = MMHyperR3ToRC(pVM, paResults);
+                uint32_t cMsrsFound   = 0;
+                uint32_t uLastMsr     = 0;
+                uint64_t uNsTsStart   = RTTimeNanoTS();
+
+                for (uint32_t uCurMsr = 0; ; uCurMsr += cMsrsPerCall)
+                {
+                    if (   uCurMsr - uLastMsr > _64K
+                        && (uCurMsr & (_4M - 1)) == 0)
+                    {
+                        if (uCurMsr - uLastMsr < 16U*_1M)
+                            RTStrmFlush(pOutStrm);
+                        RTPrintf("... %#010x [%u ns/msr] ...\n", uCurMsr, (RTTimeNanoTS() - uNsTsStart) / uCurMsr);
+                    }
+
+                    RT_BZERO(paResults, cbResults);
+                    rc = VMMR3CallRC(pVM, RCPtrEP, 4, pVM->pVMRC, uCurMsr, cMsrsPerCall, RCPtrResults);
+                    if (RT_FAILURE(rc))
+                    {
+                        RTPrintf("VMM: VMMR3CallRC failed rc=%Rrc, uCurMsr=%#x\n", rc, uCurMsr);
+                        break;
+                    }
+
+                    for (uint32_t i = 0; i < cMsrsPerCall; i++)
+                        if (paResults[i].uMsr != UINT64_MAX)
+                        {
+                            RTStrmPrintf(pOutStrm, "%#010x = %#llx\n", paResults[i].uMsr, paResults[i].uValue);
+                            RTPrintf("%#010x = %#llx\n", paResults[i].uMsr, paResults[i].uValue);
+                            cMsrsFound++;
+                            uLastMsr = paResults[i].uMsr;
+                        }
+                    if (uCurMsr + cMsrsPerCall < uCurMsr)
+                        break;
+                }
+
+                RTStrmPrintf(pOutStrm, "Total %u (%#x) MSRs\n", cMsrsFound, cMsrsFound);
+                RTPrintf("Total %u (%#x) MSRs\n", cMsrsFound, cMsrsFound);
+                MMHyperFree(pVM, paResults);
+            }
+            RTStrmClose(pOutStrm);
+        }
+    }
+    else
+        AssertMsgFailed(("Failed to resolved VMMRC.rc::VMMRCEntry(), rc=%Rrc\n", rc));
+    return rc;
+#else
+    return VERR_NOT_SUPPORTED;
+#endif
+}
+
Index: /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 49140)
+++ /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 49141)
@@ -1452,2 +1452,18 @@
 }
 
+
+/**
+ * Generic hyper trap handler that sets the EIP to @a uUser.
+ *
+ * @returns VBox status code.  (Anything but VINF_SUCCESS will cause guru.)
+ * @param   pVM         Pointer to the cross context VM structure.
+ * @param   pRegFrame   Pointer to the register frame (within VM)
+ * @param   uUser       The user arg, which should be the new EIP address.
+ */
+extern "C" DECLCALLBACK(int) TRPMRCTrapHyperHandlerSetEIP(PVM pVM, PCPUMCTXCORE pRegFrame, uintptr_t uUser)
+{
+    AssertReturn(MMHyperIsInsideArea(pVM, uUser), VERR_TRPM_IPE_3);
+    pRegFrame->eip = uUser;
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/VMM/VMMRC/VMMRC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/VMMRC.cpp	(revision 49140)
+++ /trunk/src/VBox/VMM/VMMRC/VMMRC.cpp	(revision 49141)
@@ -48,4 +48,5 @@
 static DECLCALLBACK(int) vmmGCTestTmpPFHandler(PVM pVM, PCPUMCTXCORE pRegFrame);
 static DECLCALLBACK(int) vmmGCTestTmpPFHandlerCorruptFS(PVM pVM, PCPUMCTXCORE pRegFrame);
+DECLASM(bool)   vmmRCSafeMsrRead(uint32_t uMsr, uint64_t *pu64Value);
 
 
@@ -344,4 +345,35 @@
 
 
+
+/**
+ * Reads a range of MSRs.
+ *
+ * This is called directly via VMMR3CallRC.
+ *
+ * @returns VBox status code.
+ * @param   pVM             The VM handle.
+ * @param   uMsr            The MSR to start at.
+ * @param   cMsrs           The number of MSRs to read.
+ * @param   paResults       Where to store the results.  This must be large
+ *                          enough to hold at least @a cMsrs result values.
+ */
+extern "C" VMMRCDECL(int)
+VMMRCTestReadMsrs(PVM pVM, uint32_t uMsr, uint32_t cMsrs, PVMMTESTMSRENTRY paResults)
+{
+    AssertReturn(cMsrs <= 4096, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(paResults, VERR_INVALID_POINTER);
+
+    for (uint32_t i = 0; i < cMsrs; i++, uMsr++)
+    {
+        if (vmmRCSafeMsrRead(uMsr, &paResults[i].uValue))
+            paResults[i].uMsr = uMsr;
+        else
+            paResults[i].uMsr = UINT64_MAX;
+    }
+    return VINF_SUCCESS;
+}
+
+
+
 /**
  * Temporary \#PF trap handler for the \#PF test case.
Index: /trunk/src/VBox/VMM/VMMRC/VMMRCA.asm
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/VMMRCA.asm	(revision 49140)
+++ /trunk/src/VBox/VMM/VMMRC/VMMRCA.asm	(revision 49141)
@@ -24,4 +24,5 @@
 %include "VBox/vmm/vm.mac"
 %include "VMMInternal.mac"
+%include "VMMRC.mac"
 
 
@@ -57,4 +58,5 @@
 extern NAME(RTLogLogger)
 extern NAME(vmmRCProbeFireHelper)
+extern NAME(TRPMRCTrapHyperHandlerSetEIP)
 
 
@@ -219,4 +221,40 @@
     ret
 ENDPROC vmmGCTestTrap0e
+
+
+
+;;
+; Safely reads an MSR.
+; @returns  boolean
+; @param    uMsr        The MSR to red.
+; @param    pu64Value   Where to return the value on success.
+;
+GLOBALNAME vmmRCSafeMsrRead
+    push    ebp
+    mov     ebp, esp
+    pushad
+
+    mov     ecx, [ebp + 8]              ; the MSR to read.
+    mov     eax, 0deadbeefh
+    mov     edx, 0deadbeefh
+
+TRPM_GP_HANDLER NAME(TRPMRCTrapHyperHandlerSetEIP), .trapped
+    rdmsr
+
+    mov     ecx, [ebp + 0ch]            ; Where to store the result.
+    mov     [ecx], eax
+    mov     [ecx], edx
+
+    popad
+    mov     eax, 1
+    leave
+    ret
+
+.trapped:
+    popad
+    mov     eax, 0
+    leave
+    ret
+ENDPROC vmmRCSafeMsrRead
 
 
Index: /trunk/src/VBox/VMM/include/VMMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/VMMInternal.h	(revision 49140)
+++ /trunk/src/VBox/VMM/include/VMMInternal.h	(revision 49141)
@@ -526,4 +526,21 @@
 
 
+
+/**
+ * MSR test result entry.
+ */
+typedef struct VMMTESTMSRENTRY
+{
+    /** The MSR number, including padding.
+     * Set to UINT64_MAX if invalid MSR. */
+    uint64_t    uMsr;
+    /** The register value. */
+    uint64_t    uValue;
+} VMMTESTMSRENTRY;
+/** Pointer to an MSR test result entry. */
+typedef VMMTESTMSRENTRY *PVMMTESTMSRENTRY;
+
+
+
 RT_C_DECLS_BEGIN
 
Index: /trunk/src/VBox/VMM/testcase/tstVMM.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstVMM.cpp	(revision 49140)
+++ /trunk/src/VBox/VMM/testcase/tstVMM.cpp	(revision 49141)
@@ -55,5 +55,6 @@
 *   Internal Functions                                                         *
 *******************************************************************************/
-VMMR3DECL(int) VMMDoTest(PVM pVM); /* Linked into VMM, see ../VMMTests.cpp. */
+VMMR3DECL(int) VMMDoTest(PVM pVM);    /* Linked into VMM, see ../VMMTests.cpp. */
+VMMR3DECL(int) VMMDoBruteForceMsrs(PVM pVM); /* Ditto. */
 
 
@@ -210,5 +211,5 @@
     enum
     {
-        kTstVMMTest_VMM,  kTstVMMTest_TM
+        kTstVMMTest_VMM,  kTstVMMTest_TM, kTstVMMTest_MSRs
     } enmTestOpt = kTstVMMTest_VMM;
 
@@ -230,4 +231,6 @@
                 else if (!strcmp("tm", ValueUnion.psz))
                     enmTestOpt = kTstVMMTest_TM;
+                else if (!strcmp("msr", ValueUnion.psz) || !strcmp("msrs", ValueUnion.psz))
+                    enmTestOpt = kTstVMMTest_MSRs;
                 else
                 {
@@ -238,5 +241,5 @@
 
             case 'h':
-                RTPrintf("usage: tstVMM [--cpus|-c cpus] [--test <vmm|tm>]\n");
+                RTPrintf("usage: tstVMM [--cpus|-c cpus] [--test <vmm|tm|msr>]\n");
                 return 1;
 
@@ -274,4 +277,5 @@
                 if (RT_FAILURE(rc))
                     RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc);
+                STAMR3Dump(pUVM, "*");
                 break;
             }
@@ -290,9 +294,22 @@
                 if (RT_FAILURE(rc))
                     RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc);
-                break;
-            }
-        }
-
-        STAMR3Dump(pUVM, "*");
+                STAMR3Dump(pUVM, "*");
+                break;
+            }
+
+            case kTstVMMTest_MSRs:
+            {
+                RTTestSub(hTest, "MSRs");
+                if (g_cCpus == 1)
+                {
+                    rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoBruteForceMsrs, 1, pVM);
+                    if (RT_FAILURE(rc))
+                        RTTestFailed(hTest, "VMMDoBruteForceMsrs failed: rc=%Rrc\n", rc);
+                }
+                else
+                    RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n");
+                break;
+            }
+        }
 
         /*
