Changeset 100694 in vbox
- Timestamp:
- Jul 25, 2023 10:34:22 AM (20 months ago)
- svn:sync-xref-src-repo-rev:
- 158538
- Location:
- trunk
- Files:
-
- 7 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r100566 r100694 2503 2503 /** Recompiled execution: Stop execution TB - Mode (fExec) changed. */ 2504 2504 #define VINF_IEM_REEXEC_MODE_CHANGED (5310) 2505 /** Recompilation: End translation block. */ 2506 #define VINF_IEM_RECOMPILE_END_TB (5311) 2507 2505 2508 /** Restart the current instruction. For testing only. */ 2506 2509 #define VERR_IEM_RESTART_INSTRUCTION (-5389) -
trunk/src/VBox/VMM/Makefile.kmk
r100672 r100694 249 249 VBoxVMM_SOURCES += \ 250 250 VMMAll/IEMAllThreadedRecompiler.cpp \ 251 VMMAll/IEMAllThreadedFunctions.cpp 251 VMMAll/IEMAllThreadedFunctions.cpp \ 252 VMMAll/IEMAllThreadedFunctionsBltIn.cpp 252 253 endif 253 254 -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r100672 r100694 997 997 { 998 998 Log(("iemOpcodeFetchMoreBytes: %04x:%08RX64 LB %#x + %#zx -> #GP(0)\n", 999 pVCpu->cpum.GstCtx.cs , pVCpu->cpum.GstCtx.rip, cbInstr, cbDst));999 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, cbInstr, cbDst)); 1000 1000 iemRaiseGeneralProtectionFault0Jmp(pVCpu); 1001 1001 } … … 1007 1007 pVCpu->iem.s.GCPhysInstrBuf = pTlbe->GCPhys; 1008 1008 pVCpu->iem.s.pbInstrBuf = pTlbe->pbMappingR3; 1009 pVCpu->iem.s.fTbCrossedPage |= offPg == 0; 1009 1010 memcpy(pvDst, &pTlbe->pbMappingR3[offPg], cbDst); 1010 1011 return; … … 1060 1061 { 1061 1062 Log(("iemOpcodeFetchMoreBytes: %04x:%08RX64 LB %#x + %#zx -> #GP(0) [slow]\n", 1062 pVCpu->cpum.GstCtx.cs , pVCpu->cpum.GstCtx.rip, cbInstr, cbDst));1063 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, cbInstr, cbDst)); 1063 1064 iemRaiseGeneralProtectionFault0Jmp(pVCpu); 1064 1065 } … … 1098 1099 pVCpu->iem.s.uInstrBufPc = GCPtrFirst & ~(RTGCPTR)X86_PAGE_OFFSET_MASK; 1099 1100 pVCpu->iem.s.pbInstrBuf = NULL; 1101 pVCpu->iem.s.fTbCrossedPage |= offPg == 0; 1100 1102 if (cbToRead == cbDst) 1101 1103 return; … … 1185 1187 { 1186 1188 Log(("iemOpcodeFetchMoreBytes: %04x:%08RX64 LB %#x + %#zx -> #GP(0)\n", 1187 pVCpu->cpum.GstCtx.cs , pVCpu->cpum.GstCtx.rip, offOpcode, cbMin));1189 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, offOpcode, cbMin)); 1188 1190 return iemRaiseGeneralProtectionFault0(pVCpu); 1189 1191 } -
trunk/src/VBox/VMM/VMMAll/IEMAllThreadedFunctions.cpp
r100326 r100694 610 610 611 611 612 613 /**614 * Built-in function that compares the fExec mask against uParam0.615 */616 static IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckMode,617 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2))618 {619 uint32_t const fExpectedExec = (uint32_t)uParam0;620 if (pVCpu->iem.s.fExec == fExpectedExec)621 return VINF_SUCCESS;622 Log12(("Mode changed at %04x:%08RX64: %#x -> %#x (xor: %#x)\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,623 fExpectedExec, pVCpu->iem.s.fExec, fExpectedExec ^ pVCpu->iem.s.fExec));624 RT_NOREF(uParam1, uParam2);625 return VINF_IEM_REEXEC_MODE_CHANGED;626 }627 628 629 /**630 * Built-in function that checks the EIP/IP + uParam0 is within CS.LIM,631 * raising a \#GP(0) if this isn't the case.632 */633 static IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLim,634 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2))635 {636 uint32_t const cbInstr = (uint32_t)uParam0;637 if (pVCpu->cpum.GstCtx.eip - pVCpu->cpum.GstCtx.cs.u32Limit >= cbInstr)638 return VINF_SUCCESS;639 Log(("EIP out of bounds at %04x:%08RX32 LB %u - CS.LIM=%#RX32\n",640 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip, cbInstr, pVCpu->cpum.GstCtx.cs.u32Limit));641 RT_NOREF(uParam1, uParam2);642 return iemRaiseGeneralProtectionFault0(pVCpu);643 }644 645 612 /* 646 613 * The threaded functions. -
trunk/src/VBox/VMM/VMMAll/IEMAllThreadedFunctionsBltIn.cpp
r100670 r100694 1 1 /* $Id$ */ 2 2 /** @file 3 * IEM - Instruction Decoding and Emulation, Threaded Functions. 3 * IEM - Instruction Decoding and Emulation, Built-in Threaded Functions. 4 * 5 * This is separate from IEMThreadedFunctions.cpp because it doesn't work 6 * with IEM_WITH_OPAQUE_DECODER_STATE defined. 4 7 */ 5 8 … … 30 33 * Header Files * 31 34 *********************************************************************************************************************************/ 32 #ifndef LOG_GROUP /* defined when included by tstIEMCheckMc.cpp */ 33 # define LOG_GROUP LOG_GROUP_IEM 34 #endif 35 #define LOG_GROUP LOG_GROUP_IEM_RE_THREADED 35 36 #define VMCPU_INCL_CPUM_GST_CTX 36 #define IEM_WITH_OPAQUE_DECODER_STATE37 37 #include <VBox/vmm/iem.h> 38 38 #include <VBox/vmm/cpum.h> … … 68 68 69 69 #include "IEMInline.h" 70 #include "IEMMc.h" 71 72 #include "IEMThreadedFunctions.h" 73 74 75 /********************************************************************************************************************************* 76 * Defined Constants And Macros * 77 *********************************************************************************************************************************/ 78 79 /** Variant of IEM_MC_ADVANCE_RIP_AND_FINISH with instruction length as param 80 * and only used when we're in 16-bit code on a pre-386 CPU. */ 81 #define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16(a_cbInstr) \ 82 return iemRegAddToIp16AndFinishingClearingRF(pVCpu, a_cbInstr) 83 84 /** Variant of IEM_MC_ADVANCE_RIP_AND_FINISH with instruction length as param 85 * and used for 16-bit and 32-bit code on 386 and later CPUs. */ 86 #define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32(a_cbInstr) \ 87 return iemRegAddToEip32AndFinishingClearingRF(pVCpu, a_cbInstr) 88 89 /** Variant of IEM_MC_ADVANCE_RIP_AND_FINISH with instruction length as param 90 * and only used when we're in 64-bit code. */ 91 #define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64(a_cbInstr) \ 92 return iemRegAddToRip64AndFinishingClearingRF(pVCpu, a_cbInstr) 93 94 #undef IEM_MC_ADVANCE_RIP_AND_FINISH 95 96 97 /** Variant of IEM_MC_REL_JMP_S8_AND_FINISH with instruction length as extra 98 * parameter, for use in 16-bit code on a pre-386 CPU. */ 99 #define IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16(a_i8, a_cbInstr) \ 100 return iemRegIp16RelativeJumpS8AndFinishClearingRF(pVCpu, a_cbInstr, (a_i8)) 101 102 /** Variant of IEM_MC_REL_JMP_S8_AND_FINISH with instruction length and operand 103 * size as extra parameters, for use in 16-bit and 32-bit code on 386 and 104 * later CPUs. */ 105 #define IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32(a_i8, a_cbInstr, a_enmEffOpSize) \ 106 return iemRegEip32RelativeJumpS8AndFinishClearingRF(pVCpu, a_cbInstr, (a_i8), a_enmEffOpSize) 107 108 /** Variant of IEM_MC_REL_JMP_S8_AND_FINISH with instruction length and operand 109 * size as extra parameters, for use in 64-bit code. */ 110 #define IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64(a_i8, a_cbInstr, a_enmEffOpSize) \ 111 return iemRegRip64RelativeJumpS8AndFinishClearingRF(pVCpu, a_cbInstr, (a_i8), a_enmEffOpSize) 112 113 #undef IEM_MC_REL_JMP_S8_AND_FINISH 114 115 116 /** Variant of IEM_MC_REL_JMP_S16_AND_FINISH with instruction length as 117 * param, for use in 16-bit code on a pre-386 CPU. */ 118 #define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16(a_i16, a_cbInstr) \ 119 return iemRegEip32RelativeJumpS16AndFinishClearingRF(pVCpu, a_cbInstr, (a_i16)) 120 121 /** Variant of IEM_MC_REL_JMP_S16_AND_FINISH with instruction length as 122 * param, for use in 16-bit and 32-bit code on 386 and later CPUs. */ 123 #define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32(a_i16, a_cbInstr) \ 124 return iemRegEip32RelativeJumpS16AndFinishClearingRF(pVCpu, a_cbInstr, (a_i16)) 125 126 /** Variant of IEM_MC_REL_JMP_S16_AND_FINISH with instruction length as 127 * param, for use in 64-bit code. */ 128 #define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64(a_i16, a_cbInstr) \ 129 return iemRegRip64RelativeJumpS16AndFinishClearingRF(pVCpu, a_cbInstr, (a_i16)) 130 131 #undef IEM_MC_REL_JMP_S16_AND_FINISH 132 133 134 /** Variant of IEM_MC_REL_JMP_S32_AND_FINISH with instruction length as 135 * an extra parameter - dummy for pre-386 variations not eliminated by the 136 * python script. */ 137 #define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC16(a_i32, a_cbInstr) \ 138 do { RT_NOREF(pVCpu, a_i32, a_cbInstr); AssertFailedReturn(VERR_IEM_IPE_9); } while (0) 139 140 /** Variant of IEM_MC_REL_JMP_S32_AND_FINISH with instruction length as 141 * an extra parameter, for use in 16-bit and 32-bit code on 386+. */ 142 #define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32(a_i32, a_cbInstr) \ 143 return iemRegEip32RelativeJumpS32AndFinishClearingRF(pVCpu, a_cbInstr, (a_i32)) 144 145 /** Variant of IEM_MC_REL_JMP_S32_AND_FINISH with instruction length as 146 * an extra parameter, for use in 64-bit code. */ 147 #define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64(a_i32, a_cbInstr) \ 148 return iemRegRip64RelativeJumpS32AndFinishClearingRF(pVCpu, a_cbInstr, (a_i32)) 149 150 #undef IEM_MC_REL_JMP_S32_AND_FINISH 151 152 153 /** Variant of IEM_MC_CALC_RM_EFF_ADDR with additional parameters, 16-bit. */ 154 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_16(a_GCPtrEff, a_bRm, a_u16Disp) \ 155 (a_GCPtrEff) = iemOpHlpCalcRmEffAddrThreadedAddr16(pVCpu, a_bRm, a_u16Disp) 156 157 /** Variant of IEM_MC_CALC_RM_EFF_ADDR with additional parameters, pre-386 16-bit. */ 158 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_16_PRE386(a_GCPtrEff, a_bRm, a_u16Disp) \ 159 IEM_MC_CALC_RM_EFF_ADDR_THREADED_16(a_GCPtrEff, a_bRm, a_u16Disp) 160 161 /** Variant of IEM_MC_CALC_RM_EFF_ADDR with additional parameters, 32-bit with address prefix. */ 162 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_32_ADDR16(a_GCPtrEff, a_bRm, a_u16Disp) \ 163 IEM_MC_CALC_RM_EFF_ADDR_THREADED_16(a_GCPtrEff, a_bRm, a_u16Disp) 164 165 166 /** Variant of IEM_MC_CALC_RM_EFF_ADDR with additional parameters, 32-bit. */ 167 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_32(a_GCPtrEff, a_bRm, a_uSibAndRspOffset, a_u32Disp) \ 168 (a_GCPtrEff) = iemOpHlpCalcRmEffAddrThreadedAddr32(pVCpu, a_bRm, a_uSibAndRspOffset, a_u32Disp) 169 170 /** Variant of IEM_MC_CALC_RM_EFF_ADDR with additional parameters, 32-bit flat. */ 171 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_32_FLAT(a_GCPtrEff, a_bRm, a_uSibAndRspOffset, a_u32Disp) \ 172 (a_GCPtrEff) = iemOpHlpCalcRmEffAddrThreadedAddr32(pVCpu, a_bRm, a_uSibAndRspOffset, a_u32Disp) 173 174 /** Variant of IEM_MC_CALC_RM_EFF_ADDR with additional parameters, 16-bit with address prefix. */ 175 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_16_ADDR32(a_GCPtrEff, a_bRm, a_uSibAndRspOffset, a_u32Disp) \ 176 (a_GCPtrEff) = iemOpHlpCalcRmEffAddrThreadedAddr32(pVCpu, a_bRm, a_uSibAndRspOffset, a_u32Disp) 177 178 179 /** Variant of IEM_MC_CALC_RM_EFF_ADDR with additional parameters. */ 180 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_64(a_GCPtrEff, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm) \ 181 (a_GCPtrEff) = iemOpHlpCalcRmEffAddrThreadedAddr64(pVCpu, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm) 182 183 /** Variant of IEM_MC_CALC_RM_EFF_ADDR with additional parameters. 184 * @todo How did that address prefix thing work for 64-bit code again? */ 185 #define IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_ADDR32(a_GCPtrEff, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm) \ 186 (a_GCPtrEff) = (uint32_t)iemOpHlpCalcRmEffAddrThreadedAddr64(pVCpu, a_bRmEx, a_uSibAndRspOffset, a_u32Disp, a_cbImm) 187 188 #undef IEM_MC_CALC_RM_EFF_ADDR 189 190 191 /** Variant of IEM_MC_CALL_CIMPL_1 with explicit instruction length parameter. */ 192 #define IEM_MC_CALL_CIMPL_1_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0) \ 193 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0) 194 #undef IEM_MC_CALL_CIMPL_1 195 196 /** Variant of IEM_MC_CALL_CIMPL_2 with explicit instruction length parameter. */ 197 #define IEM_MC_CALL_CIMPL_2_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1) \ 198 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0, a1) 199 #undef IEM_MC_CALL_CIMPL_2 200 201 /** Variant of IEM_MC_CALL_CIMPL_3 with explicit instruction length parameter. */ 202 #define IEM_MC_CALL_CIMPL_3_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1, a2) \ 203 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0, a1, a2) 204 #undef IEM_MC_CALL_CIMPL_3 205 206 /** Variant of IEM_MC_CALL_CIMPL_4 with explicit instruction length parameter. */ 207 #define IEM_MC_CALL_CIMPL_4_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1, a2, a3) \ 208 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0, a1, a2, a3) 209 #undef IEM_MC_CALL_CIMPL_4 210 211 /** Variant of IEM_MC_CALL_CIMPL_5 with explicit instruction length parameter. */ 212 #define IEM_MC_CALL_CIMPL_5_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1, a2, a3, a4) \ 213 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0, a1, a2, a3, a4) 214 #undef IEM_MC_CALL_CIMPL_5 215 216 217 /** Variant of IEM_MC_DEFER_TO_CIMPL_0_RET with explicit instruction 218 * length parameter. */ 219 #define IEM_MC_DEFER_TO_CIMPL_0_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl) \ 220 return (a_pfnCImpl)(pVCpu, (a_cbInstr)) 221 #undef IEM_MC_DEFER_TO_CIMPL_0_RET 222 223 /** Variant of IEM_MC_DEFER_TO_CIMPL_1_RET with explicit instruction 224 * length parameter. */ 225 #define IEM_MC_DEFER_TO_CIMPL_1_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0) \ 226 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0) 227 #undef IEM_MC_DEFER_TO_CIMPL_1_RET 228 229 /** Variant of IEM_MC_CALL_CIMPL_2 with explicit instruction length parameter. */ 230 #define IEM_MC_DEFER_TO_CIMPL_2_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1) \ 231 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0, a1) 232 #undef IEM_MC_DEFER_TO_CIMPL_2_RET 233 234 /** Variant of IEM_MC_DEFER_TO_CIMPL_3 with explicit instruction length 235 * parameter. */ 236 #define IEM_MC_DEFER_TO_CIMPL_3_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1, a2) \ 237 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0, a1, a2) 238 #undef IEM_MC_DEFER_TO_CIMPL_3_RET 239 240 /** Variant of IEM_MC_DEFER_TO_CIMPL_4 with explicit instruction length 241 * parameter. */ 242 #define IEM_MC_DEFER_TO_CIMPL_4_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1, a2, a3) \ 243 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0, a1, a2, a3) 244 #undef IEM_MC_DEFER_TO_CIMPL_4_RET 245 246 /** Variant of IEM_MC_DEFER_TO_CIMPL_5 with explicit instruction length 247 * parameter. */ 248 #define IEM_MC_DEFER_TO_CIMPL_5_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1, a2, a3, a4) \ 249 return (a_pfnCImpl)(pVCpu, (a_cbInstr), a0, a1, a2, a3, a4) 250 #undef IEM_MC_DEFER_TO_CIMPL_5_RET 251 252 253 /** Variant of IEM_MC_FETCH_GREG_U8 with extended (20) register index. */ 254 #define IEM_MC_FETCH_GREG_U8_THREADED(a_u8Dst, a_iGRegEx) \ 255 (a_u8Dst) = iemGRegFetchU8Ex(pVCpu, (a_iGRegEx)) 256 257 /** Variant of IEM_MC_FETCH_GREG_U8_ZX_U16 with extended (20) register index. */ 258 #define IEM_MC_FETCH_GREG_U8_ZX_U16_THREADED(a_u16Dst, a_iGRegEx) \ 259 (a_u16Dst) = iemGRegFetchU8Ex(pVCpu, (a_iGRegEx)) 260 261 /** Variant of IEM_MC_FETCH_GREG_U8_ZX_U32 with extended (20) register index. */ 262 #define IEM_MC_FETCH_GREG_U8_ZX_U32_THREADED(a_u32Dst, a_iGRegEx) \ 263 (a_u32Dst) = iemGRegFetchU8Ex(pVCpu, (a_iGRegEx)) 264 265 /** Variant of IEM_MC_FETCH_GREG_U8_ZX_U64 with extended (20) register index. */ 266 #define IEM_MC_FETCH_GREG_U8_ZX_U64_THREADED(a_u64Dst, a_iGRegEx) \ 267 (a_u64Dst) = iemGRegFetchU8Ex(pVCpu, (a_iGRegEx)) 268 269 /** Variant of IEM_MC_FETCH_GREG_U8_SX_U16 with extended (20) register index. */ 270 #define IEM_MC_FETCH_GREG_U8_SX_U16_THREADED(a_u16Dst, a_iGRegEx) \ 271 (a_u16Dst) = (int8_t)iemGRegFetchU8Ex(pVCpu, (a_iGRegEx)) 272 273 /** Variant of IEM_MC_FETCH_GREG_U8_SX_U32 with extended (20) register index. */ 274 #define IEM_MC_FETCH_GREG_U8_SX_U32_THREADED(a_u32Dst, a_iGRegEx) \ 275 (a_u32Dst) = (int8_t)iemGRegFetchU8Ex(pVCpu, (a_iGRegEx)) 276 #undef IEM_MC_FETCH_GREG_U8_SX_U32 277 278 /** Variant of IEM_MC_FETCH_GREG_U8_SX_U64 with extended (20) register index. */ 279 #define IEM_MC_FETCH_GREG_U8_SX_U64_THREADED(a_u64Dst, a_iGRegEx) \ 280 (a_u64Dst) = (int8_t)iemGRegFetchU8Ex(pVCpu, (a_iGRegEx)) 281 #undef IEM_MC_FETCH_GREG_U8_SX_U64 282 283 /** Variant of IEM_MC_STORE_GREG_U8 with extended (20) register index. */ 284 #define IEM_MC_STORE_GREG_U8_THREADED(a_iGRegEx, a_u8Value) \ 285 *iemGRegRefU8Ex(pVCpu, (a_iGRegEx)) = (a_u8Value) 286 #undef IEM_MC_STORE_GREG_U8 287 288 /** Variant of IEM_MC_STORE_GREG_U8 with extended (20) register index. */ 289 #define IEM_MC_STORE_GREG_U8_CONST_THREADED(a_iGRegEx, a_u8Value) \ 290 *iemGRegRefU8Ex(pVCpu, (a_iGRegEx)) = (a_u8Value) 291 #undef IEM_MC_STORE_GREG_U8 292 293 /** Variant of IEM_MC_REF_GREG_U8 with extended (20) register index. */ 294 #define IEM_MC_REF_GREG_U8_THREADED(a_pu8Dst, a_iGRegEx) \ 295 (a_pu8Dst) = iemGRegRefU8Ex(pVCpu, (a_iGRegEx)) 296 #undef IEM_MC_REF_GREG_U8 297 298 /** Variant of IEM_MC_ADD_GREG_U8 with extended (20) register index. */ 299 #define IEM_MC_ADD_GREG_U8_THREADED(a_iGRegEx, a_u8Value) \ 300 *iemGRegRefU8Ex(pVCpu, (a_iGRegEx)) += (a_u8Value) 301 #undef IEM_MC_ADD_GREG_U8 302 303 /** Variant of IEM_MC_SUB_GREG_U8 with extended (20) register index. */ 304 #define IEM_MC_SUB_GREG_U8_THREADED(a_iGRegEx, a_u8Value) \ 305 *iemGRegRefU8Ex(pVCpu, (a_iGRegEx)) -= (a_u8Value) 306 #undef IEM_MC_SUB_GREG_U8 307 308 /** Variant of IEM_MC_ADD_GREG_U8_TO_LOCAL with extended (20) register index. */ 309 #define IEM_MC_ADD_GREG_U8_TO_LOCAL_THREADED(a_u8Value, a_iGRegEx) \ 310 do { (a_u8Value) += iemGRegFetchU8Ex(pVCpu, (a_iGRegEx)); } while (0) 311 #undef IEM_MC_ADD_GREG_U8_TO_LOCAL 312 313 /** Variant of IEM_MC_AND_GREG_U8 with extended (20) register index. */ 314 #define IEM_MC_AND_GREG_U8_THREADED(a_iGRegEx, a_u8Value) \ 315 *iemGRegRefU8Ex(pVCpu, (a_iGRegEx)) &= (a_u8Value) 316 #undef IEM_MC_AND_GREG_U8 317 318 /** Variant of IEM_MC_OR_GREG_U8 with extended (20) register index. */ 319 #define IEM_MC_OR_GREG_U8_THREADED(a_iGRegEx, a_u8Value) \ 320 *iemGRegRefU8Ex(pVCpu, (a_iGRegEx)) |= (a_u8Value) 321 #undef IEM_MC_OR_GREG_U8 322 323 /** 324 * Calculates the effective address of a ModR/M memory operand, 16-bit 325 * addressing variant. 326 * 327 * Meant to be used via IEM_MC_CALC_RM_EFF_ADDR_THREADED_ADDR16. 328 * 329 * @returns The effective address. 330 * @param pVCpu The cross context virtual CPU structure of the calling thread. 331 * @param bRm The ModRM byte. 332 * @param u16Disp The displacement byte/word, if any. 333 * RIP relative addressing. 334 */ 335 static RTGCPTR iemOpHlpCalcRmEffAddrThreadedAddr16(PVMCPUCC pVCpu, uint8_t bRm, uint16_t u16Disp) RT_NOEXCEPT 336 { 337 Log5(("iemOpHlpCalcRmEffAddrThreadedAddr16: bRm=%#x u16Disp=%#x\n", bRm, u16Disp)); 338 Assert(!IEM_IS_64BIT_CODE(pVCpu)); 339 340 /* Handle the disp16 form with no registers first. */ 341 if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 6) 342 { 343 Log5(("iemOpHlpCalcRmEffAddrThreadedAddr16: EffAddr=%#010RGv\n", (RTGCPTR)u16Disp)); 344 return u16Disp; 345 } 346 347 /* Get the displacment. */ 348 /** @todo we can eliminate this step by making u16Disp have this value 349 * already! */ 350 uint16_t u16EffAddr; 351 switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK) 352 { 353 case 0: u16EffAddr = 0; break; 354 case 1: u16EffAddr = (int16_t)(int8_t)u16Disp; break; 355 case 2: u16EffAddr = u16Disp; break; 356 default: AssertFailedStmt(u16EffAddr = 0); 357 } 358 359 /* Add the base and index registers to the disp. */ 360 switch (bRm & X86_MODRM_RM_MASK) 361 { 362 case 0: u16EffAddr += pVCpu->cpum.GstCtx.bx + pVCpu->cpum.GstCtx.si; break; 363 case 1: u16EffAddr += pVCpu->cpum.GstCtx.bx + pVCpu->cpum.GstCtx.di; break; 364 case 2: u16EffAddr += pVCpu->cpum.GstCtx.bp + pVCpu->cpum.GstCtx.si; break; 365 case 3: u16EffAddr += pVCpu->cpum.GstCtx.bp + pVCpu->cpum.GstCtx.di; break; 366 case 4: u16EffAddr += pVCpu->cpum.GstCtx.si; break; 367 case 5: u16EffAddr += pVCpu->cpum.GstCtx.di; break; 368 case 6: u16EffAddr += pVCpu->cpum.GstCtx.bp; break; 369 case 7: u16EffAddr += pVCpu->cpum.GstCtx.bx; break; 370 } 371 372 Log5(("iemOpHlpCalcRmEffAddrThreadedAddr16: EffAddr=%#010RGv\n", (RTGCPTR)u16EffAddr)); 373 return u16EffAddr; 374 } 375 376 377 /** 378 * Calculates the effective address of a ModR/M memory operand, 32-bit 379 * addressing variant. 380 * 381 * Meant to be used via IEM_MC_CALC_RM_EFF_ADDR_THREADED_ADDR32 and 382 * IEM_MC_CALC_RM_EFF_ADDR_THREADED_ADDR32FLAT. 383 * 384 * @returns The effective address. 385 * @param pVCpu The cross context virtual CPU structure of the 386 * calling thread. 387 * @param bRm The ModRM byte. 388 * @param uSibAndRspOffset Two parts: 389 * - The first 8 bits make up the SIB byte. 390 * - The next 8 bits are the fixed RSP/ESP offse 391 * in case of a pop [xSP]. 392 * @param u32Disp The displacement byte/dword, if any. 393 */ 394 static RTGCPTR iemOpHlpCalcRmEffAddrThreadedAddr32(PVMCPUCC pVCpu, uint8_t bRm, uint32_t uSibAndRspOffset, 395 uint32_t u32Disp) RT_NOEXCEPT 396 { 397 Log5(("iemOpHlpCalcRmEffAddrThreadedAddr32: bRm=%#x uSibAndRspOffset=%#x u32Disp=%#x\n", bRm, uSibAndRspOffset, u32Disp)); 398 399 /* Handle the disp32 form with no registers first. */ 400 if ((bRm & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5) 401 { 402 Log5(("iemOpHlpCalcRmEffAddrThreadedAddr32: EffAddr=%#010RGv\n", (RTGCPTR)u32Disp)); 403 return u32Disp; 404 } 405 406 /* Get the register (or SIB) value. */ 407 uint32_t u32EffAddr; 408 #ifdef _MSC_VER 409 u32EffAddr = 0;/* MSC uninitialized variable analysis is too simple, it seems. */ 410 #endif 411 switch (bRm & X86_MODRM_RM_MASK) 412 { 413 case 0: u32EffAddr = pVCpu->cpum.GstCtx.eax; break; 414 case 1: u32EffAddr = pVCpu->cpum.GstCtx.ecx; break; 415 case 2: u32EffAddr = pVCpu->cpum.GstCtx.edx; break; 416 case 3: u32EffAddr = pVCpu->cpum.GstCtx.ebx; break; 417 case 4: /* SIB */ 418 { 419 /* Get the index and scale it. */ 420 switch ((uSibAndRspOffset >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK) 421 { 422 case 0: u32EffAddr = pVCpu->cpum.GstCtx.eax; break; 423 case 1: u32EffAddr = pVCpu->cpum.GstCtx.ecx; break; 424 case 2: u32EffAddr = pVCpu->cpum.GstCtx.edx; break; 425 case 3: u32EffAddr = pVCpu->cpum.GstCtx.ebx; break; 426 case 4: u32EffAddr = 0; /*none */ break; 427 case 5: u32EffAddr = pVCpu->cpum.GstCtx.ebp; break; 428 case 6: u32EffAddr = pVCpu->cpum.GstCtx.esi; break; 429 case 7: u32EffAddr = pVCpu->cpum.GstCtx.edi; break; 430 } 431 u32EffAddr <<= (uSibAndRspOffset >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK; 432 433 /* add base */ 434 switch (uSibAndRspOffset & X86_SIB_BASE_MASK) 435 { 436 case 0: u32EffAddr += pVCpu->cpum.GstCtx.eax; break; 437 case 1: u32EffAddr += pVCpu->cpum.GstCtx.ecx; break; 438 case 2: u32EffAddr += pVCpu->cpum.GstCtx.edx; break; 439 case 3: u32EffAddr += pVCpu->cpum.GstCtx.ebx; break; 440 case 4: 441 u32EffAddr += pVCpu->cpum.GstCtx.esp; 442 u32EffAddr += uSibAndRspOffset >> 8; 443 break; 444 case 5: 445 if ((bRm & X86_MODRM_MOD_MASK) != 0) 446 u32EffAddr += pVCpu->cpum.GstCtx.ebp; 447 else 448 u32EffAddr += u32Disp; 449 break; 450 case 6: u32EffAddr += pVCpu->cpum.GstCtx.esi; break; 451 case 7: u32EffAddr += pVCpu->cpum.GstCtx.edi; break; 452 } 453 break; 454 } 455 case 5: u32EffAddr = pVCpu->cpum.GstCtx.ebp; break; 456 case 6: u32EffAddr = pVCpu->cpum.GstCtx.esi; break; 457 case 7: u32EffAddr = pVCpu->cpum.GstCtx.edi; break; 458 } 459 460 /* Get and add the displacement. */ 461 switch ((bRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK) 462 { 463 case 0: break; 464 case 1: u32EffAddr += (int8_t)u32Disp; break; 465 case 2: u32EffAddr += u32Disp; break; 466 default: AssertFailed(); 467 } 468 469 Log5(("iemOpHlpCalcRmEffAddrThreadedAddr32: EffAddr=%#010RGv\n", (RTGCPTR)u32EffAddr)); 470 return u32EffAddr; 471 } 472 473 474 /** 475 * Calculates the effective address of a ModR/M memory operand. 476 * 477 * Meant to be used via IEM_MC_CALC_RM_EFF_ADDR_THREADED_ADDR64. 478 * 479 * @returns The effective address. 480 * @param pVCpu The cross context virtual CPU structure of the 481 * calling thread. 482 * @param bRmEx The ModRM byte but with bit 3 set to REX.B and 483 * bit 4 to REX.X. The two bits are part of the 484 * REG sub-field, which isn't needed in this 485 * function. 486 * @param uSibAndRspOffset Two parts: 487 * - The first 8 bits make up the SIB byte. 488 * - The next 8 bits are the fixed RSP/ESP offse 489 * in case of a pop [xSP]. 490 * @param u32Disp The displacement byte/word/dword, if any. 491 * @param cbInstr The size of the fully decoded instruction. Used 492 * for RIP relative addressing. 493 * @todo combine cbInstr and cbImm! 494 */ 495 static RTGCPTR iemOpHlpCalcRmEffAddrThreadedAddr64(PVMCPUCC pVCpu, uint8_t bRmEx, uint32_t uSibAndRspOffset, 496 uint32_t u32Disp, uint8_t cbInstr) RT_NOEXCEPT 497 { 498 Log5(("iemOpHlpCalcRmEffAddrThreadedAddr64: bRmEx=%#x\n", bRmEx)); 499 Assert(IEM_IS_64BIT_CODE(pVCpu)); 500 501 uint64_t u64EffAddr; 502 503 /* Handle the rip+disp32 form with no registers first. */ 504 if ((bRmEx & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5) 505 { 506 u64EffAddr = (int32_t)u32Disp; 507 u64EffAddr += pVCpu->cpum.GstCtx.rip + cbInstr; 508 } 509 else 510 { 511 /* Get the register (or SIB) value. */ 512 #ifdef _MSC_VER 513 u64EffAddr = 0; /* MSC uninitialized variable analysis is too simple, it seems. */ 514 #endif 515 switch (bRmEx & (X86_MODRM_RM_MASK | 0x8)) /* bRmEx[bit 3] = REX.B */ 516 { 517 default: 518 case 0: u64EffAddr = pVCpu->cpum.GstCtx.rax; break; 519 case 1: u64EffAddr = pVCpu->cpum.GstCtx.rcx; break; 520 case 2: u64EffAddr = pVCpu->cpum.GstCtx.rdx; break; 521 case 3: u64EffAddr = pVCpu->cpum.GstCtx.rbx; break; 522 case 5: u64EffAddr = pVCpu->cpum.GstCtx.rbp; break; 523 case 6: u64EffAddr = pVCpu->cpum.GstCtx.rsi; break; 524 case 7: u64EffAddr = pVCpu->cpum.GstCtx.rdi; break; 525 case 8: u64EffAddr = pVCpu->cpum.GstCtx.r8; break; 526 case 9: u64EffAddr = pVCpu->cpum.GstCtx.r9; break; 527 case 10: u64EffAddr = pVCpu->cpum.GstCtx.r10; break; 528 case 11: u64EffAddr = pVCpu->cpum.GstCtx.r11; break; 529 case 13: u64EffAddr = pVCpu->cpum.GstCtx.r13; break; 530 case 14: u64EffAddr = pVCpu->cpum.GstCtx.r14; break; 531 case 15: u64EffAddr = pVCpu->cpum.GstCtx.r15; break; 532 /* SIB */ 533 case 4: 534 case 12: 535 { 536 /* Get the index and scale it. */ 537 switch ( ((uSibAndRspOffset >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK) 538 | ((bRmEx & 0x10) >> 1)) /* bRmEx[bit 4] = REX.X */ 539 { 540 case 0: u64EffAddr = pVCpu->cpum.GstCtx.rax; break; 541 case 1: u64EffAddr = pVCpu->cpum.GstCtx.rcx; break; 542 case 2: u64EffAddr = pVCpu->cpum.GstCtx.rdx; break; 543 case 3: u64EffAddr = pVCpu->cpum.GstCtx.rbx; break; 544 case 4: u64EffAddr = 0; /*none */ break; 545 case 5: u64EffAddr = pVCpu->cpum.GstCtx.rbp; break; 546 case 6: u64EffAddr = pVCpu->cpum.GstCtx.rsi; break; 547 case 7: u64EffAddr = pVCpu->cpum.GstCtx.rdi; break; 548 case 8: u64EffAddr = pVCpu->cpum.GstCtx.r8; break; 549 case 9: u64EffAddr = pVCpu->cpum.GstCtx.r9; break; 550 case 10: u64EffAddr = pVCpu->cpum.GstCtx.r10; break; 551 case 11: u64EffAddr = pVCpu->cpum.GstCtx.r11; break; 552 case 12: u64EffAddr = pVCpu->cpum.GstCtx.r12; break; 553 case 13: u64EffAddr = pVCpu->cpum.GstCtx.r13; break; 554 case 14: u64EffAddr = pVCpu->cpum.GstCtx.r14; break; 555 case 15: u64EffAddr = pVCpu->cpum.GstCtx.r15; break; 556 } 557 u64EffAddr <<= (uSibAndRspOffset >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK; 558 559 /* add base */ 560 switch ((uSibAndRspOffset & X86_SIB_BASE_MASK) | (bRmEx & 0x8)) /* bRmEx[bit 3] = REX.B */ 561 { 562 case 0: u64EffAddr += pVCpu->cpum.GstCtx.rax; break; 563 case 1: u64EffAddr += pVCpu->cpum.GstCtx.rcx; break; 564 case 2: u64EffAddr += pVCpu->cpum.GstCtx.rdx; break; 565 case 3: u64EffAddr += pVCpu->cpum.GstCtx.rbx; break; 566 case 4: 567 u64EffAddr += pVCpu->cpum.GstCtx.rsp; 568 u64EffAddr += uSibAndRspOffset >> 8; 569 break; 570 case 6: u64EffAddr += pVCpu->cpum.GstCtx.rsi; break; 571 case 7: u64EffAddr += pVCpu->cpum.GstCtx.rdi; break; 572 case 8: u64EffAddr += pVCpu->cpum.GstCtx.r8; break; 573 case 9: u64EffAddr += pVCpu->cpum.GstCtx.r9; break; 574 case 10: u64EffAddr += pVCpu->cpum.GstCtx.r10; break; 575 case 11: u64EffAddr += pVCpu->cpum.GstCtx.r11; break; 576 case 12: u64EffAddr += pVCpu->cpum.GstCtx.r12; break; 577 case 14: u64EffAddr += pVCpu->cpum.GstCtx.r14; break; 578 case 15: u64EffAddr += pVCpu->cpum.GstCtx.r15; break; 579 /* complicated encodings */ 580 case 5: 581 if ((bRmEx & X86_MODRM_MOD_MASK) != 0) 582 u64EffAddr += pVCpu->cpum.GstCtx.rbp; 583 else 584 u64EffAddr += (int32_t)u32Disp; 585 break; 586 case 13: 587 if ((bRmEx & X86_MODRM_MOD_MASK) != 0) 588 u64EffAddr += pVCpu->cpum.GstCtx.r13; 589 else 590 u64EffAddr += (int32_t)u32Disp; 591 break; 592 } 593 break; 594 } 595 } 596 597 /* Get and add the displacement. */ 598 switch ((bRmEx >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK) 599 { 600 case 0: break; 601 case 1: u64EffAddr += (int8_t)u32Disp; break; 602 case 2: u64EffAddr += (int32_t)u32Disp; break; 603 default: AssertFailed(); 604 } 605 } 606 607 Log5(("iemOpHlpCalcRmEffAddrThreadedAddr64: EffAddr=%#010RGv\n", u64EffAddr)); 608 return u64EffAddr; 70 71 72 73 static VBOXSTRICTRC iemThreadeFuncWorkerObsoleteTb(PVMCPUCC pVCpu) 74 { 75 iemThreadedTbObsolete(pVCpu, pVCpu->iem.s.pCurTbR3); 76 return VINF_IEM_REEXEC_MODE_CHANGED; /** @todo different status code... */ 609 77 } 610 78 … … 614 82 * Built-in function that compares the fExec mask against uParam0. 615 83 */ 616 staticIEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckMode,617 84 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckMode, 85 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 618 86 { 619 87 uint32_t const fExpectedExec = (uint32_t)uParam0; 620 88 if (pVCpu->iem.s.fExec == fExpectedExec) 621 89 return VINF_SUCCESS; 622 Log 12(("Mode changed at %04x:%08RX64: %#x -> %#x (xor: %#x)\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,623 fExpectedExec, pVCpu->iem.s.fExec, fExpectedExec ^ pVCpu->iem.s.fExec));90 LogFlow(("Mode changed at %04x:%08RX64: %#x -> %#x (xor: %#x)\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, 91 fExpectedExec, pVCpu->iem.s.fExec, fExpectedExec ^ pVCpu->iem.s.fExec)); 624 92 RT_NOREF(uParam1, uParam2); 625 93 return VINF_IEM_REEXEC_MODE_CHANGED; … … 627 95 628 96 97 DECL_FORCE_INLINE(RTGCPHYS) iemTbGetRangePhysPageAddr(PCIEMTB pTb, uint8_t idxRange) 98 { 99 Assert(idxRange < RT_MIN(pTb->cRanges, RT_ELEMENTS(pTb->aRanges))); 100 uint8_t const idxPage = pTb->aRanges[idxRange].idxPhysPage; 101 Assert(idxPage <= RT_ELEMENTS(pTb->aGCPhysPages)); 102 if (idxPage == 0) 103 return pTb->GCPhysPc & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK; 104 Assert(!(pTb->aGCPhysPages[idxPage - 1] & GUEST_PAGE_OFFSET_MASK)); 105 return pTb->aGCPhysPages[idxPage - 1]; 106 } 107 108 109 /** 110 * Macro that implements the 16/32-bit CS.LIM check, as this is done by a 111 * number of functions. 112 */ 113 #define BODY_CHECK_CS_LIM(a_cbInstr) do { \ 114 if (RT_LIKELY(pVCpu->cpum.GstCtx.eip - pVCpu->cpum.GstCtx.cs.u32Limit >= cbInstr)) \ 115 { /* likely */ } \ 116 else \ 117 { \ 118 Log7(("EIP out of bounds at %04x:%08RX32 LB %u - CS.LIM=%#RX32\n", \ 119 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip, (a_cbInstr), pVCpu->cpum.GstCtx.cs.u32Limit)); \ 120 return iemRaiseGeneralProtectionFault0(pVCpu); \ 121 } \ 122 } while(0) 123 124 /** 125 * Macro that implements opcode (re-)checking. 126 */ 127 #define BODY_CHECK_OPCODES(a_pTb, a_idxRange, a_offRange, a_cbInstr) do { \ 128 Assert((a_idxRange) < (a_pTb)->cRanges && (a_pTb)->cRanges < RT_ELEMENTS((a_pTb)->aRanges)); \ 129 Assert((a_offRange) < (a_pTb)->aRanges[(a_idxRange)].cbOpcodes); \ 130 /* We can use pbInstrBuf here as it will be updated when branching (and prior to executing a TB). */ \ 131 if (RT_LIKELY(memcmp(&pVCpu->iem.s.pbInstrBuf[(a_pTb)->aRanges[(a_idxRange)].offPhysPage + (a_offRange)], \ 132 &(a_pTb)->pabOpcodes[ (a_pTb)->aRanges[(a_idxRange)].offOpcodes + (a_offRange)], \ 133 (a_pTb)->aRanges[(a_idxRange)].cbOpcodes - (a_offRange)) == 0)) \ 134 { /* likely */ } \ 135 else \ 136 { \ 137 Log7(("TB obsolete: %p at %04x:%08RX64 LB %u; range %u, off %#x LB %#x + %#x; #%u\n", (a_pTb), \ 138 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, (a_cbInstr), (a_idxRange), \ 139 (a_pTb)->aRanges[(a_idxRange)].offOpcodes, (a_pTb)->aRanges[(a_idxRange)].cbOpcodes, (a_offRange), __LINE__)); \ 140 RT_NOREF(a_cbInstr); \ 141 return iemThreadeFuncWorkerObsoleteTb(pVCpu); \ 142 } \ 143 } while(0) 144 145 /** 146 * Macro that implements TLB loading and updating pbInstrBuf updating for an 147 * instruction crossing into a new page. 148 * 149 * This may long jump if we're raising a \#PF, \#GP or similar trouble. 150 */ 151 #define BODY_LOAD_TLB_FOR_NEW_PAGE(a_pTb, a_offInstr, a_idxRange, a_cbInstr) do { \ 152 pVCpu->iem.s.pbInstrBuf = NULL; \ 153 pVCpu->iem.s.offCurInstrStart = GUEST_PAGE_SIZE - (a_offInstr); \ 154 pVCpu->iem.s.offInstrNextByte = GUEST_PAGE_SIZE; \ 155 iemOpcodeFetchBytesJmp(pVCpu, 0, NULL); \ 156 \ 157 RTGCPHYS const GCPhysNewPage = iemTbGetRangePhysPageAddr(a_pTb, a_idxRange); \ 158 if (RT_LIKELY( pVCpu->iem.s.GCPhysInstrBuf == GCPhysNewPage \ 159 && pVCpu->iem.s.pbInstrBuf)) \ 160 { /* likely */ } \ 161 else \ 162 { \ 163 Log7(("TB obsolete: %p at %04x:%08RX64 LB %u; crossing at %#x; GCPhys=%RGp expected %RGp, pbInstrBuf=%p - #%u\n", \ 164 (a_pTb), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, (a_cbInstr), (a_offInstr), \ 165 pVCpu->iem.s.GCPhysInstrBuf, GCPhysNewPage, pVCpu->iem.s.pbInstrBuf, __LINE__)); \ 166 RT_NOREF(a_cbInstr); \ 167 return iemThreadeFuncWorkerObsoleteTb(pVCpu); \ 168 } \ 169 } while(0) 170 171 /** 172 * Macro that implements TLB loading and updating pbInstrBuf updating when 173 * branching or when crossing a page on an instruction boundrary. 174 * 175 * This differs from BODY_LOAD_TLB_FOR_NEW_PAGE in that it will first check if 176 * it is an inter-page branch. 177 * 178 * This may long jump if we're raising a \#PF, \#GP or similar trouble. 179 */ 180 #define BODY_LOAD_TLB_FOR_BRANCH(a_pTb, a_idxRange, a_cbInstr) do { \ 181 /* Is RIP within the current code page? */ \ 182 Assert(pVCpu->cpum.GstCtx.cs.u64Base == 0 || !IEM_IS_64BIT_CODE(pVCpu)); \ 183 uint64_t const uPc = pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base; \ 184 uint64_t const off = uPc - pVCpu->iem.s.uInstrBufPc; \ 185 if (off < pVCpu->iem.s.cbInstrBufTotal) \ 186 Assert(!(pVCpu->iem.s.GCPhysInstrBuf & GUEST_PAGE_OFFSET_MASK)); \ 187 else \ 188 { \ 189 /* Must translate new RIP. */ \ 190 pVCpu->iem.s.pbInstrBuf = NULL; \ 191 pVCpu->iem.s.offCurInstrStart = 0; \ 192 pVCpu->iem.s.offInstrNextByte = 0; \ 193 iemOpcodeFetchBytesJmp(pVCpu, 0, NULL); \ 194 \ 195 RTGCPHYS const GCPhysNewPage = iemTbGetRangePhysPageAddr(a_pTb, a_idxRange); \ 196 if (RT_LIKELY( pVCpu->iem.s.GCPhysInstrBuf == GCPhysNewPage \ 197 && pVCpu->iem.s.pbInstrBuf)) \ 198 { /* likely */ } \ 199 else \ 200 { \ 201 Log7(("TB obsolete: %p at %04x:%08RX64 LB %u; branching; GCPhys=%RGp expected %RGp, pbInstrBuf=%p - #%u\n", \ 202 (a_pTb), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, (a_cbInstr), \ 203 pVCpu->iem.s.GCPhysInstrBuf, GCPhysNewPage, pVCpu->iem.s.pbInstrBuf, __LINE__)); \ 204 RT_NOREF(a_cbInstr); \ 205 return iemThreadeFuncWorkerObsoleteTb(pVCpu); \ 206 } \ 207 } \ 208 } while(0) 209 210 629 211 /** 630 212 * Built-in function that checks the EIP/IP + uParam0 is within CS.LIM, 631 213 * raising a \#GP(0) if this isn't the case. 632 214 */ 633 staticIEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLim,634 215 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLim, 216 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 635 217 { 636 218 uint32_t const cbInstr = (uint32_t)uParam0; 637 if (pVCpu->cpum.GstCtx.eip - pVCpu->cpum.GstCtx.cs.u32Limit >= cbInstr)638 return VINF_SUCCESS;639 Log(("EIP out of bounds at %04x:%08RX32 LB %u - CS.LIM=%#RX32\n",640 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip, cbInstr, pVCpu->cpum.GstCtx.cs.u32Limit));641 219 RT_NOREF(uParam1, uParam2); 642 return iemRaiseGeneralProtectionFault0(pVCpu); 643 } 644 645 /* 646 * The threaded functions. 647 */ 648 #include "IEMThreadedFunctions.cpp.h" 649 220 BODY_CHECK_CS_LIM(cbInstr); 221 return VINF_SUCCESS; 222 } 223 224 225 /** 226 * Built-in function for re-checking opcodes and CS.LIM after an instruction 227 * that may have modified them. 228 */ 229 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLimAndOpcodes, 230 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 231 { 232 PCIEMTB const pTb = pVCpu->iem.s.pCurTbR3; 233 uint32_t const cbInstr = (uint32_t)uParam0; 234 uint32_t const idxRange = (uint32_t)uParam1; 235 uint32_t const offRange = (uint32_t)uParam2; 236 BODY_CHECK_CS_LIM(cbInstr); 237 BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr); 238 return VINF_SUCCESS; 239 } 240 241 242 /** 243 * Built-in function for re-checking opcodes after an instruction that may have 244 * modified them. 245 */ 246 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckOpcodes, 247 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 248 { 249 PCIEMTB const pTb = pVCpu->iem.s.pCurTbR3; 250 uint32_t const cbInstr = (uint32_t)uParam0; 251 uint32_t const idxRange = (uint32_t)uParam1; 252 uint32_t const offRange = (uint32_t)uParam2; 253 BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr); 254 return VINF_SUCCESS; 255 } 256 257 258 /** 259 * Built-in function for checking CS.LIM, loading TLB and checking opcodes on 260 * both pages when transitioning to a different code page. 261 * 262 * This is used when the previous instruction requires revalidation of opcodes 263 * bytes and the current instruction stries a page boundrary with opcode bytes 264 * in both the old and new page. 265 * 266 * @see iemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlb 267 */ 268 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLimAndOpcodesAcrossPageLoadingTlb, 269 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 270 { 271 PCIEMTB const pTb = pVCpu->iem.s.pCurTbR3; 272 uint32_t const cbInstr = (uint32_t)uParam0; 273 uint32_t const cbStartPage = (uint32_t)(uParam0 >> 32); 274 uint32_t const idxRange1 = (uint32_t)uParam1; 275 uint32_t const offRange1 = (uint32_t)uParam2; 276 uint32_t const idxRange2 = idxRange1 + 1; 277 BODY_CHECK_CS_LIM(cbInstr); 278 BODY_CHECK_OPCODES(pTb, idxRange1, offRange1, cbInstr); 279 BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr); 280 BODY_CHECK_OPCODES(pTb, idxRange2, 0, cbInstr); 281 return VINF_SUCCESS; 282 } 283 284 285 /** 286 * Built-in function for loading TLB and checking opcodes on both pages when 287 * transitioning to a different code page. 288 * 289 * This is used when the previous instruction requires revalidation of opcodes 290 * bytes and the current instruction stries a page boundrary with opcode bytes 291 * in both the old and new page. 292 * 293 * @see iemThreadedFunc_BltIn_CheckCsLimAndOpcodesAcrossPageLoadingTlb 294 */ 295 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlb, 296 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 297 { 298 PCIEMTB const pTb = pVCpu->iem.s.pCurTbR3; 299 uint32_t const cbInstr = (uint32_t)uParam0; 300 uint32_t const cbStartPage = (uint32_t)(uParam0 >> 32); 301 uint32_t const idxRange1 = (uint32_t)uParam1; 302 uint32_t const offRange1 = (uint32_t)uParam2; 303 uint32_t const idxRange2 = idxRange1 + 1; 304 BODY_CHECK_OPCODES(pTb, idxRange1, offRange1, cbInstr); 305 BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr); 306 BODY_CHECK_OPCODES(pTb, idxRange2, 0, cbInstr); 307 return VINF_SUCCESS; 308 } 309 310 311 /** 312 * Built-in function for checking CS.LIM, loading TLB and checking opcodes when 313 * transitioning to a different code page. 314 * 315 * The code page transition can either be natural over onto the next page (with 316 * the instruction starting at page offset zero) or by means of branching. 317 * 318 * @see iemThreadedFunc_BltIn_CheckOpcodesLoadingTlb 319 */ 320 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLimAndOpcodesLoadingTlb, 321 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 322 { 323 PCIEMTB const pTb = pVCpu->iem.s.pCurTbR3; 324 uint32_t const cbInstr = (uint32_t)uParam0; 325 uint32_t const idxRange = (uint32_t)uParam1; 326 uint32_t const offRange = (uint32_t)uParam2; 327 BODY_CHECK_CS_LIM(cbInstr); 328 BODY_LOAD_TLB_FOR_BRANCH(pTb, idxRange, cbInstr); 329 BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr); 330 return VINF_SUCCESS; 331 } 332 333 334 /** 335 * Built-in function for loading TLB and checking opcodes when transitioning to 336 * a different code page. 337 * 338 * The code page transition can either be natural over onto the next page (with 339 * the instruction starting at page offset zero) or by means of branching. 340 * 341 * @see iemThreadedFunc_BltIn_CheckCsLimAndOpcodesLoadingTlb 342 */ 343 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckOpcodesLoadingTlb, 344 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 345 { 346 PCIEMTB const pTb = pVCpu->iem.s.pCurTbR3; 347 uint32_t const cbInstr = (uint32_t)uParam0; 348 uint32_t const idxRange = (uint32_t)uParam1; 349 uint32_t const offRange = (uint32_t)uParam2; 350 BODY_LOAD_TLB_FOR_BRANCH(pTb, idxRange, cbInstr); 351 BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr); 352 return VINF_SUCCESS; 353 } 354 355 356 /** 357 * Built-in function for checking CS.LIM, loading TLB and checking opcodes when 358 * advancing naturally to a different code page. 359 * 360 * Only opcodes on the new page is checked. 361 * 362 * @see iemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlb 363 */ 364 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNextPageLoadingTlb, 365 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 366 { 367 PCIEMTB const pTb = pVCpu->iem.s.pCurTbR3; 368 uint32_t const cbInstr = (uint32_t)uParam0; 369 uint32_t const cbStartPage = (uint32_t)(uParam0 >> 32); 370 uint32_t const idxRange1 = (uint32_t)uParam1; 371 //uint32_t const offRange1 = (uint32_t)uParam2; 372 uint32_t const idxRange2 = idxRange1 + 1; 373 BODY_CHECK_CS_LIM(cbInstr); 374 BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr); 375 BODY_CHECK_OPCODES(pTb, idxRange2, 0, cbInstr); 376 RT_NOREF(uParam2); 377 return VINF_SUCCESS; 378 } 379 380 381 /** 382 * Built-in function for loading TLB and checking opcodes when advancing 383 * naturally to a different code page. 384 * 385 * Only opcodes on the new page is checked. 386 * 387 * @see iemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNextPageLoadingTlb 388 */ 389 IEM_DECL_IMPL_DEF(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlb, 390 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)) 391 { 392 PCIEMTB const pTb = pVCpu->iem.s.pCurTbR3; 393 uint32_t const cbInstr = (uint32_t)uParam0; 394 uint32_t const cbStartPage = (uint32_t)(uParam0 >> 32); 395 uint32_t const idxRange1 = (uint32_t)uParam1; 396 //uint32_t const offRange1 = (uint32_t)uParam2; 397 uint32_t const idxRange2 = idxRange1 + 1; 398 BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr); 399 BODY_CHECK_OPCODES(pTb, idxRange2, 0, cbInstr); 400 RT_NOREF(uParam2); 401 return VINF_SUCCESS; 402 } 403 -
trunk/src/VBox/VMM/VMMAll/IEMAllThreadedPython.py
r100633 r100694 1256 1256 ' kIemThreadedFunc_Invalid = 0,', 1257 1257 '', 1258 ' /*' 1259 ' * Predefined' 1260 ' */' 1258 ' /*', 1259 ' * Predefined', 1260 ' */', 1261 1261 ' kIemThreadedFunc_CheckMode,', 1262 1262 ' kIemThreadedFunc_CheckCsLim,', 1263 ' kIemThreadedFunc_CheckCsLimAndOpcodes,', 1264 ' kIemThreadedFunc_CheckCsLimAndOpcodesAcrossPageLoadingTlb,', 1265 ' kIemThreadedFunc_CheckCsLimAndOpcodesLoadingTlb,', 1266 ' kIemThreadedFunc_CheckCsLimAndOpcodesOnNextPageLoadingTlb,', 1267 ' kIemThreadedFunc_CheckOpcodes,', 1268 ' kIemThreadedFunc_CheckOpcodesAcrossPageLoadingTlb,', 1269 ' kIemThreadedFunc_CheckOpcodesLoadingTlb,', 1270 ' kIemThreadedFunc_CheckOpcodesOnNextPageLoadingTlb,', 1263 1271 ]; 1264 1272 iThreadedFunction = 1; … … 1420 1428 + ' iemThreadedFunc_BltIn_CheckMode,\n' 1421 1429 + ' iemThreadedFunc_BltIn_CheckCsLim,\n' 1430 + ' iemThreadedFunc_BltIn_CheckCsLimAndOpcodes,\n' 1431 + ' iemThreadedFunc_BltIn_CheckCsLimAndOpcodesAcrossPageLoadingTlb,\n' 1432 + ' iemThreadedFunc_BltIn_CheckCsLimAndOpcodesLoadingTlb,\n' 1433 + ' iemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNextPageLoadingTlb,\n' 1434 + ' iemThreadedFunc_BltIn_CheckOpcodes,\n' 1435 + ' iemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlb,\n' 1436 + ' iemThreadedFunc_BltIn_CheckOpcodesLoadingTlb,\n' 1437 + ' iemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlb,\n' 1422 1438 ); 1423 1439 iThreadedFunction = 1; … … 1453 1469 + ' "BltIn_CheckMode",\n' 1454 1470 + ' "BltIn_CheckCsLim",\n' 1471 + ' "BltIn_CheckCsLimAndOpcodes",\n' 1472 + ' "BltIn_CheckCsLimAndOpcodesAcrossPageLoadingTlb",\n' 1473 + ' "BltIn_CheckCsLimAndOpcodesLoadingTlb",\n' 1474 + ' "BltIn_CheckCsLimAndOpcodesOnNextPageLoadingTlb",\n' 1475 + ' "BltIn_CheckOpcodes",\n' 1476 + ' "BltIn_CheckOpcodesAcrossPageLoadingTlb",\n' 1477 + ' "BltIn_CheckOpcodesLoadingTlb",\n' 1478 + ' "BltIn_CheckOpcodesOnNextPageLoadingTlb",\n' 1455 1479 ); 1456 1480 iThreadedFunction = 1; -
trunk/src/VBox/VMM/VMMAll/IEMAllThreadedRecompiler.cpp
r100671 r100694 11 11 * - Level 5 (Log5) : Decoding details. [same as IEM] 12 12 * - Level 6 (Log6) : 13 * - Level 7 (Log7) : 13 * - Level 7 (Log7) : TB obsoletion. 14 14 * - Level 8 (Log8) : TB compilation. 15 15 * - Level 9 (Log9) : TB exec. 16 16 * - Level 10 (Log10): TB block lookup. 17 * - Level 11 (Log11): TB block lookup .17 * - Level 11 (Log11): TB block lookup details. 18 18 * - Level 12 (Log12): TB insertion. 19 19 */ … … 114 114 * Structures and Typedefs * 115 115 *********************************************************************************************************************************/ 116 /** 117 * A call for the threaded call table. 118 */ 119 typedef struct IEMTHRDEDCALLENTRY 120 { 121 /** The function to call (IEMTHREADEDFUNCS). */ 122 uint16_t enmFunction; 123 uint16_t uUnused0; 124 125 /** Offset into IEMTB::pabOpcodes. */ 126 uint16_t offOpcode; 127 /** The opcode length. */ 128 uint8_t cbOpcode; 129 uint8_t uUnused1; 130 131 /** Generic parameters. */ 132 uint64_t auParams[3]; 133 } IEMTHRDEDCALLENTRY; 134 AssertCompileSize(IEMTHRDEDCALLENTRY, sizeof(uint64_t) * 4); 135 /** Pointer to a threaded call entry. */ 136 typedef IEMTHRDEDCALLENTRY *PIEMTHRDEDCALLENTRY; 137 /** Pointer to a const threaded call entry. */ 138 typedef IEMTHRDEDCALLENTRY const *PCIEMTHRDEDCALLENTRY; 139 140 141 142 /** 143 * Translation block. 144 */ 145 typedef struct IEMTB 146 { 147 /** Next block with the same hash table entry. */ 148 PIEMTB volatile pNext; 149 /** List on the local VCPU for blocks. */ 150 RTLISTNODE LocalList; 151 152 /** @name What uniquely identifies the block. 153 * @{ */ 154 RTGCPHYS GCPhysPc; 155 /** IEMTB_F_XXX (i.e. IEM_F_XXX ++). */ 156 uint32_t fFlags; 157 union 158 { 159 struct 160 { 161 /**< Relevant CS X86DESCATTR_XXX bits. */ 162 uint16_t fAttr; 163 } x86; 164 }; 165 /** @} */ 166 167 union 168 { 169 struct 170 { 171 /** The call sequence table. */ 172 PIEMTHRDEDCALLENTRY paCalls; 173 /** Number of calls in paCalls. */ 174 uint16_t cCalls; 175 /** Number of calls allocated. */ 176 uint16_t cAllocated; 177 } Thrd; 178 }; 179 180 181 /** Number of bytes of opcodes stored in pabOpcodes. */ 182 uint16_t cbOpcodes; 183 /** The max storage available in the pabOpcodes block. */ 184 uint16_t cbOpcodesAllocated; 185 /** Pointer to the opcode bytes this block was recompiled from. */ 186 uint8_t *pabOpcodes; 187 188 #if 0 189 struct 190 { 191 uint16_t offOpcodes; 192 uint16_t cbOpcodes; 193 } aRanges; 194 195 /** Physical pages that the . */ 196 RTGCPHYS aGCPhysPgs[2]; 197 #endif 198 199 } IEMTB; 116 200 117 201 118 … … 203 120 * Internal Functions * 204 121 *********************************************************************************************************************************/ 122 static bool iemThreadedCompileBeginEmitCallsComplications(PVMCPUCC pVCpu, PIEMTB pTb); 205 123 static VBOXSTRICTRC iemThreadedTbExec(PVMCPUCC pVCpu, PIEMTB pTb); 206 124 … … 225 143 #define IEM_MC2_BEGIN_EMIT_CALLS() \ 226 144 { \ 227 PIEMTB const pTb = pVCpu->iem.s.pCurTbR3; \ 228 AssertMsg(pVCpu->iem.s.offOpcode == IEM_GET_INSTR_LEN(pVCpu), \ 229 ("%u vs %u (%04x:%08RX64)\n", pVCpu->iem.s.offOpcode, IEM_GET_INSTR_LEN(pVCpu), \ 145 PIEMTB const pTb = pVCpu->iem.s.pCurTbR3; \ 146 uint8_t const cbInstrMc2 = IEM_GET_INSTR_LEN(pVCpu); \ 147 AssertMsg(pVCpu->iem.s.offOpcode == cbInstrMc2, \ 148 ("%u vs %u (%04x:%08RX64)\n", pVCpu->iem.s.offOpcode, cbInstrMc2, \ 230 149 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); \ 231 /** @todo check for cross page stuff */ \ 232 if (!(pTb->fFlags & IEMTB_F_CS_LIM_CHECKS)) \ 150 \ 151 /* No page crossing, right? */ \ 152 uint16_t const offOpcodeMc2 = pTb->cbOpcodes; \ 153 uint8_t const idxRangeMc2 = pTb->cRanges - 1; \ 154 if ( !pVCpu->iem.s.fTbCrossedPage \ 155 && !pVCpu->iem.s.fTbCheckOpcodes \ 156 && !pVCpu->iem.s.fTbBranched \ 157 && !(pTb->fFlags & IEMTB_F_CS_LIM_CHECKS)) \ 158 { \ 159 /** @todo Custom copy function, given range is 1 thru 15 bytes. */ \ 160 memcpy(&pTb->pabOpcodes[offOpcodeMc2], pVCpu->iem.s.abOpcode, pVCpu->iem.s.offOpcode); \ 161 pTb->cbOpcodes = offOpcodeMc2 + pVCpu->iem.s.offOpcode; \ 162 pTb->aRanges[idxRangeMc2].cbOpcodes += cbInstrMc2; \ 163 Assert(pTb->cbOpcodes <= pTb->cbOpcodesAllocated); \ 164 } \ 165 else if (iemThreadedCompileBeginEmitCallsComplications(pVCpu, pTb)) \ 233 166 { /* likely */ } \ 234 167 else \ 235 { \ 236 PIEMTHRDEDCALLENTRY const pCall = &pTb->Thrd.paCalls[pTb->Thrd.cCalls++]; \ 237 pCall->enmFunction = kIemThreadedFunc_CheckCsLim; \ 238 pCall->offOpcode = pTb->cbOpcodes; \ 239 pCall->auParams[0] = pCall->cbOpcode = IEM_GET_INSTR_LEN(pVCpu); \ 240 pCall->auParams[1] = 0; \ 241 pCall->auParams[2] = 0; \ 242 } \ 168 return VINF_IEM_RECOMPILE_END_TB; \ 169 \ 243 170 do { } while (0) 244 171 … … 248 175 PIEMTHRDEDCALLENTRY const pCall = &pTb->Thrd.paCalls[pTb->Thrd.cCalls++]; \ 249 176 pCall->enmFunction = a_enmFunction; \ 250 pCall->offOpcode = pTb->cbOpcodes; \ 251 pCall->cbOpcode = IEM_GET_INSTR_LEN(pVCpu); \ 177 pCall->offOpcode = offOpcodeMc2; \ 178 pCall->cbOpcode = cbInstrMc2; \ 179 pCall->idxRange = idxRangeMc2; \ 252 180 pCall->auParams[0] = 0; \ 253 181 pCall->auParams[1] = 0; \ … … 260 188 PIEMTHRDEDCALLENTRY const pCall = &pTb->Thrd.paCalls[pTb->Thrd.cCalls++]; \ 261 189 pCall->enmFunction = a_enmFunction; \ 262 pCall->offOpcode = pTb->cbOpcodes; \ 263 pCall->cbOpcode = IEM_GET_INSTR_LEN(pVCpu); \ 190 pCall->offOpcode = offOpcodeMc2; \ 191 pCall->cbOpcode = cbInstrMc2; \ 192 pCall->idxRange = idxRangeMc2; \ 264 193 pCall->auParams[0] = a_uArg0; \ 265 194 pCall->auParams[1] = 0; \ … … 273 202 PIEMTHRDEDCALLENTRY const pCall = &pTb->Thrd.paCalls[pTb->Thrd.cCalls++]; \ 274 203 pCall->enmFunction = a_enmFunction; \ 275 pCall->offOpcode = pTb->cbOpcodes; \ 276 pCall->cbOpcode = IEM_GET_INSTR_LEN(pVCpu); \ 204 pCall->offOpcode = offOpcodeMc2; \ 205 pCall->cbOpcode = cbInstrMc2; \ 206 pCall->idxRange = idxRangeMc2; \ 277 207 pCall->auParams[0] = a_uArg0; \ 278 208 pCall->auParams[1] = a_uArg1; \ … … 287 217 PIEMTHRDEDCALLENTRY const pCall = &pTb->Thrd.paCalls[pTb->Thrd.cCalls++]; \ 288 218 pCall->enmFunction = a_enmFunction; \ 289 pCall->offOpcode = pTb->cbOpcodes; \ 290 pCall->cbOpcode = IEM_GET_INSTR_LEN(pVCpu); \ 219 pCall->offOpcode = offOpcodeMc2; \ 220 pCall->cbOpcode = cbInstrMc2; \ 221 pCall->idxRange = idxRangeMc2; \ 291 222 pCall->auParams[0] = a_uArg0; \ 292 223 pCall->auParams[1] = a_uArg1; \ … … 295 226 296 227 #define IEM_MC2_END_EMIT_CALLS() \ 228 pTb->cInstructions++; \ 297 229 } while (0) 298 230 … … 683 615 if (pTb->pabOpcodes) 684 616 { 685 pTb->Thrd.cAllocated = cCalls;686 pTb->cbOpcodesAllocated = cCalls * 16;687 pTb->Thrd.cCalls = 0;688 pTb->cbOpcodes = 0;689 pTb->pNext = NULL;617 pTb->Thrd.cAllocated = cCalls; 618 pTb->cbOpcodesAllocated = cCalls * 16; 619 pTb->Thrd.cCalls = 0; 620 pTb->cbOpcodes = 0; 621 pTb->pNext = NULL; 690 622 RTListInit(&pTb->LocalList); 691 pTb->GCPhysPc = GCPhysPc; 692 pTb->x86.fAttr = (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u; 693 pTb->fFlags = (pVCpu->iem.s.fExec & IEMTB_F_IEM_F_MASK) | fExtraFlags; 623 pTb->GCPhysPc = GCPhysPc; 624 pTb->x86.fAttr = (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u; 625 pTb->fFlags = (pVCpu->iem.s.fExec & IEMTB_F_IEM_F_MASK) | fExtraFlags; 626 627 /* Init the first opcode range. */ 628 pTb->cRanges = 1; 629 pTb->aRanges[0].cbOpcodes = 0; 630 pTb->aRanges[0].offOpcodes = 0; 631 pTb->aRanges[0].offPhysPage = GCPhysPc & GUEST_PAGE_OFFSET_MASK; 632 pTb->aRanges[0].u2Unused = 0; 633 pTb->aRanges[0].idxPhysPage = 0; 634 pTb->aGCPhysPages[0] = NIL_RTGCPHYS; 635 pTb->aGCPhysPages[1] = NIL_RTGCPHYS; 636 694 637 pVCpu->iem.s.cTbAllocs++; 695 638 return pTb; … … 746 689 RTMemFree(pTb); 747 690 pVCpu->iem.s.cTbFrees++; 691 } 692 693 694 /** 695 * Called by opcode verifier functions when they detect a problem. 696 */ 697 void iemThreadedTbObsolete(PVMCPUCC pVCpu, PIEMTB pTb) 698 { 699 iemThreadedTbFree(pVCpu->CTX_SUFF(pVM), pVCpu, pTb); 748 700 } 749 701 … … 901 853 pVCpu->iem.s.rcPassUp = VINF_SUCCESS; 902 854 pVCpu->iem.s.fEndTb = false; 855 pVCpu->iem.s.fTbCheckOpcodes = false; 856 pVCpu->iem.s.fTbBranched = false; 857 pVCpu->iem.s.fTbCrossedPage = false; 903 858 } 904 859 else … … 907 862 Assert(pVCpu->iem.s.rcPassUp == VINF_SUCCESS); 908 863 Assert(pVCpu->iem.s.fEndTb == false); 864 Assert(pVCpu->iem.s.fTbCrossedPage == false); 909 865 } 910 866 … … 992 948 993 949 950 DECLINLINE(void) iemThreadedCopyOpcodeBytesInline(PCVMCPUCC pVCpu, uint8_t *pbDst, uint8_t cbInstr) 951 { 952 switch (cbInstr) 953 { 954 default: AssertMsgFailed(("%#x\n", cbInstr)); RT_FALL_THROUGH(); 955 case 15: pbDst[14] = pVCpu->iem.s.abOpcode[14]; RT_FALL_THROUGH(); 956 case 14: pbDst[13] = pVCpu->iem.s.abOpcode[13]; RT_FALL_THROUGH(); 957 case 13: pbDst[12] = pVCpu->iem.s.abOpcode[12]; RT_FALL_THROUGH(); 958 case 12: pbDst[11] = pVCpu->iem.s.abOpcode[11]; RT_FALL_THROUGH(); 959 case 11: pbDst[10] = pVCpu->iem.s.abOpcode[10]; RT_FALL_THROUGH(); 960 case 10: pbDst[9] = pVCpu->iem.s.abOpcode[9]; RT_FALL_THROUGH(); 961 case 9: pbDst[8] = pVCpu->iem.s.abOpcode[8]; RT_FALL_THROUGH(); 962 case 8: pbDst[7] = pVCpu->iem.s.abOpcode[7]; RT_FALL_THROUGH(); 963 case 7: pbDst[6] = pVCpu->iem.s.abOpcode[6]; RT_FALL_THROUGH(); 964 case 6: pbDst[5] = pVCpu->iem.s.abOpcode[5]; RT_FALL_THROUGH(); 965 case 5: pbDst[4] = pVCpu->iem.s.abOpcode[4]; RT_FALL_THROUGH(); 966 case 4: pbDst[3] = pVCpu->iem.s.abOpcode[3]; RT_FALL_THROUGH(); 967 case 3: pbDst[2] = pVCpu->iem.s.abOpcode[2]; RT_FALL_THROUGH(); 968 case 2: pbDst[1] = pVCpu->iem.s.abOpcode[1]; RT_FALL_THROUGH(); 969 case 1: pbDst[0] = pVCpu->iem.s.abOpcode[0]; break; 970 } 971 } 972 973 974 /** 975 * Called by IEM_MC2_BEGIN_EMIT_CALLS() under one of these conditions: 976 * 977 * - CS LIM check required. 978 * - Must recheck opcode bytes. 979 * - Previous instruction branched. 980 * - TLB load detected, probably due to page crossing. 981 * 982 * @returns true if everything went well, false if we're out of space in the TB 983 * (e.g. opcode ranges). 984 * @param pVCpu The cross context virtual CPU structure of the calling 985 * thread. 986 * @param pTb The translation block being compiled. 987 */ 988 static bool iemThreadedCompileBeginEmitCallsComplications(PVMCPUCC pVCpu, PIEMTB pTb) 989 { 990 Assert((pVCpu->iem.s.GCPhysInstrBuf & GUEST_PAGE_OFFSET_MASK) == 0); 991 992 /* 993 * Prepare call now, even before we know if can accept the instruction in this TB. 994 * This allows us amending parameters w/o making every case suffer. 995 */ 996 uint8_t const cbInstr = IEM_GET_INSTR_LEN(pVCpu); 997 uint16_t const offOpcode = pTb->cbOpcodes; 998 uint8_t idxRange = pTb->cRanges - 1; 999 1000 PIEMTHRDEDCALLENTRY const pCall = &pTb->Thrd.paCalls[pTb->Thrd.cCalls]; 1001 pCall->offOpcode = offOpcode; 1002 pCall->idxRange = idxRange; 1003 pCall->cbOpcode = cbInstr; 1004 pCall->auParams[0] = cbInstr; 1005 pCall->auParams[1] = idxRange; 1006 pCall->auParams[2] = offOpcode - pTb->aRanges[idxRange].offOpcodes; 1007 1008 /** @todo check if we require IEMTB_F_CS_LIM_CHECKS for any new page we've 1009 * gotten onto. If we do, stop */ 1010 1011 /* 1012 * Case 1: We've branched (RIP changed). 1013 * 1014 * Sub-case 1a: Same page, no TLB load, so fTbCrossedPage is false. 1015 * Req: 1 extra range, no extra phys. 1016 * 1017 * Sub-case 1b: Different page, so TLB load necessary and fTbCrossedPage is true. 1018 * Req: 1 extra range, probably 1 extra phys page entry. 1019 * 1020 * Sub-case 1c: Different page, so TLB load necessary and fTbCrossedPage is true, 1021 * but in addition we cross into the following page and require 1022 * another TLB load. 1023 * Req: 2 extra ranges, probably 2 extra phys page entries. 1024 * 1025 * Sub-case 1d: Same page, so no initial TLB load necessary, but we cross into 1026 * the following page and thus fTbCrossedPage is true. 1027 * Req: 2 extra ranges, probably 1 extra phys page entry. 1028 * 1029 * Note! We do not currently optimize branching to the next instruction (sorry 1030 * 32-bit PIC code). We could maybe do that in the branching code that sets (or not) fTbBranched. 1031 */ 1032 if (pVCpu->iem.s.fTbBranched) 1033 { 1034 AssertFailed(); /** @todo enable including branches in TBs and debug this code. */ 1035 if ( !pVCpu->iem.s.fTbCrossedPage /* 1a */ 1036 || pVCpu->iem.s.offCurInstrStart >= 0 /* 1b */ ) 1037 { 1038 /* 1a + 1b - instruction fully within the branched to page. */ 1039 Assert(pVCpu->iem.s.offCurInstrStart >= 0); 1040 Assert(pVCpu->iem.s.offCurInstrStart + cbInstr <= GUEST_PAGE_SIZE); 1041 1042 /* Check that we've got a free range. */ 1043 idxRange += 1; 1044 if (idxRange < RT_ELEMENTS(pTb->aRanges)) 1045 { /* likely */ } 1046 else 1047 return false; 1048 pCall->idxRange = idxRange; 1049 pCall->auParams[1] = idxRange; 1050 pCall->auParams[2] = 0; 1051 1052 /* Check that we've got a free page slot. */ 1053 AssertCompile(RT_ELEMENTS(pTb->aGCPhysPages) == 2); 1054 RTGCPHYS const GCPhysNew = pVCpu->iem.s.GCPhysInstrBuf & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK; 1055 if ((pTb->GCPhysPc & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK) == GCPhysNew) 1056 pTb->aRanges[idxRange].idxPhysPage = 0; 1057 else if ( pTb->aGCPhysPages[0] == NIL_RTGCPHYS 1058 || pTb->aGCPhysPages[0] == GCPhysNew) 1059 { 1060 pTb->aGCPhysPages[0] = GCPhysNew; 1061 pTb->aRanges[idxRange].idxPhysPage = 1; 1062 } 1063 else if ( pTb->aGCPhysPages[1] == NIL_RTGCPHYS 1064 || pTb->aGCPhysPages[1] == GCPhysNew) 1065 { 1066 pTb->aGCPhysPages[1] = GCPhysNew; 1067 pTb->aRanges[idxRange].idxPhysPage = 2; 1068 } 1069 else 1070 return false; 1071 1072 /* Finish setting up the new range. */ 1073 pTb->aRanges[idxRange].offPhysPage = pVCpu->iem.s.offCurInstrStart; 1074 pTb->aRanges[idxRange].offOpcodes = offOpcode; 1075 pTb->aRanges[idxRange].cbOpcodes = cbInstr; 1076 pTb->cRanges++; 1077 1078 /* Determin which function we need to load & check. 1079 Note! For jumps to a new page, we'll set both fTbBranched and 1080 fTbCrossedPage to avoid unnecessary TLB work for intra 1081 page branching */ 1082 if (pVCpu->iem.s.fTbCrossedPage) 1083 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS 1084 ? kIemThreadedFunc_CheckCsLimAndOpcodesLoadingTlb 1085 : kIemThreadedFunc_CheckOpcodesLoadingTlb; 1086 else 1087 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS 1088 ? kIemThreadedFunc_CheckCsLimAndOpcodes 1089 : kIemThreadedFunc_CheckOpcodes; 1090 } 1091 else 1092 { 1093 /* 1c + 1d - instruction crosses pages. */ 1094 Assert(pVCpu->iem.s.offCurInstrStart < 0); 1095 Assert(pVCpu->iem.s.offCurInstrStart + cbInstr > 0); 1096 1097 /* Lazy bird: Check that this isn't case 1c, since we've already 1098 load the first physical address. End the TB and 1099 make it a case 2b instead. 1100 1101 Hmm. Too much bother to detect, so just do the same 1102 with case 1d as well. */ 1103 #if 0 /** @todo get back to this later when we've got the actual branch code in 1104 * place. */ 1105 uint8_t const cbStartPage = (uint8_t)-pVCpu->iem.s.offCurInstrStart; 1106 1107 /* Check that we've got two free ranges. */ 1108 if (idxRange + 2 < RT_ELEMENTS(pTb->aRanges)) 1109 { /* likely */ } 1110 else 1111 return false; 1112 idxRange += 1; 1113 pCall->idxRange = idxRange; 1114 pCall->auParams[1] = idxRange; 1115 pCall->auParams[2] = 0; 1116 1117 /* ... */ 1118 1119 #else 1120 return false; 1121 #endif 1122 } 1123 } 1124 1125 /* 1126 * Case 2: Page crossing. 1127 * 1128 * Sub-case 2a: The instruction starts on the first byte in the next page. 1129 * 1130 * Sub-case 2b: The instruction has opcode bytes in both the current and 1131 * following page. 1132 * 1133 * Both cases requires a new range table entry and probably a new physical 1134 * page entry. The difference is in which functions to emit and whether to 1135 * add bytes to the current range. 1136 */ 1137 else if (pVCpu->iem.s.fTbCrossedPage) 1138 { 1139 /* Check that we've got a free range. */ 1140 idxRange += 1; 1141 if (idxRange < RT_ELEMENTS(pTb->aRanges)) 1142 { /* likely */ } 1143 else 1144 return false; 1145 1146 /* Check that we've got a free page slot. */ 1147 AssertCompile(RT_ELEMENTS(pTb->aGCPhysPages) == 2); 1148 RTGCPHYS const GCPhysNew = pVCpu->iem.s.GCPhysInstrBuf & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK; 1149 if ((pTb->GCPhysPc & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK) == GCPhysNew) 1150 pTb->aRanges[idxRange].idxPhysPage = 0; 1151 else if ( pTb->aGCPhysPages[0] == NIL_RTGCPHYS 1152 || pTb->aGCPhysPages[0] == GCPhysNew) 1153 { 1154 pTb->aGCPhysPages[0] = GCPhysNew; 1155 pTb->aRanges[idxRange].idxPhysPage = 1; 1156 } 1157 else if ( pTb->aGCPhysPages[1] == NIL_RTGCPHYS 1158 || pTb->aGCPhysPages[1] == GCPhysNew) 1159 { 1160 pTb->aGCPhysPages[1] = GCPhysNew; 1161 pTb->aRanges[idxRange].idxPhysPage = 2; 1162 } 1163 else 1164 return false; 1165 1166 if (((pTb->aRanges[idxRange - 1].offPhysPage + pTb->aRanges[idxRange - 1].cbOpcodes) & GUEST_PAGE_OFFSET_MASK) == 0) 1167 { 1168 Assert(pVCpu->iem.s.offCurInstrStart == 0); 1169 pCall->idxRange = idxRange; 1170 pCall->auParams[1] = idxRange; 1171 pCall->auParams[2] = 0; 1172 1173 /* Finish setting up the new range. */ 1174 pTb->aRanges[idxRange].offPhysPage = pVCpu->iem.s.offCurInstrStart; 1175 pTb->aRanges[idxRange].offOpcodes = offOpcode; 1176 pTb->aRanges[idxRange].cbOpcodes = cbInstr; 1177 pTb->cRanges++; 1178 1179 /* Determin which function we need to load & check. */ 1180 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS 1181 ? kIemThreadedFunc_CheckCsLimAndOpcodesLoadingTlb 1182 : kIemThreadedFunc_CheckOpcodesLoadingTlb; 1183 } 1184 else 1185 { 1186 Assert(pVCpu->iem.s.offCurInstrStart < 0); 1187 Assert(pVCpu->iem.s.offCurInstrStart + cbInstr > 0); 1188 uint8_t const cbStartPage = (uint8_t)-pVCpu->iem.s.offCurInstrStart; 1189 pCall->auParams[0] |= (uint64_t)cbStartPage << 32; 1190 1191 /* We've good. Split the instruction over the old and new range table entries. */ 1192 pTb->aRanges[idxRange - 1].cbOpcodes += cbStartPage; 1193 1194 pTb->aRanges[idxRange].offPhysPage = 0; 1195 pTb->aRanges[idxRange].offOpcodes = offOpcode + cbStartPage; 1196 pTb->aRanges[idxRange].cbOpcodes = cbInstr - cbStartPage; 1197 pTb->cRanges++; 1198 1199 /* Determin which function we need to load & check. */ 1200 if (pVCpu->iem.s.fTbCheckOpcodes) 1201 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS 1202 ? kIemThreadedFunc_CheckCsLimAndOpcodesAcrossPageLoadingTlb 1203 : kIemThreadedFunc_CheckOpcodesAcrossPageLoadingTlb; 1204 else 1205 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS 1206 ? kIemThreadedFunc_CheckCsLimAndOpcodesOnNextPageLoadingTlb 1207 : kIemThreadedFunc_CheckOpcodesOnNextPageLoadingTlb; 1208 } 1209 } 1210 1211 /* 1212 * Regular case: No new range required. 1213 */ 1214 else 1215 { 1216 Assert(pVCpu->iem.s.fTbCheckOpcodes || (pTb->fFlags & IEMTB_F_CS_LIM_CHECKS)); 1217 if (pVCpu->iem.s.fTbCheckOpcodes) 1218 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS 1219 ? kIemThreadedFunc_CheckCsLimAndOpcodes 1220 : kIemThreadedFunc_CheckOpcodes; 1221 else 1222 pCall->enmFunction = kIemThreadedFunc_CheckCsLim; 1223 1224 iemThreadedCopyOpcodeBytesInline(pVCpu, &pTb->pabOpcodes[offOpcode], cbInstr); 1225 pTb->cbOpcodes = offOpcode + cbInstr; 1226 pTb->aRanges[idxRange].cbOpcodes += cbInstr; 1227 Assert(pTb->cbOpcodes <= pTb->cbOpcodesAllocated); 1228 } 1229 1230 /* 1231 * Commit the call. 1232 */ 1233 pTb->Thrd.cCalls++; 1234 1235 /* 1236 * Clear state. 1237 */ 1238 pVCpu->iem.s.fTbBranched = false; 1239 pVCpu->iem.s.fTbCrossedPage = false; 1240 pVCpu->iem.s.fTbCheckOpcodes = false; 1241 1242 /* 1243 * Copy opcode bytes. 1244 */ 1245 iemThreadedCopyOpcodeBytesInline(pVCpu, &pTb->pabOpcodes[offOpcode], cbInstr); 1246 pTb->cbOpcodes = offOpcode + cbInstr; 1247 Assert(pTb->cbOpcodes <= pTb->cbOpcodesAllocated); 1248 1249 return true; 1250 } 1251 1252 1253 994 1254 /** 995 1255 * Compiles a new TB and executes it. … … 1045 1305 Assert(cCallsPrev - pTb->Thrd.cCalls < 5); 1046 1306 1047 memcpy(&pTb->pabOpcodes[pTb->cbOpcodes], pVCpu->iem.s.abOpcode, pVCpu->iem.s.offOpcode);1048 pTb->cbOpcodes += pVCpu->iem.s.offOpcode;1049 Assert(pTb->cbOpcodes <= pTb->cbOpcodesAllocated);1050 1307 pVCpu->iem.s.cInstructions++; 1051 1308 } 1052 else if (pTb->Thrd.cCalls > 0) 1053 { 1054 Log8(("%04x:%08RX64: End TB - %u calls, rc=%d\n", uCsLog, uRipLog, pTb->Thrd.cCalls, VBOXSTRICTRC_VAL(rcStrict))); 1055 1056 if (cCallsPrev != pTb->Thrd.cCalls) 1309 else 1310 { 1311 Log8(("%04x:%08RX64: End TB - %u instr, %u calls, rc=%d\n", 1312 uCsLog, uRipLog, pTb->cInstructions, pTb->Thrd.cCalls, VBOXSTRICTRC_VAL(rcStrict))); 1313 if (rcStrict == VINF_IEM_RECOMPILE_END_TB) 1314 rcStrict = VINF_SUCCESS; 1315 1316 if (pTb->Thrd.cCalls > 0) 1057 1317 { 1058 memcpy(&pTb->pabOpcodes[pTb->cbOpcodes], pVCpu->iem.s.abOpcode, pVCpu->iem.s.offOpcode); 1059 pTb->cbOpcodes += pVCpu->iem.s.offOpcode; 1060 Assert(pTb->cbOpcodes <= pTb->cbOpcodesAllocated); 1061 pVCpu->iem.s.cInstructions++; 1318 if (cCallsPrev != pTb->Thrd.cCalls) 1319 pVCpu->iem.s.cInstructions++; 1320 break; 1062 1321 } 1063 break; 1064 } 1065 else 1066 { 1067 Log8(("%04x:%08RX64: End TB - 0 calls, rc=%d\n", uCsLog, uRipLog, VBOXSTRICTRC_VAL(rcStrict))); 1322 1068 1323 pVCpu->iem.s.pCurTbR3 = NULL; 1069 1324 iemThreadedTbFree(pVM, pVCpu, pTb); … … 1072 1327 1073 1328 /* Still space in the TB? */ 1074 if (pTb->Thrd.cCalls + 5 < pTb->Thrd.cAllocated) 1329 if ( pTb->Thrd.cCalls + 5 < pTb->Thrd.cAllocated 1330 && pTb->cbOpcodes + 16 <= pTb->cbOpcodesAllocated) 1075 1331 iemThreadedCompileInitDecoder(pVCpu, true /*fReInit*/); 1076 1332 else 1077 1333 { 1078 Log8(("%04x:%08RX64: End TB - %u calls - full\n", uCsLog, uRipLog, pTb->Thrd.cCalls)); 1334 Log8(("%04x:%08RX64: End TB - %u instr, %u calls, %u opcode bytes - full\n", 1335 uCsLog, uRipLog, pTb->cInstructions, pTb->Thrd.cCalls, pTb->cbOpcodes)); 1079 1336 break; 1080 1337 } … … 1115 1372 else 1116 1373 { 1117 Log 11(("TB obsolete: %p GCPhys=%RGp\n", pTb, pTb->GCPhysPc));1374 Log7(("TB obsolete: %p GCPhys=%RGp\n", pTb, pTb->GCPhysPc)); 1118 1375 iemThreadedTbFree(pVCpu->pVMR3, pVCpu, pTb); 1119 1376 return VINF_SUCCESS; -
trunk/src/VBox/VMM/include/IEMInternal.h
r100672 r100694 39 39 40 40 #include <iprt/setjmp-without-sigmask.h> 41 #include <iprt/list.h> 41 42 42 43 … … 536 537 537 538 538 /** Pointer to a translation block. */539 typedef struct IEMTB *PIEMTB;540 541 539 /** @name IEM_F_XXX - Execution mode flags (IEMCPU::fExec, IEMTB::fFlags). 542 540 * … … 720 718 AssertCompile( IEM_F_MODE_X86_64BIT & IEM_F_MODE_X86_PROT_MASK); 721 719 AssertCompile(!(IEM_F_MODE_X86_64BIT & IEM_F_MODE_X86_FLAT_OR_PRE_386_MASK)); 720 721 /** 722 * A call for the threaded call table. 723 */ 724 typedef struct IEMTHRDEDCALLENTRY 725 { 726 /** The function to call (IEMTHREADEDFUNCS). */ 727 uint16_t enmFunction; 728 uint16_t uUnused0; 729 730 /** Offset into IEMTB::pabOpcodes. */ 731 uint16_t offOpcode; 732 /** The opcode length. */ 733 uint8_t cbOpcode; 734 /** Index in to IEMTB::aRanges. */ 735 uint8_t idxRange; 736 737 /** Generic parameters. */ 738 uint64_t auParams[3]; 739 } IEMTHRDEDCALLENTRY; 740 AssertCompileSize(IEMTHRDEDCALLENTRY, sizeof(uint64_t) * 4); 741 /** Pointer to a threaded call entry. */ 742 typedef struct IEMTHRDEDCALLENTRY *PIEMTHRDEDCALLENTRY; 743 /** Pointer to a const threaded call entry. */ 744 typedef IEMTHRDEDCALLENTRY const *PCIEMTHRDEDCALLENTRY; 745 746 /** 747 * Translation block. 748 */ 749 #pragma pack(2) /* to prevent the Thrd structure from being padded unnecessarily */ 750 typedef struct IEMTB 751 { 752 /** Next block with the same hash table entry. */ 753 struct IEMTB * volatile pNext; 754 /** List on the local VCPU for blocks. */ 755 RTLISTNODE LocalList; 756 757 /** @name What uniquely identifies the block. 758 * @{ */ 759 RTGCPHYS GCPhysPc; 760 /** IEMTB_F_XXX (i.e. IEM_F_XXX ++). */ 761 uint32_t fFlags; 762 union 763 { 764 struct 765 { 766 /**< Relevant CS X86DESCATTR_XXX bits. */ 767 uint16_t fAttr; 768 } x86; 769 }; 770 /** @} */ 771 772 /** Number of opcode ranges. */ 773 uint8_t cRanges; 774 /** Statistics: Number of instructions in the block. */ 775 uint8_t cInstructions; 776 777 /** Type specific info. */ 778 union 779 { 780 struct 781 { 782 /** The call sequence table. */ 783 PIEMTHRDEDCALLENTRY paCalls; 784 /** Number of calls in paCalls. */ 785 uint16_t cCalls; 786 /** Number of calls allocated. */ 787 uint16_t cAllocated; 788 } Thrd; 789 }; 790 791 /** Number of bytes of opcodes stored in pabOpcodes. */ 792 uint16_t cbOpcodes; 793 /** The max storage available in the pabOpcodes block. */ 794 uint16_t cbOpcodesAllocated; 795 /** Pointer to the opcode bytes this block was recompiled from. */ 796 uint8_t *pabOpcodes; 797 798 /* --- 64 byte cache line end --- */ 799 800 /** Opcode ranges. 801 * 802 * The opcode checkers and maybe TLB loading functions will use this to figure 803 * out what to do. The parameter will specify an entry and the opcode offset to 804 * start at and the minimum number of bytes to verify (instruction length). 805 * 806 * When VT-x and AMD-V looks up the opcode bytes for an exitting instruction, 807 * they'll first translate RIP (+ cbInstr - 1) to a physical address using the 808 * code TLB (must have a valid entry for that address) and scan the ranges to 809 * locate the corresponding opcodes. Probably. 810 */ 811 struct IEMTBOPCODERANGE 812 { 813 /** Offset within pabOpcodes. */ 814 uint16_t offOpcodes; 815 /** Number of bytes. */ 816 uint16_t cbOpcodes; 817 /** The page offset. */ 818 RT_GCC_EXTENSION 819 uint16_t offPhysPage : 12; 820 /** Unused bits. */ 821 RT_GCC_EXTENSION 822 uint16_t u2Unused : 2; 823 /** Index into GCPhysPc + aGCPhysPages for the physical page address. */ 824 RT_GCC_EXTENSION 825 uint16_t idxPhysPage : 2; 826 } aRanges[8]; 827 828 /** Physical pages that this TB covers. 829 * The GCPhysPc w/o page offset is element zero, so starting here with 1. */ 830 RTGCPHYS aGCPhysPages[2]; 831 } IEMTB; 832 #pragma pack() 833 AssertCompileMemberOffset(IEMTB, x86, 36); 834 AssertCompileMemberOffset(IEMTB, cRanges, 38); 835 AssertCompileMemberOffset(IEMTB, Thrd, 40); 836 AssertCompileMemberOffset(IEMTB, Thrd.cCalls, 48); 837 AssertCompileMemberOffset(IEMTB, cbOpcodes, 52); 838 AssertCompileMemberSize(IEMTB, aRanges[0], 6); 839 AssertCompileSize(IEMTB, 128); 840 /** Pointer to a translation block. */ 841 typedef IEMTB *PIEMTB; 842 /** Pointer to a const translation block. */ 843 typedef IEMTB const *PCIEMTB; 722 844 723 845 … … 1014 1136 /** Number of TBs executed. */ 1015 1137 uint64_t cTbExec; 1138 /** Whether we need to check the opcode bytes for the current instruction. 1139 * This is set by a previous instruction if it modified memory or similar. */ 1140 bool fTbCheckOpcodes; 1141 /** Whether we just branched and need to start a new opcode range and emit code 1142 * to do a TLB load and check them again. */ 1143 bool fTbBranched; 1144 /** Set when GCPhysInstrBuf is updated because of a page crossing. */ 1145 bool fTbCrossedPage; 1016 1146 /** Whether to end the current TB. */ 1017 1147 bool fEndTb; 1018 1148 /** Spaced reserved for recompiler data / alignment. */ 1019 bool afRecompilerStuff1[ 7];1149 bool afRecompilerStuff1[4]; 1020 1150 /** @} */ 1021 1151 … … 4764 4894 IEM_CIMPL_PROTO_1(iemCImpl_Hypercall, uint16_t, uDisOpcode); /* both */ 4765 4895 4896 void iemThreadedTbObsolete(PVMCPUCC pVCpu, PIEMTB pTb); 4897 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckMode, 4898 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4899 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLim, 4900 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4901 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLimAndOpcodes, 4902 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4903 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLimAndOpcodesAcrossPageLoadingTlb, 4904 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4905 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLimAndOpcodesLoadingTlb, 4906 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4907 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNextPageLoadingTlb, 4908 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4909 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckOpcodes, 4910 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4911 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlb, 4912 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4913 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckOpcodesLoadingTlb, 4914 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4915 IEM_DECL_IMPL_PROTO(VBOXSTRICTRC, iemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlb, 4916 (PVMCPU pVCpu, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)); 4917 4766 4918 4767 4919 extern const PFNIEMOP g_apfnIemInterpretOnlyOneByteMap[256];
Note:
See TracChangeset
for help on using the changeset viewer.