VirtualBox

Changeset 20328 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
Jun 5, 2009 1:23:52 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
48232
Message:

Cleanup

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r20325 r20328  
    5353*   Internal Functions                                                         *
    5454*******************************************************************************/
    55 static int SVMR0InterpretInvpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uASID);
     55static int svmR0InterpretInvpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uASID);
     56static int svmR0ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    5657
    5758/*******************************************************************************
     
    17121713            if (uFaultAddress == GCPhysApicBase + 0x80)
    17131714            {
    1714                 Log(("Replace TPR access at %RGv\n", pCtx->rip));
    1715                 DISCPUSTATE Cpu;
    1716                 unsigned cbOp;
    1717                 rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
    1718                 AssertRC(rc);
    1719                 if (    rc == VINF_SUCCESS
    1720                     &&  Cpu.pCurInstr->opcode == OP_MOV)
     1715                rc = svmR0ReplaceTprInstr(pVM, pVCpu, pCtx);
     1716                if (rc == VINF_SUCCESS)
    17211717                {
    1722                     uint8_t szInstr[15];
    1723                     if (    cbOp == 10
    1724                         &&  (errCode & X86_TRAP_PF_RW)
    1725                         &&  Cpu.param2.flags == USE_IMMEDIATE32)
    1726                     {
    1727                         /* Found:
    1728                          *   mov [fffe0080], immediate_dword                (10 bytes)
    1729                          *
    1730                          * Replace with:
    1731                          *   mov free_register, immediate_dword >> 4        (5 bytes)
    1732                          *   mov cr8, free_register                         (4 bytes)
    1733                          *   nop                                            (1 byte)
    1734                          *
    1735                          */
    1736                         RTGCPTR     oldEip = pCtx->eip;
    1737                         uint32_t    u32tpr = (uint32_t)Cpu.param2.parval;
    1738 
    1739                         u32tpr = (u32tpr >> 4) & 0xf;
    1740 
    1741                         /* Check if the next instruction overwrites a general purpose register. If
    1742                          * it does, then we can safely use it ourselves.
    1743                          */
    1744                         pCtx->eip += cbOp;
    1745                         rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
    1746                         pCtx->eip = oldEip;
    1747                         if (    rc == VINF_SUCCESS
    1748                             &&  Cpu.pCurInstr->opcode == OP_MOV
    1749                             &&  Cpu.param1.flags == USE_REG_GEN32)
    1750                         {
    1751                             /* 0xB8, dword immediate  = mov eax, dword immediate */
    1752                             szInstr[0] = 0xB8 + Cpu.param1.base.reg_gen;
    1753                             szInstr[1] = (uint8_t)u32tpr;
    1754                             szInstr[2] = 0;
    1755                             szInstr[3] = 0;
    1756                             szInstr[4] = 0;
    1757 
    1758                             /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
    1759                             szInstr[5] = 0xF0;
    1760                             szInstr[6] = 0x0F;
    1761                             szInstr[7] = 0x22;
    1762                             szInstr[8] = 0xC0 | Cpu.param1.base.reg_gen;
    1763                             szInstr[9] = 0x90; /* nop */
    1764 
    1765                             rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 10);
    1766                             AssertRC(rc);
    1767 
    1768                             Log(("Acceptable write candidate!\n"));
    1769                             STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
    1770                             goto ResumeExecution;
    1771                         }
    1772                     }
    1773                     else
    1774                     {
    1775                         if (    Cpu.param2.flags == USE_REG_GEN32
    1776                             &&  cbOp == 6)
    1777                         {
    1778                             RTGCPTR  oldEip   = pCtx->eip;
    1779                             RTGCPTR  GCPtrTpr = (uint32_t)Cpu.param1.disp32;
    1780                             uint32_t uMmioReg = Cpu.param2.base.reg_gen;
    1781 
    1782                             /* Found:
    1783                              *   mov dword [fffe0080], eax        (6 bytes)
    1784                              * Check if next instruction is a TPR read:
    1785                              *   mov ecx, dword [fffe0080]        (5 bytes)
    1786                              */
    1787                             pCtx->eip += cbOp;
    1788                             rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
    1789                             pCtx->eip = oldEip;
    1790                             if (    rc == VINF_SUCCESS
    1791                                 &&  Cpu.pCurInstr->opcode == OP_MOV
    1792                                 &&  Cpu.param1.flags == USE_REG_GEN32
    1793                                 &&  Cpu.param2.flags == USE_DISPLACEMENT32
    1794                                 &&  Cpu.param2.disp32 == (uint32_t)GCPtrTpr
    1795                                 &&  cbOp == 5)
    1796                             {
    1797                                 /* mov new_reg, uMmioReg */
    1798                                 szInstr[0] = 0x89;
    1799                                 szInstr[1] = MAKE_MODRM(3, uMmioReg, Cpu.param1.base.reg_gen);
    1800 
    1801                                 /* Let's hope the guest won't mind us trashing the source register...
    1802                                  * shr uMmioReg, 4
    1803                                  */
    1804                                 szInstr[2] = 0xC1;
    1805                                 szInstr[3] = 0xE8 | uMmioReg;
    1806                                 szInstr[4] = 4;
    1807 
    1808                                 /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
    1809                                 szInstr[5] = 0xF0;
    1810                                 szInstr[6] = 0x0F;
    1811                                 szInstr[7] = 0x22;
    1812                                 szInstr[8] = 0xC0 | uMmioReg;
    1813 
    1814                                 /* Two nop instructions */
    1815                                 szInstr[9] = 0x90;
    1816                                 szInstr[10] = 0x90;
    1817 
    1818                                 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 6+cbOp);
    1819                                 AssertRC(rc);
    1820 
    1821                                 Log(("Acceptable write candidate!\n"));
    1822                                 STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
    1823                                 goto ResumeExecution;
    1824                             }
    1825                         }
    1826                         else
    1827                         if (    Cpu.param1.flags == USE_REG_GEN32
    1828                             &&  cbOp == 5)
    1829                         {
    1830                             RTGCPTR  oldEip = pCtx->eip;
    1831                             uint32_t uMmioReg = Cpu.param1.base.reg_gen;
    1832 
    1833                             /* Found:
    1834                              *   mov eax, dword [fffe0080]        (5 bytes)
    1835                              * Check if next instruction is:
    1836                              *   shr eax, 4
    1837                              */
    1838                             pCtx->eip += cbOp;
    1839                             rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
    1840                             pCtx->eip = oldEip;
    1841                             if (    rc == VINF_SUCCESS
    1842                                 &&  Cpu.pCurInstr->opcode == OP_SHR
    1843                                 &&  Cpu.param1.flags == USE_REG_GEN32
    1844                                 &&  Cpu.param1.base.reg_gen == uMmioReg
    1845                                 &&  Cpu.param2.flags == USE_IMMEDIATE8
    1846                                 &&  Cpu.param2.parval == 4)
    1847                             {
    1848                                 /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
    1849                                 szInstr[0] = 0xF0;
    1850                                 szInstr[1] = 0x0F;
    1851                                 szInstr[2] = 0x20;
    1852                                 szInstr[3] = 0xC0 | Cpu.param1.base.reg_gen;
    1853                                 for (unsigned i = 4; i < 5+cbOp; i++)
    1854                                     szInstr[i] = 0x90;  /* nop */
    1855    
    1856                                 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 5+cbOp);
    1857                                 AssertRC(rc);
    1858    
    1859                                 Log(("Acceptable read candidate!\n"));
    1860                                 STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
    1861                                 goto ResumeExecution;
    1862                             }
    1863                         }
    1864                     }
     1718                    STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
     1719                    goto ResumeExecution;
    18651720                }
     1721
    18661722                rc = IOMMMIOPhysHandler(pVM, errCode, CPUMCTX2CORE(pCtx), uFaultAddress);
    18671723                if (rc == VINF_SUCCESS)
     
    20041860
    20051861        /* Truly a pita. Why can't SVM give the same information as VT-x? */
    2006         rc = SVMR0InterpretInvpg(pVM, pVCpu, CPUMCTX2CORE(pCtx), pVMCB->ctrl.TLBCtrl.n.u32ASID);
     1862        rc = svmR0InterpretInvpg(pVM, pVCpu, CPUMCTX2CORE(pCtx), pVMCB->ctrl.TLBCtrl.n.u32ASID);
    20071863        if (rc == VINF_SUCCESS)
    20081864        {
     
    24752331}
    24762332
     2333
     2334/**
     2335 * Attempt to patch TPR mmio instructions
     2336 *
     2337 * @returns VBox status code.
     2338 * @param   pVM         The VM to operate on.
     2339 * @param   pVCpu       The VM CPU to operate on.
     2340 * @param   pCtx        CPU context
     2341 */
     2342static int svmR0ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     2343{
     2344    DISCPUSTATE Cpu;
     2345    unsigned cbOp;
     2346
     2347    Log(("Replace TPR access at %RGv\n", pCtx->rip));
     2348
     2349    int rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
     2350    AssertRC(rc);
     2351    if (    rc == VINF_SUCCESS
     2352        &&  Cpu.pCurInstr->opcode == OP_MOV)
     2353    {
     2354        uint8_t szInstr[15];
     2355        if (    cbOp == 10
     2356            &&  Cpu.param1.flags == USE_DISPLACEMENT32
     2357            &&  Cpu.param2.flags == USE_IMMEDIATE32)
     2358        {
     2359            /* Found:
     2360             *   mov [fffe0080], immediate_dword                (10 bytes)
     2361             *
     2362             * Replace with:
     2363             *   mov free_register, immediate_dword >> 4        (5 bytes)
     2364             *   mov cr8, free_register                         (4 bytes)
     2365             *   nop                                            (1 byte)
     2366             *
     2367             */
     2368            RTGCPTR     oldEip = pCtx->eip;
     2369            uint32_t    u32tpr = (uint32_t)Cpu.param2.parval;
     2370
     2371            u32tpr = (u32tpr >> 4) & 0xf;
     2372
     2373            /* Check if the next instruction overwrites a general purpose register. If
     2374             * it does, then we can safely use it ourselves.
     2375             */
     2376            pCtx->eip += cbOp;
     2377            rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
     2378            pCtx->eip = oldEip;
     2379            if (    rc == VINF_SUCCESS
     2380                &&  Cpu.pCurInstr->opcode == OP_MOV
     2381                &&  Cpu.param1.flags == USE_REG_GEN32)
     2382            {
     2383                /* 0xB8, dword immediate  = mov eax, dword immediate */
     2384                szInstr[0] = 0xB8 + Cpu.param1.base.reg_gen;
     2385                szInstr[1] = (uint8_t)u32tpr;
     2386                szInstr[2] = 0;
     2387                szInstr[3] = 0;
     2388                szInstr[4] = 0;
     2389
     2390                /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
     2391                szInstr[5] = 0xF0;
     2392                szInstr[6] = 0x0F;
     2393                szInstr[7] = 0x22;
     2394                szInstr[8] = 0xC0 | Cpu.param1.base.reg_gen;
     2395                szInstr[9] = 0x90; /* nop */
     2396
     2397                rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 10);
     2398                AssertRC(rc);
     2399
     2400                Log(("Acceptable write candidate!\n"));
     2401                return VINF_SUCCESS;
     2402            }
     2403        }
     2404        else
     2405        {
     2406            if (    Cpu.param2.flags == USE_REG_GEN32
     2407                &&  cbOp == 6)
     2408            {
     2409                RTGCPTR  oldEip   = pCtx->eip;
     2410                RTGCPTR  GCPtrTpr = (uint32_t)Cpu.param1.disp32;
     2411                uint32_t uMmioReg = Cpu.param2.base.reg_gen;
     2412
     2413                /* Found:
     2414                 *   mov dword [fffe0080], eax        (6 bytes)
     2415                 * Check if next instruction is a TPR read:
     2416                 *   mov ecx, dword [fffe0080]        (5 bytes)
     2417                 */
     2418                pCtx->eip += cbOp;
     2419                rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
     2420                pCtx->eip = oldEip;
     2421                if (    rc == VINF_SUCCESS
     2422                    &&  Cpu.pCurInstr->opcode == OP_MOV
     2423                    &&  Cpu.param1.flags == USE_REG_GEN32
     2424                    &&  Cpu.param2.flags == USE_DISPLACEMENT32
     2425                    &&  Cpu.param2.disp32 == (uint32_t)GCPtrTpr
     2426                    &&  cbOp == 5)
     2427                {
     2428                    /* mov new_reg, uMmioReg */
     2429                    szInstr[0] = 0x89;
     2430                    szInstr[1] = MAKE_MODRM(3, uMmioReg, Cpu.param1.base.reg_gen);
     2431
     2432                    /* Let's hope the guest won't mind us trashing the source register...
     2433                     * shr uMmioReg, 4
     2434                     */
     2435                    szInstr[2] = 0xC1;
     2436                    szInstr[3] = 0xE8 | uMmioReg;
     2437                    szInstr[4] = 4;
     2438
     2439                    /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
     2440                    szInstr[5] = 0xF0;
     2441                    szInstr[6] = 0x0F;
     2442                    szInstr[7] = 0x22;
     2443                    szInstr[8] = 0xC0 | uMmioReg;
     2444
     2445                    /* Two nop instructions */
     2446                    szInstr[9] = 0x90;
     2447                    szInstr[10] = 0x90;
     2448
     2449                    rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 6+cbOp);
     2450                    AssertRC(rc);
     2451
     2452                    Log(("Acceptable write candidate!\n"));
     2453                    return VINF_SUCCESS;
     2454                }
     2455            }
     2456            else
     2457            if (    Cpu.param1.flags == USE_REG_GEN32
     2458                &&  cbOp == 5)
     2459            {
     2460                RTGCPTR  oldEip = pCtx->eip;
     2461                uint32_t uMmioReg = Cpu.param1.base.reg_gen;
     2462
     2463                /* Found:
     2464                 *   mov eax, dword [fffe0080]        (5 bytes)
     2465                 * Check if next instruction is:
     2466                 *   shr eax, 4
     2467                 */
     2468                pCtx->eip += cbOp;
     2469                rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
     2470                pCtx->eip = oldEip;
     2471                if (    rc == VINF_SUCCESS
     2472                    &&  Cpu.pCurInstr->opcode == OP_SHR
     2473                    &&  Cpu.param1.flags == USE_REG_GEN32
     2474                    &&  Cpu.param1.base.reg_gen == uMmioReg
     2475                    &&  Cpu.param2.flags == USE_IMMEDIATE8
     2476                    &&  Cpu.param2.parval == 4)
     2477                {
     2478                    /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
     2479                    szInstr[0] = 0xF0;
     2480                    szInstr[1] = 0x0F;
     2481                    szInstr[2] = 0x20;
     2482                    szInstr[3] = 0xC0 | Cpu.param1.base.reg_gen;
     2483                    for (unsigned i = 4; i < 5+cbOp; i++)
     2484                        szInstr[i] = 0x90;  /* nop */
     2485
     2486                    rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 5+cbOp);
     2487                    AssertRC(rc);
     2488
     2489                    Log(("Acceptable read candidate!\n"));
     2490                    return VINF_SUCCESS;
     2491                }
     2492            }
     2493        }
     2494    }
     2495    return VERR_ACCESS_DENIED;
     2496}
     2497
    24772498/**
    24782499 * Enters the AMD-V session
     
    25812602 *                      Updates the EIP if an instruction was executed successfully.
    25822603 */
    2583 static int SVMR0InterpretInvpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uASID)
     2604static int svmR0InterpretInvpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uASID)
    25842605{
    25852606    /*
Note: See TracChangeset for help on using the changeset viewer.

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