- Timestamp:
- Oct 17, 2008 8:40:48 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/EM.cpp
r13375 r13381 98 98 static int emR3ForcedActions(PVM pVM, int rc); 99 99 static int emR3RawGuestTrap(PVM pVM); 100 static int emR3PatchTrap(PVM pVM, PCPUMCTX pCtx, int gcret); 100 101 101 102 … … 1430 1431 } 1431 1432 1432 /* Traps can be directly forwarded in hardware accelerated mode. */ 1433 /* 1434 * Traps can be directly forwarded in hardware accelerated mode. 1435 */ 1433 1436 if (HWACCMR3IsActive(pVM)) 1434 1437 { … … 1440 1443 } 1441 1444 1442 /** Scan kernel code that traps; we might not get another chance. */ 1445 #if 1 /* Experimental: Review, disable if it causes trouble. */ 1446 /* 1447 * Handle traps in patch code first. 1448 * 1449 * We catch a few of these cases in RC before returning to R3 (#PF, #GP, #BP) 1450 * but several traps isn't handled specially by TRPM in RC and we end up here 1451 * instead. One example is #DE. 1452 */ 1453 uint32_t uCpl = CPUMGetGuestCPL(pVM, CPUMCTX2CORE(pCtx)); 1454 if ( uCpl == 0 1455 && PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip)) 1456 { 1457 LogFlow(("emR3RawGuestTrap: trap %#x in patch code; eip=%08x\n", u8TrapNo, pCtx->eip)); 1458 return emR3PatchTrap(pVM, pCtx, rc); 1459 } 1460 #endif 1461 1462 /* 1463 * If the guest gate is marked unpatched, then we will check again if we can patch it. 1464 * (This assumes that we've already tried and failed to dispatch the trap in 1465 * RC for the gates that already has been patched. Which is true for most high 1466 * volume traps, because these are handled specially, but not for odd ones like #DE.) 1467 */ 1468 if (TRPMR3GetGuestTrapHandler(pVM, u8TrapNo) == TRPM_INVALID_HANDLER) 1469 { 1470 CSAMR3CheckGates(pVM, u8TrapNo, 1); 1471 Log(("emR3RawHandleRC: recheck gate %x -> valid=%d\n", u8TrapNo, TRPMR3GetGuestTrapHandler(pVM, u8TrapNo) != TRPM_INVALID_HANDLER)); 1472 1473 /* If it was successful, then we could go back to raw mode. */ 1474 if (TRPMR3GetGuestTrapHandler(pVM, u8TrapNo) != TRPM_INVALID_HANDLER) 1475 { 1476 /* Must check pending forced actions as our IDT or GDT might be out of sync. */ 1477 rc = EMR3CheckRawForcedActions(pVM); 1478 AssertRCReturn(rc, rc); 1479 1480 TRPMERRORCODE enmError = uErrorCode != ~0U 1481 ? TRPM_TRAP_HAS_ERRORCODE 1482 : TRPM_TRAP_NO_ERRORCODE; 1483 rc = TRPMForwardTrap(pVM, CPUMCTX2CORE(pCtx), u8TrapNo, uErrorCode, enmError, TRPM_TRAP, -1); 1484 if (rc == VINF_SUCCESS /* Don't use VBOX_SUCCESS */) 1485 { 1486 TRPMResetTrap(pVM); 1487 return VINF_EM_RESCHEDULE_RAW; 1488 } 1489 AssertMsg(rc == VINF_EM_RAW_GUEST_TRAP, ("%Rrc\n", rc)); 1490 } 1491 } 1492 1493 /* 1494 * Scan kernel code that traps; we might not get another chance. 1495 */ 1496 /** @todo move this up before the dispatching? */ 1443 1497 if ( (pCtx->ss & X86_SEL_RPL) <= 1 1444 1498 && !pCtx->eflags.Bits.u1VM) … … 1448 1502 } 1449 1503 1504 /* 1505 * Trap specific handling. 1506 */ 1450 1507 if (u8TrapNo == 6) /* (#UD) Invalid opcode. */ 1451 1508 { 1509 /* 1510 * If MONITOR & MWAIT are supported, then interpret them here. 1511 */ 1452 1512 DISCPUSTATE cpu; 1453 1454 /* If MONITOR & MWAIT are supported, then interpret them here. */1455 1513 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->rip, &cpu, "Guest Trap (#UD): "); 1456 1514 if ( VBOX_SUCCESS(rc) 1457 1515 && (cpu.pCurInstr->opcode == OP_MONITOR || cpu.pCurInstr->opcode == OP_MWAIT)) 1458 1516 { 1459 uint32_t u32Dummy, u32Features, u32ExtFeatures, size; 1460 1517 uint32_t u32Dummy, u32Features, u32ExtFeatures; 1461 1518 CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Features); 1462 1463 1519 if (u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR) 1464 1520 { … … 1466 1522 AssertRC(rc); 1467 1523 1468 rc = EMInterpretInstructionCPU(pVM, &cpu, CPUMCTX2CORE(pCtx), 0, &size); 1524 uint32_t opsize; 1525 rc = EMInterpretInstructionCPU(pVM, &cpu, CPUMCTX2CORE(pCtx), 0, &opsize); 1469 1526 if (VBOX_SUCCESS(rc)) 1470 1527 { … … 1478 1535 else if (u8TrapNo == 13) /* (#GP) Privileged exception */ 1479 1536 { 1537 /* 1538 * Handle I/O bitmap? 1539 */ 1540 /** @todo We're not supposed to be here with a false guest trap concerning 1541 * I/O access. We can easily handle those in RC. */ 1480 1542 DISCPUSTATE cpu; 1481 1482 1543 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->rip, &cpu, "Guest Trap: "); 1483 if (VBOX_SUCCESS(rc) && (cpu.pCurInstr->optype & OPTYPE_PORTIO)) 1544 if ( VBOX_SUCCESS(rc) 1545 && (cpu.pCurInstr->optype & OPTYPE_PORTIO)) 1484 1546 { 1485 1547 /* … … 1576 1638 } 1577 1639 1640 1578 1641 /** 1579 1642 * Handle a trap (\#PF or \#GP) in patch code … … 1584 1647 * @param gcret GC return code 1585 1648 */ 1586 int emR3PatchTrap(PVM pVM, PCPUMCTX pCtx, int gcret)1649 static int emR3PatchTrap(PVM pVM, PCPUMCTX pCtx, int gcret) 1587 1650 { 1588 1651 uint8_t u8TrapNo; … … 2094 2157 break; 2095 2158 } 2096 2097 Assert(TRPMHasTrap(pVM));2098 Assert(!PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip));2099 2100 if (TRPMHasTrap(pVM))2101 {2102 uint8_t u8Interrupt;2103 RTGCUINT uErrorCode;2104 TRPMERRORCODE enmError = TRPM_TRAP_NO_ERRORCODE;2105 2106 rc = TRPMQueryTrapAll(pVM, &u8Interrupt, NULL, &uErrorCode, NULL);2107 AssertRC(rc);2108 2109 if (uErrorCode != ~0U)2110 enmError = TRPM_TRAP_HAS_ERRORCODE;2111 2112 /* If the guest gate is marked unpatched, then we will check again if we can patch it. */2113 if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER)2114 {2115 CSAMR3CheckGates(pVM, u8Interrupt, 1);2116 Log(("emR3RawHandleRC: recheck gate %x -> valid=%d\n", u8Interrupt, TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER));2117 2118 /** If it was successful, then we could go back to raw mode. */2119 if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER)2120 {2121 /* Must check pending forced actions as our IDT or GDT might be out of sync */2122 EMR3CheckRawForcedActions(pVM);2123 2124 rc = TRPMForwardTrap(pVM, CPUMCTX2CORE(pCtx), u8Interrupt, uErrorCode, enmError, TRPM_TRAP, -1);2125 if (rc == VINF_SUCCESS /* Don't use VBOX_SUCCESS */)2126 {2127 TRPMResetTrap(pVM);2128 return VINF_EM_RESCHEDULE_RAW;2129 }2130 }2131 }2132 }2133 2159 rc = emR3RawGuestTrap(pVM); 2134 2160 break; … … 2219 2245 case VINF_EM_RAW_INTERRUPT_PENDING: 2220 2246 case VINF_EM_RAW_RING_SWITCH_INT: 2221 {2222 uint8_t u8Interrupt;2223 2224 2247 Assert(TRPMHasTrap(pVM)); 2225 2248 Assert(!PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip)); … … 2227 2250 if (TRPMHasTrap(pVM)) 2228 2251 { 2229 u8Interrupt = TRPMGetTrapNo(pVM);2230 2231 2252 /* If the guest gate is marked unpatched, then we will check again if we can patch it. */ 2253 uint8_t u8Interrupt = TRPMGetTrapNo(pVM); 2232 2254 if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER) 2233 2255 { … … 2239 2261 rc = VINF_EM_RESCHEDULE_REM; 2240 2262 break; 2241 }2242 2263 2243 2264 /*
Note:
See TracChangeset
for help on using the changeset viewer.