VirtualBox

Changeset 347 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jan 26, 2007 9:36:22 AM (18 years ago)
Author:
vboxsync
Message:

Rewrote and simplified interrupt handler patching.

Location:
trunk/src/VBox/VMM
Files:
8 edited

Legend:

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

    r318 r347  
    20582058                break;
    20592059            }
     2060            uint8_t u8Interrupt;
     2061
     2062            Assert(TRPMHasTrap(pVM));
     2063            Assert(!PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip));
     2064
     2065            if (TRPMHasTrap(pVM))
     2066            {
     2067                u8Interrupt = TRPMGetTrapNo(pVM);
     2068
     2069                /* If the guest gate is marked unpatched, then we will check again if we can patch it. */
     2070                if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER)
     2071                {
     2072                    CSAMR3CheckGates(pVM, u8Interrupt, 1);
     2073                    Log(("emR3RawHandleRC: recheck gate %x -> valid=%d\n", u8Interrupt, TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER));
     2074                    /** @note If it was successful, then we could go back to raw mode, but let's keep things simple for now. */
     2075                }
     2076            }
    20602077            rc = emR3RawGuestTrap(pVM);
    20612078            break;
     
    21352152         */
    21362153        case VINF_EM_RAW_INTERRUPT_PENDING:
     2154        case VINF_EM_RAW_RING_SWITCH_INT:
    21372155        {
    21382156            uint8_t u8Interrupt;
     
    21452163                u8Interrupt = TRPMGetTrapNo(pVM);
    21462164
    2147                 /* If the guest gate is marked dirty, then we will check again if we can patch it. */
    2148                 if (TRPMR3IsGuestTrapHandlerDirty(pVM, u8Interrupt))
     2165                /* If the guest gate is marked unpatched, then we will check again if we can patch it. */
     2166                if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER)
    21492167                {
    2150                     Assert(TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER);
    21512168                    CSAMR3CheckGates(pVM, u8Interrupt, 1);
    21522169                    Log(("emR3RawHandleRC: recheck gate %x -> valid=%d\n", u8Interrupt, TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER));
     
    21572174            break;
    21582175        }
    2159 
    2160         case VINF_EM_RAW_RING_SWITCH_INT:
    2161             rc = VINF_EM_RESCHEDULE_REM;
    2162             break;
    21632176
    21642177        /*
  • trunk/src/VBox/VMM/PATM/CSAM.cpp

    r209 r347  
    216216    pVM->csam.s.fScanningStarted = false;
    217217
    218     memset(&pVM->csam.s.aIDT[0], 0, sizeof(pVM->csam.s.aIDT));
    219 
    220218    VM_FF_CLEAR(pVM, VM_FF_CSAM_FLUSH_DIRTY_PAGE);
    221219    pVM->csam.s.cDirtyPages = 0;
     
    454452    memcpy(pVM->csam.s.pvDirtyBasePage,  csamInfo.pvDirtyBasePage, sizeof(pVM->csam.s.pvDirtyBasePage));
    455453    memcpy(pVM->csam.s.pvDirtyFaultPage, csamInfo.pvDirtyFaultPage, sizeof(pVM->csam.s.pvDirtyFaultPage));
    456 
    457     /* Restore IDT gate info. */
    458     memcpy(&pVM->csam.s.aIDT[0], &csamInfo.aIDT[0], sizeof(pVM->csam.s.aIDT));
    459454
    460455    /* Restore pgdir bitmap (we'll change the pointers next). */
     
    21612156    }
    21622157
     2158    /* We only check all gates once during a session */
     2159    if (    !pVM->csam.s.fGatesChecked
     2160        &&   cGates != 256)
     2161        return VINF_SUCCESS;    /* too early */
     2162
     2163    /* We only check all gates once during a session */
     2164    if (    pVM->csam.s.fGatesChecked
     2165        &&  cGates != 1)
     2166        return VINF_SUCCESS;    /* ignored */
     2167
     2168    if (cGates != 1)
     2169        pVM->csam.s.fGatesChecked = true;
     2170
    21632171    Assert(GCPtrIDT && cGates <= 256);
    21642172    if (!GCPtrIDT || cGates > 256)
     
    22082216    for (/*iGate*/; iGate<iGateEnd; iGate++, pGuestIdte++)
    22092217    {
    2210         if (    pVM->csam.s.fGatesChecked
    2211             &&  cGates != 1                 /* applies only when we check the entire IDT */
    2212             &&  pGuestIdte->au64 != pVM->csam.s.aIDT[iGate].au64)
    2213         {
    2214             /* We can't check the contents here, as it might only have been partially modified at this point.
    2215              * TRPMR3InjectEvent will recheck if necessary.
    2216              */
    2217 #ifdef DEBUG
    2218             RTGCPTR pHandler = (pGuestIdte->Gen.u16OffsetHigh << 16) | pGuestIdte->Gen.u16OffsetLow;
    2219 
    2220             Log2(("IDT entry %x with handler %VGv refused (1)\n", iGate, pHandler));
    2221 #endif
    2222             TRPMR3SetGuestTrapHandler(pVM, iGate, TRPM_INVALID_HANDLER);
    2223             TRPMR3SetGuestTrapHandlerDirty(pVM, iGate, true);
    2224             continue;
    2225         }
    2226 
    2227         TRPMR3SetGuestTrapHandlerDirty(pVM, iGate, false);
     2218        Assert(TRPMR3GetGuestTrapHandler(pVM, iGate) == TRPM_INVALID_HANDLER);
    22282219
    22292220        if (    pGuestIdte->Gen.u1Present
    22302221            &&  (pGuestIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_TRAP_32 || pGuestIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32)
    22312222            &&  (pGuestIdte->Gen.u2DPL == 3 || pGuestIdte->Gen.u2DPL == 0)
    2232             &&  pGuestIdte->au64 != pVM->csam.s.aIDT[iGate].au64
    22332223           )
    22342224        {
     
    22362226            CSAMP2GLOOKUPREC cacheRec = {0};            /* Cache record for PATMGCVirtToHCVirt. */
    22372227            PCSAMPAGE pPage = NULL;
    2238 
    2239             /* Save a copy */
    2240             pVM->csam.s.aIDT[iGate].au64 = pGuestIdte->au64;
    2241 
    2242             /*
    2243              * Assume it's not safe.
    2244              */
    2245             TRPMR3SetGuestTrapHandler(pVM, iGate, TRPM_INVALID_HANDLER);
    22462228
    22472229            pHandler = (pGuestIdte->Gen.u16OffsetHigh << 16) | pGuestIdte->Gen.u16OffsetLow;
     
    22632245            {
    22642246                Log(("CSAMCheckGates: csamAnalyseCodeStream failed with %d\n", rc));
     2247                continue;
    22652248            }
     2249            if (iGate >= 0x20)
     2250            {
     2251                /* OpenBSD guest specific patch test (3.7 & 3.8) */
     2252                rc = PATMR3InstallPatch(pVM, pHandler - 3, PATMFL_CODE32 | PATMFL_GUEST_SPECIFIC);
     2253                if (VBOX_FAILURE(rc))
     2254                    /* OpenBSD guest specific patch test (3.9 & 4.0) */
     2255                    rc = PATMR3InstallPatch(pVM, pHandler - 0x2B, PATMFL_CODE32 | PATMFL_GUEST_SPECIFIC);
     2256                if (VBOX_SUCCESS(rc))
     2257                    Log(("Installed OpenBSD interrupt handler prefix instruction (push cs) patch\n"));
     2258            }
     2259
     2260            /* Trap gates and certain interrupt gates. */
     2261            uint32_t fPatchFlags = PATMFL_CODE32 | PATMFL_IDTHANDLER;
     2262
     2263            if (pGuestIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_TRAP_32)
     2264                fPatchFlags |= PATMFL_TRAPHANDLER;
    22662265            else
     2266                fPatchFlags |= PATMFL_INTHANDLER;
     2267
     2268            switch (iGate) {
     2269            case 8:
     2270            case 10:
     2271            case 11:
     2272            case 12:
     2273            case 13:
     2274            case 14:
     2275            case 17:
     2276                fPatchFlags |= PATMFL_TRAPHANDLER_WITH_ERRORCODE;
     2277                break;
     2278            default:
     2279                /* No error code. */
     2280                break;
     2281            }
     2282
     2283            Log(("Installing %s gate handler for 0x%X at %VGv\n", (pGuestIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_TRAP_32) ? "trap" : "intr", iGate, pHandler));
     2284
     2285            rc = PATMR3InstallPatch(pVM, pHandler, fPatchFlags);
     2286            if (VBOX_SUCCESS(rc) || rc == VERR_PATM_ALREADY_PATCHED)
    22672287            {
    2268                 if (iGate >= 0x20)
     2288                Log(("Gate handler 0x%X is SAFE!\n", iGate));
     2289
     2290                RTGCPTR pNewHandlerGC = PATMR3QueryPatchGCPtr(pVM, pHandler);
     2291                if (pNewHandlerGC)
    22692292                {
    2270                     /* OpenBSD guest specific patch test (3.7 & 3.8) */
    2271                     rc = PATMR3InstallPatch(pVM, pHandler - 3, PATMFL_CODE32 | PATMFL_GUEST_SPECIFIC);
     2293                    rc = TRPMR3SetGuestTrapHandler(pVM, iGate, pNewHandlerGC);
    22722294                    if (VBOX_FAILURE(rc))
    2273                         /* OpenBSD guest specific patch test (3.9 & 4.0) */
    2274                         rc = PATMR3InstallPatch(pVM, pHandler - 0x2B, PATMFL_CODE32 | PATMFL_GUEST_SPECIFIC);
    2275                     if (VBOX_SUCCESS(rc))
    2276                         Log(("Installed OpenBSD interrupt handler prefix instruction (push cs) patch\n"));
    2277                 }
    2278 
    2279                 /* Trap gates and certain interrupt gates. */
    2280                 uint32_t fPatchFlags = PATMFL_CODE32 | PATMFL_IDTHANDLER;
    2281 
    2282                 if (pGuestIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_TRAP_32)
    2283                     fPatchFlags |= PATMFL_TRAPHANDLER;
    2284                 else
    2285                     fPatchFlags |= PATMFL_INTHANDLER;
    2286 
    2287                 switch (iGate) {
    2288                 case 8:
    2289                 case 10:
    2290                 case 11:
    2291                 case 12:
    2292                 case 13:
    2293                 case 14:
    2294                 case 17:
    2295                     fPatchFlags |= PATMFL_TRAPHANDLER_WITH_ERRORCODE;
    2296                     break;
    2297                 default:
    2298                     /* No error code. */
    2299                     break;
    2300                 }
    2301 
    2302                 Log(("Installing %s gate handler for 0x%X at %VGv\n", (pGuestIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_TRAP_32) ? "trap" : "intr", iGate, pHandler));
    2303 
    2304                 rc = PATMR3InstallPatch(pVM, pHandler, fPatchFlags);
    2305                 if (VBOX_SUCCESS(rc) || rc == VERR_PATM_ALREADY_PATCHED)
    2306                 {
    2307                     RTGCPTR pNewHandlerGC;
    2308 
    2309                     Log(("Gate handler 0x%X is SAFE!\n", iGate));
    2310 
    2311                     pNewHandlerGC = PATMR3QueryPatchGCPtr(pVM, pHandler);
    2312                     if (pNewHandlerGC)
    2313                     {
    2314                         rc = TRPMR3SetGuestTrapHandler(pVM, iGate, pNewHandlerGC);
    2315                         if (VBOX_FAILURE(rc))
    2316                             Log(("TRPMR3SetGuestTrapHandler %d failed with %Vrc\n", iGate, rc));
    2317                     }
    2318                     else
    2319                         Assert(0);
     2295                        Log(("TRPMR3SetGuestTrapHandler %d failed with %Vrc\n", iGate, rc));
    23202296                }
    23212297            }
    23222298        }
    2323         else
    2324         if (pGuestIdte->au64 != pVM->csam.s.aIDT[iGate].au64)
    2325         {
    2326             /* Save a copy */
    2327             pVM->csam.s.aIDT[iGate].au64 = pGuestIdte->au64;
    2328 
    2329 #ifdef DEBUG
    2330             RTGCPTR pHandler = (pGuestIdte->Gen.u16OffsetHigh << 16) | pGuestIdte->Gen.u16OffsetLow;
    2331 
    2332             Log2(("IDT entry %x with handler %VGv refused (2)\n", iGate, pHandler));
    2333 #endif
    2334 
    2335             /*
    2336              * Everything is dangerous unless checked
    2337              */
    2338             TRPMR3SetGuestTrapHandler(pVM, iGate, TRPM_INVALID_HANDLER);
    2339         }
    2340 #ifdef DEBUG
    2341         else
    2342         if (TRPMR3GetGuestTrapHandler(pVM, iGate) == TRPM_INVALID_HANDLER)
    2343         {
    2344             RTGCPTR pHandler = (pGuestIdte->Gen.u16OffsetHigh << 16) | pGuestIdte->Gen.u16OffsetLow;
    2345 
    2346             Log2(("IDT entry %x with handler %VGv refused (3)\n", iGate, pHandler));
    2347         }
    2348 #endif
    2349     }
     2299    } /* for */
    23502300    STAM_PROFILE_STOP(&pVM->csam.s.StatCheckGates, a);
    2351 
    2352     pVM->csam.s.fGatesChecked = true;
    23532301    return VINF_SUCCESS;
    23542302}
  • trunk/src/VBox/VMM/PATM/CSAMInternal.h

    r23 r347  
    4545/** @} */
    4646
    47 #define CSAM_SSM_VERSION                       12
     47#define CSAM_SSM_VERSION                       13
    4848
    4949#define CSAM_PGDIRBMP_CHUNKS                   1024
     
    158158    HCPTRTYPE(uint8_t **) pPDBitmapHC;
    159159    HCPTRTYPE(RTGCPTR  *) pPDGCBitmapHC;
    160 
    161     /* Saved IDT entries. */
    162     VBOXIDTE            aIDT[256];
    163160
    164161    /* Temporary storage during load/save state */
  • trunk/src/VBox/VMM/PATM/PATM.cpp

    r302 r347  
    15941594        if (pCpu->pCurInstr->opcode == OP_CALL)
    15951595        {
    1596             if (PATMIsPatchGCAddr(pVM, pTargetGC))
    1597             {
    1598                 pTargetGC = PATMR3QueryPatchGCPtr(pVM, pTargetGC);
    1599                 if (pTargetGC == 0)
    1600                     return VERR_PATCHING_REFUSED;
    1601             }
    1602 
     1596            Assert(!PATMIsPatchGCAddr(pVM, pTargetGC));
    16031597            rc = patmPatchGenCall(pVM, pPatch, pCpu, pCurInstrGC, pTargetGC, false);
    16041598            if (VBOX_FAILURE(rc))
     
    48634857            iGate = TRPMR3QueryGateByHandler(pVM, PATCHCODE_PTR_GC(pPatch));
    48644858            if (iGate != (uint32_t)~0)
    4865             {
    48664859                TRPMR3SetGuestTrapHandler(pVM, iGate, TRPM_INVALID_HANDLER);
    4867                 TRPMR3SetGuestTrapHandlerDirty(pVM, iGate, false);
    4868             }
    48694860        }
    48704861
     
    55425533    // Find the patch record
    55435534    pPatchRec = (PPATMPATCHREC)RTAvloGCPtrGet(&pVM->patm.s.PatchLookupTreeHC->PatchTree, pAddrGC);
    5544     if (pPatchRec)
    5545     {
     5535    /** @todo we should only use patches that are enabled! always did this, but it's incorrect! */
     5536    if (pPatchRec && (pPatchRec->patch.uState == PATCH_ENABLED || pPatchRec->patch.uState == PATCH_DIRTY))
    55465537        return PATCHCODE_PTR_GC(&pPatchRec->patch);
    5547     }
     5538
    55485539    return 0;
    5549 }
    5550 
    5551 /**
    5552  * Handle traps in patch code.
    5553  *
    5554  * The current guest trap has an EIP inside patch code space.
    5555  *
    5556  * @returns On success VINF_SUCCESS or between VINF_EM_FIRST and VINF_EM_LAST.
    5557  * @returns On failure appropriate status code.
    5558  * @param   pVM         VM Handle.
    5559  * @param   rc          The GC return code.
    5560  */
    5561 PATMR3DECL(int) PATMR3Trap(PVM pVM, int rc)
    5562 {
    5563     /** @todo Implement PATMR3Trap! */
    5564     return VERR_NOT_IMPLEMENTED;
    55655540}
    55665541
  • trunk/src/VBox/VMM/SELM.cpp

    r106 r347  
    14781478
    14791479                /** @todo handle these dependencies better! */
    1480                 TRPMR3ClearHandler(pVM, 0x2E);
    1481                 TRPMR3ClearHandler(pVM, 0x80);
     1480                TRPMR3SetGuestTrapHandler(pVM, 0x2E, TRPM_INVALID_HANDLER);
     1481                TRPMR3SetGuestTrapHandler(pVM, 0x80, TRPM_INVALID_HANDLER);
    14821482                pVM->selm.s.fSyncTSSRing0Stack = true;
    14831483                }
  • trunk/src/VBox/VMM/TRPM.cpp

    r308 r347  
    441441    AssertRelease(sizeof(pVM->trpm.s) <= sizeof(pVM->trpm.padding));
    442442    AssertRelease(ELEMENTS(pVM->trpm.s.aGuestTrapHandler) == sizeof(pVM->trpm.s.au32IdtPatched)*8);
    443     AssertRelease(ELEMENTS(pVM->trpm.s.aGuestTrapHandler) == sizeof(pVM->trpm.s.au32IdtDirty)*8);
    444443
    445444    /*
     
    723722    SSMR3PutUInt(pSSM,      VM_FF_ISSET(pVM, VM_FF_TRPM_SYNC_IDT));
    724723    SSMR3PutMem(pSSM,       &pTrpm->au32IdtPatched[0], sizeof(pTrpm->au32IdtPatched));
    725     SSMR3PutMem(pSSM,       &pTrpm->au32IdtDirty[0], sizeof(pTrpm->au32IdtDirty));
    726724    SSMR3PutU32(pSSM, ~0);              /* separator. */
    727725
     
    798796
    799797    SSMR3GetMem(pSSM, &pTrpm->au32IdtPatched[0], sizeof(pTrpm->au32IdtPatched));
    800     SSMR3GetMem(pSSM, &pTrpm->au32IdtDirty[0], sizeof(pTrpm->au32IdtDirty));
    801798
    802799    /* check the separator */
     
    866863    if (fRawRing0 && CSAMIsEnabled(pVM))
    867864    {
    868         rc = CSAMR3CheckGates(pVM, 0, 256); /* check all gates */
    869         AssertRCReturn(rc, rc);
     865        /* Clear all handlers */
     866        /** @todo inefficient, but simple */
     867        for (unsigned iGate=0;iGate<256;iGate++)
     868            TRPMR3SetGuestTrapHandler(pVM, iGate, TRPM_INVALID_HANDLER);
     869
     870        /* Scan them all (only the first time) */
     871        CSAMR3CheckGates(pVM, 0, 256);
    870872    }
    871873
     
    994996
    995997
    996 #if 0 /* obsolete */
    997 /**
    998  * Activate guest trap gate handler
    999  * Used for setting up trap gates used for kernel calls.
     998/**
     999 * Clear passthrough interrupt gate handler (reset to default handler)
    10001000 *
    10011001 * @returns VBox status code.
    10021002 * @param   pVM         The VM to operate on.
    1003  * @param   iTrap       Interrupt/trap number.
    1004  */
    1005 TRPMR3DECL(int) TRPMR3EnableGuestTrapHandler(PVM pVM, unsigned iTrap)
    1006 {
    1007     /*
    1008      * Validate.
    1009      */
    1010     if (!EMIsRawRing0Enabled(pVM))
    1011     {
    1012         AssertMsgFailed(("Enabling interrupt gates only works when raw ring 0 is enabled\n"));
    1013         return VINF_SUCCESS;
    1014     }
    1015     if (iTrap < TRPM_HANDLER_INT_BASE || iTrap >= ELEMENTS(pVM->trpm.s.aIdt))
    1016     {
    1017         AssertMsg(iTrap < TRPM_HANDLER_INT_BASE, ("Illegal gate number %d!\n", iTrap));
     1003 * @param   iTrap       Trap/interrupt gate number.
     1004 */
     1005TRPMR3DECL(int) trpmR3ClearPassThroughHandler(PVM pVM, unsigned iTrap)
     1006{
     1007    /** @todo cleanup trpmR3ClearPassThroughHandler()! */
     1008    RTGCPTR aGCPtrs[TRPM_HANDLER_MAX];
     1009    int rc;
     1010
     1011    memset(aGCPtrs, 0, sizeof(aGCPtrs));
     1012
     1013    rc = PDMR3GetSymbolGC(pVM, VMMGC_MAIN_MODULE_NAME, "TRPMGCHandlerInterupt", &aGCPtrs[TRPM_HANDLER_INT]);
     1014    AssertReleaseMsgRC(rc, ("Couldn't find TRPMGCHandlerInterupt in VMMGC.gc!\n"));
     1015
     1016    if (    iTrap < TRPM_HANDLER_INT_BASE
     1017        ||  iTrap >= ELEMENTS(pVM->trpm.s.aIdt))
     1018    {
     1019        AssertMsg(iTrap < TRPM_HANDLER_INT_BASE, ("Illegal gate number %#x!\n", iTrap));
    10181020        return VERR_INVALID_PARAMETER;
    10191021    }
    1020 
    1021     uint16_t    cbIDT;
    1022     RTGCPTR     GCPtrIDT = CPUMGetGuestIDTR(pVM, &cbIDT);
    1023     if (iTrap * sizeof(VBOXIDTE) >= cbIDT)
    1024         return VERR_INVALID_PARAMETER;  /* Silently ignore out of range requests. */
    1025 
    1026     /*
    1027      * Read the guest IDT entry.
    1028      */
    1029     VBOXIDTE GuestIdte;
    1030     int rc = PGMPhysReadGCPtr(pVM, &GuestIdte, GCPtrIDT + iTrap * sizeof(GuestIdte),  sizeof(GuestIdte));
    1031     if (VBOX_FAILURE(rc))
    1032     {
    1033         AssertMsgRC(rc, ("Failed to read IDTE! rc=%Vrc\n", rc));
    1034         return rc;
    1035     }
    1036 
    1037     if (    GuestIdte.Gen.u1Present
    1038         &&  GuestIdte.Gen.u5Type2 == VBOX_IDTE_TYPE2_TRAP_32
    1039         &&  GuestIdte.Gen.u2DPL == 3)
    1040     {
    1041         LogFlow(("TRPMR3SetHandler: %X %04X:%04X%04X gate=%d dpl=%d present=%d\n", iTrap,
    1042                  GuestIdte.Gen.u16SegSel, GuestIdte.Gen.u16OffsetHigh, GuestIdte.Gen.u16OffsetLow,
    1043                  GuestIdte.Gen.u5Type2, GuestIdte.Gen.u2DPL, GuestIdte.Gen.u1Present));
    1044 
    1045         PVBOXIDTE pIdte = &pVM->trpm.s.aIdt[iTrap];
    1046         GuestIdte.Gen.u16SegSel |= 1;  // ring 1
    1047         *pIdte = GuestIdte;
     1022    memcpy(&pVM->trpm.s.aIdt[iTrap], &g_aIdt[iTrap], sizeof(pVM->trpm.s.aIdt[0]));
     1023
     1024    /* Unmark it for relocation purposes. */
     1025    ASMBitClear(&pVM->trpm.s.au32IdtPatched[0], iTrap);
     1026
     1027    RTSEL               SelCS         = CPUMGetHyperCS(pVM);
     1028    PVBOXIDTE           pIdte         = &pVM->trpm.s.aIdt[iTrap];
     1029    PVBOXIDTE_GENERIC   pIdteTemplate = &g_aIdt[iTrap];
     1030    if (pIdte->Gen.u1Present)
     1031    {
     1032        Assert(pIdteTemplate->u16OffsetLow == TRPM_HANDLER_INT);
     1033        Assert(sizeof(RTGCPTR) <= sizeof(aGCPtrs[0]));
     1034        RTGCPTR Offset = (RTGCPTR)aGCPtrs[pIdteTemplate->u16OffsetLow];
     1035
     1036        /*
     1037         * Generic handlers have different entrypoints for each possible
     1038         * vector number. These entrypoints make a sort of an array with
     1039         * 8 byte entries where the vector number is the index.
     1040         * See TRPMGCHandlersA.asm for details.
     1041         */
     1042        Offset += iTrap * 8;
     1043
     1044        if (pIdte->Gen.u5Type2 != VBOX_IDTE_TYPE2_TASK)
     1045        {
     1046            pIdte->Gen.u16OffsetLow  = Offset & 0xffff;
     1047            pIdte->Gen.u16OffsetHigh = Offset >> 16;
     1048            pIdte->Gen.u16SegSel     = SelCS;
     1049        }
    10481050    }
    10491051
    10501052    return VINF_SUCCESS;
    10511053}
    1052 #endif
    10531054
    10541055
     
    10831084
    10841085/**
    1085  * Marks IDT entry as dirty
    1086  *
    1087  * @returns Guest trap handler address or TRPM_INVALID_HANDLER if none installed
    1088  * @param   pVM         The VM to operate on.
    1089  * @param   iTrap       Interrupt/trap number.
    1090  * @param   fSetDirty   Set or clear
    1091  */
    1092 TRPMR3DECL(int) TRPMR3SetGuestTrapHandlerDirty(PVM pVM, unsigned iGate, bool fSetDirty)
    1093 {
    1094     AssertReturn(iGate < ELEMENTS(pVM->trpm.s.aIdt), VERR_INVALID_PARAMETER);
    1095 
    1096     if (fSetDirty)
    1097         ASMBitSet(&pVM->trpm.s.au32IdtDirty[0], iGate);
    1098     else
    1099         ASMBitClear(&pVM->trpm.s.au32IdtDirty[0], iGate);
    1100 
    1101     return VINF_SUCCESS;
    1102 }
    1103 
    1104 
    1105 /**
    1106  * Checks if IDT entry is dirty
    1107  *
    1108  * @returns dirty status
    1109  * @param   pVM         The VM to operate on.
    1110  * @param   iTrap       Interrupt/trap number.
    1111  */
    1112 TRPMR3DECL(bool) TRPMR3IsGuestTrapHandlerDirty(PVM pVM, unsigned iGate)
    1113 {
    1114     return ASMBitTest(&pVM->trpm.s.au32IdtDirty[0], iGate);
    1115 }
    1116 
    1117 
    1118 /**
    11191086 * Get guest trap/interrupt gate handler
    11201087 *
     
    11621129        /* clear trap handler */
    11631130        Log(("TRPMR3SetGuestTrapHandler: clear handler %x\n", iTrap));
     1131
     1132        if (ASMBitTest(&pVM->trpm.s.au32IdtPatched[0], iTrap))
     1133            trpmR3ClearPassThroughHandler(pVM, iTrap);
     1134
    11641135        pVM->trpm.s.aGuestTrapHandler[iTrap] = TRPM_INVALID_HANDLER;
    11651136        return VINF_SUCCESS;
     
    12291200    }
    12301201    return VERR_INVALID_PARAMETER;
    1231 }
    1232 
    1233 
    1234 /**
    1235  * Clear interrupt gate handler (reset to default handler)
    1236  *
    1237  * @returns VBox status code.
    1238  * @param   pVM         The VM to operate on.
    1239  * @param   iTrap       Trap/interrupt gate number.
    1240  */
    1241 TRPMR3DECL(int) TRPMR3ClearHandler(PVM pVM, unsigned iTrap)
    1242 {
    1243     /** @todo cleanup TRPMR3ClearHandler()! */
    1244     RTGCPTR aGCPtrs[TRPM_HANDLER_MAX];
    1245     int rc;
    1246 
    1247     memset(aGCPtrs, 0, sizeof(aGCPtrs));
    1248 
    1249     rc = PDMR3GetSymbolGC(pVM, VMMGC_MAIN_MODULE_NAME, "TRPMGCHandlerInterupt", &aGCPtrs[TRPM_HANDLER_INT]);
    1250     AssertReleaseMsgRC(rc, ("Couldn't find TRPMGCHandlerInterupt in VMMGC.gc!\n"));
    1251 
    1252     if (    iTrap < TRPM_HANDLER_INT_BASE
    1253         ||  iTrap >= ELEMENTS(pVM->trpm.s.aIdt))
    1254     {
    1255         AssertMsg(iTrap < TRPM_HANDLER_INT_BASE, ("Illegal gate number %#x!\n", iTrap));
    1256         return VERR_INVALID_PARAMETER;
    1257     }
    1258     memcpy(&pVM->trpm.s.aIdt[iTrap], &g_aIdt[iTrap], sizeof(pVM->trpm.s.aIdt[0]));
    1259 
    1260     /* Unmark it for relocation purposes. */
    1261     ASMBitClear(&pVM->trpm.s.au32IdtPatched[0], iTrap);
    1262 
    1263     RTSEL               SelCS         = CPUMGetHyperCS(pVM);
    1264     PVBOXIDTE           pIdte         = &pVM->trpm.s.aIdt[iTrap];
    1265     PVBOXIDTE_GENERIC   pIdteTemplate = &g_aIdt[iTrap];
    1266     if (pIdte->Gen.u1Present)
    1267     {
    1268         Assert(pIdteTemplate->u16OffsetLow == TRPM_HANDLER_INT);
    1269         Assert(sizeof(RTGCPTR) <= sizeof(aGCPtrs[0]));
    1270         RTGCPTR Offset = (RTGCPTR)aGCPtrs[pIdteTemplate->u16OffsetLow];
    1271 
    1272         /*
    1273          * Generic handlers have different entrypoints for each possible
    1274          * vector number. These entrypoints make a sort of an array with
    1275          * 8 byte entries where the vector number is the index.
    1276          * See TRPMGCHandlersA.asm for details.
    1277          */
    1278         Offset += iTrap * 8;
    1279 
    1280         if (pIdte->Gen.u5Type2 != VBOX_IDTE_TYPE2_TASK)
    1281         {
    1282             pIdte->Gen.u16OffsetLow  = Offset & 0xffff;
    1283             pIdte->Gen.u16OffsetHigh = Offset >> 16;
    1284             pIdte->Gen.u16SegSel     = SelCS;
    1285         }
    1286     }
    1287 
    1288     return VINF_SUCCESS;
    12891202}
    12901203
     
    14011314                return VINF_EM_RESCHEDULE_HWACC;
    14021315            }
    1403             /* If the guest gate is marked dirty, then we will check again if we can patch it. */
    1404             if (TRPMR3IsGuestTrapHandlerDirty(pVM, u8Interrupt))
     1316            /* If the guest gate is not patched, then we will check (again) if we can patch it. */
     1317            if (pVM->trpm.s.aGuestTrapHandler[u8Interrupt] == TRPM_INVALID_HANDLER)
    14051318            {
    1406                 Assert(TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER);
    14071319                CSAMR3CheckGates(pVM, u8Interrupt, 1);
    14081320                Log(("TRPMR3InjectEvent: recheck gate %x -> valid=%d\n", u8Interrupt, TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER));
  • trunk/src/VBox/VMM/TRPMInternal.h

    r23 r347  
    130130    uint32_t        au32IdtPatched[8];
    131131
    132     /** Bitmap for IDTEs that were changed. */
    133     uint32_t        au32IdtDirty[8];
    134 
    135132    /** Temporary Hypervisor trap handlers.
    136133     * NULL means default action. */
  • trunk/src/VBox/VMM/TRPMInternal.mac

    r19 r347  
    4747    .aIdt               resd 512
    4848    .au32IdtPatched     resd 8
    49     .au32IdtDirty       resd 8
    5049    .aTmpTrapHandlers   resd 256
    5150
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