VirtualBox

Changeset 20317 in vbox


Ignore:
Timestamp:
Jun 5, 2009 12:20:10 PM (16 years ago)
Author:
vboxsync
Message:

Experiment with TPR patching (disabled)

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

Legend:

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

    r20291 r20317  
    4444#include <iprt/cpuset.h>
    4545#include <iprt/mp.h>
     46#include <iprt/time.h>
    4647#ifdef VBOX_WITH_VMMR0_DISABLE_PREEMPTION
    4748# include <iprt/thread.h>
     
    858859    RTCCUINTREG uOldEFlags = ~(RTCCUINTREG)0;
    859860#ifdef VBOX_STRICT
    860     RTCPUID  idCpuCheck;
     861    RTCPUID     idCpuCheck;
     862#endif
     863#ifdef VBOX_HIGH_RES_TIMERS_HACK_IN_RING0
     864    uint64_t    u64LastTime = RTTimeMilliTS();
    861865#endif
    862866
     
    900904        pVMCB->ctrl.u64IntShadow = 0;
    901905    }
     906
     907#ifdef VBOX_HIGH_RES_TIMERS_HACK_IN_RING0
     908    if (RT_UNLIKELY(cResume & 0xf) == 0)
     909    {
     910        uint64_t u64CurTime = RTTimeMilliTS();
     911
     912        if (RT_UNLIKELY(u64CurTime > u64LastTime))
     913        {
     914            u64LastTime = u64CurTime;
     915            TMTimerPollVoid(pVM, pVCpu);
     916        }
     917    }
     918#endif
    902919
    903920    /* Check for pending actions that force us to go back to ring 3. */
     
    15141531                            AssertRC(rc);
    15151532
    1516                             pVM->hwaccm.s.svm.fTPRPatching = true;
    15171533                            Log(("Acceptable write candidate!\n"));
    15181534                            STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
     
    15341550                            AssertRC(rc);
    15351551
    1536                             pVM->hwaccm.s.svm.fTPRPatching = true;
    15371552                            Log(("Acceptable read candidate!\n"));
    15381553                            STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
     
    16841699        Assert(pVM->hwaccm.s.fNestedPaging);
    16851700        LogFlow(("Nested page fault at %RGv cr2=%RGp error code %x\n", (RTGCPTR)pCtx->rip, uFaultAddress, errCode));
     1701
     1702#if 0
     1703        /* Shortcut for APIC TPR reads and writes; 32 bits guests only */
     1704        if (    (uFaultAddress & 0xfff) == 0x080
     1705            &&  pVM->hwaccm.s.fHasIoApic
     1706            &&  !(errCode & X86_TRAP_PF_P)  /* not present */
     1707            &&  !CPUMIsGuestInLongModeEx(pCtx))
     1708        {
     1709            RTGCPHYS GCPhysApicBase;
     1710            PDMApicGetBase(pVM, &GCPhysApicBase);   /* @todo cache this */
     1711            GCPhysApicBase &= PAGE_BASE_GC_MASK;
     1712
     1713            if (uFaultAddress == GCPhysApicBase + 0x80)
     1714            {
     1715                Log(("Replace TPR access at %RGv\n", pCtx->rip));
     1716                DISCPUSTATE Cpu;
     1717                unsigned cbOp;
     1718                rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
     1719                AssertRC(rc);
     1720                if (    rc == VINF_SUCCESS
     1721                    &&  Cpu.pCurInstr->opcode == OP_MOV)
     1722                {
     1723                    uint8_t szInstr[15];
     1724                    if (    cbOp == 10
     1725                        &&  (errCode & X86_TRAP_PF_RW)
     1726                        &&  Cpu.param2.flags == USE_IMMEDIATE32)
     1727                    {
     1728                        /* Found:
     1729                         *   mov [fffe0080], immediate_dword                (10 bytes)
     1730                         *
     1731                         * Replace with:
     1732                         *   mov free_register, immediate_dword >> 4        (5 bytes)
     1733                         *   mov cr8, free_register                         (4 bytes)
     1734                         *   nop                                            (1 byte)
     1735                         *
     1736                         */
     1737                        RTGCPTR     oldEip = pCtx->eip;
     1738                        uint32_t    u32tpr = (uint32_t)Cpu.param2.parval;
     1739
     1740                        u32tpr = (u32tpr >> 4) & 0xf;
     1741
     1742                        pCtx->eip += cbOp;
     1743                        /* Check if the next instruction overwrites a general purpose register. If
     1744                         * it does, then we can safely use it ourselves.
     1745                         */
     1746                        rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
     1747                        pCtx->eip = oldEip;
     1748                        if (    rc == VINF_SUCCESS
     1749                            &&  Cpu.pCurInstr->opcode == OP_MOV
     1750                            &&  Cpu.param1.flags == USE_REG_GEN32)
     1751                        {
     1752                            /* 0xB8, dword immediate  = mov eax, dword immediate */
     1753                            szInstr[0] = 0xB8 + Cpu.param1.base.reg_gen;
     1754                            szInstr[1] = (uint8_t)u32tpr;
     1755                            szInstr[2] = 0;
     1756                            szInstr[3] = 0;
     1757                            szInstr[4] = 0;
     1758
     1759                            /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
     1760                            szInstr[5] = 0xF0;
     1761                            szInstr[6] = 0x0F;
     1762                            szInstr[7] = 0x22;
     1763                            szInstr[8] = 0xC0 | Cpu.param1.base.reg_gen;
     1764                            szInstr[9] = 0x90; /* nop */
     1765
     1766                            rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 10);
     1767                            AssertRC(rc);
     1768
     1769                            Log(("Acceptable write candidate!\n"));
     1770                            STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
     1771                            goto ResumeExecution;
     1772                        }
     1773                    }
     1774                    else
     1775                    {
     1776                        if (    Cpu.param2.flags == USE_REG_GEN32
     1777                            &&  cbOp == 6)
     1778                        {
     1779                            RTGCPTR  oldEip   = pCtx->eip;
     1780                            RTGCPTR  GCPtrTpr = Cpu.param1.parval;
     1781                            uint32_t uMmioReg = Cpu.param2.base.reg_gen;
     1782
     1783                            /* Found:
     1784                             *   mov dword [fffe0080], eax        (6 bytes)
     1785                             * Check if next instruction is a TPR read:
     1786                             *   mov ecx, dword [fffe0080]        (5 bytes)
     1787                             */
     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_IMMEDIATE32
     1794                                &&  Cpu.param2.parval == GCPtrTpr
     1795                                &&  cbOp == 5)
     1796                            {
     1797                                /* mov new_reg, uMmioReg */
     1798                                szInstr[0] = 0x89;
     1799                                szInstr[1] = MAKE_MODRM(3, uMmioReg, Cpu.param2.base.reg_gen);
     1800                                szInstr[2] = 4;
     1801
     1802                                /* Let's hope the guest won't mind us trashing the source register...
     1803                                 * shr uMmioReg, 4
     1804                                 */
     1805                                szInstr[3] = 0xC1;
     1806                                szInstr[4] = 0xE0 | uMmioReg;
     1807                                szInstr[5] = 4;
     1808
     1809                                /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
     1810                                szInstr[6] = 0xF0;
     1811                                szInstr[7] = 0x0F;
     1812                                szInstr[8] = 0x22;
     1813                                szInstr[9] = 0xC0 | uMmioReg;
     1814
     1815                                /* Two nop instructions */
     1816                                szInstr[10] = 0x90;
     1817                                szInstr[11] = 0x90;
     1818
     1819                                rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 6+cbOp);
     1820                                AssertRC(rc);
     1821
     1822                                Log(("Acceptable write candidate!\n"));
     1823                                STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
     1824                                goto ResumeExecution;
     1825                            }
     1826                        }
     1827                        else
     1828                        if (    Cpu.param1.flags == USE_REG_GEN32
     1829                            &&  cbOp == 5)
     1830                        {
     1831                            RTGCPTR  oldEip = pCtx->eip;
     1832                            uint32_t uMmioReg = Cpu.param1.base.reg_gen;
     1833
     1834                            /* Found:
     1835                             *   mov eax, dword [fffe0080]        (5 bytes)
     1836                             * Check if next instruction is:
     1837                             *   shr eax, 4
     1838                             */
     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                    }
     1865                }
     1866                rc = IOMMMIOPhysHandler(pVM, errCode, CPUMCTX2CORE(pCtx), uFaultAddress);
     1867                if (rc == VINF_SUCCESS)
     1868                    goto ResumeExecution;   /* rip already updated */
     1869            }
     1870        }
     1871#endif
     1872
    16861873        /* Exit qualification contains the linear address of the page fault. */
    16871874        TRPMAssertTrap(pVCpu, X86_XCPT_PF, TRPM_TRAP);
    16881875        TRPMSetErrorCode(pVCpu, errCode);
    16891876        TRPMSetFaultAddress(pVCpu, uFaultAddress);
    1690 
    1691 #if 0
    1692             /* Shortcut for APIC TPR reads and writes; 32 bits guests only */
    1693             if (    (uFaultAddress & 0xfff) == 0x080
    1694                 &&  pVM->hwaccm.s.fHasIoApic
    1695                 &&  !(errCode & X86_TRAP_PF_P)  /* not present */
    1696                 &&  !CPUMIsGuestInLongModeEx(pCtx))
    1697             {
    1698                 RTGCPHYS GCPhysApicBase;
    1699                 PDMApicGetBase(pVM, &GCPhysApicBase);   /* @todo cache this */
    1700                 GCPhysApicBase &= PAGE_BASE_GC_MASK;
    1701 
    1702                 if (uFaultAddress == GCPhysApicBase + 0x80)
    1703                 {
    1704                     Log(("Replace TPR access at %RGv\n", pCtx->rip));
    1705 #if 0
    1706                     DISCPUSTATE Cpu;
    1707                     unsigned cbOp;
    1708                     rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
    1709                     AssertRC(rc);
    1710                     if (    rc == VINF_SUCCESS
    1711                         &&  Cpu.pCurInstr->opcode == OP_MOV
    1712                         &&  (cbOp == 5 || cbOp == 6))
    1713                     {
    1714                         uint8_t szInstr[15];
    1715                         if (    (errCode & X86_TRAP_PF_RW)
    1716                             &&  Cpu.param1.disp32 == (uint32_t)uFaultAddress
    1717                             &&  Cpu.param2.flags == USE_REG_GEN32)
    1718                         {
    1719                             /* 0xF0, 0x0F, 0x22, 0xC0 = mov cr8, eax */
    1720                             szInstr[0] = 0xF0;
    1721                             szInstr[1] = 0x0F;
    1722                             szInstr[2] = 0x22;
    1723                             szInstr[3] = 0xC0 | Cpu.param2.base.reg_gen;
    1724                             for (unsigned i = 4; i < cbOp; i++)
    1725                                 szInstr[i] = 0x90;  /* nop */
    1726 
    1727                             rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, cbOp);
    1728                             AssertRC(rc);
    1729 
    1730                             pVM->hwaccm.s.svm.fTPRPatching = true;
    1731                             Log(("Acceptable write candidate!\n"));
    1732                             STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
    1733                             goto ResumeExecution;
    1734                         }
    1735                         else
    1736                         if (    Cpu.param2.disp32 == (uint32_t)uFaultAddress
    1737                             &&  Cpu.param1.flags == USE_REG_GEN32)
    1738                         {
    1739                             /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
    1740                             szInstr[0] = 0xF0;
    1741                             szInstr[1] = 0x0F;
    1742                             szInstr[2] = 0x20;
    1743                             szInstr[3] = 0xC0 | Cpu.param1.base.reg_gen;
    1744                             for (unsigned i = 4; i < cbOp; i++)
    1745                                 szInstr[i] = 0x90;  /* nop */
    1746 
    1747                             rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, cbOp);
    1748                             AssertRC(rc);
    1749 
    1750                             pVM->hwaccm.s.svm.fTPRPatching = true;
    1751                             Log(("Acceptable read candidate!\n"));
    1752                             STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x);
    1753                             goto ResumeExecution;
    1754                         }
    1755                     }
    1756 #endif
    1757                 }
    1758             }
    1759 #endif
    17601877
    17611878        /* Handle the pagefault trap for the nested shadow table. */
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r20222 r20317  
    4040#include <iprt/param.h>
    4141#include <iprt/string.h>
     42#include <iprt/time.h>
    4243#ifdef VBOX_WITH_VMMR0_DISABLE_PREEMPTION
    4344# include <iprt/thread.h>
     
    20092010    unsigned    cResume = 0;
    20102011#ifdef VBOX_STRICT
    2011     RTCPUID  idCpuCheck;
     2012    RTCPUID     idCpuCheck;
     2013#endif
     2014#ifdef VBOX_HIGH_RES_TIMERS_HACK_IN_RING0
     2015    uint64_t    u64LastTime = RTTimeMilliTS();
    20122016#endif
    20132017#ifdef VBOX_WITH_STATISTICS
     
    21392143    }
    21402144
     2145#ifdef VBOX_HIGH_RES_TIMERS_HACK_IN_RING0
     2146    if (RT_UNLIKELY(cResume & 0xf) == 0)
     2147    {
     2148        uint64_t u64CurTime = RTTimeMilliTS();
     2149
     2150        if (RT_UNLIKELY(u64CurTime > u64LastTime))
     2151        {
     2152            u64LastTime = u64CurTime;
     2153            TMTimerPollVoid(pVM, pVCpu);
     2154        }
     2155    }
     2156#endif
     2157
    21412158    /* Check for pending actions that force us to go back to ring 3. */
    2142     if (    VM_FF_ISPENDING(pVM, VM_FF_HWACCM_TO_R3_MASK)
    2143         ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HWACCM_TO_R3_MASK))
    2144     {
    2145         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
    2146         STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatSwitchToR3);
    2147         rc = RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_NO_MEMORY : VINF_EM_RAW_TO_R3;
    2148         goto end;
    2149     }
     2159#ifdef DEBUG
     2160    /* Intercept X86_XCPT_DB if stepping is enabled */
     2161    if (!DBGFIsStepping(pVCpu))
     2162#endif
     2163    {
     2164        if (    VM_FF_ISPENDING(pVM, VM_FF_HWACCM_TO_R3_MASK)
     2165            ||  VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HWACCM_TO_R3_MASK))
     2166        {
     2167            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
     2168            STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatSwitchToR3);
     2169            rc = RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_NO_MEMORY : VINF_EM_RAW_TO_R3;
     2170            goto end;
     2171        }
     2172    }
     2173
    21502174    /* Pending request packets might contain actions that need immediate attention, such as pending hardware interrupts. */
    21512175    if (    VM_FF_ISPENDING(pVM, VM_FF_REQUEST)
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