VirtualBox

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


Ignore:
Timestamp:
Jul 15, 2009 3:59:30 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
50144
Message:

TPR access optimization experiments (disabled).

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

Legend:

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

    r21210 r21620  
    3434#include <iprt/cpuset.h>
    3535#include <iprt/mp.h>
     36#include <iprt/avl.h>
    3637
    3738#if HC_ARCH_BITS == 64 || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) || defined (VBOX_WITH_64_BITS_GUESTS)
     
    179180    HWACCMPENDINGIO_32BIT_HACK   = 0x7fffffff
    180181} HWACCMPENDINGIO;
     182
     183
     184typedef enum
     185{
     186    HWACCMTPRINSTR_READ,
     187    HWACCMTPRINSTR_READ_SHR4,
     188    HWACCMTPRINSTR_WRITE_REG,
     189    HWACCMTPRINSTR_WRITE_IMM,
     190    HWACCMTPRINSTR_MOV,
     191    /** The usual 32-bit paranoia. */
     192    HWACCMTPRINSTR_32BIT_HACK   = 0x7fffffff
     193} HWACCMTPRINSTR;
     194
     195typedef struct
     196{
     197    /** The key is the address of patched instruction. (32 bits GC ptr) */
     198    AVLOU32NODECORE         Core;
     199    /** Original opcode. */
     200    uint8_t                 aOpcode[16];
     201    /** Instruction size. */
     202    uint32_t                cbOp;
     203    /** Instruction type. */
     204    HWACCMTPRINSTR          enmType;
     205    /** Source operand. */
     206    uint32_t                uSrcOperand;
     207    /** Destination operand. */
     208    uint32_t                uDstOperand;
     209    /** Number of times the instruction caused a fault. */
     210    uint32_t                cFaults;
     211} HWACCMTPRPATCH;
     212/** Pointer to HWACCMTPRPATCH. */
     213typedef HWACCMTPRPATCH *PHWACCMTPRPATCH;
    181214
    182215/**
     
    373406        /** SVM feature bits from cpuid 0x8000000a */
    374407        uint32_t                    u32Features;
     408
     409        /**
     410         * AVL tree with all patches (active or disabled) sorted by guest instruction address
     411         */
     412        AVLOU32TREE                 PatchTree;
     413
     414        uint32_t                    cPatches;
     415        HWACCMTPRPATCH              aPatches[64];
    375416    } svm;
    376417
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r21574 r21620  
    5555static int svmR0InterpretInvpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uASID);
    5656static int svmR0ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
     57static int svmR0EmulateTprVMMCall(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    5758
    5859/*******************************************************************************
     
    22622263        break;
    22632264
     2265    case SVM_EXIT_VMMCALL:
     2266        rc = svmR0EmulateTprVMMCall(pVM, pVCpu, pCtx);
     2267        if (rc == VINF_SUCCESS)
     2268        {
     2269            goto ResumeExecution;   /* rip already updated. */
     2270        }
     2271        /* no break */
     2272
    22642273    case SVM_EXIT_RSM:
    22652274    case SVM_EXIT_INVLPGA:
    22662275    case SVM_EXIT_VMRUN:
    2267     case SVM_EXIT_VMMCALL:
    22682276    case SVM_EXIT_VMLOAD:
    22692277    case SVM_EXIT_VMSAVE:
     
    24362444
    24372445/**
     2446 * Emulate simple mov tpr instruction
     2447 *
     2448 * @returns VBox status code.
     2449 * @param   pVM         The VM to operate on.
     2450 * @param   pVCpu       The VM CPU to operate on.
     2451 * @param   pCtx        CPU context
     2452 */
     2453static int svmR0EmulateTprVMMCall(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     2454{
     2455    int rc;
     2456
     2457    Log(("Emulated VMMCall TPR access replacement at %RGv\n", pCtx->rip));
     2458
     2459    while (true)
     2460    {
     2461        bool    fPending;
     2462        uint8_t u8Tpr;
     2463
     2464        PHWACCMTPRPATCH pPatch = (PHWACCMTPRPATCH)RTAvloU32Get(&pVM->hwaccm.s.svm.PatchTree, (AVLOU32KEY)pCtx->eip);
     2465        if (!pPatch)
     2466            break;
     2467
     2468        switch(pPatch->enmType)
     2469        {
     2470        case HWACCMTPRINSTR_READ:
     2471            /* TPR caching in CR8 */
     2472            rc = PDMApicGetTPR(pVCpu, &u8Tpr, &fPending);
     2473            AssertRC(rc);
     2474
     2475            rc = DISWriteReg32(CPUMCTX2CORE(pCtx), pPatch->uDstOperand, u8Tpr);
     2476            AssertRC(rc);
     2477
     2478            Log(("Emulated read successfully\n"));
     2479            pCtx->rip += pPatch->cbOp;
     2480            break;
     2481
     2482        case HWACCMTPRINSTR_WRITE_REG:
     2483        case HWACCMTPRINSTR_WRITE_IMM:
     2484            /* Fetch the new TPR value */
     2485            if (pPatch->enmType == HWACCMTPRINSTR_WRITE_REG)
     2486            {
     2487                uint32_t val;
     2488
     2489                rc = DISFetchReg32(CPUMCTX2CORE(pCtx), pPatch->uSrcOperand, &val);
     2490                AssertRC(rc);
     2491                u8Tpr = val;
     2492            }
     2493            else
     2494                u8Tpr = (uint8_t)pPatch->uSrcOperand;
     2495
     2496            rc = PDMApicSetTPR(pVCpu, u8Tpr);
     2497            AssertRC(rc);
     2498            Log(("Emulated write successfully\n"));
     2499            pCtx->rip += pPatch->cbOp;
     2500            break;
     2501        }
     2502    }
     2503    return VINF_SUCCESS;
     2504}
     2505
     2506/**
    24382507 * Attempt to patch TPR mmio instructions
    24392508 *
     
    24562525        &&  pDis->pCurInstr->opcode == OP_MOV)
    24572526    {
    2458 #if 0
    2459         uint8_t szInstr[15];
    2460         if (    cbOp == 10
    2461             &&  pDis->param1.flags == USE_DISPLACEMENT32
    2462             &&  pDis->param2.flags == USE_IMMEDIATE32)
    2463         {
    2464             /* Found:
    2465              *   mov [fffe0080], immediate_dword                (10 bytes)
    2466              *
    2467              * Replace with:
    2468              *   mov free_register, immediate_dword >> 4        (5 bytes)
    2469              *   mov cr8, free_register                         (4 bytes)
    2470              *   nop                                            (1 byte)
    2471              *
    2472              */
    2473             uint32_t    u32tpr = (uint32_t)pDis->param2.parval;
    2474 
    2475             u32tpr = (u32tpr >> 4) & 0xf;
    2476 
    2477             /* Check if the next instruction overwrites a general purpose register. If
    2478              * it does, then we can safely use it ourselves.
    2479              */
    2480             pCtx->rip += cbOp;
    2481             rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
    2482             pCtx->rip = oldrip;
    2483             if (    rc == VINF_SUCCESS
    2484                 &&  pDis->pCurInstr->opcode == OP_MOV
    2485                 &&  pDis->param1.flags == USE_REG_GEN32)
     2527        if (pVM->hwaccm.s.svm.cPatches < RT_ELEMENTS(pVM->hwaccm.s.svm.aPatches))
     2528        {
     2529            uint8_t         aVMMCall[3] = { 0xf, 0x1, 0xd9};
     2530            uint32_t        idx = pVM->hwaccm.s.svm.cPatches;
     2531            PHWACCMTPRPATCH pPatch = &pVM->hwaccm.s.svm.aPatches[idx];
     2532
     2533            rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
     2534            AssertRC(rc);
     2535
     2536            pPatch->cbOp     = cbOp;
     2537
     2538            if (pDis->param1.flags == USE_DISPLACEMENT32)
    24862539            {
    2487                 /* 0xB8, dword immediate  = mov eax, dword immediate */
    2488                 szInstr[0] = 0xB8 + pDis->param1.base.reg_gen;
    2489                 szInstr[1] = (uint8_t)u32tpr;
    2490                 szInstr[2] = 0;
    2491                 szInstr[3] = 0;
    2492                 szInstr[4] = 0;
    2493 
    2494                 /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
    2495                 szInstr[5] = 0xF0;
    2496                 szInstr[6] = 0x0F;
    2497                 szInstr[7] = 0x22;
    2498                 szInstr[8] = 0xC0 | pDis->param1.base.reg_gen;
    2499                 szInstr[9] = 0x90; /* nop */
    2500 
    2501                 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 10);
     2540                /* write. */
     2541                if (pDis->param2.flags == USE_REG_GEN32)
     2542                {
     2543                    pPatch->enmType     = HWACCMTPRINSTR_WRITE_REG;
     2544                    pPatch->uSrcOperand = pDis->param2.base.reg_gen;
     2545                }
     2546                else
     2547                {
     2548                    Assert(pDis->param2.flags == USE_IMMEDIATE32);
     2549                    pPatch->enmType     = HWACCMTPRINSTR_WRITE_IMM;
     2550                    pPatch->uSrcOperand = pDis->param2.parval;
     2551                }
     2552                rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));
    25022553                AssertRC(rc);
    2503 
    2504                 Log(("Acceptable write candidate!\n"));
    2505                 return VINF_SUCCESS;
    2506             }
    2507         }
    2508         else
    2509         {
    2510             if (    pDis->param2.flags == USE_REG_GEN32
    2511                 &&  cbOp == 6)
    2512             {
    2513                 RTGCPTR  GCPtrTpr = (uint32_t)pDis->param1.disp32;
    2514                 uint32_t uMmioReg = pDis->param2.base.reg_gen;
    2515 
    2516                 /* Found:
    2517                  *   mov dword [fffe0080], eax        (6 bytes)
    2518                  * Check if next instruction is a TPR read:
    2519                  *   mov ecx, dword [fffe0080]        (5 bytes)
    2520                  */
    2521                 pCtx->rip += cbOp;
    2522                 rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
    2523                 pCtx->rip = oldrip;
    2524                 if (    rc == VINF_SUCCESS
    2525                     &&  pDis->pCurInstr->opcode == OP_MOV
    2526                     &&  pDis->param1.flags == USE_REG_GEN32
    2527                     &&  pDis->param2.flags == USE_DISPLACEMENT32
    2528                     &&  pDis->param2.disp32 == (uint32_t)GCPtrTpr
    2529                     &&  cbOp == 5)
    2530                 {
    2531                     /* mov new_reg, uMmioReg */
    2532                     szInstr[0] = 0x89;
    2533                     szInstr[1] = MAKE_MODRM(3, uMmioReg, pDis->param1.base.reg_gen);
    2534 
    2535                     /* Let's hope the guest won't mind us trashing the source register...
    2536                      * shr uMmioReg, 4
    2537                      */
    2538                     szInstr[2] = 0xC1;
    2539                     szInstr[3] = 0xE8 | uMmioReg;
    2540                     szInstr[4] = 4;
    2541 
    2542                     /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
    2543                     szInstr[5] = 0xF0;
    2544                     szInstr[6] = 0x0F;
    2545                     szInstr[7] = 0x22;
    2546                     szInstr[8] = 0xC0 | uMmioReg;
    2547 
    2548                     /* Two nop instructions */
    2549                     szInstr[9] = 0x90;
    2550                     szInstr[10] = 0x90;
    2551 
    2552                     rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 6+cbOp);
    2553                     AssertRC(rc);
    2554 
    2555                     Log(("Acceptable read/write candidate!\n"));
    2556                     return VINF_SUCCESS;
    2557                 }
    25582554            }
    25592555            else
    2560             if (    pDis->param1.flags == USE_REG_GEN32
    2561                 &&  cbOp == 5)
    25622556            {
     2557                RTGCPTR  oldrip   = pCtx->rip;
     2558                uint32_t oldcbOp  = cbOp;
    25632559                uint32_t uMmioReg = pDis->param1.base.reg_gen;
     2560
     2561                /* read */
     2562                Assert(pDis->param1.flags == USE_REG_GEN32);
    25642563
    25652564                /* Found:
     
    25762575                    &&  pDis->param1.base.reg_gen == uMmioReg
    25772576                    &&  pDis->param2.flags == USE_IMMEDIATE8
    2578                     &&  pDis->param2.parval == 4)
     2577                    &&  pDis->param2.parval == 4
     2578                    &&  oldcbOp + cbOp < sizeof(pVM->hwaccm.s.svm.aPatches[idx]))
    25792579                {
     2580                    uint8_t szInstr[15];
     2581
     2582                    /* Replacing two instructions now. */
     2583                    rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, oldcbOp + cbOp);
     2584                    AssertRC(rc);
     2585
     2586                    pPatch->cbOp = oldcbOp + cbOp;
     2587
    25802588                    /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
    25812589                    szInstr[0] = 0xF0;
     
    25892597                    AssertRC(rc);
    25902598
    2591                     Log(("Acceptable read candidate!\n"));
    2592                     return VINF_SUCCESS;
     2599                    Log(("Acceptable read/shr candidate!\n"));
     2600                    pPatch->enmType = HWACCMTPRINSTR_READ_SHR4;
     2601                }
     2602                else
     2603                {
     2604                    pPatch->enmType     = HWACCMTPRINSTR_READ;
     2605                    pPatch->uDstOperand = pDis->param1.base.reg_gen;
     2606
     2607                    rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));
     2608                    AssertRC(rc);
    25932609                }
    25942610            }
    2595         }
    2596 #endif
    2597         rc = svmR0EmulateTprMov(pVCpu, pDis, pCtx, cbOp);
    2598         if (rc != VINF_SUCCESS)
    2599             return rc;
    2600 
    2601         /* Emulated successfully, so continue. */
    2602         return VINF_SUCCESS;
     2611
     2612            pPatch->Core.Key = pCtx->eip;
     2613            rc = RTAvloU32Insert(&pVM->hwaccm.s.svm.PatchTree, &pPatch->Core);
     2614            AssertRC(rc);
     2615
     2616            pVM->hwaccm.s.svm.cPatches++;
     2617            return VINF_SUCCESS;
     2618        }
     2619        return svmR0EmulateTprMov(pVCpu, pDis, pCtx, cbOp);
    26032620    }
    26042621    return VERR_ACCESS_DENIED;
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