VirtualBox

Ignore:
Timestamp:
Jul 26, 2019 1:37:47 PM (5 years ago)
Author:
vboxsync
Message:

VMM: Kicking out raw-mode (work in progress). bugref:9517

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/VMMTests.cpp

    r76553 r80003  
    4545
    4646
    47 #ifdef VBOX_WITH_RAW_MODE
    48 
    49 static void vmmR3TestClearStack(PVMCPU pVCpu)
    50 {
    51     /* We leave the first 64 bytes of the stack alone because of strict
    52        ring-0 long jump code uses it. */
    53     memset(pVCpu->vmm.s.pbEMTStackR3 + 64, 0xaa, VMM_STACK_SIZE - 64);
    54 }
    55 
    56 
    57 static int vmmR3ReportMsrRange(PVM pVM, uint32_t uMsr, uint64_t cMsrs, PRTSTREAM pReportStrm, uint32_t *pcMsrsFound)
    58 {
    59     /*
    60      * Preps.
    61      */
    62     RTRCPTR RCPtrEP;
    63     int rc = PDMR3LdrGetSymbolRC(pVM, VMMRC_MAIN_MODULE_NAME, "VMMRCTestReadMsrs", &RCPtrEP);
    64     AssertMsgRCReturn(rc, ("Failed to resolved VMMRC.rc::VMMRCEntry(), rc=%Rrc\n", rc), rc);
    65 
    66     uint32_t const      cMsrsPerCall = 16384;
    67     uint32_t            cbResults = cMsrsPerCall * sizeof(VMMTESTMSRENTRY);
    68     PVMMTESTMSRENTRY    paResults;
    69     rc = MMHyperAlloc(pVM, cbResults, 0, MM_TAG_VMM, (void **)&paResults);
    70     AssertMsgRCReturn(rc, ("Error allocating %#x bytes off the hyper heap: %Rrc\n", cbResults, rc), rc);
    71     /*
    72      * The loop.
    73      */
    74     RTRCPTR  RCPtrResults = MMHyperR3ToRC(pVM, paResults);
    75     uint32_t cMsrsFound   = 0;
    76     uint32_t uLastMsr     = uMsr;
    77     uint64_t uNsTsStart   = RTTimeNanoTS();
    78 
    79     for (;;)
    80     {
    81         if (   pReportStrm
    82             && uMsr - uLastMsr > _64K
    83             && (uMsr & (_4M - 1)) == 0)
    84         {
    85             if (uMsr - uLastMsr < 16U*_1M)
    86                 RTStrmFlush(pReportStrm);
    87             RTPrintf("... %#010x [%u ns/msr] ...\n", uMsr, (RTTimeNanoTS() - uNsTsStart) / uMsr);
    88         }
    89 
    90         /*RT_BZERO(paResults, cbResults);*/
    91         uint32_t const cBatch = RT_MIN(cMsrsPerCall, cMsrs);
    92         rc = VMMR3CallRC(pVM, RCPtrEP, 4, pVM->pVMRC, uMsr, cBatch, RCPtrResults);
    93         if (RT_FAILURE(rc))
    94         {
    95             RTPrintf("VMM: VMMR3CallRC failed rc=%Rrc, uMsr=%#x\n", rc, uMsr);
    96             break;
    97         }
    98 
    99         for (uint32_t i = 0; i < cBatch; i++)
    100             if (paResults[i].uMsr != UINT64_MAX)
    101             {
    102                 if (paResults[i].uValue == 0)
    103                 {
    104                     if (pReportStrm)
    105                         RTStrmPrintf(pReportStrm,
    106                                      "    MVO(%#010llx, \"MSR\", UINT64_C(%#018llx)),\n", paResults[i].uMsr, paResults[i].uValue);
    107                     RTPrintf("%#010llx = 0\n", paResults[i].uMsr);
    108                 }
    109                 else
    110                 {
    111                     if (pReportStrm)
    112                         RTStrmPrintf(pReportStrm,
    113                                      "    MVO(%#010llx, \"MSR\", UINT64_C(%#018llx)),\n", paResults[i].uMsr, paResults[i].uValue);
    114                     RTPrintf("%#010llx = %#010x`%08x\n", paResults[i].uMsr,
    115                              RT_HI_U32(paResults[i].uValue), RT_LO_U32(paResults[i].uValue));
    116                 }
    117                 cMsrsFound++;
    118                 uLastMsr = paResults[i].uMsr;
    119             }
    120 
    121         /* Advance. */
    122         if (cMsrs <= cMsrsPerCall)
    123             break;
    124         cMsrs -= cMsrsPerCall;
    125         uMsr  += cMsrsPerCall;
    126     }
    127 
    128     *pcMsrsFound += cMsrsFound;
    129     MMHyperFree(pVM, paResults);
    130     return rc;
    131 }
    132 
    133 
    134 /**
    135  * Produces a quick report of MSRs.
    136  *
    137  * @returns VBox status code.
    138  * @param   pVM             The cross context VM structure.
    139  * @param   pReportStrm     Pointer to the report output stream. Optional.
    140  * @param   fWithCpuId      Whether CPUID should be included.
    141  */
    142 static int vmmR3DoMsrQuickReport(PVM pVM, PRTSTREAM pReportStrm, bool fWithCpuId)
    143 {
    144     uint64_t uTsStart = RTTimeNanoTS();
    145     RTPrintf("=== MSR Quick Report Start ===\n");
    146     RTStrmFlush(g_pStdOut);
    147     if (fWithCpuId)
    148     {
    149         DBGFR3InfoStdErr(pVM->pUVM, "cpuid", "verbose");
    150         RTPrintf("\n");
    151     }
    152     if (pReportStrm)
    153         RTStrmPrintf(pReportStrm, "\n\n{\n");
    154 
    155     static struct { uint32_t uFirst, cMsrs; } const s_aRanges[] =
    156     {
    157         { 0x00000000, 0x00042000 },
    158         { 0x10000000, 0x00001000 },
    159         { 0x20000000, 0x00001000 },
    160         { 0x40000000, 0x00012000 },
    161         { 0x80000000, 0x00012000 },
    162 //   Need 0xc0000000..0xc001106f (at least), but trouble on solaris w/ 10h and 0fh family cpus:
    163 //      { 0xc0000000, 0x00022000 },
    164         { 0xc0000000, 0x00010000 },
    165         { 0xc0010000, 0x00001040 },
    166         { 0xc0011040, 0x00004040 }, /* should cause trouble... */
    167     };
    168     uint32_t cMsrsFound = 0;
    169     int rc = VINF_SUCCESS;
    170     for (unsigned i = 0; i < RT_ELEMENTS(s_aRanges) && RT_SUCCESS(rc); i++)
    171     {
    172 //if (i >= 3)
    173 //{
    174 //RTStrmFlush(g_pStdOut);
    175 //RTThreadSleep(40);
    176 //}
    177         rc = vmmR3ReportMsrRange(pVM, s_aRanges[i].uFirst, s_aRanges[i].cMsrs, pReportStrm, &cMsrsFound);
    178     }
    179 
    180     if (pReportStrm)
    181         RTStrmPrintf(pReportStrm, "}; /* %u (%#x) MSRs; rc=%Rrc */\n", cMsrsFound, cMsrsFound, rc);
    182     RTPrintf("Total %u (%#x) MSRs\n", cMsrsFound, cMsrsFound);
    183     RTPrintf("=== MSR Quick Report End (rc=%Rrc, %'llu ns) ===\n", rc, RTTimeNanoTS() - uTsStart);
    184     return rc;
    185 }
    186 
    187 
    188 /**
    189  * Performs a testcase.
    190  *
    191  * @returns return value from the test.
    192  * @param   pVM         The cross context VM structure.
    193  * @param   enmTestcase The testcase operation to perform.
    194  * @param   uVariation  The testcase variation id.
    195  */
    196 static int vmmR3DoGCTest(PVM pVM, VMMRCOPERATION enmTestcase, unsigned uVariation)
    197 {
    198     PVMCPU pVCpu = &pVM->aCpus[0];
    199 
    200     RTRCPTR RCPtrEP;
    201     int rc = PDMR3LdrGetSymbolRC(pVM, VMMRC_MAIN_MODULE_NAME, "VMMRCEntry", &RCPtrEP);
    202     if (RT_FAILURE(rc))
    203         return rc;
    204 
    205     Log(("vmmR3DoGCTest: %d %#x\n", enmTestcase, uVariation));
    206     CPUMSetHyperState(pVCpu, pVM->vmm.s.pfnCallTrampolineRC, pVCpu->vmm.s.pbEMTStackBottomRC, 0, 0);
    207     vmmR3TestClearStack(pVCpu);
    208     CPUMPushHyper(pVCpu, uVariation);
    209     CPUMPushHyper(pVCpu, enmTestcase);
    210     CPUMPushHyper(pVCpu, pVM->pVMRC);
    211     CPUMPushHyper(pVCpu, 3 * sizeof(RTRCPTR));    /* stack frame size */
    212     CPUMPushHyper(pVCpu, RCPtrEP);                /* what to call */
    213     Assert(CPUMGetHyperCR3(pVCpu) && CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu));
    214     rc = SUPR3CallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN, 0);
    215 
    216 # if 1
    217     /* flush the raw-mode logs. */
    218 #  ifdef LOG_ENABLED
    219     PRTLOGGERRC pLogger = pVM->vmm.s.pRCLoggerR3;
    220     if (   pLogger
    221         && pLogger->offScratch > 0)
    222         RTLogFlushRC(NULL, pLogger);
    223 #  endif
    224 #  ifdef VBOX_WITH_RC_RELEASE_LOGGING
    225     PRTLOGGERRC pRelLogger = pVM->vmm.s.pRCRelLoggerR3;
    226     if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))
    227         RTLogFlushRC(RTLogRelGetDefaultInstance(), pRelLogger);
    228 #  endif
    229 # endif
    230 
    231     Log(("vmmR3DoGCTest: rc=%Rrc iLastGZRc=%Rrc\n", rc, pVCpu->vmm.s.iLastGZRc));
    232     if (RT_LIKELY(rc == VINF_SUCCESS))
    233         rc = pVCpu->vmm.s.iLastGZRc;
    234     return rc;
    235 }
    236 
    237 
    238 /**
    239  * Performs a trap test.
    240  *
    241  * @returns Return value from the trap test.
    242  * @param   pVM         The cross context VM structure.
    243  * @param   u8Trap      The trap number to test.
    244  * @param   uVariation  The testcase variation.
    245  * @param   rcExpect    The expected result.
    246  * @param   u32Eax      The expected eax value.
    247  * @param   pszFaultEIP The fault address. Pass NULL if this isn't available or doesn't apply.
    248  * @param   pszDesc     The test description.
    249  */
    250 static int vmmR3DoTrapTest(PVM pVM, uint8_t u8Trap, unsigned uVariation, int rcExpect, uint32_t u32Eax, const char *pszFaultEIP, const char *pszDesc)
    251 {
    252     PVMCPU pVCpu = &pVM->aCpus[0];
    253 
    254     RTPrintf("VMM: testing 0%x / %d - %s\n", u8Trap, uVariation, pszDesc);
    255 
    256     RTRCPTR RCPtrEP;
    257     int rc = PDMR3LdrGetSymbolRC(pVM, VMMRC_MAIN_MODULE_NAME, "VMMRCEntry", &RCPtrEP);
    258     if (RT_FAILURE(rc))
    259         return rc;
    260 
    261     CPUMSetHyperState(pVCpu, pVM->vmm.s.pfnCallTrampolineRC, pVCpu->vmm.s.pbEMTStackBottomRC, 0, 0);
    262     vmmR3TestClearStack(pVCpu);
    263     CPUMPushHyper(pVCpu, uVariation);
    264     CPUMPushHyper(pVCpu, u8Trap + VMMRC_DO_TESTCASE_TRAP_FIRST);
    265     CPUMPushHyper(pVCpu, pVM->pVMRC);
    266     CPUMPushHyper(pVCpu, 3 * sizeof(RTRCPTR));    /* stack frame size */
    267     CPUMPushHyper(pVCpu, RCPtrEP);                /* what to call */
    268     Assert(CPUMGetHyperCR3(pVCpu) && CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu));
    269     rc = SUPR3CallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN, 0);
    270     if (RT_LIKELY(rc == VINF_SUCCESS))
    271         rc = pVCpu->vmm.s.iLastGZRc;
    272     bool fDump = false;
    273     if (rc != rcExpect)
    274     {
    275         RTPrintf("VMM: FAILURE - rc=%Rrc expected %Rrc\n", rc, rcExpect);
    276         if (rc != VERR_NOT_IMPLEMENTED)
    277             fDump = true;
    278     }
    279     else if (    rcExpect != VINF_SUCCESS
    280              &&  u8Trap != 8 /* double fault doesn't dare set TrapNo. */
    281              &&  u8Trap != 3 /* guest only, we're not in guest. */
    282              &&  u8Trap != 1 /* guest only, we're not in guest. */
    283              &&  u8Trap != TRPMGetTrapNo(pVCpu))
    284     {
    285         RTPrintf("VMM: FAILURE - Trap %#x expected %#x\n", TRPMGetTrapNo(pVCpu), u8Trap);
    286         fDump = true;
    287     }
    288     else if (pszFaultEIP)
    289     {
    290         RTRCPTR RCPtrFault;
    291         int rc2 = PDMR3LdrGetSymbolRC(pVM, VMMRC_MAIN_MODULE_NAME, pszFaultEIP, &RCPtrFault);
    292         if (RT_FAILURE(rc2))
    293             RTPrintf("VMM: FAILURE - Failed to resolve symbol '%s', %Rrc!\n", pszFaultEIP, rc);
    294         else if (RCPtrFault != CPUMGetHyperEIP(pVCpu))
    295         {
    296             RTPrintf("VMM: FAILURE - EIP=%08RX32 expected %RRv (%s)\n", CPUMGetHyperEIP(pVCpu), RCPtrFault, pszFaultEIP);
    297             fDump = true;
    298         }
    299     }
    300     else if (rcExpect != VINF_SUCCESS)
    301     {
    302         if (CPUMGetHyperSS(pVCpu) == SELMGetHyperDS(pVM))
    303             RTPrintf("VMM: FAILURE - ss=%x expected %x\n", CPUMGetHyperSS(pVCpu), SELMGetHyperDS(pVM));
    304         if (CPUMGetHyperES(pVCpu) == SELMGetHyperDS(pVM))
    305             RTPrintf("VMM: FAILURE - es=%x expected %x\n", CPUMGetHyperES(pVCpu), SELMGetHyperDS(pVM));
    306         if (CPUMGetHyperDS(pVCpu) == SELMGetHyperDS(pVM))
    307             RTPrintf("VMM: FAILURE - ds=%x expected %x\n", CPUMGetHyperDS(pVCpu), SELMGetHyperDS(pVM));
    308         if (CPUMGetHyperFS(pVCpu) == SELMGetHyperDS(pVM))
    309             RTPrintf("VMM: FAILURE - fs=%x expected %x\n", CPUMGetHyperFS(pVCpu), SELMGetHyperDS(pVM));
    310         if (CPUMGetHyperGS(pVCpu) == SELMGetHyperDS(pVM))
    311             RTPrintf("VMM: FAILURE - gs=%x expected %x\n", CPUMGetHyperGS(pVCpu), SELMGetHyperDS(pVM));
    312         if (CPUMGetHyperEDI(pVCpu) == 0x01234567)
    313             RTPrintf("VMM: FAILURE - edi=%x expected %x\n", CPUMGetHyperEDI(pVCpu), 0x01234567);
    314         if (CPUMGetHyperESI(pVCpu) == 0x42000042)
    315             RTPrintf("VMM: FAILURE - esi=%x expected %x\n", CPUMGetHyperESI(pVCpu), 0x42000042);
    316         if (CPUMGetHyperEBP(pVCpu) == 0xffeeddcc)
    317             RTPrintf("VMM: FAILURE - ebp=%x expected %x\n", CPUMGetHyperEBP(pVCpu), 0xffeeddcc);
    318         if (CPUMGetHyperEBX(pVCpu) == 0x89abcdef)
    319             RTPrintf("VMM: FAILURE - ebx=%x expected %x\n", CPUMGetHyperEBX(pVCpu), 0x89abcdef);
    320         if (CPUMGetHyperECX(pVCpu) == 0xffffaaaa)
    321             RTPrintf("VMM: FAILURE - ecx=%x expected %x\n", CPUMGetHyperECX(pVCpu), 0xffffaaaa);
    322         if (CPUMGetHyperEDX(pVCpu) == 0x77778888)
    323             RTPrintf("VMM: FAILURE - edx=%x expected %x\n", CPUMGetHyperEDX(pVCpu), 0x77778888);
    324         if (CPUMGetHyperEAX(pVCpu) == u32Eax)
    325             RTPrintf("VMM: FAILURE - eax=%x expected %x\n", CPUMGetHyperEAX(pVCpu), u32Eax);
    326     }
    327     if (fDump)
    328         VMMR3FatalDump(pVM, pVCpu, rc);
    329     return rc;
    330 }
    331 
    332 #endif /* VBOX_WITH_RAW_MODE */
    333 
    334 
    335 /* execute the switch. */
    336 VMMR3DECL(int) VMMDoTest(PVM pVM)
    337 {
    338     int rc = VINF_SUCCESS;
    339 
    340 #ifdef VBOX_WITH_RAW_MODE
    341     PVMCPU pVCpu = &pVM->aCpus[0];
    342     PUVM   pUVM  = pVM->pUVM;
    343 
    344 # ifdef NO_SUPCALLR0VMM
    345     RTPrintf("NO_SUPCALLR0VMM\n");
    346     return rc;
    347 # endif
    348 
    349     /*
    350      * Setup stack for calling VMMRCEntry().
    351      */
    352     RTRCPTR RCPtrEP;
    353     rc = PDMR3LdrGetSymbolRC(pVM, VMMRC_MAIN_MODULE_NAME, "VMMRCEntry", &RCPtrEP);
    354     if (RT_SUCCESS(rc))
    355     {
    356         RTPrintf("VMM: VMMRCEntry=%RRv\n", RCPtrEP);
    357 
    358         /*
    359          * Test various crashes which we must be able to recover from.
    360          */
    361         vmmR3DoTrapTest(pVM, 0x3, 0, VINF_EM_DBG_HYPER_ASSERTION,  0xf0f0f0f0, "vmmGCTestTrap3_FaultEIP", "int3");
    362         vmmR3DoTrapTest(pVM, 0x3, 1, VINF_EM_DBG_HYPER_ASSERTION,  0xf0f0f0f0, "vmmGCTestTrap3_FaultEIP", "int3 WP");
    363 
    364 # if 0//defined(DEBUG_bird) /* guess most people would like to skip these since they write to com1. */
    365         vmmR3DoTrapTest(pVM, 0x8, 0, VERR_TRPM_PANIC,       0x00000000, "vmmGCTestTrap8_FaultEIP", "#DF [#PG]");
    366         SELMR3Relocate(pVM); /* this resets the busy flag of the Trap 08 TSS */
    367         bool f;
    368         rc = CFGMR3QueryBool(CFGMR3GetRoot(pVM), "DoubleFault", &f);
    369 # if !defined(DEBUG_bird)
    370         if (RT_SUCCESS(rc) && f)
    371 # endif
    372         {
    373             /* see triple fault warnings in SELM and VMMRC.cpp. */
    374             vmmR3DoTrapTest(pVM, 0x8, 1, VERR_TRPM_PANIC,       0x00000000, "vmmGCTestTrap8_FaultEIP", "#DF [#PG] WP");
    375             SELMR3Relocate(pVM); /* this resets the busy flag of the Trap 08 TSS */
    376         }
    377 # endif
    378 
    379         vmmR3DoTrapTest(pVM, 0xd, 0, VERR_TRPM_DONT_PANIC,  0xf0f0f0f0, "vmmGCTestTrap0d_FaultEIP", "ltr #GP");
    380         /// @todo find a better \#GP case, on intel ltr will \#PF (busy update?) and not \#GP.
    381         //vmmR3DoTrapTest(pVM, 0xd, 1, VERR_TRPM_DONT_PANIC,  0xf0f0f0f0, "vmmGCTestTrap0d_FaultEIP", "ltr #GP WP");
    382 
    383         vmmR3DoTrapTest(pVM, 0xe, 0, VERR_TRPM_DONT_PANIC,  0x00000000, "vmmGCTestTrap0e_FaultEIP", "#PF (NULL)");
    384         vmmR3DoTrapTest(pVM, 0xe, 1, VERR_TRPM_DONT_PANIC,  0x00000000, "vmmGCTestTrap0e_FaultEIP", "#PF (NULL) WP");
    385         vmmR3DoTrapTest(pVM, 0xe, 2, VINF_SUCCESS,          0x00000000, NULL,                       "#PF w/Tmp Handler");
    386         /* This test is no longer relevant as fs and gs are loaded with NULL
    387            selectors and we will always return to HC if a #GP occurs while
    388            returning to guest code.
    389         vmmR3DoTrapTest(pVM, 0xe, 4, VINF_SUCCESS,          0x00000000, NULL,                       "#PF w/Tmp Handler and bad fs");
    390         */
    391 
    392         /*
    393          * Set a debug register and perform a context switch.
    394          */
    395         rc = vmmR3DoGCTest(pVM, VMMRC_DO_TESTCASE_NOP, 0);
    396         if (rc != VINF_SUCCESS)
    397         {
    398             RTPrintf("VMM: Nop test failed, rc=%Rrc not VINF_SUCCESS\n", rc);
    399             return RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_INFO_STATUS;
    400         }
    401 
    402         /* a harmless breakpoint */
    403         RTPrintf("VMM: testing hardware bp at 0x10000 (not hit)\n");
    404         DBGFADDRESS Addr;
    405         DBGFR3AddrFromFlat(pUVM, &Addr, 0x10000);
    406         RTUINT iBp0;
    407         rc = DBGFR3BpSetReg(pUVM, &Addr, 0,  ~(uint64_t)0, X86_DR7_RW_EO, 1, &iBp0);
    408         AssertReleaseRC(rc);
    409         rc = vmmR3DoGCTest(pVM, VMMRC_DO_TESTCASE_NOP, 0);
    410         if (rc != VINF_SUCCESS)
    411         {
    412             RTPrintf("VMM: DR0=0x10000 test failed with rc=%Rrc!\n", rc);
    413             return RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_INFO_STATUS;
    414         }
    415 
    416         /* a bad one at VMMRCEntry */
    417         RTPrintf("VMM: testing hardware bp at VMMRCEntry (hit)\n");
    418         DBGFR3AddrFromFlat(pUVM, &Addr, RCPtrEP);
    419         RTUINT iBp1;
    420         rc = DBGFR3BpSetReg(pUVM, &Addr, 0,  ~(uint64_t)0, X86_DR7_RW_EO, 1, &iBp1);
    421         AssertReleaseRC(rc);
    422         rc = vmmR3DoGCTest(pVM, VMMRC_DO_TESTCASE_NOP, 0);
    423         if (rc != VINF_EM_DBG_HYPER_BREAKPOINT)
    424         {
    425             RTPrintf("VMM: DR1=VMMRCEntry test failed with rc=%Rrc! expected VINF_EM_RAW_BREAKPOINT_HYPER\n", rc);
    426             return RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_INFO_STATUS;
    427         }
    428 
    429         /* resume the breakpoint */
    430         RTPrintf("VMM: resuming hyper after breakpoint\n");
    431         CPUMSetHyperEFlags(pVCpu, CPUMGetHyperEFlags(pVCpu) | X86_EFL_RF);
    432         rc = VMMR3ResumeHyper(pVM, pVCpu);
    433         if (rc != VINF_SUCCESS)
    434         {
    435             RTPrintf("VMM: failed to resume on hyper breakpoint, rc=%Rrc = KNOWN BUG\n", rc); /** @todo fix VMMR3ResumeHyper */
    436             return RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_INFO_STATUS;
    437         }
    438 
    439         /* engage the breakpoint again and try single stepping. */
    440         RTPrintf("VMM: testing hardware bp at VMMRCEntry + stepping\n");
    441         rc = vmmR3DoGCTest(pVM, VMMRC_DO_TESTCASE_NOP, 0);
    442         if (rc != VINF_EM_DBG_HYPER_BREAKPOINT)
    443         {
    444             RTPrintf("VMM: DR1=VMMRCEntry test failed with rc=%Rrc! expected VINF_EM_RAW_BREAKPOINT_HYPER\n", rc);
    445             return RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_INFO_STATUS;
    446         }
    447 
    448         RTGCUINTREG OldPc = CPUMGetHyperEIP(pVCpu);
    449         RTPrintf("%RGr=>", OldPc);
    450         unsigned i;
    451         for (i = 0; i < 8; i++)
    452         {
    453             CPUMSetHyperEFlags(pVCpu, CPUMGetHyperEFlags(pVCpu) | X86_EFL_TF | X86_EFL_RF);
    454             rc = VMMR3ResumeHyper(pVM, pVCpu);
    455             if (rc != VINF_EM_DBG_HYPER_STEPPED)
    456             {
    457                 RTPrintf("\nVMM: failed to step on hyper breakpoint, rc=%Rrc\n", rc);
    458                 return RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_INFO_STATUS;
    459             }
    460             RTGCUINTREG Pc = CPUMGetHyperEIP(pVCpu);
    461             RTPrintf("%RGr=>", Pc);
    462             if (Pc == OldPc)
    463             {
    464                 RTPrintf("\nVMM: step failed, PC: %RGr -> %RGr\n", OldPc, Pc);
    465                 return VERR_GENERAL_FAILURE;
    466             }
    467             OldPc = Pc;
    468         }
    469         RTPrintf("ok\n");
    470 
    471         /* done, clear it */
    472         if (    RT_FAILURE(DBGFR3BpClear(pUVM, iBp0))
    473             ||  RT_FAILURE(DBGFR3BpClear(pUVM, iBp1)))
    474         {
    475             RTPrintf("VMM: Failed to clear breakpoints!\n");
    476             return VERR_GENERAL_FAILURE;
    477         }
    478         rc = vmmR3DoGCTest(pVM, VMMRC_DO_TESTCASE_NOP, 0);
    479         if (rc != VINF_SUCCESS)
    480         {
    481             RTPrintf("VMM: NOP failed, rc=%Rrc\n", rc);
    482             return RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_INFO_STATUS;
    483         }
    484 
    485         /*
    486          * Interrupt masking.  Failure may indiate NMI watchdog activity.
    487          */
    488         RTPrintf("VMM: interrupt masking...\n"); RTStrmFlush(g_pStdOut); RTThreadSleep(250);
    489         for (i = 0; i < 10000; i++)
    490         {
    491             uint64_t StartTick = ASMReadTSC();
    492             rc = vmmR3DoGCTest(pVM, VMMRC_DO_TESTCASE_INTERRUPT_MASKING, 0);
    493             if (rc != VINF_SUCCESS)
    494             {
    495                 RTPrintf("VMM: Interrupt masking failed: rc=%Rrc\n", rc);
    496                 return RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_INFO_STATUS;
    497             }
    498             uint64_t Ticks = ASMReadTSC() - StartTick;
    499             if (Ticks < (SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) / 10000))
    500                 RTPrintf("Warning: Ticks=%RU64 (< %RU64)\n", Ticks, SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) / 10000);
    501         }
    502 
    503         /*
    504          * Interrupt forwarding.
    505          */
    506         CPUMSetHyperState(pVCpu, pVM->vmm.s.pfnCallTrampolineRC, pVCpu->vmm.s.pbEMTStackBottomRC, 0, 0);
    507         CPUMPushHyper(pVCpu, 0);
    508         CPUMPushHyper(pVCpu, VMMRC_DO_TESTCASE_HYPER_INTERRUPT);
    509         CPUMPushHyper(pVCpu, pVM->pVMRC);
    510         CPUMPushHyper(pVCpu, 3 * sizeof(RTRCPTR));    /* stack frame size */
    511         CPUMPushHyper(pVCpu, RCPtrEP);                /* what to call */
    512         Log(("trampoline=%x\n", pVM->vmm.s.pfnCallTrampolineRC));
    513 
    514         /*
    515          * Switch and do da thing.
    516          */
    517         RTPrintf("VMM: interrupt forwarding...\n"); RTStrmFlush(g_pStdOut); RTThreadSleep(250);
    518         i = 0;
    519         uint64_t    tsBegin = RTTimeNanoTS();
    520         uint64_t    TickStart = ASMReadTSC();
    521         Assert(CPUMGetHyperCR3(pVCpu) && CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu));
    522         do
    523         {
    524             rc = SUPR3CallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN, 0);
    525             if (RT_LIKELY(rc == VINF_SUCCESS))
    526                 rc = pVCpu->vmm.s.iLastGZRc;
    527             if (RT_FAILURE(rc))
    528             {
    529                 Log(("VMM: GC returned fatal %Rra in iteration %d\n", rc, i));
    530                 VMMR3FatalDump(pVM, pVCpu, rc);
    531                 return rc;
    532             }
    533             i++;
    534             if (!(i % 32))
    535                 Log(("VMM: iteration %d, esi=%08x edi=%08x ebx=%08x\n",
    536                        i, CPUMGetHyperESI(pVCpu), CPUMGetHyperEDI(pVCpu), CPUMGetHyperEBX(pVCpu)));
    537         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
    538         uint64_t    TickEnd = ASMReadTSC();
    539         uint64_t    tsEnd = RTTimeNanoTS();
    540 
    541         uint64_t    Elapsed = tsEnd - tsBegin;
    542         uint64_t    PerIteration = Elapsed / (uint64_t)i;
    543         uint64_t    cTicksElapsed = TickEnd - TickStart;
    544         uint64_t    cTicksPerIteration = cTicksElapsed / (uint64_t)i;
    545 
    546         RTPrintf("VMM: %8d interrupts in %11llu ns (%11llu ticks),  %10llu ns/iteration (%11llu ticks)\n",
    547                  i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration);
    548         Log(("VMM: %8d interrupts in %11llu ns (%11llu ticks),  %10llu ns/iteration (%11llu ticks)\n",
    549              i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration));
    550 
    551         /*
    552          * These forced actions are not necessary for the test and trigger breakpoints too.
    553          */
    554         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TRPM_SYNC_IDT);
    555         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
    556 
    557         /*
    558          * Profile switching.
    559          */
    560         RTPrintf("VMM: profiling switcher...\n");
    561         Log(("VMM: profiling switcher...\n"));
    562         uint64_t TickMin = UINT64_MAX;
    563         tsBegin = RTTimeNanoTS();
    564         TickStart = ASMReadTSC();
    565         Assert(CPUMGetHyperCR3(pVCpu) && CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu));
    566         for (i = 0; i < 1000000; i++)
    567         {
    568             CPUMSetHyperState(pVCpu, pVM->vmm.s.pfnCallTrampolineRC, pVCpu->vmm.s.pbEMTStackBottomRC, 0, 0);
    569             CPUMPushHyper(pVCpu, 0);
    570             CPUMPushHyper(pVCpu, VMMRC_DO_TESTCASE_NOP);
    571             CPUMPushHyper(pVCpu, pVM->pVMRC);
    572             CPUMPushHyper(pVCpu, 3 * sizeof(RTRCPTR));    /* stack frame size */
    573             CPUMPushHyper(pVCpu, RCPtrEP);                /* what to call */
    574 
    575             uint64_t TickThisStart = ASMReadTSC();
    576             rc = SUPR3CallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN, 0);
    577             if (RT_LIKELY(rc == VINF_SUCCESS))
    578                 rc = pVCpu->vmm.s.iLastGZRc;
    579             uint64_t TickThisElapsed = ASMReadTSC() - TickThisStart;
    580             if (RT_FAILURE(rc))
    581             {
    582                 Log(("VMM: GC returned fatal %Rra in iteration %d\n", rc, i));
    583                 VMMR3FatalDump(pVM, pVCpu, rc);
    584                 return rc;
    585             }
    586             if (TickThisElapsed < TickMin)
    587                 TickMin = TickThisElapsed;
    588         }
    589         TickEnd = ASMReadTSC();
    590         tsEnd = RTTimeNanoTS();
    591 
    592         Elapsed = tsEnd - tsBegin;
    593         PerIteration = Elapsed / (uint64_t)i;
    594         cTicksElapsed = TickEnd - TickStart;
    595         cTicksPerIteration = cTicksElapsed / (uint64_t)i;
    596 
    597         RTPrintf("VMM: %8d cycles     in %11llu ns (%11lld ticks),  %10llu ns/iteration (%11lld ticks)  Min %11lld ticks\n",
    598                  i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration, TickMin);
    599         Log(("VMM: %8d cycles     in %11llu ns (%11lld ticks),  %10llu ns/iteration (%11lld ticks)  Min %11lld ticks\n",
    600              i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration, TickMin));
    601 
    602         rc = VINF_SUCCESS;
    603 
    604 # if 0  /* drop this for now as it causes trouble on AMDs (Opteron 2384 and possibly others). */
    605         /*
    606          * A quick MSR report.
    607          */
    608         vmmR3DoMsrQuickReport(pVM, NULL, true);
    609 # endif
    610     }
    611     else
    612         AssertMsgFailed(("Failed to resolved VMMRC.rc::VMMRCEntry(), rc=%Rrc\n", rc));
    613 #else  /* !VBOX_WITH_RAW_MODE */
    614     RT_NOREF(pVM);
    615 #endif /* !VBOX_WITH_RAW_MODE */
    616     return rc;
    617 }
    618 
    61947#define SYNC_SEL(pHyperCtx, reg)                                                        \
    62048        if (pHyperCtx->reg.Sel)                                                         \
     
    63866VMMR3DECL(int) VMMDoHmTest(PVM pVM)
    63967{
     68#if 1
     69    RTPrintf("FIXME!\n");
     70    RT_NOREF(pVM);
     71    return 0;
     72#else
     73
    64074    uint32_t i;
    64175    int      rc;
     
    758192
    759193    return rc;
    760 }
    761 
    762 
    763 #ifdef VBOX_WITH_RAW_MODE
    764 
    765 /**
    766  * Used by VMMDoBruteForceMsrs to dump the CPUID info of the host CPU as a
    767  * prefix to the MSR report.
    768  */
    769 static DECLCALLBACK(void) vmmDoPrintfVToStream(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list va)
    770 {
    771     PRTSTREAM pOutStrm = ((PRTSTREAM *)pHlp)[-1];
    772     RTStrmPrintfV(pOutStrm, pszFormat, va);
    773 }
    774 
    775 /**
    776  * Used by VMMDoBruteForceMsrs to dump the CPUID info of the host CPU as a
    777  * prefix to the MSR report.
    778  */
    779 static DECLCALLBACK(void) vmmDoPrintfToStream(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
    780 {
    781     va_list va;
    782     va_start(va, pszFormat);
    783     vmmDoPrintfVToStream(pHlp, pszFormat, va);
    784     va_end(va);
    785 }
    786 
    787 #endif
    788 
    789 
    790 /**
    791  * Uses raw-mode to query all possible MSRs on the real hardware.
    792  *
    793  * This generates a msr-report.txt file (appending, no overwriting) as well as
    794  * writing the values and process to stdout.
    795  *
    796  * @returns VBox status code.
    797  * @param   pVM         The cross context VM structure.
    798  */
    799 VMMR3DECL(int) VMMDoBruteForceMsrs(PVM pVM)
    800 {
    801 #ifdef VBOX_WITH_RAW_MODE
    802     PRTSTREAM pOutStrm;
    803     int rc = RTStrmOpen("msr-report.txt", "a", &pOutStrm);
    804     if (RT_SUCCESS(rc))
    805     {
    806         /* Header */
    807         struct
    808         {
    809             PRTSTREAM   pOutStrm;
    810             DBGFINFOHLP Hlp;
    811         } MyHlp = { pOutStrm, { vmmDoPrintfToStream, vmmDoPrintfVToStream } };
    812         DBGFR3Info(pVM->pUVM, "cpuid", "verbose", &MyHlp.Hlp);
    813         RTStrmPrintf(pOutStrm, "\n");
    814 
    815         uint32_t cMsrsFound = 0;
    816         vmmR3ReportMsrRange(pVM, 0, _4G, pOutStrm, &cMsrsFound);
    817 
    818         RTStrmPrintf(pOutStrm, "Total %u (%#x) MSRs\n", cMsrsFound, cMsrsFound);
    819         RTPrintf("Total %u (%#x) MSRs\n", cMsrsFound, cMsrsFound);
    820 
    821         RTStrmClose(pOutStrm);
    822     }
    823     return rc;
    824 #else
    825     RT_NOREF(pVM);
    826     return VERR_NOT_SUPPORTED;
    827194#endif
    828195}
    829196
    830 
    831 /**
    832  * Uses raw-mode to query all known MSRS on the real hardware.
    833  *
    834  * This generates a known-msr-report.txt file (appending, no overwriting) as
    835  * well as writing the values and process to stdout.
    836  *
    837  * @returns VBox status code.
    838  * @param   pVM         The cross context VM structure.
    839  */
    840 VMMR3DECL(int) VMMDoKnownMsrs(PVM pVM)
    841 {
    842 #ifdef VBOX_WITH_RAW_MODE
    843     PRTSTREAM pOutStrm;
    844     int rc = RTStrmOpen("known-msr-report.txt", "a", &pOutStrm);
    845     if (RT_SUCCESS(rc))
    846     {
    847         vmmR3DoMsrQuickReport(pVM, pOutStrm, false);
    848         RTStrmClose(pOutStrm);
    849     }
    850     return rc;
    851 #else
    852     RT_NOREF(pVM);
    853     return VERR_NOT_SUPPORTED;
    854 #endif
    855 }
    856 
    857 
    858 /**
    859  * MSR experimentation.
    860  *
    861  * @returns VBox status code.
    862  * @param   pVM         The cross context VM structure.
    863  */
    864 VMMR3DECL(int) VMMDoMsrExperiments(PVM pVM)
    865 {
    866 #ifdef VBOX_WITH_RAW_MODE
    867     /*
    868      * Preps.
    869      */
    870     RTRCPTR RCPtrEP;
    871     int rc = PDMR3LdrGetSymbolRC(pVM, VMMRC_MAIN_MODULE_NAME, "VMMRCTestTestWriteMsr", &RCPtrEP);
    872     AssertMsgRCReturn(rc, ("Failed to resolved VMMRC.rc::VMMRCEntry(), rc=%Rrc\n", rc), rc);
    873 
    874     uint64_t *pauValues;
    875     rc = MMHyperAlloc(pVM, 2 * sizeof(uint64_t), 0, MM_TAG_VMM, (void **)&pauValues);
    876     AssertMsgRCReturn(rc, ("Error allocating %#x bytes off the hyper heap: %Rrc\n", 2 * sizeof(uint64_t), rc), rc);
    877     RTRCPTR RCPtrValues = MMHyperR3ToRC(pVM, pauValues);
    878 
    879     /*
    880      * Do the experiments.
    881      */
    882     uint32_t uMsr   = 0x00000277;
    883     uint64_t uValue = UINT64_C(0x0007010600070106);
    884 # if 0
    885     uValue &= ~(RT_BIT_64(17) | RT_BIT_64(16) | RT_BIT_64(15) | RT_BIT_64(14) | RT_BIT_64(13));
    886     uValue |= RT_BIT_64(13);
    887     rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
    888                      RCPtrValues, RCPtrValues + sizeof(uint64_t));
    889     RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\n",
    890              uMsr, pauValues[0], uValue, pauValues[1], rc);
    891 # elif 1
    892     const uint64_t uOrgValue = uValue;
    893     uint32_t       cChanges = 0;
    894     for (int iBit = 63; iBit >= 58; iBit--)
    895     {
    896         uValue = uOrgValue & ~RT_BIT_64(iBit);
    897         rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
    898                          RCPtrValues, RCPtrValues + sizeof(uint64_t));
    899         RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\nclear bit=%u -> %s\n",
    900                  uMsr, pauValues[0], uValue, pauValues[1], rc, iBit,
    901                  (pauValues[0] ^  pauValues[1]) & RT_BIT_64(iBit) ?  "changed" : "unchanged");
    902         cChanges += RT_BOOL(pauValues[0] ^ pauValues[1]);
    903 
    904         uValue = uOrgValue | RT_BIT_64(iBit);
    905         rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
    906                          RCPtrValues, RCPtrValues + sizeof(uint64_t));
    907         RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\nset   bit=%u -> %s\n",
    908                  uMsr, pauValues[0], uValue, pauValues[1], rc, iBit,
    909                  (pauValues[0] ^  pauValues[1]) & RT_BIT_64(iBit) ?  "changed" : "unchanged");
    910         cChanges += RT_BOOL(pauValues[0] ^ pauValues[1]);
    911     }
    912     RTPrintf("%u change(s)\n", cChanges);
    913 # else
    914     uint64_t fWriteable = 0;
    915     for (uint32_t i = 0; i <= 63; i++)
    916     {
    917         uValue = RT_BIT_64(i);
    918 # if 0
    919         if (uValue & (0x7))
    920             continue;
    921 # endif
    922         rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
    923                          RCPtrValues, RCPtrValues + sizeof(uint64_t));
    924         RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\n",
    925                  uMsr, pauValues[0], uValue, pauValues[1], rc);
    926         if (RT_SUCCESS(rc))
    927             fWriteable |= RT_BIT_64(i);
    928     }
    929 
    930     uValue = 0;
    931     rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
    932                      RCPtrValues, RCPtrValues + sizeof(uint64_t));
    933     RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\n",
    934              uMsr, pauValues[0], uValue, pauValues[1], rc);
    935 
    936     uValue = UINT64_MAX;
    937     rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
    938                      RCPtrValues, RCPtrValues + sizeof(uint64_t));
    939     RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc\n",
    940              uMsr, pauValues[0], uValue, pauValues[1], rc);
    941 
    942     uValue = fWriteable;
    943     rc = VMMR3CallRC(pVM, RCPtrEP, 6, pVM->pVMRC, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue),
    944                      RCPtrValues, RCPtrValues + sizeof(uint64_t));
    945     RTPrintf("uMsr=%#010x before=%#018llx written=%#018llx after=%#018llx rc=%Rrc [fWriteable]\n",
    946              uMsr, pauValues[0], uValue, pauValues[1], rc);
    947 
    948 # endif
    949 
    950     /*
    951      * Cleanups.
    952      */
    953     MMHyperFree(pVM, pauValues);
    954     return rc;
    955 #else
    956     RT_NOREF(pVM);
    957     return VERR_NOT_SUPPORTED;
    958 #endif
    959 }
    960 
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette