Changeset 13698 in vbox
- Timestamp:
- Oct 30, 2008 10:54:28 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 38664
- Location:
- trunk
- Files:
-
- 9 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm.h
r13697 r13698 110 110 } VMMCALLHOST; 111 111 112 RTGCPTR VMMGetStackGC(PVM pVM); 113 RTHCPTR VMMGetHCStack(PVM pVM); 112 RTRCPTR VMMGetStackRC(PVM pVM); 114 113 VMCPUID VMMGetCpuId(PVM pVM); 115 114 VMMDECL(uint32_t) VMMGetSvnRev(void); -
trunk/src/VBox/VMM/Makefile.kmk
r13565 r13698 92 92 VMReq.cpp \ 93 93 VMM.cpp \ 94 VMMGuruMeditation.cpp \ 94 95 VMMTests.cpp \ 95 96 HWACCM.cpp \ -
trunk/src/VBox/VMM/SELM.cpp
r13577 r13698 418 418 pVM->selm.s.Tss.cr3 = PGMGetHyperCR3(pVM); 419 419 pVM->selm.s.Tss.ss0 = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; 420 pVM->selm.s.Tss.esp0 = VMMGetStack GC(pVM);420 pVM->selm.s.Tss.esp0 = VMMGetStackRC(pVM); 421 421 pVM->selm.s.Tss.cs = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]; 422 422 pVM->selm.s.Tss.ds = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; … … 428 428 pVM->selm.s.TssTrap08.ss0 = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; 429 429 pVM->selm.s.TssTrap08.ss = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]; 430 pVM->selm.s.TssTrap08.esp0 = VMMGetStack GC(pVM) - PAGE_SIZE / 2; /* upper half can be analysed this way. */430 pVM->selm.s.TssTrap08.esp0 = VMMGetStackRC(pVM) - PAGE_SIZE / 2; /* upper half can be analysed this way. */ 431 431 pVM->selm.s.TssTrap08.esp = pVM->selm.s.TssTrap08.esp0; 432 432 pVM->selm.s.TssTrap08.ebp = pVM->selm.s.TssTrap08.esp0; -
trunk/src/VBox/VMM/VMM.cpp
r13697 r13698 214 214 { 215 215 /* 216 * Allocate & init VMM GC stack.216 * Allocate & init VMM RC stack. 217 217 * The stack pages are also used by the VMM R0 when VMMR0CallHost is invoked. 218 218 * (The page protection is modifed during R3 init completion.) 219 219 */ 220 /** @todo SMP: Per vCPU. */ 220 221 #ifdef VBOX_STRICT_VMM_STACK 221 222 rc = MMHyperAlloc(pVM, VMM_STACK_SIZE + PAGE_SIZE + PAGE_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbHCStack); 222 223 #else 223 rc = MMHyperAlloc(pVM, VMM_STACK_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pb HCStack);224 rc = MMHyperAlloc(pVM, VMM_STACK_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbEMTStackR3); 224 225 #endif 225 226 if (VBOX_SUCCESS(rc)) 226 227 { 227 228 /* Set HC and GC stack pointers to top of stack. */ 228 pVM->vmm.s.CallHostR0JmpBuf.pvSavedStack = (RTR0PTR)pVM->vmm.s.pbHCStack;229 pVM->vmm.s.pb GCStack = MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack);230 pVM->vmm.s.pb GCStackBottom = pVM->vmm.s.pbGCStack+ VMM_STACK_SIZE;231 AssertRelease(pVM->vmm.s.pb GCStack);232 233 /* Set hypervisor e ip. */234 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStack);229 pVM->vmm.s.CallHostR0JmpBuf.pvSavedStack = MMHyperR3ToR0(pVM, pVM->vmm.s.pbEMTStackR3); 230 pVM->vmm.s.pbEMTStackRC = MMHyperR3ToRC(pVM, pVM->vmm.s.pbEMTStackR3); 231 pVM->vmm.s.pbEMTStackBottomRC = pVM->vmm.s.pbEMTStackRC + VMM_STACK_SIZE; 232 AssertRelease(pVM->vmm.s.pbEMTStackRC); 233 234 /* Set hypervisor esp. */ 235 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); 235 236 236 237 /* … … 528 529 * Set page attributes to r/w for stack pages. 529 530 */ 530 int rc = PGMMapSetPage(pVM, pVM->vmm.s.pb GCStack, VMM_STACK_SIZE, X86_PTE_P | X86_PTE_A | X86_PTE_D | X86_PTE_RW);531 int rc = PGMMapSetPage(pVM, pVM->vmm.s.pbEMTStackRC, VMM_STACK_SIZE, X86_PTE_P | X86_PTE_A | X86_PTE_D | X86_PTE_RW); 531 532 AssertRC(rc); 532 533 if (VBOX_SUCCESS(rc)) … … 628 629 { 629 630 CPUMHyperSetCtxCore(pVM, NULL); 630 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStackBottom); /* Clear the stack. */631 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */ 631 632 uint64_t u64TS = RTTimeProgramStartNanoTS(); 632 633 CPUMPushHyper(pVM, (uint32_t)(u64TS >> 32)); /* Param 3: The program startup TS - Hi. */ … … 748 749 */ 749 750 CPUMSetHyperESP(pVM, CPUMGetHyperESP(pVM) + offDelta); 750 pVM->vmm.s.pb GCStack = MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack);751 pVM->vmm.s.pb GCStackBottom = pVM->vmm.s.pbGCStack+ VMM_STACK_SIZE;751 pVM->vmm.s.pbEMTStackRC = MMHyperR3ToRC(pVM, pVM->vmm.s.pbEMTStackR3); 752 pVM->vmm.s.pbEMTStackBottomRC = pVM->vmm.s.pbEMTStackRC + VMM_STACK_SIZE; 752 753 753 754 /* … … 1546 1547 /* 1547 1548 * The hypervisor stack. 1548 */ 1549 SSMR3PutRCPtr(pSSM, pVM->vmm.s.pbGCStackBottom); 1550 RTRCPTR GCPtrESP = CPUMGetHyperESP(pVM); 1551 AssertMsg(pVM->vmm.s.pbGCStackBottom - GCPtrESP <= VMM_STACK_SIZE, ("Bottom %VGv ESP=%VGv\n", pVM->vmm.s.pbGCStackBottom, GCPtrESP)); 1552 SSMR3PutRCPtr(pSSM, GCPtrESP); 1553 SSMR3PutMem(pSSM, pVM->vmm.s.pbHCStack, VMM_STACK_SIZE); 1549 * Note! See not in vmmR3Load. 1550 */ 1551 SSMR3PutRCPtr(pSSM, pVM->vmm.s.pbEMTStackBottomRC); 1552 RTRCPTR RCPtrESP = CPUMGetHyperESP(pVM); 1553 AssertMsg(pVM->vmm.s.pbEMTStackBottomRC - RCPtrESP <= VMM_STACK_SIZE, ("Bottom %RRv ESP=%RRv\n", pVM->vmm.s.pbEMTStackBottomRC, RCPtrESP)); 1554 SSMR3PutRCPtr(pSSM, RCPtrESP); 1555 SSMR3PutMem(pSSM, pVM->vmm.s.pbEMTStackR3, VMM_STACK_SIZE); 1554 1556 return SSMR3PutU32(pSSM, ~0); /* terminator */ 1555 1557 } … … 1579 1581 /* 1580 1582 * Check that the stack is in the same place, or that it's fearly empty. 1581 */ 1582 RTRCPTR GCPtrStackBottom; 1583 SSMR3GetRCPtr(pSSM, &GCPtrStackBottom); 1584 RTRCPTR GCPtrESP; 1585 int rc = SSMR3GetRCPtr(pSSM, &GCPtrESP); 1583 * 1584 * Note! This can be skipped next time we update saved state as we will 1585 * never be in a R0/RC -> ring-3 call when saving the state. The 1586 * stack and the two associated pointers are not required. 1587 */ 1588 RTRCPTR RCPtrStackBottom; 1589 SSMR3GetRCPtr(pSSM, &RCPtrStackBottom); 1590 RTRCPTR RCPtrESP; 1591 int rc = SSMR3GetRCPtr(pSSM, &RCPtrESP); 1586 1592 if (VBOX_FAILURE(rc)) 1587 1593 return rc; 1588 1594 1589 /* Previously we checked if the location of the stack was identical or that the stack was empty. 1590 * This is not required as we can never initiate a save when GC context code performs a ring 3 call. 1591 */ 1592 /* restore the stack. (not necessary; just consistency checking) */ 1593 SSMR3GetMem(pSSM, pVM->vmm.s.pbHCStack, VMM_STACK_SIZE); 1595 /* restore the stack. */ 1596 SSMR3GetMem(pSSM, pVM->vmm.s.pbEMTStackR3, VMM_STACK_SIZE); 1594 1597 1595 1598 /* terminator */ … … 1863 1866 ? pVM->vmm.s.pfnCPUMGCResumeGuestV86 1864 1867 : pVM->vmm.s.pfnCPUMGCResumeGuest); 1865 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStackBottom);1868 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); 1866 1869 1867 1870 /* … … 1987 1990 */ 1988 1991 CPUMHyperSetCtxCore(pVM, NULL); 1989 memset(pVM->vmm.s.pb HCStack, 0xaa, VMM_STACK_SIZE); /* Clear the stack. */1990 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStackBottom- cArgs * sizeof(RTGCUINTPTR32));1991 PRTGCUINTPTR32 pFrame = (PRTGCUINTPTR32)(pVM->vmm.s.pb HCStack+ VMM_STACK_SIZE) - cArgs;1992 memset(pVM->vmm.s.pbEMTStackR3, 0xaa, VMM_STACK_SIZE); /* Clear the stack. */ 1993 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC - cArgs * sizeof(RTGCUINTPTR32)); 1994 PRTGCUINTPTR32 pFrame = (PRTGCUINTPTR32)(pVM->vmm.s.pbEMTStackR3 + VMM_STACK_SIZE) - cArgs; 1992 1995 int i = cArgs; 1993 1996 while (i-- > 0) … … 2228 2231 return VINF_SUCCESS; 2229 2232 } 2230 2231 2232 2233 /**2234 * Structure to pass to DBGFR3Info() and for doing all other2235 * output during fatal dump.2236 */2237 typedef struct VMMR3FATALDUMPINFOHLP2238 {2239 /** The helper core. */2240 DBGFINFOHLP Core;2241 /** The release logger instance. */2242 PRTLOGGER pRelLogger;2243 /** The saved release logger flags. */2244 RTUINT fRelLoggerFlags;2245 /** The logger instance. */2246 PRTLOGGER pLogger;2247 /** The saved logger flags. */2248 RTUINT fLoggerFlags;2249 /** The saved logger destination flags. */2250 RTUINT fLoggerDestFlags;2251 /** Whether to output to stderr or not. */2252 bool fStdErr;2253 } VMMR3FATALDUMPINFOHLP, *PVMMR3FATALDUMPINFOHLP;2254 typedef const VMMR3FATALDUMPINFOHLP *PCVMMR3FATALDUMPINFOHLP;2255 2256 2257 /**2258 * Print formatted string.2259 *2260 * @param pHlp Pointer to this structure.2261 * @param pszFormat The format string.2262 * @param ... Arguments.2263 */2264 static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)2265 {2266 va_list args;2267 va_start(args, pszFormat);2268 pHlp->pfnPrintfV(pHlp, pszFormat, args);2269 va_end(args);2270 }2271 2272 2273 /**2274 * Print formatted string.2275 *2276 * @param pHlp Pointer to this structure.2277 * @param pszFormat The format string.2278 * @param args Argument list.2279 */2280 static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)2281 {2282 PCVMMR3FATALDUMPINFOHLP pMyHlp = (PCVMMR3FATALDUMPINFOHLP)pHlp;2283 2284 if (pMyHlp->pRelLogger)2285 {2286 va_list args2;2287 va_copy(args2, args);2288 RTLogLoggerV(pMyHlp->pRelLogger, pszFormat, args2);2289 va_end(args2);2290 }2291 if (pMyHlp->pLogger)2292 {2293 va_list args2;2294 va_copy(args2, args);2295 RTLogLoggerV(pMyHlp->pLogger, pszFormat, args);2296 va_end(args2);2297 }2298 if (pMyHlp->fStdErr)2299 {2300 va_list args2;2301 va_copy(args2, args);2302 RTStrmPrintfV(g_pStdErr, pszFormat, args);2303 va_end(args2);2304 }2305 }2306 2307 2308 /**2309 * Initializes the fatal dump output helper.2310 *2311 * @param pHlp The structure to initialize.2312 */2313 static void vmmR3FatalDumpInfoHlpInit(PVMMR3FATALDUMPINFOHLP pHlp)2314 {2315 memset(pHlp, 0, sizeof(*pHlp));2316 2317 pHlp->Core.pfnPrintf = vmmR3FatalDumpInfoHlp_pfnPrintf;2318 pHlp->Core.pfnPrintfV = vmmR3FatalDumpInfoHlp_pfnPrintfV;2319 2320 /*2321 * The loggers.2322 */2323 pHlp->pRelLogger = RTLogRelDefaultInstance();2324 #ifndef LOG_ENABLED2325 if (!pHlp->pRelLogger)2326 #endif2327 pHlp->pLogger = RTLogDefaultInstance();2328 2329 if (pHlp->pRelLogger)2330 {2331 pHlp->fRelLoggerFlags = pHlp->pRelLogger->fFlags;2332 pHlp->pRelLogger->fFlags &= ~(RTLOGFLAGS_BUFFERED | RTLOGFLAGS_DISABLED);2333 }2334 2335 if (pHlp->pLogger)2336 {2337 pHlp->fLoggerFlags = pHlp->pLogger->fFlags;2338 pHlp->fLoggerDestFlags = pHlp->pLogger->fDestFlags;2339 pHlp->pLogger->fFlags &= ~(RTLOGFLAGS_BUFFERED | RTLOGFLAGS_DISABLED);2340 #ifndef DEBUG_sandervl2341 pHlp->pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;2342 #endif2343 }2344 2345 /*2346 * Check if we need write to stderr.2347 */2348 #ifdef DEBUG_sandervl2349 pHlp->fStdErr = false; /* takes too long to display here */2350 #else2351 pHlp->fStdErr = (!pHlp->pRelLogger || !(pHlp->pRelLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))2352 && (!pHlp->pLogger || !(pHlp->pLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)));2353 #endif2354 }2355 2356 2357 /**2358 * Deletes the fatal dump output helper.2359 *2360 * @param pHlp The structure to delete.2361 */2362 static void vmmR3FatalDumpInfoHlpDelete(PVMMR3FATALDUMPINFOHLP pHlp)2363 {2364 if (pHlp->pRelLogger)2365 {2366 RTLogFlush(pHlp->pRelLogger);2367 pHlp->pRelLogger->fFlags = pHlp->fRelLoggerFlags;2368 }2369 2370 if (pHlp->pLogger)2371 {2372 RTLogFlush(pHlp->pLogger);2373 pHlp->pLogger->fFlags = pHlp->fLoggerFlags;2374 pHlp->pLogger->fDestFlags = pHlp->fLoggerDestFlags;2375 }2376 }2377 2378 2379 /**2380 * Dumps the VM state on a fatal error.2381 *2382 * @param pVM VM Handle.2383 * @param rcErr VBox status code.2384 */2385 VMMR3DECL(void) VMMR3FatalDump(PVM pVM, int rcErr)2386 {2387 /*2388 * Create our output helper and sync it with the log settings.2389 * This helper will be used for all the output.2390 */2391 VMMR3FATALDUMPINFOHLP Hlp;2392 PCDBGFINFOHLP pHlp = &Hlp.Core;2393 vmmR3FatalDumpInfoHlpInit(&Hlp);2394 2395 /*2396 * Header.2397 */2398 pHlp->pfnPrintf(pHlp,2399 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"2400 "!!\n"2401 "!! Guru Meditation %d (%Vrc)\n"2402 "!!\n",2403 rcErr, rcErr);2404 2405 /*2406 * Continue according to context.2407 */2408 bool fDoneHyper = false;2409 switch (rcErr)2410 {2411 /*2412 * Hypervisor errors.2413 */2414 case VINF_EM_DBG_HYPER_ASSERTION:2415 {2416 const char *pszMsg1 = HWACCMR3IsActive(pVM) ? pVM->vmm.s.szRing0AssertMsg1 : VMMR3GetGCAssertMsg1(pVM);2417 while (pszMsg1 && *pszMsg1 == '\n')2418 pszMsg1++;2419 const char *pszMsg2 = HWACCMR3IsActive(pVM) ? pVM->vmm.s.szRing0AssertMsg2 : VMMR3GetGCAssertMsg2(pVM);2420 while (pszMsg2 && *pszMsg2 == '\n')2421 pszMsg2++;2422 pHlp->pfnPrintf(pHlp,2423 "%s"2424 "%s",2425 pszMsg1,2426 pszMsg2);2427 if ( !pszMsg22428 || !*pszMsg22429 || strchr(pszMsg2, '\0')[-1] != '\n')2430 pHlp->pfnPrintf(pHlp, "\n");2431 pHlp->pfnPrintf(pHlp, "!!\n");2432 /* fall thru */2433 }2434 case VERR_TRPM_DONT_PANIC:2435 case VERR_TRPM_PANIC:2436 case VINF_EM_RAW_STALE_SELECTOR:2437 case VINF_EM_RAW_IRET_TRAP:2438 case VINF_EM_DBG_HYPER_BREAKPOINT:2439 case VINF_EM_DBG_HYPER_STEPPED:2440 {2441 /*2442 * Active trap? This is only of partial interest when in hardware2443 * assisted virtualization mode, thus the different messages.2444 */2445 uint32_t uEIP = CPUMGetHyperEIP(pVM);2446 TRPMEVENT enmType;2447 uint8_t u8TrapNo = 0xce;2448 RTGCUINT uErrorCode = 0xdeadface;2449 RTGCUINTPTR uCR2 = 0xdeadface;2450 int rc2 = TRPMQueryTrapAll(pVM, &u8TrapNo, &enmType, &uErrorCode, &uCR2);2451 if (!HWACCMR3IsActive(pVM))2452 {2453 if (RT_SUCCESS(rc2))2454 pHlp->pfnPrintf(pHlp,2455 "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d\n",2456 u8TrapNo, uErrorCode, uCR2, uEIP, enmType);2457 else2458 pHlp->pfnPrintf(pHlp,2459 "!! EIP=%RX32 NOTRAP\n",2460 uEIP);2461 }2462 else if (RT_SUCCESS(rc2))2463 pHlp->pfnPrintf(pHlp,2464 "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d (Guest!)\n",2465 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVM), enmType);2466 2467 /*2468 * The hypervisor dump is not relevant when we're in VT-x/AMD-V mode.2469 */2470 if (HWACCMR3IsActive(pVM))2471 pHlp->pfnPrintf(pHlp, "\n");2472 else2473 {2474 /*2475 * Try figure out where eip is.2476 */2477 /* core code? */2478 if (uEIP - (RTGCUINTPTR)pVM->vmm.s.pvGCCoreCode < pVM->vmm.s.cbCoreCode)2479 pHlp->pfnPrintf(pHlp,2480 "!! EIP is in CoreCode, offset %#x\n",2481 uEIP - (RTGCUINTPTR)pVM->vmm.s.pvGCCoreCode);2482 else2483 { /* ask PDM */ /** @todo ask DBGFR3Sym later? */2484 char szModName[64];2485 RTRCPTR RCPtrMod;2486 char szNearSym1[260];2487 RTRCPTR RCPtrNearSym1;2488 char szNearSym2[260];2489 RTRCPTR RCPtrNearSym2;2490 int rc = PDMR3LdrQueryRCModFromPC(pVM, uEIP,2491 &szModName[0], sizeof(szModName), &RCPtrMod,2492 &szNearSym1[0], sizeof(szNearSym1), &RCPtrNearSym1,2493 &szNearSym2[0], sizeof(szNearSym2), &RCPtrNearSym2);2494 if (VBOX_SUCCESS(rc))2495 pHlp->pfnPrintf(pHlp,2496 "!! EIP in %s (%RRv) at rva %x near symbols:\n"2497 "!! %RRv rva %RRv off %08x %s\n"2498 "!! %RRv rva %RRv off -%08x %s\n",2499 szModName, RCPtrMod, (unsigned)(uEIP - RCPtrMod),2500 RCPtrNearSym1, RCPtrNearSym1 - RCPtrMod, (unsigned)(uEIP - RCPtrNearSym1), szNearSym1,2501 RCPtrNearSym2, RCPtrNearSym2 - RCPtrMod, (unsigned)(RCPtrNearSym2 - uEIP), szNearSym2);2502 else2503 pHlp->pfnPrintf(pHlp,2504 "!! EIP is not in any code known to VMM!\n");2505 }2506 2507 /* Disassemble the instruction. */2508 char szInstr[256];2509 rc2 = DBGFR3DisasInstrEx(pVM, 0, 0, DBGF_DISAS_FLAGS_CURRENT_HYPER, &szInstr[0], sizeof(szInstr), NULL);2510 if (VBOX_SUCCESS(rc2))2511 pHlp->pfnPrintf(pHlp,2512 "!! %s\n", szInstr);2513 2514 /* Dump the hypervisor cpu state. */2515 pHlp->pfnPrintf(pHlp,2516 "!!\n"2517 "!!\n"2518 "!!\n");2519 rc2 = DBGFR3Info(pVM, "cpumhyper", "verbose", pHlp);2520 fDoneHyper = true;2521 2522 /* Callstack. */2523 DBGFSTACKFRAME Frame = {0};2524 rc2 = DBGFR3StackWalkBeginHyper(pVM, &Frame);2525 if (VBOX_SUCCESS(rc2))2526 {2527 pHlp->pfnPrintf(pHlp,2528 "!!\n"2529 "!! Call Stack:\n"2530 "!!\n"2531 "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP Symbol [line]\n");2532 do2533 {2534 pHlp->pfnPrintf(pHlp,2535 "%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",2536 (uint32_t)Frame.AddrFrame.off,2537 (uint32_t)Frame.AddrReturnFrame.off,2538 (uint32_t)Frame.AddrReturnPC.Sel,2539 (uint32_t)Frame.AddrReturnPC.off,2540 Frame.Args.au32[0],2541 Frame.Args.au32[1],2542 Frame.Args.au32[2],2543 Frame.Args.au32[3]);2544 pHlp->pfnPrintf(pHlp, " %RTsel:%08RGv", Frame.AddrPC.Sel, Frame.AddrPC.off);2545 if (Frame.pSymPC)2546 {2547 RTGCINTPTR offDisp = Frame.AddrPC.FlatPtr - Frame.pSymPC->Value;2548 if (offDisp > 0)2549 pHlp->pfnPrintf(pHlp, " %s+%llx", Frame.pSymPC->szName, (int64_t)offDisp);2550 else if (offDisp < 0)2551 pHlp->pfnPrintf(pHlp, " %s-%llx", Frame.pSymPC->szName, -(int64_t)offDisp);2552 else2553 pHlp->pfnPrintf(pHlp, " %s", Frame.pSymPC->szName);2554 }2555 if (Frame.pLinePC)2556 pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", Frame.pLinePC->szFilename, Frame.pLinePC->uLineNo);2557 pHlp->pfnPrintf(pHlp, "\n");2558 2559 /* next */2560 rc2 = DBGFR3StackWalkNext(pVM, &Frame);2561 } while (VBOX_SUCCESS(rc2));2562 DBGFR3StackWalkEnd(pVM, &Frame);2563 }2564 2565 /* raw stack */2566 pHlp->pfnPrintf(pHlp,2567 "!!\n"2568 "!! Raw stack (mind the direction).\n"2569 "!!\n"2570 "%.*Vhxd\n",2571 VMM_STACK_SIZE, (char *)pVM->vmm.s.pbHCStack);2572 } /* !HWACCMR3IsActive */2573 break;2574 }2575 2576 default:2577 {2578 break;2579 }2580 2581 } /* switch (rcErr) */2582 2583 2584 /*2585 * Generic info dumper loop.2586 */2587 static struct2588 {2589 const char *pszInfo;2590 const char *pszArgs;2591 } const aInfo[] =2592 {2593 { "mappings", NULL },2594 { "hma", NULL },2595 { "cpumguest", "verbose" },2596 { "cpumguestinstr", "verbose" },2597 { "cpumhyper", "verbose" },2598 { "cpumhost", "verbose" },2599 { "mode", "all" },2600 { "cpuid", "verbose" },2601 { "gdt", NULL },2602 { "ldt", NULL },2603 //{ "tss", NULL },2604 { "ioport", NULL },2605 { "mmio", NULL },2606 { "phys", NULL },2607 //{ "pgmpd", NULL }, - doesn't always work at init time...2608 { "timers", NULL },2609 { "activetimers", NULL },2610 { "handlers", "phys virt hyper stats" },2611 { "cfgm", NULL },2612 };2613 for (unsigned i = 0; i < RT_ELEMENTS(aInfo); i++)2614 {2615 if (fDoneHyper && !strcmp(aInfo[i].pszInfo, "cpumhyper"))2616 continue;2617 pHlp->pfnPrintf(pHlp,2618 "!!\n"2619 "!! {%s, %s}\n"2620 "!!\n",2621 aInfo[i].pszInfo, aInfo[i].pszArgs);2622 DBGFR3Info(pVM, aInfo[i].pszInfo, aInfo[i].pszArgs, pHlp);2623 }2624 2625 /* done */2626 pHlp->pfnPrintf(pHlp,2627 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");2628 2629 2630 /*2631 * Delete the output instance (flushing and restoring of flags).2632 */2633 vmmR3FatalDumpInfoHlpDelete(&Hlp);2634 }2635 2636 2233 2637 2234 -
trunk/src/VBox/VMM/VMMAll/VMMAll.cpp
r12667 r13698 32 32 33 33 #ifndef IN_RING0 34 35 34 /** 36 * Gets the bottom of the hypervisor stack - GC Ptr. 37 * I.e. the returned address is not actually writable. 35 * Gets the bottom of the hypervisor stack - RC Ptr. 36 * 37 * (The returned address is not actually writable, only after it's decremented 38 * by a push/ret/whatever does it become writable.) 38 39 * 39 40 * @returns bottom of the stack. 40 41 * @param pVM The VM handle. 41 42 */ 42 RT GCPTR VMMGetStackGC(PVM pVM)43 RTRCPTR VMMGetStackRC(PVM pVM) 43 44 { 44 return (RT GCPTR)pVM->vmm.s.pbGCStackBottom;45 return (RTRCPTR)pVM->vmm.s.pbEMTStackBottomRC; 45 46 } 46 47 48 /**49 * Gets the bottom of the hypervisor stack - HC Ptr.50 * I.e. the returned address is not actually writable.51 *52 * @returns bottom of the stack.53 * @param pVM The VM handle.54 */55 RTHCPTR VMMGetHCStack(PVM pVM)56 {57 return pVM->vmm.s.pbHCStack + VMM_STACK_SIZE;58 }59 60 47 #endif /* !IN_RING0 */ 61 48 -
trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp
r13635 r13698 1102 1102 * a guru meditation (the alternative is a triple fault). 1103 1103 */ 1104 RT GCUINTPTR cbStackUsed = (RTGCUINTPTR)VMMGetStackGC(pVM) - pRegFrame->esp;1104 RTRCUINTPTR cbStackUsed = (RTRCUINTPTR)VMMGetStackRC(pVM) - pRegFrame->esp; 1105 1105 if (cbStackUsed > VMM_STACK_SIZE - _1K) 1106 1106 { -
trunk/src/VBox/VMM/VMMGuruMeditation.cpp
r13697 r13698 1 1 /* $Id$ */ 2 2 /** @file 3 * VMM - The Virtual Machine Monitor Core.3 * VMM - The Virtual Machine Monitor, Guru Meditation Code. 4 4 */ 5 5 … … 20 20 */ 21 21 22 //#define NO_SUPCALLR0VMM23 24 /** @page pg_vmm VMM - The Virtual Machine Monitor25 *26 * The VMM component is two things at the moment, it's a component doing a few27 * management and routing tasks, and it's the whole virtual machine monitor28 * thing. For hysterical reasons, it is not doing all the management that one29 * would expect, this is instead done by @ref pg_vm. We'll address this30 * misdesign eventually.31 *32 * @see grp_vmm, grp_vm33 *34 *35 * @section sec_vmmstate VMM State36 *37 * @image html VM_Statechart_Diagram.gif38 *39 * To be written.40 *41 *42 * @subsection subsec_vmm_init VMM Initialization43 *44 * To be written.45 *46 *47 * @subsection subsec_vmm_term VMM Termination48 *49 * To be written.50 *51 */52 53 22 /******************************************************************************* 54 23 * Header Files * … … 56 25 #define LOG_GROUP LOG_GROUP_VMM 57 26 #include <VBox/vmm.h> 58 #include <VBox/vmapi.h>59 #include <VBox/pgm.h>60 #include <VBox/cfgm.h>61 #include <VBox/pdmqueue.h>62 27 #include <VBox/pdmapi.h> 63 #include <VBox/cpum.h>64 #include <VBox/mm.h>65 #include <VBox/iom.h>66 28 #include <VBox/trpm.h> 67 #include <VBox/selm.h>68 #include <VBox/em.h>69 #include <VBox/sup.h>70 29 #include <VBox/dbgf.h> 71 #include <VBox/csam.h>72 #include <VBox/patm.h>73 #include <VBox/rem.h>74 #include <VBox/ssm.h>75 #include <VBox/tm.h>76 30 #include "VMMInternal.h" 77 #include "VMMSwitcher/VMMSwitcher.h"78 31 #include <VBox/vm.h> 79 32 … … 81 34 #include <VBox/param.h> 82 35 #include <VBox/version.h> 83 #include <VBox/x86.h>84 36 #include <VBox/hwaccm.h> 85 37 #include <iprt/assert.h> 86 #include <iprt/alloc.h>87 #include <iprt/asm.h>88 38 #include <iprt/time.h> 89 39 #include <iprt/stream.h> 90 40 #include <iprt/string.h> 91 41 #include <iprt/stdarg.h> 92 #include <iprt/ctype.h>93 94 95 96 /** The saved state version. */97 #define VMM_SAVED_STATE_VERSION 398 42 99 43 100 44 /******************************************************************************* 101 * Global Variables*45 * Structures and Typedefs * 102 46 *******************************************************************************/ 103 /** Array of switcher defininitions.104 * The type and index shall match!105 */106 static PVMMSWITCHERDEF s_apSwitchers[VMMSWITCHER_MAX] =107 {108 NULL, /* invalid entry */109 #ifndef RT_ARCH_AMD64110 &vmmR3Switcher32BitTo32Bit_Def,111 &vmmR3Switcher32BitToPAE_Def,112 NULL, //&vmmR3Switcher32BitToAMD64_Def,113 &vmmR3SwitcherPAETo32Bit_Def,114 &vmmR3SwitcherPAEToPAE_Def,115 NULL, //&vmmR3SwitcherPAEToAMD64_Def,116 # ifdef VBOX_WITH_HYBIRD_32BIT_KERNEL117 &vmmR3SwitcherAMD64ToPAE_Def,118 # else119 NULL, //&vmmR3SwitcherAMD64ToPAE_Def,120 # endif121 NULL //&vmmR3SwitcherAMD64ToAMD64_Def,122 #else /* RT_ARCH_AMD64 */123 NULL, //&vmmR3Switcher32BitTo32Bit_Def,124 NULL, //&vmmR3Switcher32BitToPAE_Def,125 NULL, //&vmmR3Switcher32BitToAMD64_Def,126 NULL, //&vmmR3SwitcherPAETo32Bit_Def,127 NULL, //&vmmR3SwitcherPAEToPAE_Def,128 NULL, //&vmmR3SwitcherPAEToAMD64_Def,129 &vmmR3SwitcherAMD64ToPAE_Def,130 NULL //&vmmR3SwitcherAMD64ToAMD64_Def,131 #endif /* RT_ARCH_AMD64 */132 };133 134 135 /*******************************************************************************136 * Internal Functions *137 *******************************************************************************/138 static int vmmR3InitCoreCode(PVM pVM);139 static DECLCALLBACK(int) vmmR3Save(PVM pVM, PSSMHANDLE pSSM);140 static DECLCALLBACK(int) vmmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);141 static DECLCALLBACK(void) vmmR3YieldEMT(PVM pVM, PTMTIMER pTimer, void *pvUser);142 static int vmmR3ServiceCallHostRequest(PVM pVM);143 static DECLCALLBACK(void) vmmR3InfoFF(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);144 145 146 /**147 * Initializes the VMM.148 *149 * @returns VBox status code.150 * @param pVM The VM to operate on.151 */152 VMMR3DECL(int) VMMR3Init(PVM pVM)153 {154 LogFlow(("VMMR3Init\n"));155 156 /*157 * Assert alignment, sizes and order.158 */159 AssertMsg(pVM->vmm.s.offVM == 0, ("Already initialized!\n"));160 AssertMsg(sizeof(pVM->vmm.padding) >= sizeof(pVM->vmm.s),161 ("pVM->vmm.padding is too small! vmm.padding %d while vmm.s is %d\n",162 sizeof(pVM->vmm.padding), sizeof(pVM->vmm.s)));163 164 /*165 * Init basic VM VMM members.166 */167 pVM->vmm.s.offVM = RT_OFFSETOF(VM, vmm);168 int rc = CFGMR3QueryU32(CFGMR3GetRoot(pVM), "YieldEMTInterval", &pVM->vmm.s.cYieldEveryMillies);169 if (rc == VERR_CFGM_VALUE_NOT_FOUND)170 pVM->vmm.s.cYieldEveryMillies = 23; /* Value arrived at after experimenting with the grub boot prompt. */171 //pVM->vmm.s.cYieldEveryMillies = 8; //debugging172 else173 AssertMsgRCReturn(rc, ("Configuration error. Failed to query \"YieldEMTInterval\", rc=%Vrc\n", rc), rc);174 175 /* GC switchers are enabled by default. Turned off by HWACCM. */176 pVM->vmm.s.fSwitcherDisabled = false;177 178 /* Get the CPU count.*/179 rc = CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "NumCPUs", &pVM->cCPUs, 1);180 AssertLogRelMsgRCReturn(rc, ("Configuration error: Querying \"NumCPUs\" as integer failed, rc=%Vrc\n", rc), rc);181 #ifdef VBOX_WITH_SMP_GUESTS182 AssertLogRelMsgReturn(pVM->cCPUs > 0 && pVM->cCPUs <= 256,183 ("Configuration error: \"NumCPUs\"=%RU32 is out of range [1..256]\n", pVM->cCPUs), VERR_INVALID_PARAMETER);184 #else185 AssertLogRelMsgReturn(pVM->cCPUs != 0,186 ("Configuration error: \"NumCPUs\"=%RU32, expected 1\n", pVM->cCPUs), VERR_INVALID_PARAMETER);187 #endif188 189 #ifdef VBOX_WITH_SMP_GUESTS190 LogRel(("[SMP] VMM with %RU32 CPUs\n", pVM->cCPUs));191 #endif192 193 /*194 * Register the saved state data unit.195 */196 rc = SSMR3RegisterInternal(pVM, "vmm", 1, VMM_SAVED_STATE_VERSION, VMM_STACK_SIZE + sizeof(RTGCPTR),197 NULL, vmmR3Save, NULL,198 NULL, vmmR3Load, NULL);199 if (VBOX_FAILURE(rc))200 return rc;201 202 /*203 * Register the Ring-0 VM handle with the session for fast ioctl calls.204 */205 rc = SUPSetVMForFastIOCtl(pVM->pVMR0);206 if (VBOX_FAILURE(rc))207 return rc;208 209 /*210 * Init core code.211 */212 rc = vmmR3InitCoreCode(pVM);213 if (VBOX_SUCCESS(rc))214 {215 /*216 * Allocate & init VMM GC stack.217 * The stack pages are also used by the VMM R0 when VMMR0CallHost is invoked.218 * (The page protection is modifed during R3 init completion.)219 */220 #ifdef VBOX_STRICT_VMM_STACK221 rc = MMHyperAlloc(pVM, VMM_STACK_SIZE + PAGE_SIZE + PAGE_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbHCStack);222 #else223 rc = MMHyperAlloc(pVM, VMM_STACK_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbHCStack);224 #endif225 if (VBOX_SUCCESS(rc))226 {227 /* Set HC and GC stack pointers to top of stack. */228 pVM->vmm.s.CallHostR0JmpBuf.pvSavedStack = (RTR0PTR)pVM->vmm.s.pbHCStack;229 pVM->vmm.s.pbGCStack = MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack);230 pVM->vmm.s.pbGCStackBottom = pVM->vmm.s.pbGCStack + VMM_STACK_SIZE;231 AssertRelease(pVM->vmm.s.pbGCStack);232 233 /* Set hypervisor eip. */234 CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStack);235 236 /*237 * Allocate GC & R0 Logger instances (they are finalized in the relocator).238 */239 #ifdef LOG_ENABLED240 PRTLOGGER pLogger = RTLogDefaultInstance();241 if (pLogger)242 {243 pVM->vmm.s.cbLoggerGC = RT_OFFSETOF(RTLOGGERRC, afGroups[pLogger->cGroups]);244 rc = MMHyperAlloc(pVM, pVM->vmm.s.cbLoggerGC, 0, MM_TAG_VMM, (void **)&pVM->vmm.s.pLoggerHC);245 if (VBOX_SUCCESS(rc))246 {247 pVM->vmm.s.pLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pLoggerHC);248 249 # ifdef VBOX_WITH_R0_LOGGING250 rc = MMHyperAlloc(pVM, RT_OFFSETOF(VMMR0LOGGER, Logger.afGroups[pLogger->cGroups]),251 0, MM_TAG_VMM, (void **)&pVM->vmm.s.pR0Logger);252 if (VBOX_SUCCESS(rc))253 {254 pVM->vmm.s.pR0Logger->pVM = pVM->pVMR0;255 //pVM->vmm.s.pR0Logger->fCreated = false;256 pVM->vmm.s.pR0Logger->cbLogger = RT_OFFSETOF(RTLOGGER, afGroups[pLogger->cGroups]);257 }258 # endif259 }260 }261 #endif /* LOG_ENABLED */262 263 #ifdef VBOX_WITH_RC_RELEASE_LOGGING264 /*265 * Allocate RC release logger instances (finalized in the relocator).266 */267 if (VBOX_SUCCESS(rc))268 {269 PRTLOGGER pRelLogger = RTLogRelDefaultInstance();270 if (pRelLogger)271 {272 pVM->vmm.s.cbRelLoggerGC = RT_OFFSETOF(RTLOGGERRC, afGroups[pRelLogger->cGroups]);273 rc = MMHyperAlloc(pVM, pVM->vmm.s.cbRelLoggerGC, 0, MM_TAG_VMM, (void **)&pVM->vmm.s.pRelLoggerHC);274 if (VBOX_SUCCESS(rc))275 pVM->vmm.s.pRelLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pRelLoggerHC);276 }277 }278 #endif /* VBOX_WITH_RC_RELEASE_LOGGING */279 280 #ifdef VBOX_WITH_NMI281 /*282 * Allocate mapping for the host APIC.283 */284 if (VBOX_SUCCESS(rc))285 {286 rc = MMR3HyperReserve(pVM, PAGE_SIZE, "Host APIC", &pVM->vmm.s.GCPtrApicBase);287 AssertRC(rc);288 }289 #endif290 if (VBOX_SUCCESS(rc))291 {292 rc = RTCritSectInit(&pVM->vmm.s.CritSectVMLock);293 if (VBOX_SUCCESS(rc))294 {295 /*296 * Debug info.297 */298 DBGFR3InfoRegisterInternal(pVM, "ff", "Displays the current Forced actions Flags.", vmmR3InfoFF);299 300 /*301 * Statistics.302 */303 STAM_REG(pVM, &pVM->vmm.s.StatRunGC, STAMTYPE_COUNTER, "/VMM/RunGC", STAMUNIT_OCCURENCES, "Number of context switches.");304 STAM_REG(pVM, &pVM->vmm.s.StatGCRetNormal, STAMTYPE_COUNTER, "/VMM/GCRet/Normal", STAMUNIT_OCCURENCES, "Number of VINF_SUCCESS returns.");305 STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterrupt, STAMTYPE_COUNTER, "/VMM/GCRet/Interrupt", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT returns.");306 STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterruptHyper, STAMTYPE_COUNTER, "/VMM/GCRet/InterruptHyper", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT_HYPER returns.");307 STAM_REG(pVM, &pVM->vmm.s.StatGCRetGuestTrap, STAMTYPE_COUNTER, "/VMM/GCRet/GuestTrap", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_GUEST_TRAP returns.");308 STAM_REG(pVM, &pVM->vmm.s.StatGCRetRingSwitch, STAMTYPE_COUNTER, "/VMM/GCRet/RingSwitch", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_RING_SWITCH returns.");309 STAM_REG(pVM, &pVM->vmm.s.StatGCRetRingSwitchInt, STAMTYPE_COUNTER, "/VMM/GCRet/RingSwitchInt", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_RING_SWITCH_INT returns.");310 STAM_REG(pVM, &pVM->vmm.s.StatGCRetExceptionPrivilege, STAMTYPE_COUNTER, "/VMM/GCRet/ExceptionPrivilege", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_EXCEPTION_PRIVILEGED returns.");311 STAM_REG(pVM, &pVM->vmm.s.StatGCRetStaleSelector, STAMTYPE_COUNTER, "/VMM/GCRet/StaleSelector", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_STALE_SELECTOR returns.");312 STAM_REG(pVM, &pVM->vmm.s.StatGCRetIRETTrap, STAMTYPE_COUNTER, "/VMM/GCRet/IRETTrap", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_IRET_TRAP returns.");313 STAM_REG(pVM, &pVM->vmm.s.StatGCRetEmulate, STAMTYPE_COUNTER, "/VMM/GCRet/Emulate", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION returns.");314 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchEmulate, STAMTYPE_COUNTER, "/VMM/GCRet/PatchEmulate", STAMUNIT_OCCURENCES, "Number of VINF_PATCH_EMULATE_INSTR returns.");315 STAM_REG(pVM, &pVM->vmm.s.StatGCRetIORead, STAMTYPE_COUNTER, "/VMM/GCRet/IORead", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_IOPORT_READ returns.");316 STAM_REG(pVM, &pVM->vmm.s.StatGCRetIOWrite, STAMTYPE_COUNTER, "/VMM/GCRet/IOWrite", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_IOPORT_WRITE returns.");317 STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIORead, STAMTYPE_COUNTER, "/VMM/GCRet/MMIORead", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_READ returns.");318 STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOWrite, STAMTYPE_COUNTER, "/VMM/GCRet/MMIOWrite", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_WRITE returns.");319 STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOReadWrite, STAMTYPE_COUNTER, "/VMM/GCRet/MMIOReadWrite", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_READ_WRITE returns.");320 STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOPatchRead, STAMTYPE_COUNTER, "/VMM/GCRet/MMIOPatchRead", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_PATCH_READ returns.");321 STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOPatchWrite, STAMTYPE_COUNTER, "/VMM/GCRet/MMIOPatchWrite", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_PATCH_WRITE returns.");322 STAM_REG(pVM, &pVM->vmm.s.StatGCRetLDTFault, STAMTYPE_COUNTER, "/VMM/GCRet/LDTFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_GDT_FAULT returns.");323 STAM_REG(pVM, &pVM->vmm.s.StatGCRetGDTFault, STAMTYPE_COUNTER, "/VMM/GCRet/GDTFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_LDT_FAULT returns.");324 STAM_REG(pVM, &pVM->vmm.s.StatGCRetIDTFault, STAMTYPE_COUNTER, "/VMM/GCRet/IDTFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_IDT_FAULT returns.");325 STAM_REG(pVM, &pVM->vmm.s.StatGCRetTSSFault, STAMTYPE_COUNTER, "/VMM/GCRet/TSSFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_TSS_FAULT returns.");326 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDFault, STAMTYPE_COUNTER, "/VMM/GCRet/PDFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_PD_FAULT returns.");327 STAM_REG(pVM, &pVM->vmm.s.StatGCRetCSAMTask, STAMTYPE_COUNTER, "/VMM/GCRet/CSAMTask", STAMUNIT_OCCURENCES, "Number of VINF_CSAM_PENDING_ACTION returns.");328 STAM_REG(pVM, &pVM->vmm.s.StatGCRetSyncCR3, STAMTYPE_COUNTER, "/VMM/GCRet/SyncCR", STAMUNIT_OCCURENCES, "Number of VINF_PGM_SYNC_CR3 returns.");329 STAM_REG(pVM, &pVM->vmm.s.StatGCRetMisc, STAMTYPE_COUNTER, "/VMM/GCRet/Misc", STAMUNIT_OCCURENCES, "Number of misc returns.");330 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchInt3, STAMTYPE_COUNTER, "/VMM/GCRet/PatchInt3", STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_INT3 returns.");331 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchPF, STAMTYPE_COUNTER, "/VMM/GCRet/PatchPF", STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_TRAP_PF returns.");332 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchGP, STAMTYPE_COUNTER, "/VMM/GCRet/PatchGP", STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_TRAP_GP returns.");333 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchIretIRQ, STAMTYPE_COUNTER, "/VMM/GCRet/PatchIret", STAMUNIT_OCCURENCES, "Number of VINF_PATM_PENDING_IRQ_AFTER_IRET returns.");334 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPageOverflow, STAMTYPE_COUNTER, "/VMM/GCRet/InvlpgOverflow", STAMUNIT_OCCURENCES, "Number of VERR_REM_FLUSHED_PAGES_OVERFLOW returns.");335 STAM_REG(pVM, &pVM->vmm.s.StatGCRetRescheduleREM, STAMTYPE_COUNTER, "/VMM/GCRet/ScheduleREM", STAMUNIT_OCCURENCES, "Number of VINF_EM_RESCHEDULE_REM returns.");336 STAM_REG(pVM, &pVM->vmm.s.StatGCRetToR3, STAMTYPE_COUNTER, "/VMM/GCRet/ToR3", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_TO_R3 returns.");337 STAM_REG(pVM, &pVM->vmm.s.StatGCRetTimerPending, STAMTYPE_COUNTER, "/VMM/GCRet/TimerPending", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_TIMER_PENDING returns.");338 STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterruptPending, STAMTYPE_COUNTER, "/VMM/GCRet/InterruptPending", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT_PENDING returns.");339 STAM_REG(pVM, &pVM->vmm.s.StatGCRetCallHost, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/Misc", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");340 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMGrowRAM, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/GrowRAM", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");341 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDMLock, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PDMLock", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");342 STAM_REG(pVM, &pVM->vmm.s.StatGCRetLogFlush, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/LogFlush", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");343 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDMQueueFlush, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/QueueFlush", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");344 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMPoolGrow, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PGMPoolGrow",STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");345 STAM_REG(pVM, &pVM->vmm.s.StatGCRetRemReplay, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/REMReplay", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");346 STAM_REG(pVM, &pVM->vmm.s.StatGCRetVMSetError, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/VMSetError", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");347 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMLock, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PGMLock", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");348 STAM_REG(pVM, &pVM->vmm.s.StatGCRetHyperAssertion, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/HyperAssert", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");349 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPATMDuplicateFn, STAMTYPE_COUNTER, "/VMM/GCRet/PATMDuplicateFn", STAMUNIT_OCCURENCES, "Number of VINF_PATM_DUPLICATE_FUNCTION returns.");350 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMChangeMode, STAMTYPE_COUNTER, "/VMM/GCRet/PGMChangeMode", STAMUNIT_OCCURENCES, "Number of VINF_PGM_CHANGE_MODE returns.");351 STAM_REG(pVM, &pVM->vmm.s.StatGCRetEmulHlt, STAMTYPE_COUNTER, "/VMM/GCRet/EmulHlt", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_EMULATE_INSTR_HLT returns.");352 STAM_REG(pVM, &pVM->vmm.s.StatGCRetPendingRequest, STAMTYPE_COUNTER, "/VMM/GCRet/PendingRequest", STAMUNIT_OCCURENCES, "Number of VINF_EM_PENDING_REQUEST returns.");353 354 return VINF_SUCCESS;355 }356 AssertRC(rc);357 }358 }359 /** @todo: Need failure cleanup. */360 361 //more todo in here?362 //if (VBOX_SUCCESS(rc))363 //{364 //}365 //int rc2 = vmmR3TermCoreCode(pVM);366 //AssertRC(rc2));367 }368 369 return rc;370 }371 372 373 /**374 * VMMR3Init worker that initiates the core code.375 *376 * This is core per VM code which might need fixups and/or for ease of use are377 * put on linear contiguous backing.378 *379 * @returns VBox status code.380 * @param pVM Pointer to the shared VM structure.381 */382 static int vmmR3InitCoreCode(PVM pVM)383 {384 /*385 * Calc the size.386 */387 unsigned cbCoreCode = 0;388 for (unsigned iSwitcher = 0; iSwitcher < RT_ELEMENTS(s_apSwitchers); iSwitcher++)389 {390 pVM->vmm.s.aoffSwitchers[iSwitcher] = cbCoreCode;391 PVMMSWITCHERDEF pSwitcher = s_apSwitchers[iSwitcher];392 if (pSwitcher)393 {394 AssertRelease((unsigned)pSwitcher->enmType == iSwitcher);395 cbCoreCode += RT_ALIGN_32(pSwitcher->cbCode + 1, 32);396 }397 }398 399 /*400 * Allocate continguous pages for switchers and deal with401 * conflicts in the intermediate mapping of the code.402 */403 pVM->vmm.s.cbCoreCode = RT_ALIGN_32(cbCoreCode, PAGE_SIZE);404 pVM->vmm.s.pvHCCoreCodeR3 = SUPContAlloc2(pVM->vmm.s.cbCoreCode >> PAGE_SHIFT, &pVM->vmm.s.pvHCCoreCodeR0, &pVM->vmm.s.HCPhysCoreCode);405 int rc = VERR_NO_MEMORY;406 if (pVM->vmm.s.pvHCCoreCodeR3)407 {408 rc = PGMR3MapIntermediate(pVM, pVM->vmm.s.pvHCCoreCodeR0, pVM->vmm.s.HCPhysCoreCode, cbCoreCode);409 if (rc == VERR_PGM_INTERMEDIATE_PAGING_CONFLICT)410 {411 /* try more allocations - Solaris, Linux. */412 const unsigned cTries = 8234;413 struct VMMInitBadTry414 {415 RTR0PTR pvR0;416 void *pvR3;417 RTHCPHYS HCPhys;418 RTUINT cb;419 } *paBadTries = (struct VMMInitBadTry *)RTMemTmpAlloc(sizeof(*paBadTries) * cTries);420 AssertReturn(paBadTries, VERR_NO_TMP_MEMORY);421 unsigned i = 0;422 do423 {424 paBadTries[i].pvR3 = pVM->vmm.s.pvHCCoreCodeR3;425 paBadTries[i].pvR0 = pVM->vmm.s.pvHCCoreCodeR0;426 paBadTries[i].HCPhys = pVM->vmm.s.HCPhysCoreCode;427 i++;428 pVM->vmm.s.pvHCCoreCodeR0 = NIL_RTR0PTR;429 pVM->vmm.s.HCPhysCoreCode = NIL_RTHCPHYS;430 pVM->vmm.s.pvHCCoreCodeR3 = SUPContAlloc2(pVM->vmm.s.cbCoreCode >> PAGE_SHIFT, &pVM->vmm.s.pvHCCoreCodeR0, &pVM->vmm.s.HCPhysCoreCode);431 if (!pVM->vmm.s.pvHCCoreCodeR3)432 break;433 rc = PGMR3MapIntermediate(pVM, pVM->vmm.s.pvHCCoreCodeR0, pVM->vmm.s.HCPhysCoreCode, cbCoreCode);434 } while ( rc == VERR_PGM_INTERMEDIATE_PAGING_CONFLICT435 && i < cTries - 1);436 437 /* cleanup */438 if (VBOX_FAILURE(rc))439 {440 paBadTries[i].pvR3 = pVM->vmm.s.pvHCCoreCodeR3;441 paBadTries[i].pvR0 = pVM->vmm.s.pvHCCoreCodeR0;442 paBadTries[i].HCPhys = pVM->vmm.s.HCPhysCoreCode;443 paBadTries[i].cb = pVM->vmm.s.cbCoreCode;444 i++;445 LogRel(("Failed to allocated and map core code: rc=%Vrc\n", rc));446 }447 while (i-- > 0)448 {449 LogRel(("Core code alloc attempt #%d: pvR3=%p pvR0=%p HCPhys=%VHp\n",450 i, paBadTries[i].pvR3, paBadTries[i].pvR0, paBadTries[i].HCPhys));451 SUPContFree(paBadTries[i].pvR3, paBadTries[i].cb >> PAGE_SHIFT);452 }453 RTMemTmpFree(paBadTries);454 }455 }456 if (VBOX_SUCCESS(rc))457 {458 /*459 * copy the code.460 */461 for (unsigned iSwitcher = 0; iSwitcher < RT_ELEMENTS(s_apSwitchers); iSwitcher++)462 {463 PVMMSWITCHERDEF pSwitcher = s_apSwitchers[iSwitcher];464 if (pSwitcher)465 memcpy((uint8_t *)pVM->vmm.s.pvHCCoreCodeR3 + pVM->vmm.s.aoffSwitchers[iSwitcher],466 pSwitcher->pvCode, pSwitcher->cbCode);467 }468 469 /*470 * Map the code into the GC address space.471 */472 RTGCPTR GCPtr;473 rc = MMR3HyperMapHCPhys(pVM, pVM->vmm.s.pvHCCoreCodeR3, pVM->vmm.s.HCPhysCoreCode, cbCoreCode, "Core Code", &GCPtr);474 if (VBOX_SUCCESS(rc))475 {476 pVM->vmm.s.pvGCCoreCode = GCPtr;477 MMR3HyperReserve(pVM, PAGE_SIZE, "fence", NULL);478 LogRel(("CoreCode: R3=%VHv R0=%VHv GC=%VRv Phys=%VHp cb=%#x\n",479 pVM->vmm.s.pvHCCoreCodeR3, pVM->vmm.s.pvHCCoreCodeR0, pVM->vmm.s.pvGCCoreCode, pVM->vmm.s.HCPhysCoreCode, pVM->vmm.s.cbCoreCode));480 481 /*482 * Finally, PGM probably have selected a switcher already but we need483 * to get the routine addresses, so we'll reselect it.484 * This may legally fail so, we're ignoring the rc.485 */486 VMMR3SelectSwitcher(pVM, pVM->vmm.s.enmSwitcher);487 return rc;488 }489 490 /* shit */491 AssertMsgFailed(("PGMR3Map(,%VRv, %VGp, %#x, 0) failed with rc=%Vrc\n", pVM->vmm.s.pvGCCoreCode, pVM->vmm.s.HCPhysCoreCode, cbCoreCode, rc));492 SUPContFree(pVM->vmm.s.pvHCCoreCodeR3, pVM->vmm.s.cbCoreCode >> PAGE_SHIFT);493 }494 else495 VMSetError(pVM, rc, RT_SRC_POS,496 N_("Failed to allocate %d bytes of contiguous memory for the world switcher code"),497 cbCoreCode);498 499 pVM->vmm.s.pvHCCoreCodeR3 = NULL;500 pVM->vmm.s.pvHCCoreCodeR0 = NIL_RTR0PTR;501 pVM->vmm.s.pvGCCoreCode = 0;502 return rc;503 }504 505 506 /**507 * Ring-3 init finalizing.508 *509 * @returns VBox status code.510 * @param pVM The VM handle.511 */512 VMMR3DECL(int) VMMR3InitFinalize(PVM pVM)513 {514 #ifdef VBOX_STRICT_VMM_STACK515 /*516 * Two inaccessible pages at each sides of the stack to catch over/under-flows.517 */518 memset(pVM->vmm.s.pbHCStack - PAGE_SIZE, 0xcc, PAGE_SIZE);519 PGMMapSetPage(pVM, MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack - PAGE_SIZE), PAGE_SIZE, 0);520 RTMemProtect(pVM->vmm.s.pbHCStack - PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_NONE);521 522 memset(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE, 0xcc, PAGE_SIZE);523 PGMMapSetPage(pVM, MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack + VMM_STACK_SIZE), PAGE_SIZE, 0);524 RTMemProtect(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE, PAGE_SIZE, RTMEM_PROT_NONE);525 #endif526 527 /*528 * Set page attributes to r/w for stack pages.529 */530 int rc = PGMMapSetPage(pVM, pVM->vmm.s.pbGCStack, VMM_STACK_SIZE, X86_PTE_P | X86_PTE_A | X86_PTE_D | X86_PTE_RW);531 AssertRC(rc);532 if (VBOX_SUCCESS(rc))533 {534 /*535 * Create the EMT yield timer.536 */537 rc = TMR3TimerCreateInternal(pVM, TMCLOCK_REAL, vmmR3YieldEMT, NULL, "EMT Yielder", &pVM->vmm.s.pYieldTimer);538 if (VBOX_SUCCESS(rc))539 rc = TMTimerSetMillies(pVM->vmm.s.pYieldTimer, pVM->vmm.s.cYieldEveryMillies);540 }541 542 #ifdef VBOX_WITH_NMI543 /*544 * Map the host APIC into GC - This may be host os specific!545 */546 if (VBOX_SUCCESS(rc))547 rc = PGMMap(pVM, pVM->vmm.s.GCPtrApicBase, 0xfee00000, PAGE_SIZE,548 X86_PTE_P | X86_PTE_RW | X86_PTE_PWT | X86_PTE_PCD | X86_PTE_A | X86_PTE_D);549 #endif550 return rc;551 }552 553 554 /**555 * Initializes the R0 VMM.556 *557 * @returns VBox status code.558 * @param pVM The VM to operate on.559 */560 VMMR3DECL(int) VMMR3InitR0(PVM pVM)561 {562 int rc;563 564 /*565 * Initialize the ring-0 logger if we haven't done so yet.566 */567 if ( pVM->vmm.s.pR0Logger568 && !pVM->vmm.s.pR0Logger->fCreated)569 {570 rc = VMMR3UpdateLoggers(pVM);571 if (VBOX_FAILURE(rc))572 return rc;573 }574 575 /*576 * Call Ring-0 entry with init code.577 */578 for (;;)579 {580 #ifdef NO_SUPCALLR0VMM581 //rc = VERR_GENERAL_FAILURE;582 rc = VINF_SUCCESS;583 #else584 rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_VMMR0_INIT, VMMGetSvnRev(), NULL);585 #endif586 if ( pVM->vmm.s.pR0Logger587 && pVM->vmm.s.pR0Logger->Logger.offScratch > 0)588 RTLogFlushToLogger(&pVM->vmm.s.pR0Logger->Logger, NULL);589 if (rc != VINF_VMM_CALL_HOST)590 break;591 rc = vmmR3ServiceCallHostRequest(pVM);592 if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))593 break;594 /* Resume R0 */595 }596 597 if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))598 {599 LogRel(("R0 init failed, rc=%Vra\n", rc));600 if (VBOX_SUCCESS(rc))601 rc = VERR_INTERNAL_ERROR;602 }603 return rc;604 }605 606 607 /**608 * Initializes the RC VMM.609 *610 * @returns VBox status code.611 * @param pVM The VM to operate on.612 */613 VMMR3DECL(int) VMMR3InitRC(PVM pVM)614 {615 /* In VMX mode, there's no need to init GC. */616 if (pVM->vmm.s.fSwitcherDisabled)617 return VINF_SUCCESS;618 619 /*620 * Call VMMGCInit():621 * -# resolve the address.622 * -# setup stackframe and EIP to use the trampoline.623 * -# do a generic hypervisor call.624 */625 RTGCPTR32 GCPtrEP;626 int rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "VMMGCEntry", &GCPtrEP);627 if (VBOX_SUCCESS(rc))628 {629 CPUMHyperSetCtxCore(pVM, NULL);630 CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom); /* Clear the stack. */631 uint64_t u64TS = RTTimeProgramStartNanoTS();632 CPUMPushHyper(pVM, (uint32_t)(u64TS >> 32)); /* Param 3: The program startup TS - Hi. */633 CPUMPushHyper(pVM, (uint32_t)u64TS); /* Param 3: The program startup TS - Lo. */634 CPUMPushHyper(pVM, VMMGetSvnRev()); /* Param 2: Version argument. */635 CPUMPushHyper(pVM, VMMGC_DO_VMMGC_INIT); /* Param 1: Operation. */636 CPUMPushHyper(pVM, pVM->pVMGC); /* Param 0: pVM */637 CPUMPushHyper(pVM, 3 * sizeof(RTGCPTR32)); /* trampoline param: stacksize. */638 CPUMPushHyper(pVM, GCPtrEP); /* Call EIP. */639 CPUMSetHyperEIP(pVM, pVM->vmm.s.pfnGCCallTrampoline);640 641 for (;;)642 {643 #ifdef NO_SUPCALLR0VMM644 //rc = VERR_GENERAL_FAILURE;645 rc = VINF_SUCCESS;646 #else647 rc = SUPCallVMMR0(pVM->pVMR0, VMMR0_DO_CALL_HYPERVISOR, NULL);648 #endif649 #ifdef LOG_ENABLED650 PRTLOGGERRC pLogger = pVM->vmm.s.pLoggerHC;651 if ( pLogger652 && pLogger->offScratch > 0)653 RTLogFlushGC(NULL, pLogger);654 #endif655 #ifdef VBOX_WITH_RC_RELEASE_LOGGING656 PRTLOGGERRC pRelLogger = pVM->vmm.s.pRelLoggerHC;657 if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))658 RTLogFlushGC(RTLogRelDefaultInstance(), pRelLogger);659 #endif660 if (rc != VINF_VMM_CALL_HOST)661 break;662 rc = vmmR3ServiceCallHostRequest(pVM);663 if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))664 break;665 }666 667 if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))668 {669 VMMR3FatalDump(pVM, rc);670 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)671 rc = VERR_INTERNAL_ERROR;672 }673 AssertRC(rc);674 }675 return rc;676 }677 678 679 /**680 * Terminate the VMM bits.681 *682 * @returns VINF_SUCCESS.683 * @param pVM The VM handle.684 */685 VMMR3DECL(int) VMMR3Term(PVM pVM)686 {687 /*688 * Call Ring-0 entry with termination code.689 */690 int rc;691 for (;;)692 {693 #ifdef NO_SUPCALLR0VMM694 //rc = VERR_GENERAL_FAILURE;695 rc = VINF_SUCCESS;696 #else697 rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_VMMR0_TERM, 0, NULL);698 #endif699 if ( pVM->vmm.s.pR0Logger700 && pVM->vmm.s.pR0Logger->Logger.offScratch > 0)701 RTLogFlushToLogger(&pVM->vmm.s.pR0Logger->Logger, NULL);702 if (rc != VINF_VMM_CALL_HOST)703 break;704 rc = vmmR3ServiceCallHostRequest(pVM);705 if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))706 break;707 /* Resume R0 */708 }709 if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))710 {711 LogRel(("VMMR3Term: R0 term failed, rc=%Vra. (warning)\n", rc));712 if (VBOX_SUCCESS(rc))713 rc = VERR_INTERNAL_ERROR;714 }715 716 #ifdef VBOX_STRICT_VMM_STACK717 /*718 * Make the two stack guard pages present again.719 */720 RTMemProtect(pVM->vmm.s.pbHCStack - PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);721 RTMemProtect(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);722 #endif723 return rc;724 }725 726 727 /**728 * Applies relocations to data and code managed by this729 * component. This function will be called at init and730 * whenever the VMM need to relocate it self inside the GC.731 *732 * The VMM will need to apply relocations to the core code.733 *734 * @param pVM The VM handle.735 * @param offDelta The relocation delta.736 */737 VMMR3DECL(void) VMMR3Relocate(PVM pVM, RTGCINTPTR offDelta)738 {739 LogFlow(("VMMR3Relocate: offDelta=%VGv\n", offDelta));740 741 /*742 * Recalc the GC address.743 */744 pVM->vmm.s.pvGCCoreCode = MMHyperHC2GC(pVM, pVM->vmm.s.pvHCCoreCodeR3);745 746 /*747 * The stack.748 */749 CPUMSetHyperESP(pVM, CPUMGetHyperESP(pVM) + offDelta);750 pVM->vmm.s.pbGCStack = MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack);751 pVM->vmm.s.pbGCStackBottom = pVM->vmm.s.pbGCStack + VMM_STACK_SIZE;752 753 /*754 * All the switchers.755 */756 for (unsigned iSwitcher = 0; iSwitcher < RT_ELEMENTS(s_apSwitchers); iSwitcher++)757 {758 PVMMSWITCHERDEF pSwitcher = s_apSwitchers[iSwitcher];759 if (pSwitcher && pSwitcher->pfnRelocate)760 {761 unsigned off = pVM->vmm.s.aoffSwitchers[iSwitcher];762 pSwitcher->pfnRelocate(pVM,763 pSwitcher,764 (uint8_t *)pVM->vmm.s.pvHCCoreCodeR0 + off,765 (uint8_t *)pVM->vmm.s.pvHCCoreCodeR3 + off,766 pVM->vmm.s.pvGCCoreCode + off,767 pVM->vmm.s.HCPhysCoreCode + off);768 }769 }770 771 /*772 * Recalc the GC address for the current switcher.773 */774 PVMMSWITCHERDEF pSwitcher = s_apSwitchers[pVM->vmm.s.enmSwitcher];775 RTGCPTR GCPtr = pVM->vmm.s.pvGCCoreCode + pVM->vmm.s.aoffSwitchers[pVM->vmm.s.enmSwitcher];776 pVM->vmm.s.pfnGCGuestToHost = GCPtr + pSwitcher->offGCGuestToHost;777 pVM->vmm.s.pfnGCCallTrampoline = GCPtr + pSwitcher->offGCCallTrampoline;778 pVM->pfnVMMGCGuestToHostAsm = GCPtr + pSwitcher->offGCGuestToHostAsm;779 pVM->pfnVMMGCGuestToHostAsmHyperCtx = GCPtr + pSwitcher->offGCGuestToHostAsmHyperCtx;780 pVM->pfnVMMGCGuestToHostAsmGuestCtx = GCPtr + pSwitcher->offGCGuestToHostAsmGuestCtx;781 782 /*783 * Get other GC entry points.784 */785 int rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "CPUMGCResumeGuest", &pVM->vmm.s.pfnCPUMGCResumeGuest);786 AssertReleaseMsgRC(rc, ("CPUMGCResumeGuest not found! rc=%Vra\n", rc));787 788 rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "CPUMGCResumeGuestV86", &pVM->vmm.s.pfnCPUMGCResumeGuestV86);789 AssertReleaseMsgRC(rc, ("CPUMGCResumeGuestV86 not found! rc=%Vra\n", rc));790 791 /*792 * Update the logger.793 */794 VMMR3UpdateLoggers(pVM);795 }796 797 798 /**799 * Updates the settings for the GC and R0 loggers.800 *801 * @returns VBox status code.802 * @param pVM The VM handle.803 */804 VMMR3DECL(int) VMMR3UpdateLoggers(PVM pVM)805 {806 /*807 * Simply clone the logger instance (for GC).808 */809 int rc = VINF_SUCCESS;810 RTGCPTR32 GCPtrLoggerFlush = 0;811 812 if (pVM->vmm.s.pLoggerHC813 #ifdef VBOX_WITH_RC_RELEASE_LOGGING814 || pVM->vmm.s.pRelLoggerHC815 #endif816 )817 {818 rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "vmmGCLoggerFlush", &GCPtrLoggerFlush);819 AssertReleaseMsgRC(rc, ("vmmGCLoggerFlush not found! rc=%Vra\n", rc));820 }821 822 if (pVM->vmm.s.pLoggerHC)823 {824 RTGCPTR32 GCPtrLoggerWrapper = 0;825 rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "vmmGCLoggerWrapper", &GCPtrLoggerWrapper);826 AssertReleaseMsgRC(rc, ("vmmGCLoggerWrapper not found! rc=%Vra\n", rc));827 pVM->vmm.s.pLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pLoggerHC);828 rc = RTLogCloneRC(NULL /* default */, pVM->vmm.s.pLoggerHC, pVM->vmm.s.cbLoggerGC,829 GCPtrLoggerWrapper, GCPtrLoggerFlush, RTLOGFLAGS_BUFFERED);830 AssertReleaseMsgRC(rc, ("RTLogCloneGC failed! rc=%Vra\n", rc));831 }832 833 #ifdef VBOX_WITH_RC_RELEASE_LOGGING834 if (pVM->vmm.s.pRelLoggerHC)835 {836 RTGCPTR32 GCPtrLoggerWrapper = 0;837 rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "vmmGCRelLoggerWrapper", &GCPtrLoggerWrapper);838 AssertReleaseMsgRC(rc, ("vmmGCRelLoggerWrapper not found! rc=%Vra\n", rc));839 pVM->vmm.s.pRelLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pRelLoggerHC);840 rc = RTLogCloneRC(RTLogRelDefaultInstance(), pVM->vmm.s.pRelLoggerHC, pVM->vmm.s.cbRelLoggerGC,841 GCPtrLoggerWrapper, GCPtrLoggerFlush, RTLOGFLAGS_BUFFERED);842 AssertReleaseMsgRC(rc, ("RTLogCloneGC failed! rc=%Vra\n", rc));843 }844 #endif /* VBOX_WITH_RC_RELEASE_LOGGING */845 846 /*847 * For the ring-0 EMT logger, we use a per-thread logger848 * instance in ring-0. Only initialize it once.849 */850 PVMMR0LOGGER pR0Logger = pVM->vmm.s.pR0Logger;851 if (pR0Logger)852 {853 if (!pR0Logger->fCreated)854 {855 RTR0PTR pfnLoggerWrapper = NIL_RTR0PTR;856 rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerWrapper", &pfnLoggerWrapper);857 AssertReleaseMsgRCReturn(rc, ("VMMLoggerWrapper not found! rc=%Vra\n", rc), rc);858 859 RTR0PTR pfnLoggerFlush = NIL_RTR0PTR;860 rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerFlush", &pfnLoggerFlush);861 AssertReleaseMsgRCReturn(rc, ("VMMLoggerFlush not found! rc=%Vra\n", rc), rc);862 863 rc = RTLogCreateForR0(&pR0Logger->Logger, pR0Logger->cbLogger,864 *(PFNRTLOGGER *)&pfnLoggerWrapper, *(PFNRTLOGFLUSH *)&pfnLoggerFlush,865 RTLOGFLAGS_BUFFERED, RTLOGDEST_DUMMY);866 AssertReleaseMsgRCReturn(rc, ("RTLogCloneGC failed! rc=%Vra\n", rc), rc);867 pR0Logger->fCreated = true;868 }869 870 rc = RTLogCopyGroupsAndFlags(&pR0Logger->Logger, NULL /* default */, pVM->vmm.s.pLoggerHC->fFlags, RTLOGFLAGS_BUFFERED);871 AssertRC(rc);872 }873 874 return rc;875 }876 877 878 /**879 * Generic switch code relocator.880 *881 * @param pVM The VM handle.882 * @param pSwitcher The switcher definition.883 * @param pu8CodeR3 Pointer to the core code block for the switcher, ring-3 mapping.884 * @param pu8CodeR0 Pointer to the core code block for the switcher, ring-0 mapping.885 * @param GCPtrCode The guest context address corresponding to pu8Code.886 * @param u32IDCode The identity mapped (ID) address corresponding to pu8Code.887 * @param SelCS The hypervisor CS selector.888 * @param SelDS The hypervisor DS selector.889 * @param SelTSS The hypervisor TSS selector.890 * @param GCPtrGDT The GC address of the hypervisor GDT.891 * @param SelCS64 The 64-bit mode hypervisor CS selector.892 */893 static void vmmR3SwitcherGenericRelocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode,894 RTSEL SelCS, RTSEL SelDS, RTSEL SelTSS, RTGCPTR GCPtrGDT, RTSEL SelCS64)895 {896 union897 {898 const uint8_t *pu8;899 const uint16_t *pu16;900 const uint32_t *pu32;901 const uint64_t *pu64;902 const void *pv;903 uintptr_t u;904 } u;905 u.pv = pSwitcher->pvFixups;906 907 /*908 * Process fixups.909 */910 uint8_t u8;911 while ((u8 = *u.pu8++) != FIX_THE_END)912 {913 /*914 * Get the source (where to write the fixup).915 */916 uint32_t offSrc = *u.pu32++;917 Assert(offSrc < pSwitcher->cbCode);918 union919 {920 uint8_t *pu8;921 uint16_t *pu16;922 uint32_t *pu32;923 uint64_t *pu64;924 uintptr_t u;925 } uSrc;926 uSrc.pu8 = pu8CodeR3 + offSrc;927 928 /* The fixup target and method depends on the type. */929 switch (u8)930 {931 /*932 * 32-bit relative, source in HC and target in GC.933 */934 case FIX_HC_2_GC_NEAR_REL:935 {936 Assert(offSrc - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offSrc - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);937 uint32_t offTrg = *u.pu32++;938 Assert(offTrg - pSwitcher->offGCCode < pSwitcher->cbGCCode);939 *uSrc.pu32 = (uint32_t)((GCPtrCode + offTrg) - (uSrc.u + 4));940 break;941 }942 943 /*944 * 32-bit relative, source in HC and target in ID.945 */946 case FIX_HC_2_ID_NEAR_REL:947 {948 Assert(offSrc - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offSrc - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);949 uint32_t offTrg = *u.pu32++;950 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);951 *uSrc.pu32 = (uint32_t)((u32IDCode + offTrg) - ((uintptr_t)pu8CodeR0 + offSrc + 4));952 break;953 }954 955 /*956 * 32-bit relative, source in GC and target in HC.957 */958 case FIX_GC_2_HC_NEAR_REL:959 {960 Assert(offSrc - pSwitcher->offGCCode < pSwitcher->cbGCCode);961 uint32_t offTrg = *u.pu32++;962 Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);963 *uSrc.pu32 = (uint32_t)(((uintptr_t)pu8CodeR0 + offTrg) - (GCPtrCode + offSrc + 4));964 break;965 }966 967 /*968 * 32-bit relative, source in GC and target in ID.969 */970 case FIX_GC_2_ID_NEAR_REL:971 {972 Assert(offSrc - pSwitcher->offGCCode < pSwitcher->cbGCCode);973 uint32_t offTrg = *u.pu32++;974 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);975 *uSrc.pu32 = (uint32_t)((u32IDCode + offTrg) - (GCPtrCode + offSrc + 4));976 break;977 }978 979 /*980 * 32-bit relative, source in ID and target in HC.981 */982 case FIX_ID_2_HC_NEAR_REL:983 {984 Assert(offSrc - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offSrc - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);985 uint32_t offTrg = *u.pu32++;986 Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);987 *uSrc.pu32 = (uint32_t)(((uintptr_t)pu8CodeR0 + offTrg) - (u32IDCode + offSrc + 4));988 break;989 }990 991 /*992 * 32-bit relative, source in ID and target in HC.993 */994 case FIX_ID_2_GC_NEAR_REL:995 {996 Assert(offSrc - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offSrc - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);997 uint32_t offTrg = *u.pu32++;998 Assert(offTrg - pSwitcher->offGCCode < pSwitcher->cbGCCode);999 *uSrc.pu32 = (uint32_t)((GCPtrCode + offTrg) - (u32IDCode + offSrc + 4));1000 break;1001 }1002 1003 /*1004 * 16:32 far jump, target in GC.1005 */1006 case FIX_GC_FAR32:1007 {1008 uint32_t offTrg = *u.pu32++;1009 Assert(offTrg - pSwitcher->offGCCode < pSwitcher->cbGCCode);1010 *uSrc.pu32++ = (uint32_t)(GCPtrCode + offTrg);1011 *uSrc.pu16++ = SelCS;1012 break;1013 }1014 1015 /*1016 * Make 32-bit GC pointer given CPUM offset.1017 */1018 case FIX_GC_CPUM_OFF:1019 {1020 uint32_t offCPUM = *u.pu32++;1021 Assert(offCPUM < sizeof(pVM->cpum));1022 *uSrc.pu32 = (uint32_t)(VM_GUEST_ADDR(pVM, &pVM->cpum) + offCPUM);1023 break;1024 }1025 1026 /*1027 * Make 32-bit GC pointer given VM offset.1028 */1029 case FIX_GC_VM_OFF:1030 {1031 uint32_t offVM = *u.pu32++;1032 Assert(offVM < sizeof(VM));1033 *uSrc.pu32 = (uint32_t)(VM_GUEST_ADDR(pVM, pVM) + offVM);1034 break;1035 }1036 1037 /*1038 * Make 32-bit HC pointer given CPUM offset.1039 */1040 case FIX_HC_CPUM_OFF:1041 {1042 uint32_t offCPUM = *u.pu32++;1043 Assert(offCPUM < sizeof(pVM->cpum));1044 *uSrc.pu32 = (uint32_t)pVM->pVMR0 + RT_OFFSETOF(VM, cpum) + offCPUM;1045 break;1046 }1047 1048 /*1049 * Make 32-bit R0 pointer given VM offset.1050 */1051 case FIX_HC_VM_OFF:1052 {1053 uint32_t offVM = *u.pu32++;1054 Assert(offVM < sizeof(VM));1055 *uSrc.pu32 = (uint32_t)pVM->pVMR0 + offVM;1056 break;1057 }1058 1059 /*1060 * Store the 32-Bit CR3 (32-bit) for the intermediate memory context.1061 */1062 case FIX_INTER_32BIT_CR3:1063 {1064 1065 *uSrc.pu32 = PGMGetInter32BitCR3(pVM);1066 break;1067 }1068 1069 /*1070 * Store the PAE CR3 (32-bit) for the intermediate memory context.1071 */1072 case FIX_INTER_PAE_CR3:1073 {1074 1075 *uSrc.pu32 = PGMGetInterPaeCR3(pVM);1076 break;1077 }1078 1079 /*1080 * Store the AMD64 CR3 (32-bit) for the intermediate memory context.1081 */1082 case FIX_INTER_AMD64_CR3:1083 {1084 1085 *uSrc.pu32 = PGMGetInterAmd64CR3(pVM);1086 break;1087 }1088 1089 /*1090 * Store the 32-Bit CR3 (32-bit) for the hypervisor (shadow) memory context.1091 */1092 case FIX_HYPER_32BIT_CR3:1093 {1094 1095 *uSrc.pu32 = PGMGetHyper32BitCR3(pVM);1096 break;1097 }1098 1099 /*1100 * Store the PAE CR3 (32-bit) for the hypervisor (shadow) memory context.1101 */1102 case FIX_HYPER_PAE_CR3:1103 {1104 1105 *uSrc.pu32 = PGMGetHyperPaeCR3(pVM);1106 break;1107 }1108 1109 /*1110 * Store the AMD64 CR3 (32-bit) for the hypervisor (shadow) memory context.1111 */1112 case FIX_HYPER_AMD64_CR3:1113 {1114 1115 *uSrc.pu32 = PGMGetHyperAmd64CR3(pVM);1116 break;1117 }1118 1119 /*1120 * Store Hypervisor CS (16-bit).1121 */1122 case FIX_HYPER_CS:1123 {1124 *uSrc.pu16 = SelCS;1125 break;1126 }1127 1128 /*1129 * Store Hypervisor DS (16-bit).1130 */1131 case FIX_HYPER_DS:1132 {1133 *uSrc.pu16 = SelDS;1134 break;1135 }1136 1137 /*1138 * Store Hypervisor TSS (16-bit).1139 */1140 case FIX_HYPER_TSS:1141 {1142 *uSrc.pu16 = SelTSS;1143 break;1144 }1145 1146 /*1147 * Store the 32-bit GC address of the 2nd dword of the TSS descriptor (in the GDT).1148 */1149 case FIX_GC_TSS_GDTE_DW2:1150 {1151 RTGCPTR GCPtr = GCPtrGDT + (SelTSS & ~7) + 4;1152 *uSrc.pu32 = (uint32_t)GCPtr;1153 break;1154 }1155 1156 1157 ///@todo case FIX_CR4_MASK:1158 ///@todo case FIX_CR4_OSFSXR:1159 1160 /*1161 * Insert relative jump to specified target it FXSAVE/FXRSTOR isn't supported by the cpu.1162 */1163 case FIX_NO_FXSAVE_JMP:1164 {1165 uint32_t offTrg = *u.pu32++;1166 Assert(offTrg < pSwitcher->cbCode);1167 if (!CPUMSupportsFXSR(pVM))1168 {1169 *uSrc.pu8++ = 0xe9; /* jmp rel32 */1170 *uSrc.pu32++ = offTrg - (offSrc + 5);1171 }1172 else1173 {1174 *uSrc.pu8++ = *((uint8_t *)pSwitcher->pvCode + offSrc);1175 *uSrc.pu32++ = *(uint32_t *)((uint8_t *)pSwitcher->pvCode + offSrc + 1);1176 }1177 break;1178 }1179 1180 /*1181 * Insert relative jump to specified target it SYSENTER isn't used by the host.1182 */1183 case FIX_NO_SYSENTER_JMP:1184 {1185 uint32_t offTrg = *u.pu32++;1186 Assert(offTrg < pSwitcher->cbCode);1187 if (!CPUMIsHostUsingSysEnter(pVM))1188 {1189 *uSrc.pu8++ = 0xe9; /* jmp rel32 */1190 *uSrc.pu32++ = offTrg - (offSrc + 5);1191 }1192 else1193 {1194 *uSrc.pu8++ = *((uint8_t *)pSwitcher->pvCode + offSrc);1195 *uSrc.pu32++ = *(uint32_t *)((uint8_t *)pSwitcher->pvCode + offSrc + 1);1196 }1197 break;1198 }1199 1200 /*1201 * Insert relative jump to specified target it SYSENTER isn't used by the host.1202 */1203 case FIX_NO_SYSCALL_JMP:1204 {1205 uint32_t offTrg = *u.pu32++;1206 Assert(offTrg < pSwitcher->cbCode);1207 if (!CPUMIsHostUsingSysEnter(pVM))1208 {1209 *uSrc.pu8++ = 0xe9; /* jmp rel32 */1210 *uSrc.pu32++ = offTrg - (offSrc + 5);1211 }1212 else1213 {1214 *uSrc.pu8++ = *((uint8_t *)pSwitcher->pvCode + offSrc);1215 *uSrc.pu32++ = *(uint32_t *)((uint8_t *)pSwitcher->pvCode + offSrc + 1);1216 }1217 break;1218 }1219 1220 /*1221 * 32-bit HC pointer fixup to (HC) target within the code (32-bit offset).1222 */1223 case FIX_HC_32BIT:1224 {1225 uint32_t offTrg = *u.pu32++;1226 Assert(offSrc < pSwitcher->cbCode);1227 Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);1228 *uSrc.pu32 = (uintptr_t)pu8CodeR0 + offTrg;1229 break;1230 }1231 1232 #if defined(RT_ARCH_AMD64) || defined(VBOX_WITH_HYBIRD_32BIT_KERNEL)1233 /*1234 * 64-bit HC pointer fixup to (HC) target within the code (32-bit offset).1235 */1236 case FIX_HC_64BIT:1237 {1238 uint32_t offTrg = *u.pu32++;1239 Assert(offSrc < pSwitcher->cbCode);1240 Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);1241 *uSrc.pu64 = (uintptr_t)pu8CodeR0 + offTrg;1242 break;1243 }1244 1245 /*1246 * 64-bit HC Code Selector (no argument).1247 */1248 case FIX_HC_64BIT_CS:1249 {1250 Assert(offSrc < pSwitcher->cbCode);1251 #if defined(RT_OS_DARWIN) && defined(VBOX_WITH_HYBIRD_32BIT_KERNEL)1252 *uSrc.pu16 = 0x80; /* KERNEL64_CS from i386/seg.h */1253 #else1254 AssertFatalMsgFailed(("FIX_HC_64BIT_CS not implemented for this host\n"));1255 #endif1256 break;1257 }1258 1259 /*1260 * 64-bit HC pointer to the CPUM instance data (no argument).1261 */1262 case FIX_HC_64BIT_CPUM:1263 {1264 Assert(offSrc < pSwitcher->cbCode);1265 *uSrc.pu64 = pVM->pVMR0 + RT_OFFSETOF(VM, cpum);1266 break;1267 }1268 #endif1269 1270 /*1271 * 32-bit ID pointer to (ID) target within the code (32-bit offset).1272 */1273 case FIX_ID_32BIT:1274 {1275 uint32_t offTrg = *u.pu32++;1276 Assert(offSrc < pSwitcher->cbCode);1277 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);1278 *uSrc.pu32 = u32IDCode + offTrg;1279 break;1280 }1281 1282 /*1283 * 64-bit ID pointer to (ID) target within the code (32-bit offset).1284 */1285 case FIX_ID_64BIT:1286 {1287 uint32_t offTrg = *u.pu32++;1288 Assert(offSrc < pSwitcher->cbCode);1289 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);1290 *uSrc.pu64 = u32IDCode + offTrg;1291 break;1292 }1293 1294 /*1295 * Far 16:32 ID pointer to 64-bit mode (ID) target within the code (32-bit offset).1296 */1297 case FIX_ID_FAR32_TO_64BIT_MODE:1298 {1299 uint32_t offTrg = *u.pu32++;1300 Assert(offSrc < pSwitcher->cbCode);1301 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);1302 *uSrc.pu32++ = u32IDCode + offTrg;1303 *uSrc.pu16 = SelCS64;1304 AssertRelease(SelCS64);1305 break;1306 }1307 1308 #ifdef VBOX_WITH_NMI1309 /*1310 * 32-bit address to the APIC base.1311 */1312 case FIX_GC_APIC_BASE_32BIT:1313 {1314 *uSrc.pu32 = pVM->vmm.s.GCPtrApicBase;1315 break;1316 }1317 #endif1318 1319 default:1320 AssertReleaseMsgFailed(("Unknown fixup %d in switcher %s\n", u8, pSwitcher->pszDesc));1321 break;1322 }1323 }1324 1325 #ifdef LOG_ENABLED1326 /*1327 * If Log2 is enabled disassemble the switcher code.1328 *1329 * The switcher code have 1-2 HC parts, 1 GC part and 0-2 ID parts.1330 */1331 if (LogIs2Enabled())1332 {1333 RTLogPrintf("*** Disassembly of switcher %d '%s' %#x bytes ***\n"1334 " pu8CodeR0 = %p\n"1335 " pu8CodeR3 = %p\n"1336 " GCPtrCode = %VGv\n"1337 " u32IDCode = %08x\n"1338 " pVMGC = %VGv\n"1339 " pCPUMGC = %VGv\n"1340 " pVMHC = %p\n"1341 " pCPUMHC = %p\n"1342 " GCPtrGDT = %VGv\n"1343 " InterCR3s = %08x, %08x, %08x (32-Bit, PAE, AMD64)\n"1344 " HyperCR3s = %08x, %08x, %08x (32-Bit, PAE, AMD64)\n"1345 " SelCS = %04x\n"1346 " SelDS = %04x\n"1347 " SelCS64 = %04x\n"1348 " SelTSS = %04x\n",1349 pSwitcher->enmType, pSwitcher->pszDesc, pSwitcher->cbCode,1350 pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode, VM_GUEST_ADDR(pVM, pVM),1351 VM_GUEST_ADDR(pVM, &pVM->cpum), pVM, &pVM->cpum,1352 GCPtrGDT,1353 PGMGetHyper32BitCR3(pVM), PGMGetHyperPaeCR3(pVM), PGMGetHyperAmd64CR3(pVM),1354 PGMGetInter32BitCR3(pVM), PGMGetInterPaeCR3(pVM), PGMGetInterAmd64CR3(pVM),1355 SelCS, SelDS, SelCS64, SelTSS);1356 1357 uint32_t offCode = 0;1358 while (offCode < pSwitcher->cbCode)1359 {1360 /*1361 * Figure out where this is.1362 */1363 const char *pszDesc = NULL;1364 RTUINTPTR uBase;1365 uint32_t cbCode;1366 if (offCode - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0)1367 {1368 pszDesc = "HCCode0";1369 uBase = (RTUINTPTR)pu8CodeR0;1370 offCode = pSwitcher->offHCCode0;1371 cbCode = pSwitcher->cbHCCode0;1372 }1373 else if (offCode - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1)1374 {1375 pszDesc = "HCCode1";1376 uBase = (RTUINTPTR)pu8CodeR0;1377 offCode = pSwitcher->offHCCode1;1378 cbCode = pSwitcher->cbHCCode1;1379 }1380 else if (offCode - pSwitcher->offGCCode < pSwitcher->cbGCCode)1381 {1382 pszDesc = "GCCode";1383 uBase = GCPtrCode;1384 offCode = pSwitcher->offGCCode;1385 cbCode = pSwitcher->cbGCCode;1386 }1387 else if (offCode - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0)1388 {1389 pszDesc = "IDCode0";1390 uBase = u32IDCode;1391 offCode = pSwitcher->offIDCode0;1392 cbCode = pSwitcher->cbIDCode0;1393 }1394 else if (offCode - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1)1395 {1396 pszDesc = "IDCode1";1397 uBase = u32IDCode;1398 offCode = pSwitcher->offIDCode1;1399 cbCode = pSwitcher->cbIDCode1;1400 }1401 else1402 {1403 RTLogPrintf(" %04x: %02x '%c' (nowhere)\n",1404 offCode, pu8CodeR3[offCode], isprint(pu8CodeR3[offCode]) ? pu8CodeR3[offCode] : ' ');1405 offCode++;1406 continue;1407 }1408 1409 /*1410 * Disassemble it.1411 */1412 RTLogPrintf(" %s: offCode=%#x cbCode=%#x\n", pszDesc, offCode, cbCode);1413 DISCPUSTATE Cpu;1414 1415 memset(&Cpu, 0, sizeof(Cpu));1416 Cpu.mode = CPUMODE_32BIT;1417 while (cbCode > 0)1418 {1419 /* try label it */1420 if (pSwitcher->offR0HostToGuest == offCode)1421 RTLogPrintf(" *R0HostToGuest:\n");1422 if (pSwitcher->offGCGuestToHost == offCode)1423 RTLogPrintf(" *GCGuestToHost:\n");1424 if (pSwitcher->offGCCallTrampoline == offCode)1425 RTLogPrintf(" *GCCallTrampoline:\n");1426 if (pSwitcher->offGCGuestToHostAsm == offCode)1427 RTLogPrintf(" *GCGuestToHostAsm:\n");1428 if (pSwitcher->offGCGuestToHostAsmHyperCtx == offCode)1429 RTLogPrintf(" *GCGuestToHostAsmHyperCtx:\n");1430 if (pSwitcher->offGCGuestToHostAsmGuestCtx == offCode)1431 RTLogPrintf(" *GCGuestToHostAsmGuestCtx:\n");1432 1433 /* disas */1434 uint32_t cbInstr = 0;1435 char szDisas[256];1436 if (RT_SUCCESS(DISInstr(&Cpu, (RTUINTPTR)pu8CodeR3 + offCode, uBase - (RTUINTPTR)pu8CodeR3, &cbInstr, szDisas)))1437 RTLogPrintf(" %04x: %s", offCode, szDisas); //for whatever reason szDisas includes '\n'.1438 else1439 {1440 RTLogPrintf(" %04x: %02x '%c'\n",1441 offCode, pu8CodeR3[offCode], isprint(pu8CodeR3[offCode]) ? pu8CodeR3[offCode] : ' ');1442 cbInstr = 1;1443 }1444 offCode += cbInstr;1445 cbCode -= RT_MIN(cbInstr, cbCode);1446 }1447 }1448 }1449 #endif1450 }1451 1452 1453 /**1454 * Relocator for the 32-Bit to 32-Bit world switcher.1455 */1456 DECLCALLBACK(void) vmmR3Switcher32BitTo32Bit_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)1457 {1458 vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,1459 SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), 0);1460 }1461 1462 1463 /**1464 * Relocator for the 32-Bit to PAE world switcher.1465 */1466 DECLCALLBACK(void) vmmR3Switcher32BitToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)1467 {1468 vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,1469 SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), 0);1470 }1471 1472 1473 /**1474 * Relocator for the PAE to 32-Bit world switcher.1475 */1476 DECLCALLBACK(void) vmmR3SwitcherPAETo32Bit_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)1477 {1478 vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,1479 SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), 0);1480 }1481 1482 1483 /**1484 * Relocator for the PAE to PAE world switcher.1485 */1486 DECLCALLBACK(void) vmmR3SwitcherPAEToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)1487 {1488 vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,1489 SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), 0);1490 }1491 1492 1493 /**1494 * Relocator for the AMD64 to PAE world switcher.1495 */1496 DECLCALLBACK(void) vmmR3SwitcherAMD64ToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)1497 {1498 vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,1499 SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), SELMGetHyperCS64(pVM));1500 }1501 1502 1503 /**1504 * Gets the pointer to g_szRTAssertMsg1 in GC.1505 * @returns Pointer to VMMGC::g_szRTAssertMsg1.1506 * Returns NULL if not present.1507 * @param pVM The VM handle.1508 */1509 VMMR3DECL(const char *) VMMR3GetGCAssertMsg1(PVM pVM)1510 {1511 RTGCPTR32 GCPtr;1512 int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_szRTAssertMsg1", &GCPtr);1513 if (VBOX_SUCCESS(rc))1514 return (const char *)MMHyperGC2HC(pVM, GCPtr);1515 return NULL;1516 }1517 1518 1519 /**1520 * Gets the pointer to g_szRTAssertMsg2 in GC.1521 * @returns Pointer to VMMGC::g_szRTAssertMsg2.1522 * Returns NULL if not present.1523 * @param pVM The VM handle.1524 */1525 VMMR3DECL(const char *) VMMR3GetGCAssertMsg2(PVM pVM)1526 {1527 RTGCPTR32 GCPtr;1528 int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_szRTAssertMsg2", &GCPtr);1529 if (VBOX_SUCCESS(rc))1530 return (const char *)MMHyperGC2HC(pVM, GCPtr);1531 return NULL;1532 }1533 1534 1535 /**1536 * Execute state save operation.1537 *1538 * @returns VBox status code.1539 * @param pVM VM Handle.1540 * @param pSSM SSM operation handle.1541 */1542 static DECLCALLBACK(int) vmmR3Save(PVM pVM, PSSMHANDLE pSSM)1543 {1544 LogFlow(("vmmR3Save:\n"));1545 1546 /*1547 * The hypervisor stack.1548 */1549 SSMR3PutRCPtr(pSSM, pVM->vmm.s.pbGCStackBottom);1550 RTRCPTR GCPtrESP = CPUMGetHyperESP(pVM);1551 AssertMsg(pVM->vmm.s.pbGCStackBottom - GCPtrESP <= VMM_STACK_SIZE, ("Bottom %VGv ESP=%VGv\n", pVM->vmm.s.pbGCStackBottom, GCPtrESP));1552 SSMR3PutRCPtr(pSSM, GCPtrESP);1553 SSMR3PutMem(pSSM, pVM->vmm.s.pbHCStack, VMM_STACK_SIZE);1554 return SSMR3PutU32(pSSM, ~0); /* terminator */1555 }1556 1557 1558 /**1559 * Execute state load operation.1560 *1561 * @returns VBox status code.1562 * @param pVM VM Handle.1563 * @param pSSM SSM operation handle.1564 * @param u32Version Data layout version.1565 */1566 static DECLCALLBACK(int) vmmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)1567 {1568 LogFlow(("vmmR3Load:\n"));1569 1570 /*1571 * Validate version.1572 */1573 if (u32Version != VMM_SAVED_STATE_VERSION)1574 {1575 AssertMsgFailed(("vmmR3Load: Invalid version u32Version=%d!\n", u32Version));1576 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;1577 }1578 1579 /*1580 * Check that the stack is in the same place, or that it's fearly empty.1581 */1582 RTRCPTR GCPtrStackBottom;1583 SSMR3GetRCPtr(pSSM, &GCPtrStackBottom);1584 RTRCPTR GCPtrESP;1585 int rc = SSMR3GetRCPtr(pSSM, &GCPtrESP);1586 if (VBOX_FAILURE(rc))1587 return rc;1588 1589 /* Previously we checked if the location of the stack was identical or that the stack was empty.1590 * This is not required as we can never initiate a save when GC context code performs a ring 3 call.1591 */1592 /* restore the stack. (not necessary; just consistency checking) */1593 SSMR3GetMem(pSSM, pVM->vmm.s.pbHCStack, VMM_STACK_SIZE);1594 1595 /* terminator */1596 uint32_t u32;1597 rc = SSMR3GetU32(pSSM, &u32);1598 if (VBOX_FAILURE(rc))1599 return rc;1600 if (u32 != ~0U)1601 {1602 AssertMsgFailed(("u32=%#x\n", u32));1603 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;1604 }1605 return VINF_SUCCESS;1606 }1607 1608 1609 /**1610 * Selects the switcher to be used for switching to GC.1611 *1612 * @returns VBox status code.1613 * @param pVM VM handle.1614 * @param enmSwitcher The new switcher.1615 * @remark This function may be called before the VMM is initialized.1616 */1617 VMMR3DECL(int) VMMR3SelectSwitcher(PVM pVM, VMMSWITCHER enmSwitcher)1618 {1619 /*1620 * Validate input.1621 */1622 if ( enmSwitcher < VMMSWITCHER_INVALID1623 || enmSwitcher >= VMMSWITCHER_MAX)1624 {1625 AssertMsgFailed(("Invalid input enmSwitcher=%d\n", enmSwitcher));1626 return VERR_INVALID_PARAMETER;1627 }1628 1629 /* Do nothing if the switcher is disabled. */1630 if (pVM->vmm.s.fSwitcherDisabled)1631 return VINF_SUCCESS;1632 1633 /*1634 * Select the new switcher.1635 */1636 PVMMSWITCHERDEF pSwitcher = s_apSwitchers[enmSwitcher];1637 if (pSwitcher)1638 {1639 Log(("VMMR3SelectSwitcher: enmSwitcher %d -> %d %s\n", pVM->vmm.s.enmSwitcher, enmSwitcher, pSwitcher->pszDesc));1640 pVM->vmm.s.enmSwitcher = enmSwitcher;1641 1642 RTR0PTR pbCodeR0 = (RTR0PTR)pVM->vmm.s.pvHCCoreCodeR0 + pVM->vmm.s.aoffSwitchers[enmSwitcher]; /** @todo fix the pvHCCoreCodeR0 type */1643 pVM->vmm.s.pfnR0HostToGuest = pbCodeR0 + pSwitcher->offR0HostToGuest;1644 1645 RTGCPTR GCPtr = pVM->vmm.s.pvGCCoreCode + pVM->vmm.s.aoffSwitchers[enmSwitcher];1646 pVM->vmm.s.pfnGCGuestToHost = GCPtr + pSwitcher->offGCGuestToHost;1647 pVM->vmm.s.pfnGCCallTrampoline = GCPtr + pSwitcher->offGCCallTrampoline;1648 pVM->pfnVMMGCGuestToHostAsm = GCPtr + pSwitcher->offGCGuestToHostAsm;1649 pVM->pfnVMMGCGuestToHostAsmHyperCtx = GCPtr + pSwitcher->offGCGuestToHostAsmHyperCtx;1650 pVM->pfnVMMGCGuestToHostAsmGuestCtx = GCPtr + pSwitcher->offGCGuestToHostAsmGuestCtx;1651 return VINF_SUCCESS;1652 }1653 return VERR_NOT_IMPLEMENTED;1654 }1655 1656 /**1657 * Disable the switcher logic permanently.1658 *1659 * @returns VBox status code.1660 * @param pVM VM handle.1661 */1662 VMMR3DECL(int) VMMR3DisableSwitcher(PVM pVM)1663 {1664 /** @todo r=bird: I would suggest that we create a dummy switcher which just does something like:1665 * @code1666 * mov eax, VERR_INTERNAL_ERROR1667 * ret1668 * @endcode1669 * And then check for fSwitcherDisabled in VMMR3SelectSwitcher() in order to prevent it from being removed.1670 */1671 pVM->vmm.s.fSwitcherDisabled = true;1672 return VINF_SUCCESS;1673 }1674 1675 1676 /**1677 * Resolve a builtin GC symbol.1678 * Called by PDM when loading or relocating GC modules.1679 *1680 * @returns VBox status1681 * @param pVM VM Handle.1682 * @param pszSymbol Symbol to resolv1683 * @param pGCPtrValue Where to store the symbol value.1684 * @remark This has to work before VMMR3Relocate() is called.1685 */1686 VMMR3DECL(int) VMMR3GetImportGC(PVM pVM, const char *pszSymbol, PRTGCPTR pGCPtrValue)1687 {1688 if (!strcmp(pszSymbol, "g_Logger"))1689 {1690 if (pVM->vmm.s.pLoggerHC)1691 pVM->vmm.s.pLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pLoggerHC);1692 *pGCPtrValue = pVM->vmm.s.pLoggerGC;1693 }1694 else if (!strcmp(pszSymbol, "g_RelLogger"))1695 {1696 #ifdef VBOX_WITH_RC_RELEASE_LOGGING1697 if (pVM->vmm.s.pRelLoggerHC)1698 pVM->vmm.s.pRelLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pRelLoggerHC);1699 *pGCPtrValue = pVM->vmm.s.pRelLoggerGC;1700 #else1701 *pGCPtrValue = NIL_RTGCPTR;1702 #endif1703 }1704 else1705 return VERR_SYMBOL_NOT_FOUND;1706 return VINF_SUCCESS;1707 }1708 1709 1710 /**1711 * Suspends the the CPU yielder.1712 *1713 * @param pVM The VM handle.1714 */1715 VMMR3DECL(void) VMMR3YieldSuspend(PVM pVM)1716 {1717 if (!pVM->vmm.s.cYieldResumeMillies)1718 {1719 uint64_t u64Now = TMTimerGet(pVM->vmm.s.pYieldTimer);1720 uint64_t u64Expire = TMTimerGetExpire(pVM->vmm.s.pYieldTimer);1721 if (u64Now >= u64Expire || u64Expire == ~(uint64_t)0)1722 pVM->vmm.s.cYieldResumeMillies = pVM->vmm.s.cYieldEveryMillies;1723 else1724 pVM->vmm.s.cYieldResumeMillies = TMTimerToMilli(pVM->vmm.s.pYieldTimer, u64Expire - u64Now);1725 TMTimerStop(pVM->vmm.s.pYieldTimer);1726 }1727 pVM->vmm.s.u64LastYield = RTTimeNanoTS();1728 }1729 1730 1731 /**1732 * Stops the the CPU yielder.1733 *1734 * @param pVM The VM handle.1735 */1736 VMMR3DECL(void) VMMR3YieldStop(PVM pVM)1737 {1738 if (!pVM->vmm.s.cYieldResumeMillies)1739 TMTimerStop(pVM->vmm.s.pYieldTimer);1740 pVM->vmm.s.cYieldResumeMillies = pVM->vmm.s.cYieldEveryMillies;1741 pVM->vmm.s.u64LastYield = RTTimeNanoTS();1742 }1743 1744 1745 /**1746 * Resumes the CPU yielder when it has been a suspended or stopped.1747 *1748 * @param pVM The VM handle.1749 */1750 VMMR3DECL(void) VMMR3YieldResume(PVM pVM)1751 {1752 if (pVM->vmm.s.cYieldResumeMillies)1753 {1754 TMTimerSetMillies(pVM->vmm.s.pYieldTimer, pVM->vmm.s.cYieldResumeMillies);1755 pVM->vmm.s.cYieldResumeMillies = 0;1756 }1757 }1758 1759 1760 /**1761 * Internal timer callback function.1762 *1763 * @param pVM The VM.1764 * @param pTimer The timer handle.1765 * @param pvUser User argument specified upon timer creation.1766 */1767 static DECLCALLBACK(void) vmmR3YieldEMT(PVM pVM, PTMTIMER pTimer, void *pvUser)1768 {1769 /*1770 * This really needs some careful tuning. While we shouldn't be too gready since1771 * that'll cause the rest of the system to stop up, we shouldn't be too nice either1772 * because that'll cause us to stop up.1773 *1774 * The current logic is to use the default interval when there is no lag worth1775 * mentioning, but when we start accumulating lag we don't bother yielding at all.1776 *1777 * (This depends on the TMCLOCK_VIRTUAL_SYNC to be scheduled before TMCLOCK_REAL1778 * so the lag is up to date.)1779 */1780 const uint64_t u64Lag = TMVirtualSyncGetLag(pVM);1781 if ( u64Lag < 50000000 /* 50ms */1782 || ( u64Lag < 1000000000 /* 1s */1783 && RTTimeNanoTS() - pVM->vmm.s.u64LastYield < 500000000 /* 500 ms */)1784 )1785 {1786 uint64_t u64Elapsed = RTTimeNanoTS();1787 pVM->vmm.s.u64LastYield = u64Elapsed;1788 1789 RTThreadYield();1790 1791 #ifdef LOG_ENABLED1792 u64Elapsed = RTTimeNanoTS() - u64Elapsed;1793 Log(("vmmR3YieldEMT: %RI64 ns\n", u64Elapsed));1794 #endif1795 }1796 TMTimerSetMillies(pTimer, pVM->vmm.s.cYieldEveryMillies);1797 }1798 1799 1800 /**1801 * Acquire global VM lock.1802 *1803 * @returns VBox status code1804 * @param pVM The VM to operate on.1805 */1806 VMMR3DECL(int) VMMR3Lock(PVM pVM)1807 {1808 return RTCritSectEnter(&pVM->vmm.s.CritSectVMLock);1809 }1810 1811 1812 /**1813 * Release global VM lock.1814 *1815 * @returns VBox status code1816 * @param pVM The VM to operate on.1817 */1818 VMMR3DECL(int) VMMR3Unlock(PVM pVM)1819 {1820 return RTCritSectLeave(&pVM->vmm.s.CritSectVMLock);1821 }1822 1823 1824 /**1825 * Return global VM lock owner.1826 *1827 * @returns Thread id of owner.1828 * @returns NIL_RTTHREAD if no owner.1829 * @param pVM The VM to operate on.1830 */1831 VMMR3DECL(RTNATIVETHREAD) VMMR3LockGetOwner(PVM pVM)1832 {1833 return RTCritSectGetOwner(&pVM->vmm.s.CritSectVMLock);1834 }1835 1836 1837 /**1838 * Checks if the current thread is the owner of the global VM lock.1839 *1840 * @returns true if owner.1841 * @returns false if not owner.1842 * @param pVM The VM to operate on.1843 */1844 VMMR3DECL(bool) VMMR3LockIsOwner(PVM pVM)1845 {1846 return RTCritSectIsOwner(&pVM->vmm.s.CritSectVMLock);1847 }1848 1849 1850 /**1851 * Executes guest code.1852 *1853 * @param pVM VM handle.1854 */1855 VMMR3DECL(int) VMMR3RawRunGC(PVM pVM)1856 {1857 Log2(("VMMR3RawRunGC: (cs:eip=%04x:%08x)\n", CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));1858 1859 /*1860 * Set the EIP and ESP.1861 */1862 CPUMSetHyperEIP(pVM, CPUMGetGuestEFlags(pVM) & X86_EFL_VM1863 ? pVM->vmm.s.pfnCPUMGCResumeGuestV861864 : pVM->vmm.s.pfnCPUMGCResumeGuest);1865 CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom);1866 1867 /*1868 * We hide log flushes (outer) and hypervisor interrupts (inner).1869 */1870 for (;;)1871 {1872 int rc;1873 do1874 {1875 #ifdef NO_SUPCALLR0VMM1876 rc = VERR_GENERAL_FAILURE;1877 #else1878 rc = SUPCallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN);1879 if (RT_LIKELY(rc == VINF_SUCCESS))1880 rc = pVM->vmm.s.iLastGCRc;1881 #endif1882 } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);1883 1884 /*1885 * Flush the logs.1886 */1887 #ifdef LOG_ENABLED1888 PRTLOGGERRC pLogger = pVM->vmm.s.pLoggerHC;1889 if ( pLogger1890 && pLogger->offScratch > 0)1891 RTLogFlushGC(NULL, pLogger);1892 #endif1893 #ifdef VBOX_WITH_RC_RELEASE_LOGGING1894 PRTLOGGERRC pRelLogger = pVM->vmm.s.pRelLoggerHC;1895 if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))1896 RTLogFlushGC(RTLogRelDefaultInstance(), pRelLogger);1897 #endif1898 if (rc != VINF_VMM_CALL_HOST)1899 {1900 Log2(("VMMR3RawRunGC: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));1901 return rc;1902 }1903 rc = vmmR3ServiceCallHostRequest(pVM);1904 if (VBOX_FAILURE(rc))1905 return rc;1906 /* Resume GC */1907 }1908 }1909 1910 1911 /**1912 * Executes guest code (Intel VT-x and AMD-V).1913 *1914 * @param pVM VM handle.1915 */1916 VMMR3DECL(int) VMMR3HwAccRunGC(PVM pVM)1917 {1918 Log2(("VMMR3HwAccRunGC: (cs:eip=%04x:%08x)\n", CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));1919 1920 for (;;)1921 {1922 int rc;1923 do1924 {1925 #ifdef NO_SUPCALLR0VMM1926 rc = VERR_GENERAL_FAILURE;1927 #else1928 rc = SUPCallVMMR0Fast(pVM->pVMR0, VMMR0_DO_HWACC_RUN);1929 if (RT_LIKELY(rc == VINF_SUCCESS))1930 rc = pVM->vmm.s.iLastGCRc;1931 #endif1932 } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);1933 1934 #ifdef LOG_ENABLED1935 /*1936 * Flush the log1937 */1938 PVMMR0LOGGER pR0Logger = pVM->vmm.s.pR0Logger;1939 if ( pR0Logger1940 && pR0Logger->Logger.offScratch > 0)1941 RTLogFlushToLogger(&pR0Logger->Logger, NULL);1942 #endif /* !LOG_ENABLED */1943 if (rc != VINF_VMM_CALL_HOST)1944 {1945 Log2(("VMMR3HwAccRunGC: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));1946 return rc;1947 }1948 rc = vmmR3ServiceCallHostRequest(pVM);1949 if (VBOX_FAILURE(rc) || rc == VINF_EM_DBG_HYPER_ASSERTION)1950 return rc;1951 /* Resume R0 */1952 }1953 }1954 1955 /**1956 * Calls GC a function.1957 *1958 * @param pVM The VM handle.1959 * @param GCPtrEntry The GC function address.1960 * @param cArgs The number of arguments in the ....1961 * @param ... Arguments to the function.1962 */1963 VMMR3DECL(int) VMMR3CallGC(PVM pVM, RTRCPTR GCPtrEntry, unsigned cArgs, ...)1964 {1965 va_list args;1966 va_start(args, cArgs);1967 int rc = VMMR3CallGCV(pVM, GCPtrEntry, cArgs, args);1968 va_end(args);1969 return rc;1970 }1971 1972 1973 /**1974 * Calls GC a function.1975 *1976 * @param pVM The VM handle.1977 * @param GCPtrEntry The GC function address.1978 * @param cArgs The number of arguments in the ....1979 * @param args Arguments to the function.1980 */1981 VMMR3DECL(int) VMMR3CallGCV(PVM pVM, RTRCPTR GCPtrEntry, unsigned cArgs, va_list args)1982 {1983 Log2(("VMMR3CallGCV: GCPtrEntry=%VRv cArgs=%d\n", GCPtrEntry, cArgs));1984 1985 /*1986 * Setup the call frame using the trampoline.1987 */1988 CPUMHyperSetCtxCore(pVM, NULL);1989 memset(pVM->vmm.s.pbHCStack, 0xaa, VMM_STACK_SIZE); /* Clear the stack. */1990 CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom - cArgs * sizeof(RTGCUINTPTR32));1991 PRTGCUINTPTR32 pFrame = (PRTGCUINTPTR32)(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE) - cArgs;1992 int i = cArgs;1993 while (i-- > 0)1994 *pFrame++ = va_arg(args, RTGCUINTPTR32);1995 1996 CPUMPushHyper(pVM, cArgs * sizeof(RTGCUINTPTR32)); /* stack frame size */1997 CPUMPushHyper(pVM, GCPtrEntry); /* what to call */1998 CPUMSetHyperEIP(pVM, pVM->vmm.s.pfnGCCallTrampoline);1999 2000 /*2001 * We hide log flushes (outer) and hypervisor interrupts (inner).2002 */2003 for (;;)2004 {2005 int rc;2006 do2007 {2008 #ifdef NO_SUPCALLR0VMM2009 rc = VERR_GENERAL_FAILURE;2010 #else2011 rc = SUPCallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN);2012 if (RT_LIKELY(rc == VINF_SUCCESS))2013 rc = pVM->vmm.s.iLastGCRc;2014 #endif2015 } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);2016 2017 /*2018 * Flush the logs.2019 */2020 #ifdef LOG_ENABLED2021 PRTLOGGERRC pLogger = pVM->vmm.s.pLoggerHC;2022 if ( pLogger2023 && pLogger->offScratch > 0)2024 RTLogFlushGC(NULL, pLogger);2025 #endif2026 #ifdef VBOX_WITH_RC_RELEASE_LOGGING2027 PRTLOGGERRC pRelLogger = pVM->vmm.s.pRelLoggerHC;2028 if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))2029 RTLogFlushGC(RTLogRelDefaultInstance(), pRelLogger);2030 #endif2031 if (rc == VERR_TRPM_PANIC || rc == VERR_TRPM_DONT_PANIC)2032 VMMR3FatalDump(pVM, rc);2033 if (rc != VINF_VMM_CALL_HOST)2034 {2035 Log2(("VMMR3CallGCV: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));2036 return rc;2037 }2038 rc = vmmR3ServiceCallHostRequest(pVM);2039 if (VBOX_FAILURE(rc))2040 return rc;2041 }2042 }2043 2044 2045 /**2046 * Resumes executing hypervisor code when interrupted2047 * by a queue flush or a debug event.2048 *2049 * @returns VBox status code.2050 * @param pVM VM handle.2051 */2052 VMMR3DECL(int) VMMR3ResumeHyper(PVM pVM)2053 {2054 Log(("VMMR3ResumeHyper: eip=%VGv esp=%VGv\n", CPUMGetHyperEIP(pVM), CPUMGetHyperESP(pVM)));2055 2056 /*2057 * We hide log flushes (outer) and hypervisor interrupts (inner).2058 */2059 for (;;)2060 {2061 int rc;2062 do2063 {2064 #ifdef NO_SUPCALLR0VMM2065 rc = VERR_GENERAL_FAILURE;2066 #else2067 rc = SUPCallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN);2068 if (RT_LIKELY(rc == VINF_SUCCESS))2069 rc = pVM->vmm.s.iLastGCRc;2070 #endif2071 } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);2072 2073 /*2074 * Flush the loggers,2075 */2076 #ifdef LOG_ENABLED2077 PRTLOGGERRC pLogger = pVM->vmm.s.pLoggerHC;2078 if ( pLogger2079 && pLogger->offScratch > 0)2080 RTLogFlushGC(NULL, pLogger);2081 #endif2082 #ifdef VBOX_WITH_RC_RELEASE_LOGGING2083 PRTLOGGERRC pRelLogger = pVM->vmm.s.pRelLoggerHC;2084 if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))2085 RTLogFlushGC(RTLogRelDefaultInstance(), pRelLogger);2086 #endif2087 if (rc == VERR_TRPM_PANIC || rc == VERR_TRPM_DONT_PANIC)2088 VMMR3FatalDump(pVM, rc);2089 if (rc != VINF_VMM_CALL_HOST)2090 {2091 Log(("VMMR3ResumeHyper: returns %Vrc\n", rc));2092 return rc;2093 }2094 rc = vmmR3ServiceCallHostRequest(pVM);2095 if (VBOX_FAILURE(rc))2096 return rc;2097 }2098 }2099 2100 2101 /**2102 * Service a call to the ring-3 host code.2103 *2104 * @returns VBox status code.2105 * @param pVM VM handle.2106 * @remark Careful with critsects.2107 */2108 static int vmmR3ServiceCallHostRequest(PVM pVM)2109 {2110 switch (pVM->vmm.s.enmCallHostOperation)2111 {2112 /*2113 * Acquire the PDM lock.2114 */2115 case VMMCALLHOST_PDM_LOCK:2116 {2117 pVM->vmm.s.rcCallHost = PDMR3LockCall(pVM);2118 break;2119 }2120 2121 /*2122 * Flush a PDM queue.2123 */2124 case VMMCALLHOST_PDM_QUEUE_FLUSH:2125 {2126 PDMR3QueueFlushWorker(pVM, NULL);2127 pVM->vmm.s.rcCallHost = VINF_SUCCESS;2128 break;2129 }2130 2131 /*2132 * Grow the PGM pool.2133 */2134 case VMMCALLHOST_PGM_POOL_GROW:2135 {2136 pVM->vmm.s.rcCallHost = PGMR3PoolGrow(pVM);2137 break;2138 }2139 2140 /*2141 * Maps an page allocation chunk into ring-3 so ring-0 can use it.2142 */2143 case VMMCALLHOST_PGM_MAP_CHUNK:2144 {2145 pVM->vmm.s.rcCallHost = PGMR3PhysChunkMap(pVM, pVM->vmm.s.u64CallHostArg);2146 break;2147 }2148 2149 /*2150 * Allocates more handy pages.2151 */2152 case VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES:2153 {2154 pVM->vmm.s.rcCallHost = PGMR3PhysAllocateHandyPages(pVM);2155 break;2156 }2157 #ifndef VBOX_WITH_NEW_PHYS_CODE2158 2159 case VMMCALLHOST_PGM_RAM_GROW_RANGE:2160 {2161 const RTGCPHYS GCPhys = pVM->vmm.s.u64CallHostArg;2162 pVM->vmm.s.rcCallHost = PGM3PhysGrowRange(pVM, &GCPhys);2163 break;2164 }2165 #endif2166 2167 /*2168 * Acquire the PGM lock.2169 */2170 case VMMCALLHOST_PGM_LOCK:2171 {2172 pVM->vmm.s.rcCallHost = PGMR3LockCall(pVM);2173 break;2174 }2175 2176 /*2177 * Flush REM handler notifications.2178 */2179 case VMMCALLHOST_REM_REPLAY_HANDLER_NOTIFICATIONS:2180 {2181 REMR3ReplayHandlerNotifications(pVM);2182 break;2183 }2184 2185 /*2186 * This is a noop. We just take this route to avoid unnecessary2187 * tests in the loops.2188 */2189 case VMMCALLHOST_VMM_LOGGER_FLUSH:2190 break;2191 2192 /*2193 * Set the VM error message.2194 */2195 case VMMCALLHOST_VM_SET_ERROR:2196 VMR3SetErrorWorker(pVM);2197 break;2198 2199 /*2200 * Set the VM runtime error message.2201 */2202 case VMMCALLHOST_VM_SET_RUNTIME_ERROR:2203 VMR3SetRuntimeErrorWorker(pVM);2204 break;2205 2206 /*2207 * Signal a ring 0 hypervisor assertion.2208 * Cancel the longjmp operation that's in progress.2209 */2210 case VMMCALLHOST_VM_R0_HYPER_ASSERTION:2211 pVM->vmm.s.enmCallHostOperation = VMMCALLHOST_INVALID;2212 pVM->vmm.s.CallHostR0JmpBuf.fInRing3Call = false;2213 #ifdef RT_ARCH_X862214 pVM->vmm.s.CallHostR0JmpBuf.eip = 0;2215 #else2216 pVM->vmm.s.CallHostR0JmpBuf.rip = 0;2217 #endif2218 LogRel((pVM->vmm.s.szRing0AssertMsg1));2219 LogRel((pVM->vmm.s.szRing0AssertMsg2));2220 return VINF_EM_DBG_HYPER_ASSERTION;2221 2222 default:2223 AssertMsgFailed(("enmCallHostOperation=%d\n", pVM->vmm.s.enmCallHostOperation));2224 return VERR_INTERNAL_ERROR;2225 }2226 2227 pVM->vmm.s.enmCallHostOperation = VMMCALLHOST_INVALID;2228 return VINF_SUCCESS;2229 }2230 2231 2232 2233 47 /** 2234 48 * Structure to pass to DBGFR3Info() and for doing all other … … 2252 66 bool fStdErr; 2253 67 } VMMR3FATALDUMPINFOHLP, *PVMMR3FATALDUMPINFOHLP; 68 /** Pointer to a VMMR3FATALDUMPINFOHLP structure. */ 2254 69 typedef const VMMR3FATALDUMPINFOHLP *PCVMMR3FATALDUMPINFOHLP; 2255 70 … … 2569 384 "!!\n" 2570 385 "%.*Vhxd\n", 2571 VMM_STACK_SIZE, (char *)pVM->vmm.s.pbHCStack);386 VMM_STACK_SIZE, pVM->vmm.s.pbEMTStackR3); 2572 387 } /* !HWACCMR3IsActive */ 2573 388 break; … … 2634 449 } 2635 450 2636 2637 2638 /**2639 * Displays the Force action Flags.2640 *2641 * @param pVM The VM handle.2642 * @param pHlp The output helpers.2643 * @param pszArgs The additional arguments (ignored).2644 */2645 static DECLCALLBACK(void) vmmR3InfoFF(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)2646 {2647 const uint32_t fForcedActions = pVM->fForcedActions;2648 2649 pHlp->pfnPrintf(pHlp, "Forced action Flags: %#RX32", fForcedActions);2650 2651 /* show the flag mnemonics */2652 int c = 0;2653 uint32_t f = fForcedActions;2654 #define PRINT_FLAG(flag) do { \2655 if (f & (flag)) \2656 { \2657 static const char *s_psz = #flag; \2658 if (!(c % 6)) \2659 pHlp->pfnPrintf(pHlp, "%s\n %s", c ? "," : "", s_psz + 6); \2660 else \2661 pHlp->pfnPrintf(pHlp, ", %s", s_psz + 6); \2662 c++; \2663 f &= ~(flag); \2664 } \2665 } while (0)2666 PRINT_FLAG(VM_FF_INTERRUPT_APIC);2667 PRINT_FLAG(VM_FF_INTERRUPT_PIC);2668 PRINT_FLAG(VM_FF_TIMER);2669 PRINT_FLAG(VM_FF_PDM_QUEUES);2670 PRINT_FLAG(VM_FF_PDM_DMA);2671 PRINT_FLAG(VM_FF_PDM_CRITSECT);2672 PRINT_FLAG(VM_FF_DBGF);2673 PRINT_FLAG(VM_FF_REQUEST);2674 PRINT_FLAG(VM_FF_TERMINATE);2675 PRINT_FLAG(VM_FF_RESET);2676 PRINT_FLAG(VM_FF_PGM_SYNC_CR3);2677 PRINT_FLAG(VM_FF_PGM_SYNC_CR3_NON_GLOBAL);2678 PRINT_FLAG(VM_FF_TRPM_SYNC_IDT);2679 PRINT_FLAG(VM_FF_SELM_SYNC_TSS);2680 PRINT_FLAG(VM_FF_SELM_SYNC_GDT);2681 PRINT_FLAG(VM_FF_SELM_SYNC_LDT);2682 PRINT_FLAG(VM_FF_INHIBIT_INTERRUPTS);2683 PRINT_FLAG(VM_FF_CSAM_SCAN_PAGE);2684 PRINT_FLAG(VM_FF_CSAM_PENDING_ACTION);2685 PRINT_FLAG(VM_FF_TO_R3);2686 PRINT_FLAG(VM_FF_DEBUG_SUSPEND);2687 if (f)2688 pHlp->pfnPrintf(pHlp, "%s\n Unknown bits: %#RX32\n", c ? "," : "", f);2689 else2690 pHlp->pfnPrintf(pHlp, "\n");2691 #undef PRINT_FLAG2692 2693 /* the groups */2694 c = 0;2695 #define PRINT_GROUP(grp) do { \2696 if (fForcedActions & (grp)) \2697 { \2698 static const char *s_psz = #grp; \2699 if (!(c % 5)) \2700 pHlp->pfnPrintf(pHlp, "%s %s", c ? ",\n" : "Groups:\n", s_psz + 6); \2701 else \2702 pHlp->pfnPrintf(pHlp, ", %s", s_psz + 6); \2703 c++; \2704 } \2705 } while (0)2706 PRINT_GROUP(VM_FF_EXTERNAL_SUSPENDED_MASK);2707 PRINT_GROUP(VM_FF_EXTERNAL_HALTED_MASK);2708 PRINT_GROUP(VM_FF_HIGH_PRIORITY_PRE_MASK);2709 PRINT_GROUP(VM_FF_HIGH_PRIORITY_PRE_RAW_MASK);2710 PRINT_GROUP(VM_FF_HIGH_PRIORITY_POST_MASK);2711 PRINT_GROUP(VM_FF_NORMAL_PRIORITY_POST_MASK);2712 PRINT_GROUP(VM_FF_NORMAL_PRIORITY_MASK);2713 PRINT_GROUP(VM_FF_RESUME_GUEST_MASK);2714 PRINT_GROUP(VM_FF_ALL_BUT_RAW_MASK);2715 if (c)2716 pHlp->pfnPrintf(pHlp, "\n");2717 #undef PRINT_GROUP2718 }2719 -
trunk/src/VBox/VMM/VMMInternal.h
r13697 r13698 206 206 #endif 207 207 208 /** VMM stack, pointer to the top of the stack in HC.208 /** VMM stack, pointer to the top of the stack in R3. 209 209 * Stack is allocated from the hypervisor heap and is page aligned 210 * and always writable in GC. */211 R3PTRTYPE(uint8_t *) pb HCStack;210 * and always writable in RC. */ 211 R3PTRTYPE(uint8_t *) pbEMTStackR3; 212 212 /** Pointer to the bottom of the stack - needed for doing relocations. */ 213 RCPTRTYPE(uint8_t *) pb GCStack;213 RCPTRTYPE(uint8_t *) pbEMTStackRC; 214 214 /** Pointer to the bottom of the stack - needed for doing relocations. */ 215 RCPTRTYPE(uint8_t *) pb GCStackBottom;215 RCPTRTYPE(uint8_t *) pbEMTStackBottomRC; 216 216 217 217 /** Pointer to the GC logger instance - GC Ptr. -
trunk/src/VBox/VMM/VMMTests.cpp
r13532 r13698 62 62 63 63 CPUMHyperSetCtxCore(pVM, NULL); 64 memset(pVM->vmm.s.pb HCStack, 0xaa, VMM_STACK_SIZE);65 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStackBottom); /* Clear the stack. */64 memset(pVM->vmm.s.pbEMTStackR3, 0xaa, VMM_STACK_SIZE); 65 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */ 66 66 CPUMPushHyper(pVM, uVariation); 67 67 CPUMPushHyper(pVM, enmTestcase); … … 99 99 100 100 CPUMHyperSetCtxCore(pVM, NULL); 101 memset(pVM->vmm.s.pb HCStack, 0xaa, VMM_STACK_SIZE);102 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStackBottom); /* Clear the stack. */101 memset(pVM->vmm.s.pbEMTStackR3, 0xaa, VMM_STACK_SIZE); 102 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */ 103 103 CPUMPushHyper(pVM, uVariation); 104 104 CPUMPushHyper(pVM, u8Trap + VMMGC_DO_TESTCASE_TRAP_FIRST); … … 334 334 */ 335 335 CPUMHyperSetCtxCore(pVM, NULL); 336 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStackBottom); /* Clear the stack. */336 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */ 337 337 CPUMPushHyper(pVM, 0); 338 338 CPUMPushHyper(pVM, VMMGC_DO_TESTCASE_HYPER_INTERRUPT); … … 396 396 { 397 397 CPUMHyperSetCtxCore(pVM, NULL); 398 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStackBottom); /* Clear the stack. */398 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */ 399 399 CPUMPushHyper(pVM, 0); 400 400 CPUMPushHyper(pVM, VMMGC_DO_TESTCASE_NOP); … … 523 523 CPUMHyperSetCtxCore(pVM, NULL); 524 524 525 CPUMSetHyperESP(pVM, pVM->vmm.s.pb GCStackBottom); /* Clear the stack. */525 CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */ 526 526 CPUMPushHyper(pVM, 0); 527 527 CPUMPushHyper(pVM, VMMGC_DO_TESTCASE_HWACCM_NOP); -
trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp
r13633 r13698 838 838 GEN_CHECK_OFF(VMM, pfnCPUMGCResumeGuestV86); 839 839 GEN_CHECK_OFF(VMM, iLastGCRc); 840 GEN_CHECK_OFF(VMM, pb HCStack);841 GEN_CHECK_OFF(VMM, pb GCStack);842 GEN_CHECK_OFF(VMM, pb GCStackBottom);840 GEN_CHECK_OFF(VMM, pbEMTStackR3); 841 GEN_CHECK_OFF(VMM, pbEMTStackRC); 842 GEN_CHECK_OFF(VMM, pbEMTStackBottomRC); 843 843 GEN_CHECK_OFF(VMM, pLoggerGC); 844 844 GEN_CHECK_OFF(VMM, pLoggerHC);
Note:
See TracChangeset
for help on using the changeset viewer.