VirtualBox

Changeset 41775 in vbox


Ignore:
Timestamp:
Jun 16, 2012 5:49:00 PM (12 years ago)
Author:
vboxsync
Message:

HWACCM: Fixed bug in the read-without-shr4 case in hwaccmR3ReplaceTprInstr. Plugged potential allocation race and did some cleaning up.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/HWACCM.cpp

    r41744 r41775  
    16731673    for (unsigned i = 0; i < pVM->hwaccm.s.cPatches; i++)
    16741674    {
    1675         uint8_t         szInstr[15];
     1675        uint8_t         abInstr[15];
    16761676        PHWACCMTPRPATCH pPatch = &pVM->hwaccm.s.aPatches[i];
    16771677        RTGCPTR         pInstrGC = (RTGCPTR)pPatch->Core.Key;
     
    16881688
    16891689        /* Check if the instruction is still the same. */
    1690         rc = PGMPhysSimpleReadGCPtr(pVCpu, szInstr, pInstrGC, pPatch->cbNewOp);
     1690        rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pInstrGC, pPatch->cbNewOp);
    16911691        if (rc != VINF_SUCCESS)
    16921692        {
     
    16951695        }
    16961696
    1697         if (memcmp(szInstr, pPatch->aNewOpcode, pPatch->cbNewOp))
     1697        if (memcmp(abInstr, pPatch->aNewOpcode, pPatch->cbNewOp))
    16981698        {
    16991699            Log(("Patched instruction was changed! (rc=%Rrc0\n", rc));
     
    17991799DECLCALLBACK(VBOXSTRICTRC) hwaccmR3ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser)
    18001800{
    1801     VMCPUID      idCpu  = (VMCPUID)(uintptr_t)pvUser;
    1802     PCPUMCTX     pCtx   = CPUMQueryGuestCtxPtr(pVCpu);
    1803     PDISCPUSTATE pDis   = &pVCpu->hwaccm.s.DisState;
    1804     unsigned     cbOp;
    1805 
    1806     /* Only execute the handler on the VCPU the original patch request was issued. (the other CPU(s) might not yet have switched to protected mode) */
     1801    /*
     1802     * Only execute the handler on the VCPU the original patch request was
     1803     * issued. (The other CPU(s) might not yet have switched to protected
     1804     * mode, nor have the correct memory context.)
     1805     */
     1806    VMCPUID         idCpu  = (VMCPUID)(uintptr_t)pvUser;
    18071807    if (pVCpu->idCpu != idCpu)
    18081808        return VINF_SUCCESS;
    18091809
    1810     Log(("hwaccmR3ReplaceTprInstr: %RGv\n", pCtx->rip));
    1811 
    1812     /* Two or more VCPUs were racing to patch this instruction. */
     1810    /*
     1811     * We're racing other VCPUs here, so don't try patch the instruction twice
     1812     * and make sure there is still room for our patch record.
     1813     */
     1814    PCPUMCTX        pCtx   = CPUMQueryGuestCtxPtr(pVCpu);
    18131815    PHWACCMTPRPATCH pPatch = (PHWACCMTPRPATCH)RTAvloU32Get(&pVM->hwaccm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
    18141816    if (pPatch)
     1817    {
     1818        Log(("hwaccmR3ReplaceTprInstr: already patched %RGv\n", pCtx->rip));
    18151819        return VINF_SUCCESS;
    1816 
    1817     Assert(pVM->hwaccm.s.cPatches < RT_ELEMENTS(pVM->hwaccm.s.aPatches));
    1818 
     1820    }
     1821    uint32_t const  idx = pVM->hwaccm.s.cPatches;
     1822    if (idx >= RT_ELEMENTS(pVM->hwaccm.s.aPatches))
     1823    {
     1824        Log(("hwaccmR3ReplaceTprInstr: no available patch slots (%RGv)\n", pCtx->rip));
     1825        return VINF_SUCCESS;
     1826    }
     1827    pPatch = &pVM->hwaccm.s.aPatches[idx];
     1828
     1829    Log(("hwaccmR3ReplaceTprInstr: rip=%RGv idxPatch=%u\n", pCtx->rip, idx));
     1830
     1831    /*
     1832     * Disassembler the instruction and get cracking.
     1833     */
     1834    DBGFR3DisasInstrCurrentLog(pVCpu, "hwaccmR3ReplaceTprInstr");
     1835    PDISCPUSTATE    pDis = &pVCpu->hwaccm.s.DisState;
     1836    uint32_t        cbOp;
    18191837    int rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
    18201838    AssertRC(rc);
     
    18231841        &&  cbOp >= 3)
    18241842    {
    1825         uint8_t         aVMMCall[3] = { 0xf, 0x1, 0xd9};
    1826         uint32_t        idx = pVM->hwaccm.s.cPatches;
    1827 
    1828         pPatch = &pVM->hwaccm.s.aPatches[idx];
     1843        static uint8_t const s_abVMMCall[3] = { 0x0f, 0x01, 0xd9 };
    18291844
    18301845        rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
    18311846        AssertRC(rc);
    18321847
    1833         pPatch->cbOp     = cbOp;
     1848        pPatch->cbOp = cbOp;
    18341849
    18351850        if (pDis->Param1.fUse == DISUSE_DISPLACEMENT32)
     
    18401855                pPatch->enmType     = HWACCMTPRINSTR_WRITE_REG;
    18411856                pPatch->uSrcOperand = pDis->Param2.Base.idxGenReg;
     1857                Log(("hwaccmR3ReplaceTprInstr: HWACCMTPRINSTR_WRITE_REG %u\n", pDis->Param2.Base.idxGenReg));
    18421858            }
    18431859            else
     
    18461862                pPatch->enmType     = HWACCMTPRINSTR_WRITE_IMM;
    18471863                pPatch->uSrcOperand = pDis->Param2.uValue;
     1864                Log(("hwaccmR3ReplaceTprInstr: HWACCMTPRINSTR_WRITE_IMM %#llx\n", pDis->Param2.uValue));
    18481865            }
    1849             rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));
     1866            rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, s_abVMMCall, sizeof(s_abVMMCall));
    18501867            AssertRC(rc);
    18511868
    1852             memcpy(pPatch->aNewOpcode, aVMMCall, sizeof(aVMMCall));
    1853             pPatch->cbNewOp = sizeof(aVMMCall);
     1869            memcpy(pPatch->aNewOpcode, s_abVMMCall, sizeof(s_abVMMCall));
     1870            pPatch->cbNewOp = sizeof(s_abVMMCall);
    18541871        }
    18551872        else
    18561873        {
    1857             RTGCPTR  oldrip   = pCtx->rip;
    1858             uint32_t oldcbOp  = cbOp;
    1859             uint32_t uMmioReg = pDis->Param1.Base.idxGenReg;
    1860 
    1861             /* read */
    1862             Assert(pDis->Param1.fUse == DISUSE_REG_GEN32);
    1863 
    1864             /* Found:
     1874            /*
     1875             * TPR Read.
     1876             *
     1877             * Found:
    18651878             *   mov eax, dword [fffe0080]        (5 bytes)
    18661879             * Check if next instruction is:
    18671880             *   shr eax, 4
    18681881             */
     1882            Assert(pDis->Param1.fUse == DISUSE_REG_GEN32);
     1883
     1884            uint8_t  const idxMmioReg = pDis->Param1.Base.idxGenReg;
     1885            uint8_t  const cbOpMmio   = cbOp;
     1886            uint64_t const uSavedRip  = pCtx->rip;
     1887
    18691888            pCtx->rip += cbOp;
    18701889            rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
    1871             pCtx->rip = oldrip;
     1890            DBGFR3DisasInstrCurrentLog(pVCpu, "Following read");
     1891            pCtx->rip = uSavedRip;
     1892
    18721893            if (    rc == VINF_SUCCESS
    18731894                &&  pDis->pCurInstr->uOpcode == OP_SHR
    18741895                &&  pDis->Param1.fUse == DISUSE_REG_GEN32
    1875                 &&  pDis->Param1.Base.idxGenReg == uMmioReg
     1896                &&  pDis->Param1.Base.idxGenReg == idxMmioReg
    18761897                &&  pDis->Param2.fUse == DISUSE_IMMEDIATE8
    18771898                &&  pDis->Param2.uValue == 4
    1878                 &&  oldcbOp + cbOp < sizeof(pVM->hwaccm.s.aPatches[idx].aOpcode))
     1899                &&  cbOpMmio + cbOp < sizeof(pVM->hwaccm.s.aPatches[idx].aOpcode))
    18791900            {
    1880                 uint8_t szInstr[15];
     1901                uint8_t abInstr[15];
    18811902
    18821903                /* Replacing two instructions now. */
    1883                 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, oldcbOp + cbOp);
     1904                rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, cbOpMmio + cbOp);
    18841905                AssertRC(rc);
    18851906
    1886                 pPatch->cbOp = oldcbOp + cbOp;
     1907                pPatch->cbOp = cbOpMmio + cbOp;
    18871908
    18881909                /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
    1889                 szInstr[0] = 0xF0;
    1890                 szInstr[1] = 0x0F;
    1891                 szInstr[2] = 0x20;
    1892                 szInstr[3] = 0xC0 | pDis->Param1.Base.idxGenReg;
     1910                abInstr[0] = 0xF0;
     1911                abInstr[1] = 0x0F;
     1912                abInstr[2] = 0x20;
     1913                abInstr[3] = 0xC0 | pDis->Param1.Base.idxGenReg;
    18931914                for (unsigned i = 4; i < pPatch->cbOp; i++)
    1894                     szInstr[i] = 0x90;  /* nop */
    1895 
    1896                 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, pPatch->cbOp);
     1915                    abInstr[i] = 0x90;  /* nop */
     1916
     1917                rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, abInstr, pPatch->cbOp);
    18971918                AssertRC(rc);
    18981919
    1899                 memcpy(pPatch->aNewOpcode, szInstr, pPatch->cbOp);
     1920                memcpy(pPatch->aNewOpcode, abInstr, pPatch->cbOp);
    19001921                pPatch->cbNewOp = pPatch->cbOp;
    19011922
     
    19061927            {
    19071928                pPatch->enmType     = HWACCMTPRINSTR_READ;
    1908                 pPatch->uDstOperand = pDis->Param1.Base.idxGenReg;
    1909 
    1910                 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));
     1929                pPatch->uDstOperand = idxMmioReg;
     1930
     1931                rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, s_abVMMCall, sizeof(s_abVMMCall));
    19111932                AssertRC(rc);
    19121933
    1913                 memcpy(pPatch->aNewOpcode, aVMMCall, sizeof(aVMMCall));
    1914                 pPatch->cbNewOp = sizeof(aVMMCall);
     1934                memcpy(pPatch->aNewOpcode, s_abVMMCall, sizeof(s_abVMMCall));
     1935                pPatch->cbNewOp = sizeof(s_abVMMCall);
     1936                Log(("hwaccmR3ReplaceTprInstr: HWACCMTPRINSTR_READ %u\n", pPatch->uDstOperand));
    19151937            }
    19161938        }
     
    19251947    }
    19261948
    1927     /* Save invalid patch, so we will not try again. */
    1928     uint32_t  idx = pVM->hwaccm.s.cPatches;
    1929 
    1930 #ifdef LOG_ENABLED
    1931     char      szOutput[256];
    1932     rc = DBGFR3DisasInstrEx(pVM, pVCpu->idCpu, pCtx->cs, pCtx->rip, DBGF_DISAS_FLAGS_DEFAULT_MODE,
    1933                             szOutput, sizeof(szOutput), NULL);
    1934     if (RT_SUCCESS(rc))
    1935         Log(("Failed to patch instr: %s\n", szOutput));
    1936 #endif
    1937 
    1938     pPatch = &pVM->hwaccm.s.aPatches[idx];
     1949    /*
     1950     * Save invalid patch, so we will not try again.
     1951     */
     1952    Log(("hwaccmR3ReplaceTprInstr: Failed to patch instr!\n"));
    19391953    pPatch->Core.Key = pCtx->eip;
    19401954    pPatch->enmType  = HWACCMTPRINSTR_INVALID;
     
    19571971DECLCALLBACK(VBOXSTRICTRC) hwaccmR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser)
    19581972{
    1959     VMCPUID      idCpu  = (VMCPUID)(uintptr_t)pvUser;
    1960     PCPUMCTX     pCtx   = CPUMQueryGuestCtxPtr(pVCpu);
    1961     PDISCPUSTATE pDis   = &pVCpu->hwaccm.s.DisState;
    1962     unsigned     cbOp;
    1963     int          rc;
    1964 #ifdef LOG_ENABLED
    1965     RTGCPTR      pInstr;
    1966     char         szOutput[256];
    1967 #endif
    1968 
    1969     /* Only execute the handler on the VCPU the original patch request was issued. (the other CPU(s) might not yet have switched to protected mode) */
     1973    /*
     1974     * Only execute the handler on the VCPU the original patch request was
     1975     * issued. (The other CPU(s) might not yet have switched to protected
     1976     * mode, nor have the correct memory context.)
     1977     */
     1978    VMCPUID         idCpu  = (VMCPUID)(uintptr_t)pvUser;
    19701979    if (pVCpu->idCpu != idCpu)
    19711980        return VINF_SUCCESS;
    19721981
    1973     Assert(pVM->hwaccm.s.cPatches < RT_ELEMENTS(pVM->hwaccm.s.aPatches));
    1974 
    1975     /* Two or more VCPUs were racing to patch this instruction. */
     1982    /*
     1983     * We're racing other VCPUs here, so don't try patch the instruction twice
     1984     * and make sure there is still room for our patch record.
     1985     */
     1986    PCPUMCTX        pCtx   = CPUMQueryGuestCtxPtr(pVCpu);
    19761987    PHWACCMTPRPATCH pPatch = (PHWACCMTPRPATCH)RTAvloU32Get(&pVM->hwaccm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
    19771988    if (pPatch)
     
    19801991        return VINF_SUCCESS;
    19811992    }
    1982 
    1983     Log(("hwaccmR3PatchTprInstr %RGv\n", pCtx->rip));
    1984 
    1985     rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
     1993    uint32_t const  idx = pVM->hwaccm.s.cPatches;
     1994    if (idx >= RT_ELEMENTS(pVM->hwaccm.s.aPatches))
     1995    {
     1996        Log(("hwaccmR3PatchTprInstr: no available patch slots (%RGv)\n", pCtx->rip));
     1997        return VINF_SUCCESS;
     1998    }
     1999    pPatch = &pVM->hwaccm.s.aPatches[idx];
     2000
     2001    Log(("hwaccmR3PatchTprInstr: rip=%RGv idxPatch=%u\n", pCtx->rip, idx));
     2002    DBGFR3DisasInstrCurrentLog(pVCpu, "hwaccmR3PatchTprInstr");
     2003
     2004    /*
     2005     * Disassemble the instruction and get cracking.
     2006     */
     2007    PDISCPUSTATE    pDis   = &pVCpu->hwaccm.s.DisState;
     2008    uint32_t        cbOp;
     2009    int rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);
    19862010    AssertRC(rc);
    19872011    if (    rc == VINF_SUCCESS
     
    19892013        &&  cbOp >= 5)
    19902014    {
    1991         uint32_t        idx = pVM->hwaccm.s.cPatches;
    19922015        uint8_t         aPatch[64];
    19932016        uint32_t        off = 0;
    1994 
    1995         pPatch = &pVM->hwaccm.s.aPatches[idx];
    1996 
    1997 #ifdef LOG_ENABLED
    1998         rc = DBGFR3DisasInstrEx(pVM, pVCpu->idCpu, pCtx->cs, pCtx->rip, DBGF_DISAS_FLAGS_DEFAULT_MODE,
    1999                                 szOutput, sizeof(szOutput), NULL);
    2000         if (RT_SUCCESS(rc))
    2001             Log(("Original instr: %s\n", szOutput));
    2002 #endif
    20032017
    20042018        rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
     
    21222136
    21232137#ifdef LOG_ENABLED
    2124             pInstr = pVM->hwaccm.s.pFreeGuestPatchMem;
    2125             while (true)
     2138            uint32_t cbCurInstr;
     2139            for (RTGCPTR GCPtrInstr = pVM->hwaccm.s.pFreeGuestPatchMem;
     2140                 GCPtrInstr < pVM->hwaccm.s.pFreeGuestPatchMem + off;
     2141                 GCPtrInstr += RT_MAX(cbCurInstr, 1))
    21262142            {
    2127                 uint32_t cb;
    2128 
    2129                 rc = DBGFR3DisasInstrEx(pVM, pVCpu->idCpu, pCtx->cs, pInstr, DBGF_DISAS_FLAGS_DEFAULT_MODE,
    2130                                         szOutput, sizeof(szOutput), &cb);
     2143                char     szOutput[256];
     2144                rc = DBGFR3DisasInstrEx(pVM, pVCpu->idCpu, pCtx->cs, GCPtrInstr, DBGF_DISAS_FLAGS_DEFAULT_MODE,
     2145                                        szOutput, sizeof(szOutput), &cbCurInstr);
    21312146                if (RT_SUCCESS(rc))
    21322147                    Log(("Patch instr %s\n", szOutput));
    2133 
    2134                 pInstr += cb;
    2135 
    2136                 if (pInstr >= pVM->hwaccm.s.pFreeGuestPatchMem + off)
    2137                     break;
     2148                else
     2149                    Log(("%RGv: rc=%Rrc\n", GCPtrInstr, rc));
    21382150            }
    21392151#endif
     
    21462158            AssertRC(rc);
    21472159
    2148 #ifdef LOG_ENABLED
    2149             rc = DBGFR3DisasInstrEx(pVM, pVCpu->idCpu, pCtx->cs, pCtx->rip, DBGF_DISAS_FLAGS_DEFAULT_MODE,
    2150                                     szOutput, sizeof(szOutput), NULL);
    2151             if (RT_SUCCESS(rc))
    2152                 Log(("Jump: %s\n", szOutput));
    2153 #endif
     2160            DBGFR3DisasInstrCurrentLog(pVCpu, "Jump");
     2161
    21542162            pVM->hwaccm.s.pFreeGuestPatchMem += off;
    21552163            pPatch->cbNewOp = 5;
     
    21642172            return VINF_SUCCESS;
    21652173        }
    2166         else
    2167             Log(("Ran out of space in our patch buffer!\n"));
    2168     }
    2169 
    2170     /* Save invalid patch, so we will not try again. */
    2171     uint32_t  idx = pVM->hwaccm.s.cPatches;
    2172 
    2173 #ifdef LOG_ENABLED
    2174     rc = DBGFR3DisasInstrEx(pVM, pVCpu->idCpu, pCtx->cs, pCtx->rip, DBGF_DISAS_FLAGS_DEFAULT_MODE,
    2175                             szOutput, sizeof(szOutput), NULL);
    2176     if (RT_SUCCESS(rc))
    2177         Log(("Failed to patch instr: %s\n", szOutput));
    2178 #endif
    2179 
     2174
     2175        Log(("Ran out of space in our patch buffer!\n"));
     2176    }
     2177    else
     2178        Log(("hwaccmR3PatchTprInstr: Failed to patch instr!\n"));
     2179
     2180
     2181    /*
     2182     * Save invalid patch, so we will not try again.
     2183     */
    21802184    pPatch = &pVM->hwaccm.s.aPatches[idx];
    21812185    pPatch->Core.Key = pCtx->eip;
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