VirtualBox

Changeset 13381 in vbox for trunk/src


Ignore:
Timestamp:
Oct 17, 2008 8:40:48 PM (16 years ago)
Author:
vboxsync
Message:

EM: experimental fix for #DE loop during ubuntu boot w/ busted apic: Check for CPL=0 traps in patch code and hand them on to emR3PatchTrap.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/EM.cpp

    r13375 r13381  
    9898static int emR3ForcedActions(PVM pVM, int rc);
    9999static int emR3RawGuestTrap(PVM pVM);
     100static int emR3PatchTrap(PVM pVM, PCPUMCTX pCtx, int gcret);
    100101
    101102
     
    14301431    }
    14311432
    1432     /* Traps can be directly forwarded in hardware accelerated mode. */
     1433    /*
     1434     * Traps can be directly forwarded in hardware accelerated mode.
     1435     */
    14331436    if (HWACCMR3IsActive(pVM))
    14341437    {
     
    14401443    }
    14411444
    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? */
    14431497    if (    (pCtx->ss & X86_SEL_RPL) <= 1
    14441498        &&  !pCtx->eflags.Bits.u1VM)
     
    14481502    }
    14491503
     1504    /*
     1505     * Trap specific handling.
     1506     */
    14501507    if (u8TrapNo == 6) /* (#UD) Invalid opcode. */
    14511508    {
     1509        /*
     1510         * If MONITOR & MWAIT are supported, then interpret them here.
     1511         */
    14521512        DISCPUSTATE cpu;
    1453 
    1454         /* If MONITOR & MWAIT are supported, then interpret them here. */
    14551513        rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->rip, &cpu, "Guest Trap (#UD): ");
    14561514        if (    VBOX_SUCCESS(rc)
    14571515            && (cpu.pCurInstr->opcode == OP_MONITOR || cpu.pCurInstr->opcode == OP_MWAIT))
    14581516        {
    1459             uint32_t u32Dummy, u32Features, u32ExtFeatures, size;
    1460 
     1517            uint32_t u32Dummy, u32Features, u32ExtFeatures;
    14611518            CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Features);
    1462 
    14631519            if (u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR)
    14641520            {
     
    14661522                AssertRC(rc);
    14671523
    1468                 rc = EMInterpretInstructionCPU(pVM, &cpu, CPUMCTX2CORE(pCtx), 0, &size);
     1524                uint32_t opsize;
     1525                rc = EMInterpretInstructionCPU(pVM, &cpu, CPUMCTX2CORE(pCtx), 0, &opsize);
    14691526                if (VBOX_SUCCESS(rc))
    14701527                {
     
    14781535    else if (u8TrapNo == 13) /* (#GP) Privileged exception */
    14791536    {
     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.  */
    14801542        DISCPUSTATE cpu;
    1481 
    14821543        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))
    14841546        {
    14851547            /*
     
    15761638}
    15771639
     1640
    15781641/**
    15791642 * Handle a trap (\#PF or \#GP) in patch code
     
    15841647 * @param   gcret   GC return code
    15851648 */
    1586 int emR3PatchTrap(PVM pVM, PCPUMCTX pCtx, int gcret)
     1649static int emR3PatchTrap(PVM pVM, PCPUMCTX pCtx, int gcret)
    15871650{
    15881651    uint8_t         u8TrapNo;
     
    20942157                break;
    20952158            }
    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             }
    21332159            rc = emR3RawGuestTrap(pVM);
    21342160            break;
     
    22192245        case VINF_EM_RAW_INTERRUPT_PENDING:
    22202246        case VINF_EM_RAW_RING_SWITCH_INT:
    2221         {
    2222             uint8_t u8Interrupt;
    2223 
    22242247            Assert(TRPMHasTrap(pVM));
    22252248            Assert(!PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip));
     
    22272250            if (TRPMHasTrap(pVM))
    22282251            {
    2229                 u8Interrupt = TRPMGetTrapNo(pVM);
    2230 
    22312252                /* If the guest gate is marked unpatched, then we will check again if we can patch it. */
     2253                uint8_t u8Interrupt = TRPMGetTrapNo(pVM);
    22322254                if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER)
    22332255                {
     
    22392261            rc = VINF_EM_RESCHEDULE_REM;
    22402262            break;
    2241         }
    22422263
    22432264        /*
Note: See TracChangeset for help on using the changeset viewer.

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