Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:zhubr
virtualbox52
vbox-upd09-splitlock-madness.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File vbox-upd09-splitlock-madness.diff of Package virtualbox52
Modifications to workaround this crazy split lock detection thing (on 10+ generation Intel CPUs with 5.18+ kernel version). As a prerequisite, patch manager had to be disabled first. https://www.virtualbox.org/ticket/20180 https://www.virtualbox.org/changeset/89975/vbox/trunk https://www.virtualbox.org/changeset/89974/vbox/trunk https://www.virtualbox.org/changeset/89976/vbox/trunk https://www.virtualbox.org/changeset/89993/vbox/trunk https://www.virtualbox.org/changeset/90000/vbox/trunk --- a/src/VBox/VMM/VMMR3/PATM.cpp 2020-07-09 19:57:56.000000000 +0300 +++ b/src/VBox/VMM/VMMR3/PATM.cpp 2023-03-04 15:56:17.749755086 +0300 @@ -157,7 +157,6 @@ /* * We only need a saved state dummy loader if HM is enabled. */ - if (HMIsEnabled(pVM)) { pVM->fPATMEnabled = false; return SSMR3RegisterStub(pVM, "PATM", 0); @@ -215,16 +214,7 @@ AssertRCReturn(rc, rc); pVM->patm.s.PatchLookupTreeGC = MMHyperR3ToRC(pVM, pVM->patm.s.PatchLookupTreeHC); -#ifdef RT_ARCH_AMD64 /* see patmReinit(). */ - /* Check CFGM option. */ - rc = CFGMR3QueryBool(CFGMR3GetRoot(pVM), "PATMEnabled", &pVM->fPATMEnabled); - if (RT_FAILURE(rc)) -# ifdef PATM_DISABLE_ALL - pVM->fPATMEnabled = false; -# else - pVM->fPATMEnabled = true; -# endif -#endif + pVM->fPATMEnabled = false; rc = patmReinit(pVM); AssertRC(rc); @@ -415,11 +405,7 @@ */ pVM->patm.s.offVM = RT_UOFFSETOF(VM, patm); -#ifndef RT_ARCH_AMD64 /* would be nice if this was changed everywhere. was driving me crazy on AMD64. */ -#ifndef PATM_DISABLE_ALL - pVM->fPATMEnabled = true; -#endif -#endif + pVM->fPATMEnabled = false; Assert(pVM->patm.s.pGCStateHC); memset(pVM->patm.s.pGCStateHC, 0, PAGE_SIZE); @@ -1052,10 +1038,8 @@ PVM pVM = pUVM->pVM; VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); - if (!HMIsEnabled(pVM)) - pVM->fPATMEnabled = fAllowPatching; - else - Assert(!pVM->fPATMEnabled); + if (fAllowPatching) + return VERR_PATCHING_REFUSED; return VINF_SUCCESS; } @@ -6875,12 +6859,7 @@ PVM pVM = pUVM->pVM; VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); - if (HMIsEnabled(pVM)) - return DBGCCmdHlpPrintf(pCmdHlp, "PATM is permanently disabled by HM.\n"); - - PATMR3AllowPatching(pVM->pUVM, true); - RTAvloU32DoWithAll(&pVM->patm.s.PatchLookupTreeHC->PatchTree, true, EnableAllPatches, pVM); - return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Patching enabled\n"); + return DBGCCmdHlpPrintf(pCmdHlp, "PATM is permanently disabled.\n"); } #endif /* VBOX_WITH_DEBUGGER */ --- a/src/VBox/VMM/VMMR3/VM.cpp 2020-07-09 19:57:57.000000000 +0300 +++ b/src/VBox/VMM/VMMR3/VM.cpp 2023-03-04 16:01:07.057757821 +0300 @@ -782,7 +782,7 @@ # ifdef VBOX_WITH_RAW_RING1 rc = CFGMR3QueryBoolDef(pRoot, "RawR1Enabled", &pVM->fRawRing1Enabled, false); # endif - rc = CFGMR3QueryBoolDef(pRoot, "PATMEnabled", &pVM->fPATMEnabled, true); AssertRCReturn(rc, rc); + pVM->fPATMEnabled = false; rc = CFGMR3QueryBoolDef(pRoot, "CSAMEnabled", &pVM->fCSAMEnabled, true); AssertRCReturn(rc, rc); rc = CFGMR3QueryBoolDef(pRoot, "HMEnabled", &pVM->fHMEnabled, true); AssertRCReturn(rc, rc); #else --- a/src/VBox/VMM/VMMAll/IEMAllAImpl.asm 2020-07-09 19:57:52.000000000 +0300 +++ b/src/VBox/VMM/VMMAll/IEMAllAImpl.asm 2023-03-04 02:44:26.525231676 +0300 @@ -262,6 +262,7 @@ %define T1 edi %define T1_32 edi %define T1_16 di + %define T1_8 dl %endif @@ -614,6 +615,45 @@ ENDPROC iemAImpl_xchg_u64 %endif +; Unlocked variants for fDisregardLock mode. + +BEGINPROC_FASTCALL iemAImpl_xchg_u8_unlocked, 8 + PROLOGUE_2_ARGS + mov T0_8, [A1] + mov T1_8, [A0] + mov [A0], T0_8 + mov [A1], T1_8 + EPILOGUE_2_ARGS +ENDPROC iemAImpl_xchg_u8_unlocked + +BEGINPROC_FASTCALL iemAImpl_xchg_u16_unlocked, 8 + PROLOGUE_2_ARGS + mov T0_16, [A1] + mov T1_16, [A0] + mov [A0], T0_16 + mov [A1], T1_16 + EPILOGUE_2_ARGS +ENDPROC iemAImpl_xchg_u16_unlocked + +BEGINPROC_FASTCALL iemAImpl_xchg_u32_unlocked, 8 + PROLOGUE_2_ARGS + mov T0_32, [A1] + mov T1_32, [A0] + mov [A0], T0_32 + mov [A1], T1_32 + EPILOGUE_2_ARGS +ENDPROC iemAImpl_xchg_u32_unlocked + +%ifdef RT_ARCH_AMD64 +BEGINPROC_FASTCALL iemAImpl_xchg_u64_unlocked, 8 + PROLOGUE_2_ARGS + mov T0, [A1] + mov T1, [A0] + mov [A0], T0 + mov [A1], T1 + EPILOGUE_2_ARGS +ENDPROC iemAImpl_xchg_u64_unlocked +%endif ; ; XADD for memory operands. --- a/src/VBox/VMM/include/IEMInternal.h 2020-07-09 19:57:59.000000000 +0300 +++ b/src/VBox/VMM/include/IEMInternal.h 2023-03-04 02:59:28.621228233 +0300 @@ -466,8 +466,8 @@ /** Whether to bypass access handlers or not. */ bool fBypassHandlers; /* 0x06 */ - /** Indicates that we're interpreting patch code - RC only! */ - bool fInPatchCode; /* 0x07 */ + /** Whether to disregard the lock prefix (implied or not). */ + bool fDisregardLock; /* 0x07 */ /** @name Decoder state. * @{ */ @@ -1190,6 +1190,10 @@ IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u16,(uint16_t *pu16Mem, uint16_t *pu16Reg)); IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u32,(uint32_t *pu32Mem, uint32_t *pu32Reg)); IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u64,(uint64_t *pu64Mem, uint64_t *pu64Reg)); +IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u8_unlocked, (uint8_t *pu8Mem, uint8_t *pu8Reg)); +IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u16_unlocked,(uint16_t *pu16Mem, uint16_t *pu16Reg)); +IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u32_unlocked,(uint32_t *pu32Mem, uint32_t *pu32Reg)); +IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u64_unlocked,(uint64_t *pu64Mem, uint64_t *pu64Reg)); /** @} */ /** @name Exchange and add operations. --- a/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp 2020-07-09 19:57:52.000000000 +0300 +++ b/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp 2023-03-04 19:44:14.249884397 +0300 @@ -1129,6 +1129,15 @@ *puReg = uOldMem; } +IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u64_unlocked,(uint64_t *puMem, uint64_t *puReg)) +{ + /* Quite doubious, as well as the above one actually, but this + is to only fix 32-bit compilation so likely irrelevant + for any real use case anyway. */ + uint64_t uOldMem = *puMem; + *puMem = *puReg; + *puReg = uOldMem; +} #endif /* RT_ARCH_X86 */ #ifdef RT_ARCH_X86 --- a/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h 2020-07-09 19:57:53.000000000 +0300 +++ b/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h 2023-03-04 03:10:21.869225740 +0300 @@ -3623,7 +3623,10 @@ IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); IEM_MC_MEM_MAP(pu8Mem, IEM_ACCESS_DATA_RW, pVCpu->iem.s.iEffSeg, GCPtrEffDst, 0 /*arg*/); IEM_MC_REF_GREG_U8(pu8Reg, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg); + if (!pVCpu->iem.s.fDisregardLock) IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u8, pu8Mem, pu8Reg); + else + IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u8_unlocked, pu8Mem, pu8Reg); IEM_MC_MEM_COMMIT_AND_UNMAP(pu8Mem, IEM_ACCESS_DATA_RW); IEM_MC_ADVANCE_RIP(); @@ -3712,7 +3715,10 @@ IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); IEM_MC_MEM_MAP(pu16Mem, IEM_ACCESS_DATA_RW, pVCpu->iem.s.iEffSeg, GCPtrEffDst, 0 /*arg*/); IEM_MC_REF_GREG_U16(pu16Reg, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg); + if (!pVCpu->iem.s.fDisregardLock) IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u16, pu16Mem, pu16Reg); + else + IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u16_unlocked, pu16Mem, pu16Reg); IEM_MC_MEM_COMMIT_AND_UNMAP(pu16Mem, IEM_ACCESS_DATA_RW); IEM_MC_ADVANCE_RIP(); @@ -3728,7 +3734,10 @@ IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); IEM_MC_MEM_MAP(pu32Mem, IEM_ACCESS_DATA_RW, pVCpu->iem.s.iEffSeg, GCPtrEffDst, 0 /*arg*/); IEM_MC_REF_GREG_U32(pu32Reg, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg); + if (!pVCpu->iem.s.fDisregardLock) IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u32, pu32Mem, pu32Reg); + else + IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u32_unlocked, pu32Mem, pu32Reg); IEM_MC_MEM_COMMIT_AND_UNMAP(pu32Mem, IEM_ACCESS_DATA_RW); IEM_MC_CLEAR_HIGH_GREG_U64_BY_REF(pu32Reg); @@ -3745,7 +3754,10 @@ IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); IEM_MC_MEM_MAP(pu64Mem, IEM_ACCESS_DATA_RW, pVCpu->iem.s.iEffSeg, GCPtrEffDst, 0 /*arg*/); IEM_MC_REF_GREG_U64(pu64Reg, ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) | pVCpu->iem.s.uRexReg); + if (!pVCpu->iem.s.fDisregardLock) IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u64, pu64Mem, pu64Reg); + else + IEM_MC_CALL_VOID_AIMPL_2(iemAImpl_xchg_u64_unlocked, pu64Mem, pu64Reg); IEM_MC_MEM_COMMIT_AND_UNMAP(pu64Mem, IEM_ACCESS_DATA_RW); IEM_MC_ADVANCE_RIP(); @@ -10572,6 +10584,7 @@ FNIEMOP_DEF(iemOp_lock) { IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("lock"); + if (!pVCpu->iem.s.fDisregardLock) pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_LOCK; uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b); --- a/include/VBox/vmm/iem.h 2020-07-09 19:49:51.000000000 +0300 +++ b/include/VBox/vmm/iem.h 2023-03-04 03:13:41.289224979 +0300 @@ -186,6 +186,7 @@ VMMDECL(VBOXSTRICTRC) IEMExecOneBypassWithPrefetchedByPCWritten(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint64_t OpcodeBytesPC, const void *pvOpcodeBytes, size_t cbOpcodeBytes, uint32_t *pcbWritten); +VMMDECL(VBOXSTRICTRC) IEMExecOneIgnoreLock(PVMCPU pVCpu); VMMDECL(VBOXSTRICTRC) IEMExecLots(PVMCPU pVCpu, uint32_t *pcInstructions); VMMDECL(VBOXSTRICTRC) IEMInjectTrpmEvent(PVMCPU pVCpu); VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2, --- a/src/VBox/VMM/VMMAll/IEMAll.cpp 2020-07-09 19:57:52.000000000 +0300 +++ b/src/VBox/VMM/VMMAll/IEMAll.cpp 2023-03-04 03:36:31.957219747 +0300 @@ -1025,11 +1025,6 @@ pVCpu->iem.s.rcPassUp = VINF_SUCCESS; pVCpu->iem.s.fBypassHandlers = fBypassHandlers; #ifdef VBOX_WITH_RAW_MODE_NOT_R0 - pVCpu->iem.s.fInPatchCode = pVCpu->iem.s.uCpl == 0 - && pCtx->cs.u64Base == 0 - && pCtx->cs.u32Limit == UINT32_MAX - && PATMIsPatchGCAddr(pVCpu->CTX_SUFF(pVM), pCtx->eip); - if (!pVCpu->iem.s.fInPatchCode) CPUMRawLeave(pVCpu, VINF_SUCCESS); #endif @@ -1086,7 +1081,6 @@ */ DECLINLINE(void) iemUninitExec(PVMCPU pVCpu) { - /* Note! do not touch fInPatchCode here! (see iemUninitExecAndFiddleStatusAndMaybeReenter) */ #ifdef IEM_VERIFICATION_MODE_FULL pVCpu->iem.s.fNoRem = pVCpu->iem.s.fNoRemSavedByExec; #endif @@ -1111,7 +1105,7 @@ * calling thread. * @param fBypassHandlers Whether to bypass access handlers. */ -DECLINLINE(void) iemInitDecoder(PVMCPU pVCpu, bool fBypassHandlers) +DECLINLINE(void) iemInitDecoder(PVMCPU pVCpu, bool fBypassHandlers, bool fDisregardLock) { PCPUMCTX const pCtx = IEM_GET_CTX(pVCpu); @@ -1176,12 +1170,8 @@ pVCpu->iem.s.iNextMapping = 0; pVCpu->iem.s.rcPassUp = VINF_SUCCESS; pVCpu->iem.s.fBypassHandlers = fBypassHandlers; + pVCpu->iem.s.fDisregardLock = fDisregardLock; #ifdef VBOX_WITH_RAW_MODE_NOT_R0 - pVCpu->iem.s.fInPatchCode = pVCpu->iem.s.uCpl == 0 - && pCtx->cs.u64Base == 0 - && pCtx->cs.u32Limit == UINT32_MAX - && PATMIsPatchGCAddr(pVCpu->CTX_SUFF(pVM), pCtx->eip); - if (!pVCpu->iem.s.fInPatchCode) CPUMRawLeave(pVCpu, VINF_SUCCESS); #endif @@ -1293,17 +1283,6 @@ Assert(pVCpu->iem.s.rcPassUp == VINF_SUCCESS); Assert(pVCpu->iem.s.fBypassHandlers == false); #ifdef VBOX_WITH_RAW_MODE_NOT_R0 - if (!pVCpu->iem.s.fInPatchCode) - { /* likely */ } - else - { - pVCpu->iem.s.fInPatchCode = pVCpu->iem.s.uCpl == 0 - && pCtx->cs.u64Base == 0 - && pCtx->cs.u32Limit == UINT32_MAX - && PATMIsPatchGCAddr(pVCpu->CTX_SUFF(pVM), pCtx->eip); - if (!pVCpu->iem.s.fInPatchCode) - CPUMRawLeave(pVCpu, VINF_SUCCESS); - } #endif #ifdef DBGFTRACE_ENABLED @@ -1332,12 +1311,12 @@ * calling thread. * @param fBypassHandlers Whether to bypass access handlers. */ -IEM_STATIC VBOXSTRICTRC iemInitDecoderAndPrefetchOpcodes(PVMCPU pVCpu, bool fBypassHandlers) +IEM_STATIC VBOXSTRICTRC iemInitDecoderAndPrefetchOpcodes(PVMCPU pVCpu, bool fBypassHandlers, bool fDisregardLock) { #ifdef IEM_VERIFICATION_MODE_FULL uint8_t const cbOldOpcodes = pVCpu->iem.s.cbOpcode; #endif - iemInitDecoder(pVCpu, fBypassHandlers); + iemInitDecoder(pVCpu, fBypassHandlers, fDisregardLock); #ifdef IEM_WITH_CODE_TLB /** @todo Do ITLB lookup here. */ @@ -1382,14 +1361,6 @@ # ifdef VBOX_WITH_RAW_MODE_NOT_R0 /* Allow interpretation of patch manager code blocks since they can for instance throw #PFs for perfectly good reasons. */ - if (pVCpu->iem.s.fInPatchCode) - { - size_t cbRead = 0; - int rc = PATMReadPatchCode(pVCpu->CTX_SUFF(pVM), GCPtrPC, pVCpu->iem.s.abOpcode, sizeof(pVCpu->iem.s.abOpcode), &cbRead); - AssertRCReturn(rc, rc); - pVCpu->iem.s.cbOpcode = (uint8_t)cbRead; Assert(pVCpu->iem.s.cbOpcode == cbRead); Assert(cbRead > 0); - return VINF_SUCCESS; - } # endif /* VBOX_WITH_RAW_MODE_NOT_R0 */ RTGCPHYS GCPhys; @@ -1997,14 +1968,6 @@ # ifdef VBOX_WITH_RAW_MODE_NOT_R0 /* Allow interpretation of patch manager code blocks since they can for instance throw #PFs for perfectly good reasons. */ - if (pVCpu->iem.s.fInPatchCode) - { - size_t cbRead = 0; - int rc = PATMReadPatchCode(pVCpu->CTX_SUFF(pVM), GCPtrNext, pVCpu->iem.s.abOpcode, cbToTryRead, &cbRead); - AssertRCReturn(rc, rc); - pVCpu->iem.s.cbOpcode = (uint8_t)cbRead; Assert(pVCpu->iem.s.cbOpcode == cbRead); Assert(cbRead > 0); - return VINF_SUCCESS; - } # endif /* VBOX_WITH_RAW_MODE_NOT_R0 */ RTGCPHYS GCPhys; @@ -14948,7 +14911,7 @@ && VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS) && EMGetInhibitInterruptsPC(pVCpu) == IEM_GET_CTX(pVCpu)->rip ) { - rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, pVCpu->iem.s.fBypassHandlers); + rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, pVCpu->iem.s.fBypassHandlers, false); if (rcStrict == VINF_SUCCESS) { #ifdef LOG_ENABLED @@ -15007,8 +14970,8 @@ */ DECLINLINE(VBOXSTRICTRC) iemRCRawMaybeReenter(PVMCPU pVCpu, PCPUMCTX pCtx, VBOXSTRICTRC rcStrict) { - if ( !pVCpu->iem.s.fInPatchCode - && ( rcStrict == VINF_SUCCESS + if ( + ( rcStrict == VINF_SUCCESS || rcStrict == VERR_IEM_INSTR_NOT_IMPLEMENTED /* pgmPoolAccessPfHandlerFlush */ || rcStrict == VERR_IEM_ASPECT_NOT_IMPLEMENTED /* ditto */ ) ) { @@ -15045,7 +15008,7 @@ /* * Do the decoding and emulation. */ - VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false); + VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false, false); if (rcStrict == VINF_SUCCESS) rcStrict = iemExecOneInner(pVCpu, true); @@ -15073,7 +15036,7 @@ AssertReturn(CPUMCTX2CORE(pCtx) == pCtxCore, VERR_IEM_IPE_3); uint32_t const cbOldWritten = pVCpu->iem.s.cbWritten; - VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false); + VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false, false); if (rcStrict == VINF_SUCCESS) { rcStrict = iemExecOneInner(pVCpu, true); @@ -15098,7 +15061,7 @@ if ( cbOpcodeBytes && pCtx->rip == OpcodeBytesPC) { - iemInitDecoder(pVCpu, false); + iemInitDecoder(pVCpu, false, false); #ifdef IEM_WITH_CODE_TLB pVCpu->iem.s.uInstrBufPc = OpcodeBytesPC; pVCpu->iem.s.pbInstrBuf = (uint8_t const *)pvOpcodeBytes; @@ -15112,7 +15075,7 @@ rcStrict = VINF_SUCCESS; } else - rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false); + rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false, false); if (rcStrict == VINF_SUCCESS) { rcStrict = iemExecOneInner(pVCpu, true); @@ -15131,7 +15094,7 @@ AssertReturn(CPUMCTX2CORE(pCtx) == pCtxCore, VERR_IEM_IPE_3); uint32_t const cbOldWritten = pVCpu->iem.s.cbWritten; - VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, true); + VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, true, false); if (rcStrict == VINF_SUCCESS) { rcStrict = iemExecOneInner(pVCpu, false); @@ -15156,7 +15119,7 @@ if ( cbOpcodeBytes && pCtx->rip == OpcodeBytesPC) { - iemInitDecoder(pVCpu, true); + iemInitDecoder(pVCpu, true, false); #ifdef IEM_WITH_CODE_TLB pVCpu->iem.s.uInstrBufPc = OpcodeBytesPC; pVCpu->iem.s.pbInstrBuf = (uint8_t const *)pvOpcodeBytes; @@ -15170,7 +15133,7 @@ rcStrict = VINF_SUCCESS; } else - rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, true); + rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, true, false); if (rcStrict == VINF_SUCCESS) rcStrict = iemExecOneInner(pVCpu, false); @@ -15206,7 +15169,7 @@ if ( cbOpcodeBytes && pCtx->rip == OpcodeBytesPC) { - iemInitDecoder(pVCpu, true); + iemInitDecoder(pVCpu, true, false); #ifdef IEM_WITH_CODE_TLB pVCpu->iem.s.uInstrBufPc = OpcodeBytesPC; pVCpu->iem.s.pbInstrBuf = (uint8_t const *)pvOpcodeBytes; @@ -15220,7 +15183,7 @@ rcStrict = VINF_SUCCESS; } else - rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, true); + rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, true, false); if (rcStrict == VINF_SUCCESS) { rcStrict = iemExecOneInner(pVCpu, false); @@ -15234,6 +15197,21 @@ return rcStrict; } +VMMDECL(VBOXSTRICTRC) IEMExecOneIgnoreLock(PVMCPU pVCpu) +{ + /* + * Do the decoding and emulation. + */ + VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false, true /*fDisregardLock*/); + if (rcStrict == VINF_SUCCESS) + rcStrict = iemExecOneInner(pVCpu, true); + else if (pVCpu->iem.s.cActiveMappings > 0) + iemMemRollback(pVCpu); + + if (rcStrict != VINF_SUCCESS) + LogFlow(("IEMExecOneIgnoreLock failed: rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); + return rcStrict; +} VMMDECL(VBOXSTRICTRC) IEMExecLots(PVMCPU pVCpu, uint32_t *pcInstructions) { @@ -15285,7 +15263,7 @@ /* * Do the decoding and emulation. */ - VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false); + VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false, false); if (rcStrict == VINF_SUCCESS) rcStrict = iemExecOneInner(pVCpu, true); @@ -15344,7 +15322,7 @@ /* * Initial decoder init w/ prefetch, then setup setjmp. */ - VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false); + VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false, false); if (rcStrict == VINF_SUCCESS) { # ifdef IEM_WITH_SETJMP @@ -15491,7 +15469,7 @@ VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2, uint8_t cbInstr) { - iemInitDecoder(pVCpu, false); + iemInitDecoder(pVCpu, false, false); #ifdef DBGFTRACE_ENABLED RTTraceBufAddMsgF(pVCpu->CTX_SUFF(pVM)->CTX_SUFF(hTraceBuf), "IEMInjectTrap: %x %d %x %llx", u8TrapNo, enmType, uErrCode, uCr2); --- a/include/VBox/err.h 2023-03-03 23:38:01.000000000 +0300 +++ b/include/VBox/err.h 2023-03-04 00:16:09.637265634 +0300 @@ -252,6 +252,8 @@ #define VINF_EM_RAW_INJECT_TRPM_EVENT 1157 /** Guest tried to trigger a CPU hang. The guest is probably up to no good. */ #define VERR_EM_GUEST_CPU_HANG (-1158) +/** Emulate split-lock access on SMP. */ +#define VINF_EM_EMULATE_SPLIT_LOCK 1162 /** @} */ --- a/src/VBox/VMM/include/EMInternal.h 2020-07-09 19:57:59.000000000 +0300 +++ b/src/VBox/VMM/include/EMInternal.h 2023-03-04 00:22:27.533264191 +0300 @@ -465,6 +465,7 @@ int emR3RawStep(PVM pVM, PVMCPU pVCpu); int emR3SingleStepExecRem(PVM pVM, PVMCPU pVCpu, uint32_t cIterations); bool emR3IsExecutionAllowed(PVM pVM, PVMCPU pVCpu); +int emR3ExecuteSplitLockInstruction(PVM pVM, PVMCPU pVCpu); RT_C_DECLS_END --- a/src/VBox/VMM/include/EMHandleRCTmpl.h 2020-07-09 19:57:59.000000000 +0300 +++ b/src/VBox/VMM/include/EMHandleRCTmpl.h 2023-03-04 00:27:54.437262943 +0300 @@ -318,6 +318,9 @@ rc = emR3ExecuteInstruction(pVM, pVCpu, "EVENT: "); break; + case VINF_EM_EMULATE_SPLIT_LOCK: + rc = VBOXSTRICTRC_TODO(emR3ExecuteSplitLockInstruction(pVM, pVCpu)); + break; #ifdef EMHANDLERC_WITH_PATM /* --- a/src/VBox/VMM/VMMR0/HMVMXR0.cpp 2020-07-09 19:57:54.000000000 +0300 +++ b/src/VBox/VMM/VMMR0/HMVMXR0.cpp 2023-03-04 00:58:09.885256014 +0300 @@ -13365,10 +13365,28 @@ RT_NOREF_PV(pMixedCtx); HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(); + int rc = hmR0VmxSaveGuestCR0(pVCpu, pMixedCtx) + | hmR0VmxSaveGuestRflags(pVCpu, pMixedCtx) + | hmR0VmxSaveGuestSegmentRegs(pVCpu, pMixedCtx); + AssertRCReturn(rc, rc); + if ( /* 1. If 486-style alignment checks aren't enabled, then this must be a split-lock exception */ + !(pMixedCtx->cr0 & X86_CR0_AM) + /* 2. #AC cannot happen in rings 0-2 except for split-lock detection. */ + || CPUMGetGuestCPL(pVCpu) != 3 + /* 3. When the EFLAGS.AC != 0 this can only be a split-lock case. */ + || !(pMixedCtx->eflags.u32 & X86_EFL_AC) ) + { + rc = hmR0VmxSaveGuestState(pVCpu, pMixedCtx); + AssertRCReturn(rc, rc); + Log8Func(("cs:rip=%#04x:%#RX64 rflags=%#RX64 cr0=%#RX64 split-lock #AC -> VINF_EM_EMULATE_SPLIT_LOCK\n", + pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rflags, pVCpu->cpum.GstCtx.cr0)); + return VINF_EM_EMULATE_SPLIT_LOCK; + } + /* * Re-inject it. We'll detect any nesting before getting here. */ - int rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); + rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); AssertRCReturn(rc, rc); Assert(pVmxTransient->fVmcsFieldsRead & HMVMX_UPDATED_TRANSIENT_EXIT_INTERRUPTION_INFO); --- a/src/VBox/VMM/VMMR3/EM.cpp 2020-07-09 19:57:55.000000000 +0300 +++ b/src/VBox/VMM/VMMR3/EM.cpp 2023-03-04 01:00:42.593255431 +0300 @@ -793,6 +793,33 @@ } #endif /* LOG_ENABLED || VBOX_STRICT */ +/** + * @callback_method_impl{FNVMMEMTRENDEZVOUS, + * Worker for emR3ExecuteSplitLockInstruction} + */ +static DECLCALLBACK(VBOXSTRICTRC) emR3ExecuteSplitLockInstructionRendezvous(PVM pVM, PVMCPU pVCpu, void *pvUser) +{ + /* Only execute on the specified EMT. */ + if (pVCpu == (PVMCPU)pvUser) + { + LogFunc(("\n")); + VBOXSTRICTRC rcStrict = IEMExecOneIgnoreLock(pVCpu); + LogFunc(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); + if (rcStrict == VINF_IEM_RAISED_XCPT) + rcStrict = VINF_SUCCESS; + return rcStrict; + } + RT_NOREF(pVM); + return VINF_SUCCESS; +} + + +VBOXSTRICTRC emR3ExecuteSplitLockInstruction(PVM pVM, PVMCPU pVCpu) +{ + LogFunc(("\n")); + return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, emR3ExecuteSplitLockInstructionRendezvous, pVCpu); +} + /** * Debug loop.
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor