Changeset 41775 in vbox
- Timestamp:
- Jun 16, 2012 5:49:00 PM (12 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/VMM/VMMR3/HWACCM.cpp (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/HWACCM.cpp
r41744 r41775 1673 1673 for (unsigned i = 0; i < pVM->hwaccm.s.cPatches; i++) 1674 1674 { 1675 uint8_t szInstr[15];1675 uint8_t abInstr[15]; 1676 1676 PHWACCMTPRPATCH pPatch = &pVM->hwaccm.s.aPatches[i]; 1677 1677 RTGCPTR pInstrGC = (RTGCPTR)pPatch->Core.Key; … … 1688 1688 1689 1689 /* Check if the instruction is still the same. */ 1690 rc = PGMPhysSimpleReadGCPtr(pVCpu, szInstr, pInstrGC, pPatch->cbNewOp);1690 rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pInstrGC, pPatch->cbNewOp); 1691 1691 if (rc != VINF_SUCCESS) 1692 1692 { … … 1695 1695 } 1696 1696 1697 if (memcmp( szInstr, pPatch->aNewOpcode, pPatch->cbNewOp))1697 if (memcmp(abInstr, pPatch->aNewOpcode, pPatch->cbNewOp)) 1698 1698 { 1699 1699 Log(("Patched instruction was changed! (rc=%Rrc0\n", rc)); … … 1799 1799 DECLCALLBACK(VBOXSTRICTRC) hwaccmR3ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser) 1800 1800 { 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; 1807 1807 if (pVCpu->idCpu != idCpu) 1808 1808 return VINF_SUCCESS; 1809 1809 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); 1813 1815 PHWACCMTPRPATCH pPatch = (PHWACCMTPRPATCH)RTAvloU32Get(&pVM->hwaccm.s.PatchTree, (AVLOU32KEY)pCtx->eip); 1814 1816 if (pPatch) 1817 { 1818 Log(("hwaccmR3ReplaceTprInstr: already patched %RGv\n", pCtx->rip)); 1815 1819 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; 1819 1837 int rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp); 1820 1838 AssertRC(rc); … … 1823 1841 && cbOp >= 3) 1824 1842 { 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 }; 1829 1844 1830 1845 rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp); 1831 1846 AssertRC(rc); 1832 1847 1833 pPatch->cbOp = cbOp;1848 pPatch->cbOp = cbOp; 1834 1849 1835 1850 if (pDis->Param1.fUse == DISUSE_DISPLACEMENT32) … … 1840 1855 pPatch->enmType = HWACCMTPRINSTR_WRITE_REG; 1841 1856 pPatch->uSrcOperand = pDis->Param2.Base.idxGenReg; 1857 Log(("hwaccmR3ReplaceTprInstr: HWACCMTPRINSTR_WRITE_REG %u\n", pDis->Param2.Base.idxGenReg)); 1842 1858 } 1843 1859 else … … 1846 1862 pPatch->enmType = HWACCMTPRINSTR_WRITE_IMM; 1847 1863 pPatch->uSrcOperand = pDis->Param2.uValue; 1864 Log(("hwaccmR3ReplaceTprInstr: HWACCMTPRINSTR_WRITE_IMM %#llx\n", pDis->Param2.uValue)); 1848 1865 } 1849 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));1866 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, s_abVMMCall, sizeof(s_abVMMCall)); 1850 1867 AssertRC(rc); 1851 1868 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); 1854 1871 } 1855 1872 else 1856 1873 { 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: 1865 1878 * mov eax, dword [fffe0080] (5 bytes) 1866 1879 * Check if next instruction is: 1867 1880 * shr eax, 4 1868 1881 */ 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 1869 1888 pCtx->rip += cbOp; 1870 1889 rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp); 1871 pCtx->rip = oldrip; 1890 DBGFR3DisasInstrCurrentLog(pVCpu, "Following read"); 1891 pCtx->rip = uSavedRip; 1892 1872 1893 if ( rc == VINF_SUCCESS 1873 1894 && pDis->pCurInstr->uOpcode == OP_SHR 1874 1895 && pDis->Param1.fUse == DISUSE_REG_GEN32 1875 && pDis->Param1.Base.idxGenReg == uMmioReg1896 && pDis->Param1.Base.idxGenReg == idxMmioReg 1876 1897 && pDis->Param2.fUse == DISUSE_IMMEDIATE8 1877 1898 && pDis->Param2.uValue == 4 1878 && oldcbOp+ cbOp < sizeof(pVM->hwaccm.s.aPatches[idx].aOpcode))1899 && cbOpMmio + cbOp < sizeof(pVM->hwaccm.s.aPatches[idx].aOpcode)) 1879 1900 { 1880 uint8_t szInstr[15];1901 uint8_t abInstr[15]; 1881 1902 1882 1903 /* Replacing two instructions now. */ 1883 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, oldcbOp+ cbOp);1904 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, cbOpMmio + cbOp); 1884 1905 AssertRC(rc); 1885 1906 1886 pPatch->cbOp = oldcbOp+ cbOp;1907 pPatch->cbOp = cbOpMmio + cbOp; 1887 1908 1888 1909 /* 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; 1893 1914 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); 1897 1918 AssertRC(rc); 1898 1919 1899 memcpy(pPatch->aNewOpcode, szInstr, pPatch->cbOp);1920 memcpy(pPatch->aNewOpcode, abInstr, pPatch->cbOp); 1900 1921 pPatch->cbNewOp = pPatch->cbOp; 1901 1922 … … 1906 1927 { 1907 1928 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)); 1911 1932 AssertRC(rc); 1912 1933 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)); 1915 1937 } 1916 1938 } … … 1925 1947 } 1926 1948 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")); 1939 1953 pPatch->Core.Key = pCtx->eip; 1940 1954 pPatch->enmType = HWACCMTPRINSTR_INVALID; … … 1957 1971 DECLCALLBACK(VBOXSTRICTRC) hwaccmR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser) 1958 1972 { 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; 1970 1979 if (pVCpu->idCpu != idCpu) 1971 1980 return VINF_SUCCESS; 1972 1981 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); 1976 1987 PHWACCMTPRPATCH pPatch = (PHWACCMTPRPATCH)RTAvloU32Get(&pVM->hwaccm.s.PatchTree, (AVLOU32KEY)pCtx->eip); 1977 1988 if (pPatch) … … 1980 1991 return VINF_SUCCESS; 1981 1992 } 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); 1986 2010 AssertRC(rc); 1987 2011 if ( rc == VINF_SUCCESS … … 1989 2013 && cbOp >= 5) 1990 2014 { 1991 uint32_t idx = pVM->hwaccm.s.cPatches;1992 2015 uint8_t aPatch[64]; 1993 2016 uint32_t off = 0; 1994 1995 pPatch = &pVM->hwaccm.s.aPatches[idx];1996 1997 #ifdef LOG_ENABLED1998 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 #endif2003 2017 2004 2018 rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp); … … 2122 2136 2123 2137 #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)) 2126 2142 { 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); 2131 2146 if (RT_SUCCESS(rc)) 2132 2147 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)); 2138 2150 } 2139 2151 #endif … … 2146 2158 AssertRC(rc); 2147 2159 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 2154 2162 pVM->hwaccm.s.pFreeGuestPatchMem += off; 2155 2163 pPatch->cbNewOp = 5; … … 2164 2172 return VINF_SUCCESS; 2165 2173 } 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 */ 2180 2184 pPatch = &pVM->hwaccm.s.aPatches[idx]; 2181 2185 pPatch->Core.Key = pCtx->eip;
Note:
See TracChangeset
for help on using the changeset viewer.

