VirtualBox

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


Ignore:
Timestamp:
Jul 16, 2009 3:18:07 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
50188
Message:

TPR patching updates

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/EMHandleRCTmpl.h

    r21222 r21653  
    220220            rc = HWACCMR3EmulateIoBlock(pVM, pCtx);
    221221            break;
     222
     223        case VINF_EM_HWACCM_PATCH_TPR_INSTR:
     224            rc = HWACCMR3PatchTprInstr(pVM, pVCpu, pCtx);
     225            break;
    222226#endif
    223227
  • trunk/src/VBox/VMM/HWACCM.cpp

    r21652 r21653  
    14311431
    14321432/**
     1433 * Emulate simple mov tpr instruction
     1434 *
     1435 * @returns VBox status code.
     1436 * @param   pVCpu       The VM CPU to operate on.
     1437 * @param   pDis        Disassembly state
     1438 * @param   pCtx        CPU context
     1439 * @param   cbOp        Opcode size
     1440 */
     1441static int hwaccmR0EmulateTprMov(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTX pCtx, unsigned cbOp)
     1442{
     1443    int rc;
     1444
     1445    if (pDis->param1.flags == USE_DISPLACEMENT32)
     1446    {
     1447        /* write */
     1448        uint8_t u8Tpr;
     1449
     1450        /* Fetch the new TPR value */
     1451        if (pDis->param2.flags == USE_REG_GEN32)
     1452        {
     1453            uint32_t val;
     1454
     1455            rc = DISFetchReg32(CPUMCTX2CORE(pCtx), pDis->param2.base.reg_gen, &val);
     1456            AssertRC(rc);
     1457            u8Tpr = val;
     1458        }
     1459        else
     1460        if (pDis->param2.flags == USE_IMMEDIATE32)
     1461        {
     1462            u8Tpr = (uint8_t)pDis->param2.parval;
     1463        }
     1464        else
     1465            return VERR_EM_INTERPRETER;
     1466
     1467        rc = PDMApicSetTPR(pVCpu, u8Tpr);
     1468        AssertRC(rc);
     1469
     1470        Log(("Emulated write successfully\n"));
     1471        pCtx->rip += cbOp;
     1472        return VINF_SUCCESS;
     1473    }
     1474    else
     1475    if (pDis->param2.flags == USE_DISPLACEMENT32)
     1476    {
     1477        /* read */
     1478        bool    fPending;
     1479        uint8_t u8Tpr;
     1480
     1481        /* TPR caching in CR8 */
     1482        rc = PDMApicGetTPR(pVCpu, &u8Tpr, &fPending);
     1483        AssertRC(rc);
     1484
     1485        rc = DISWriteReg32(CPUMCTX2CORE(pCtx), pDis->param1.base.reg_gen, u8Tpr);
     1486        AssertRC(rc);
     1487
     1488        Log(("Emulated read successfully\n"));
     1489        pCtx->rip += cbOp;
     1490        return VINF_SUCCESS;
     1491    }
     1492    return VERR_EM_INTERPRETER;
     1493}
     1494
     1495/**
     1496 * Callback to patch a TPR instruction
     1497 *
     1498 * @returns VBox status code.
     1499 * @param   pVM     The VM handle.
     1500 * @param   pVCpu   The VMCPU for the EMT we're being called on.
     1501 * @param   pvUser  User specified CPU context
     1502 *
     1503 */
     1504DECLCALLBACK(int) hwaccmR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1505{
     1506    PCPUMCTX     pCtx   = (PCPUMCTX)pvUser;
     1507    RTGCPTR      oldrip = pCtx->rip;
     1508    PDISCPUSTATE pDis   = &pVCpu->hwaccm.s.DisState;
     1509    unsigned     cbOp;
     1510
     1511    Log(("Replace TPR access at %RGv\n", pCtx->rip));
     1512
     1513    int rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
     1514    AssertRC(rc);
     1515    if (    rc == VINF_SUCCESS
     1516        &&  pDis->pCurInstr->opcode == OP_MOV)
     1517    {
     1518        if (pVM->hwaccm.s.svm.cPatches < RT_ELEMENTS(pVM->hwaccm.s.svm.aPatches))
     1519        {
     1520            uint8_t         aVMMCall[3] = { 0xf, 0x1, 0xd9};
     1521            uint32_t        idx = pVM->hwaccm.s.svm.cPatches;
     1522            PHWACCMTPRPATCH pPatch = &pVM->hwaccm.s.svm.aPatches[idx];
     1523
     1524            rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
     1525            AssertRC(rc);
     1526
     1527            pPatch->cbOp     = cbOp;
     1528
     1529            if (pDis->param1.flags == USE_DISPLACEMENT32)
     1530            {
     1531                /* write. */
     1532                if (pDis->param2.flags == USE_REG_GEN32)
     1533                {
     1534                    pPatch->enmType     = HWACCMTPRINSTR_WRITE_REG;
     1535                    pPatch->uSrcOperand = pDis->param2.base.reg_gen;
     1536                }
     1537                else
     1538                {
     1539                    Assert(pDis->param2.flags == USE_IMMEDIATE32);
     1540                    pPatch->enmType     = HWACCMTPRINSTR_WRITE_IMM;
     1541                    pPatch->uSrcOperand = pDis->param2.parval;
     1542                }
     1543                rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));
     1544                AssertRC(rc);
     1545            }
     1546            else
     1547            {
     1548                RTGCPTR  oldrip   = pCtx->rip;
     1549                uint32_t oldcbOp  = cbOp;
     1550                uint32_t uMmioReg = pDis->param1.base.reg_gen;
     1551
     1552                /* read */
     1553                Assert(pDis->param1.flags == USE_REG_GEN32);
     1554
     1555                /* Found:
     1556                 *   mov eax, dword [fffe0080]        (5 bytes)
     1557                 * Check if next instruction is:
     1558                 *   shr eax, 4
     1559                 */
     1560                pCtx->rip += cbOp;
     1561                rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
     1562                pCtx->rip = oldrip;
     1563                if (    rc == VINF_SUCCESS
     1564                    &&  pDis->pCurInstr->opcode == OP_SHR
     1565                    &&  pDis->param1.flags == USE_REG_GEN32
     1566                    &&  pDis->param1.base.reg_gen == uMmioReg
     1567                    &&  pDis->param2.flags == USE_IMMEDIATE8
     1568                    &&  pDis->param2.parval == 4
     1569                    &&  oldcbOp + cbOp < sizeof(pVM->hwaccm.s.svm.aPatches[idx]))
     1570                {
     1571                    uint8_t szInstr[15];
     1572
     1573                    /* Replacing two instructions now. */
     1574                    rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, oldcbOp + cbOp);
     1575                    AssertRC(rc);
     1576
     1577                    pPatch->cbOp = oldcbOp + cbOp;
     1578
     1579                    /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
     1580                    szInstr[0] = 0xF0;
     1581                    szInstr[1] = 0x0F;
     1582                    szInstr[2] = 0x20;
     1583                    szInstr[3] = 0xC0 | pDis->param1.base.reg_gen;
     1584                    for (unsigned i = 4; i < 5+cbOp; i++)
     1585                        szInstr[i] = 0x90;  /* nop */
     1586
     1587                    rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 5+cbOp);
     1588                    AssertRC(rc);
     1589
     1590                    Log(("Acceptable read/shr candidate!\n"));
     1591                    pPatch->enmType = HWACCMTPRINSTR_READ_SHR4;
     1592                }
     1593                else
     1594                {
     1595                    pPatch->enmType     = HWACCMTPRINSTR_READ;
     1596                    pPatch->uDstOperand = pDis->param1.base.reg_gen;
     1597
     1598                    rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));
     1599                    AssertRC(rc);
     1600                }
     1601            }
     1602
     1603            pPatch->Core.Key = pCtx->eip;
     1604            rc = RTAvloU32Insert(&pVM->hwaccm.s.svm.PatchTree, &pPatch->Core);
     1605            AssertRC(rc);
     1606
     1607            pVM->hwaccm.s.svm.cPatches++;
     1608            return VINF_SUCCESS;
     1609        }
     1610        return hwaccmR0EmulateTprMov(pVCpu, pDis, pCtx, cbOp);
     1611    }
     1612    return VERR_ACCESS_DENIED;
     1613}
     1614
     1615/**
     1616 * Attempt to patch TPR mmio instructions
     1617 *
     1618 * @returns VBox status code.
     1619 * @param   pVM         The VM to operate on.
     1620 * @param   pVCpu       The VM CPU to operate on.
     1621 * @param   pCtx        CPU context
     1622 */
     1623VMMR3DECL(int) HWACCMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     1624{
     1625    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, hwaccmR3PatchTprInstr, pCtx);
     1626    AssertRC(rc);
     1627    return rc;
     1628}
     1629
     1630/**
    14331631 * Force execution of the current IO code in the recompiler
    14341632 *
  • trunk/src/VBox/VMM/VMM.cpp

    r21649 r21653  
    383383    STAM_REG(pVM, &pVM->vmm.s.StatRZRetPGMChangeMode,       STAMTYPE_COUNTER, "/VMM/RZRet/PGMChangeMode",       STAMUNIT_OCCURENCES, "Number of VINF_PGM_CHANGE_MODE returns.");
    384384    STAM_REG(pVM, &pVM->vmm.s.StatRZRetPendingRequest,      STAMTYPE_COUNTER, "/VMM/RZRet/PendingRequest",      STAMUNIT_OCCURENCES, "Number of VINF_EM_PENDING_REQUEST returns.");
    385 
     385    STAM_REG(pVM, &pVM->vmm.s.StatRZRetPatchTPR,            STAMTYPE_COUNTER, "/VMM/RZRet/PatchTPR",            STAMUNIT_OCCURENCES, "Number of VINF_EM_HWACCM_PATCH_TPR_INSTR returns.");
    386386    STAM_REG(pVM, &pVM->vmm.s.StatRZRetCallRing3,           STAMTYPE_COUNTER, "/VMM/RZCallR3/Misc",             STAMUNIT_OCCURENCES, "Number of Other ring-3 calls.");
    387387    STAM_REG(pVM, &pVM->vmm.s.StatRZCallPDMLock,            STAMTYPE_COUNTER, "/VMM/RZCallR3/PDMLock",          STAMUNIT_OCCURENCES, "Number of VMMCALLRING3_PDM_LOCK calls.");
  • trunk/src/VBox/VMM/VMMInternal.h

    r21196 r21653  
    364364    STAMCOUNTER                 StatRZRetPGMChangeMode;
    365365    STAMCOUNTER                 StatRZRetPendingRequest;
     366    STAMCOUNTER                 StatRZRetPatchTPR;
    366367    STAMCOUNTER                 StatRZCallPDMLock;
    367368    STAMCOUNTER                 StatRZCallLogFlush;
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r21649 r21653  
    5454*******************************************************************************/
    5555static int svmR0InterpretInvpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uASID);
    56 static int svmR0ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    5756static int svmR0EmulateTprVMMCall(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    5857
     
    17471746            if (uFaultAddress == GCPhysApicBase + 0x80)
    17481747            {
    1749                 rc = svmR0ReplaceTprInstr(pVM, pVCpu, pCtx);
    1750                 if (rc == VINF_SUCCESS)
    1751                 {
    1752                     STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
    1753                     goto ResumeExecution;
    1754                 }
    1755 
    1756                 rc = IOMMMIOPhysHandler(pVM, errCode, CPUMCTX2CORE(pCtx), uFaultAddress);
    1757                 if (rc == VINF_SUCCESS)
    1758                 {
    1759                     STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
    1760                     goto ResumeExecution;   /* rip already updated */
    1761                 }
     1748                rc = VINF_EM_HWACCM_PATCH_TPR_INSTR;
     1749                break;
    17621750            }
    17631751        }
     
    23852373 *
    23862374 * @returns VBox status code.
    2387  * @param   pVCpu       The VM CPU to operate on.
    2388  * @param   pDis        Disassembly state
    2389  * @param   pCtx        CPU context
    2390  * @param   cbOp        Opcode size
    2391  */
    2392 static int svmR0EmulateTprMov(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTX pCtx, unsigned cbOp)
    2393 {
    2394     int rc;
    2395 
    2396     if (pDis->param1.flags == USE_DISPLACEMENT32)
    2397     {
    2398         /* write */
    2399         uint8_t u8Tpr;
    2400 
    2401         /* Fetch the new TPR value */
    2402         if (pDis->param2.flags == USE_REG_GEN32)
    2403         {
    2404             uint32_t val;
    2405 
    2406             rc = DISFetchReg32(CPUMCTX2CORE(pCtx), pDis->param2.base.reg_gen, &val);
    2407             AssertRC(rc);
    2408             u8Tpr = val;
    2409         }
    2410         else
    2411         if (pDis->param2.flags == USE_IMMEDIATE32)
    2412         {
    2413             u8Tpr = (uint8_t)pDis->param2.parval;
    2414         }
    2415         else
    2416             return VERR_EM_INTERPRETER;
    2417 
    2418         rc = PDMApicSetTPR(pVCpu, u8Tpr);
    2419         AssertRC(rc);
    2420 
    2421         Log(("Emulated write successfully\n"));
    2422         pCtx->rip += cbOp;
    2423         return VINF_SUCCESS;
    2424     }
    2425     else
    2426     if (pDis->param2.flags == USE_DISPLACEMENT32)
    2427     {
    2428         /* read */
    2429         bool    fPending;
    2430         uint8_t u8Tpr;
    2431 
    2432         /* TPR caching in CR8 */
    2433         rc = PDMApicGetTPR(pVCpu, &u8Tpr, &fPending);
    2434         AssertRC(rc);
    2435 
    2436         rc = DISWriteReg32(CPUMCTX2CORE(pCtx), pDis->param1.base.reg_gen, u8Tpr);
    2437         AssertRC(rc);
    2438 
    2439         Log(("Emulated read successfully\n"));
    2440         pCtx->rip += cbOp;
    2441         return VINF_SUCCESS;
    2442     }
    2443     return VERR_EM_INTERPRETER;
    2444 }
    2445 
    2446 /**
    2447  * Emulate simple mov tpr instruction
    2448  *
    2449  * @returns VBox status code.
    24502375 * @param   pVM         The VM to operate on.
    24512376 * @param   pVCpu       The VM CPU to operate on.
     
    25052430}
    25062431
    2507 /**
    2508  * Attempt to patch TPR mmio instructions
    2509  *
    2510  * @returns VBox status code.
    2511  * @param   pVM         The VM to operate on.
    2512  * @param   pVCpu       The VM CPU to operate on.
    2513  * @param   pCtx        CPU context
    2514  */
    2515 static int svmR0ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    2516 {
    2517     RTGCPTR      oldrip = pCtx->rip;
    2518     PDISCPUSTATE pDis   = &pVCpu->hwaccm.s.DisState;
    2519     unsigned     cbOp;
    2520 
    2521     Log(("Replace TPR access at %RGv\n", pCtx->rip));
    2522 
    2523     int rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
    2524     AssertRC(rc);
    2525     if (    rc == VINF_SUCCESS
    2526         &&  pDis->pCurInstr->opcode == OP_MOV)
    2527     {
    2528         if (pVM->hwaccm.s.svm.cPatches < RT_ELEMENTS(pVM->hwaccm.s.svm.aPatches))
    2529         {
    2530             uint8_t         aVMMCall[3] = { 0xf, 0x1, 0xd9};
    2531             uint32_t        idx = pVM->hwaccm.s.svm.cPatches;
    2532             PHWACCMTPRPATCH pPatch = &pVM->hwaccm.s.svm.aPatches[idx];
    2533 
    2534             rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
    2535             AssertRC(rc);
    2536 
    2537             pPatch->cbOp     = cbOp;
    2538 
    2539             if (pDis->param1.flags == USE_DISPLACEMENT32)
    2540             {
    2541                 /* write. */
    2542                 if (pDis->param2.flags == USE_REG_GEN32)
    2543                 {
    2544                     pPatch->enmType     = HWACCMTPRINSTR_WRITE_REG;
    2545                     pPatch->uSrcOperand = pDis->param2.base.reg_gen;
    2546                 }
    2547                 else
    2548                 {
    2549                     Assert(pDis->param2.flags == USE_IMMEDIATE32);
    2550                     pPatch->enmType     = HWACCMTPRINSTR_WRITE_IMM;
    2551                     pPatch->uSrcOperand = pDis->param2.parval;
    2552                 }
    2553                 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));
    2554                 AssertRC(rc);
    2555             }
    2556             else
    2557             {
    2558                 RTGCPTR  oldrip   = pCtx->rip;
    2559                 uint32_t oldcbOp  = cbOp;
    2560                 uint32_t uMmioReg = pDis->param1.base.reg_gen;
    2561 
    2562                 /* read */
    2563                 Assert(pDis->param1.flags == USE_REG_GEN32);
    2564 
    2565                 /* Found:
    2566                  *   mov eax, dword [fffe0080]        (5 bytes)
    2567                  * Check if next instruction is:
    2568                  *   shr eax, 4
    2569                  */
    2570                 pCtx->rip += cbOp;
    2571                 rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
    2572                 pCtx->rip = oldrip;
    2573                 if (    rc == VINF_SUCCESS
    2574                     &&  pDis->pCurInstr->opcode == OP_SHR
    2575                     &&  pDis->param1.flags == USE_REG_GEN32
    2576                     &&  pDis->param1.base.reg_gen == uMmioReg
    2577                     &&  pDis->param2.flags == USE_IMMEDIATE8
    2578                     &&  pDis->param2.parval == 4
    2579                     &&  oldcbOp + cbOp < sizeof(pVM->hwaccm.s.svm.aPatches[idx]))
    2580                 {
    2581                     uint8_t szInstr[15];
    2582 
    2583                     /* Replacing two instructions now. */
    2584                     rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, oldcbOp + cbOp);
    2585                     AssertRC(rc);
    2586 
    2587                     pPatch->cbOp = oldcbOp + cbOp;
    2588 
    2589                     /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
    2590                     szInstr[0] = 0xF0;
    2591                     szInstr[1] = 0x0F;
    2592                     szInstr[2] = 0x20;
    2593                     szInstr[3] = 0xC0 | pDis->param1.base.reg_gen;
    2594                     for (unsigned i = 4; i < 5+cbOp; i++)
    2595                         szInstr[i] = 0x90;  /* nop */
    2596 
    2597                     rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 5+cbOp);
    2598                     AssertRC(rc);
    2599 
    2600                     Log(("Acceptable read/shr candidate!\n"));
    2601                     pPatch->enmType = HWACCMTPRINSTR_READ_SHR4;
    2602                 }
    2603                 else
    2604                 {
    2605                     pPatch->enmType     = HWACCMTPRINSTR_READ;
    2606                     pPatch->uDstOperand = pDis->param1.base.reg_gen;
    2607 
    2608                     rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));
    2609                     AssertRC(rc);
    2610                 }
    2611             }
    2612 
    2613             pPatch->Core.Key = pCtx->eip;
    2614             rc = RTAvloU32Insert(&pVM->hwaccm.s.svm.PatchTree, &pPatch->Core);
    2615             AssertRC(rc);
    2616 
    2617             pVM->hwaccm.s.svm.cPatches++;
    2618             return VINF_SUCCESS;
    2619         }
    2620         return svmR0EmulateTprMov(pVCpu, pDis, pCtx, cbOp);
    2621     }
    2622     return VERR_ACCESS_DENIED;
    2623 }
    26242432
    26252433/**
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r21196 r21653  
    468468            STAM_COUNTER_INC(&pVM->vmm.s.StatRZRetPendingRequest);
    469469            break;
     470        case VINF_EM_HWACCM_PATCH_TPR_INSTR:
     471            STAM_COUNTER_INC(&pVM->vmm.s.StatRZRetPatchTPR);
     472            break;
    470473        default:
    471474            STAM_COUNTER_INC(&pVM->vmm.s.StatRZRetMisc);
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