CPUMDbg.cpp revision aae8a6a38fd27661046ab1d06cb2cb5c096c40ed
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * CPUM - CPU Monitor / Manager, Debugger & Debugging APIs.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Copyright (C) 2010-2015 Oracle Corporation
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * available from http://www.virtualbox.org. This file is free software;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * you can redistribute it and/or modify it under the terms of the GNU
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * General Public License (GPL) as published by the Free Software
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/*******************************************************************************
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync* Header Files *
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync*******************************************************************************/
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGet_Generic(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync void const *pv = (uint8_t const *)&pVCpu->cpum + pDesc->offRegister;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U8: pValue->u8 = *(uint8_t const *)pv; return VINF_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U16: pValue->u16 = *(uint16_t const *)pv; return VINF_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U32: pValue->u32 = *(uint32_t const *)pv; return VINF_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U64: pValue->u64 = *(uint64_t const *)pv; return VINF_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U128: pValue->u128 = *(PCRTUINT128U )pv; return VINF_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertMsgFailedReturn(("%d %s\n", pDesc->enmType, pDesc->pszName), VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegSet_Generic(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync void *pv = (uint8_t *)&pVCpu->cpum + pDesc->offRegister;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RTUInt128AssignAnd((PRTUINT128U)pv, RTUInt128AssignBitwiseNot(RTUInt128Assign(&Val, &pfMask->u128)));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RTUInt128AssignOr((PRTUINT128U)pv, RTUInt128AssignAnd(RTUInt128Assign(&Val, &pValue->u128), &pfMask->u128));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertMsgFailedReturn(("%d %s\n", pDesc->enmType, pDesc->pszName), VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegSet_seg(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /** @todo perform a selector load, updating hidden selectors and stuff. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGet_gdtr(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXGDTR const *pGdtr = (VBOXGDTR const *)((uint8_t const *)&pVCpu->cpum + pDesc->offRegister);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegSet_gdtr(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGet_idtr(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXIDTR const *pIdtr = (VBOXIDTR const *)((uint8_t const *)&pVCpu->cpum + pDesc->offRegister);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegSet_idtr(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Is the FPU state in FXSAVE format or not.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @returns true if it is, false if it's in FNSAVE.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @param pVCpu Pointer to the VMCPU.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncDECLINLINE(bool) cpumR3RegIsFxSaveFormat(PVMCPU pVCpu)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return true;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return pVCpu->pVMR3->cpum.s.CPUFeatures.edx.u1FXSR;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Determins the tag register value for a CPU register when the FPU state
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * format is FXSAVE.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @returns The tag register value.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @param pFpu Pointer to the guest FPU.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @param iReg The register number (0..7).
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncDECLINLINE(uint16_t) cpumR3RegCalcFpuTagFromFxSave(PCX86FXSTATE pFpu, unsigned iReg)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * See table 11-1 in the AMD docs.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pFpu->aRegs[iReg].au64[0] == 0) /* J & M == 0 */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!(pFpu->aRegs[iReg].au64[0] >> 63)) /* J == 0 */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return 0; /* b00 - valid (normal) */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGet_ftw(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PCX86FXSTATE pFpu = (PCX86FXSTATE)((uint8_t const *)&pVCpu->cpum + pDesc->offRegister);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pValue->u16 = cpumR3RegCalcFpuTagFromFxSave(pFpu, 0)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegSet_ftw(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Guest register access functions.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGstGet_crX(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync int rc = CPUMGetGuestCRx(pVCpu, pDesc->offRegister, &u64Value);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U64: pValue->u64 = u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U32: pValue->u32 = (uint32_t)u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGstSet_crX(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Calculate the new value.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync rc = CPUMGetGuestCRx(pVCpu, pDesc->offRegister, &u64FullValue);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Perform the assignment.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case 0: rc = CPUMSetGuestCR0(pVCpu, u64Value); break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case 2: rc = CPUMSetGuestCR2(pVCpu, u64Value); break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case 3: rc = CPUMSetGuestCR3(pVCpu, u64Value); break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case 4: rc = CPUMSetGuestCR4(pVCpu, u64Value); break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case 8: rc = PDMApicSetTPR(pVCpu, (uint8_t)(u64Value << 4)); break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGstGet_drX(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync int rc = CPUMGetGuestDRx(pVCpu, pDesc->offRegister, &u64Value);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U64: pValue->u64 = u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U32: pValue->u32 = (uint32_t)u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGstSet_drX(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Calculate the new value.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync rc = CPUMGetGuestDRx(pVCpu, pDesc->offRegister, &u64FullValue);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Perform the assignment.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return CPUMSetGuestDRx(pVCpu, pDesc->offRegister, u64Value);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGstGet_msr(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXSTRICTRC rcStrict = CPUMQueryGuestMsr(pVCpu, pDesc->offRegister, &u64Value);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U64: pValue->u64 = u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U32: pValue->u32 = (uint32_t)u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U16: pValue->u16 = (uint16_t)u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /** @todo what to do about errors? */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGstSet_msr(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Calculate the new value.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXSTRICTRC rcStrict = CPUMQueryGuestMsr(pVCpu, pDesc->offRegister, &u64FullValue);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Perform the assignment.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXSTRICTRC rcStrict = CPUMSetGuestMsr(pVCpu, pDesc->offRegister, u64Value);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGstGet_stN(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync unsigned iReg = (pVCpu->cpum.s.Guest.fpu.FSW >> 11) & 7;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pValue->r80Ex = pVCpu->cpum.s.Guest.fpu.aRegs[iReg].r80Ex;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PCX86FPUSTATE pOldFpu = (PCX86FPUSTATE)&pVCpu->cpum.s.Guest.fpu;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegGstSet_stN(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Hypervisor register access functions.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegHyperGet_crX(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U64: pValue->u64 = u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U32: pValue->u32 = (uint32_t)u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegHyperSet_crX(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* Not settable, prevents killing your host. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegHyperGet_drX(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U64: pValue->u64 = u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U32: pValue->u32 = (uint32_t)u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegHyperSet_drX(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* Not settable, prevents killing your host. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegHyperGet_msr(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* Not availble at present, return all FFs to keep things quiet */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U64: pValue->u64 = u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U32: pValue->u32 = (uint32_t)u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync case DBGFREGVALTYPE_U16: pValue->u16 = (uint16_t)u64Value; break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegHyperSet_msr(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* Not settable, return failure. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegHyperGet_stN(void *pvUser, PCDBGFREGDESC pDesc, PDBGFREGVAL pValue)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync unsigned iReg = (pVCpu->cpum.s.Guest.fpu.FSW >> 11) & 7;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pValue->r80Ex = pVCpu->cpum.s.Guest.fpu.aRegs[iReg].r80Ex;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PCX86FPUSTATE pOldFpu = (PCX86FPUSTATE)&pVCpu->cpum.s.Guest.fpu;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @interface_method_impl{DBGFREGDESC, pfnGet}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic DECLCALLBACK(int) cpumR3RegHyperSet_stN(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* There isn't a FPU context for the hypervisor yet, so no point in trying to set stuff. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NOREF(pvUser); NOREF(pDesc); NOREF(pValue); NOREF(pfMask);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Set up aliases.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define CPUMREGALIAS_STD(Name, psz32, psz16, psz8) \
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync static DBGFREGALIAS const g_aCpumRegAliases_##Name[] = \
#define CPU_REG_EX_AS(a_szName, a_RegSuff, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
{ a_szName, DBGFREG_##a_RegSuff, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
CPU_REG_RW_AS(#LName, UName, U64, LName, cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_##LName, NULL)
CPU_REG_RW_AS(#LName, UName, U16, LName.Sel, cpumR3RegGet_Generic, cpumR3RegSet_seg, NULL, NULL ), \
CPU_REG_RW_AS(#LName "_attr", UName##_ATTR, U32, LName.Attr.u, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_seg), \
CPU_REG_RW_AS(#LName "_base", UName##_BASE, U64, LName.u64Base, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ), \
CPU_REG_RW_AS(#LName "_lim", UName##_LIMIT, U32, LName.u32Limit, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL )
#define CPU_REG_MM(n) \
CPU_REG_RW_AS("mm" #n, MM##n, U64, fpu.aRegs[n].mmx, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_mmN)
#define CPU_REG_XMM(n) \
CPU_REG_RW_AS("xmm" #n, XMM##n, U128, fpu.aXMM[n].xmm, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_xmmN)
#define CPU_REG_RW_AS(a_szName, a_RegSuff, a_TypeSuff, a_CpumCtxMemb, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
{ a_szName, DBGFREG_##a_RegSuff, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, RT_OFFSETOF(CPUMCPU, Guest.a_CpumCtxMemb), a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
#define CPU_REG_RO_AS(a_szName, a_RegSuff, a_TypeSuff, a_CpumCtxMemb, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
{ a_szName, DBGFREG_##a_RegSuff, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, RT_OFFSETOF(CPUMCPU, Guest.a_CpumCtxMemb), a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
CPU_REG_EX_AS(a_szName, MSR_##UName, a_TypeSuff, MSR_##UName, cpumR3RegGstGet_msr, cpumR3RegGstSet_msr, NULL, a_paSubFields)
#define CPU_REG_ST(n) \
CPU_REG_EX_AS("st" #n, ST##n, R80, n, cpumR3RegGstGet_stN, cpumR3RegGstSet_stN, NULL, g_aCpumRegFields_stN)
CPU_REG_RW_AS("rflags", RFLAGS, U64, rflags, cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_rflags, g_aCpumRegFields_rflags ),
CPU_REG_RW_AS("fcw", FCW, U16, fpu.FCW, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_fcw ),
CPU_REG_RW_AS("fsw", FSW, U16, fpu.FSW, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_fsw ),
CPU_REG_RO_AS("ftw", FTW, U16, fpu, cpumR3RegGet_ftw, cpumR3RegSet_ftw, NULL, g_aCpumRegFields_ftw ),
CPU_REG_RW_AS("fpuip", FPUIP, U32, fpu.FPUIP, cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_fpuip, NULL ),
CPU_REG_RW_AS("fpucs", FPUCS, U16, fpu.CS, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("fpudp", FPUDP, U32, fpu.FPUDP, cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_fpudp, NULL ),
CPU_REG_RW_AS("fpuds", FPUDS, U16, fpu.DS, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("mxcsr", MXCSR, U32, fpu.MXCSR, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_mxcsr ),
CPU_REG_RW_AS("mxcsr_mask", MXCSR_MASK, U32, fpu.MXCSR_MASK, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_mxcsr ),
CPU_REG_ST(0),
CPU_REG_MM(0),
CPU_REG_XMM(0),
CPU_REG_RW_AS("gdtr_base", GDTR_BASE, U64, gdtr.pGdt, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("gdtr_lim", GDTR_LIMIT, U16, gdtr.cbGdt, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("idtr_base", IDTR_BASE, U64, idtr.pIdt, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("idtr_lim", IDTR_LIMIT, U16, idtr.cbIdt, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_EX_AS("cr0", CR0, U32, 0, cpumR3RegGstGet_crX, cpumR3RegGstSet_crX, g_aCpumRegAliases_cr0, g_aCpumRegFields_cr0 ),
CPU_REG_EX_AS("cr3", CR3, U64, 3, cpumR3RegGstGet_crX, cpumR3RegGstSet_crX, NULL, g_aCpumRegFields_cr3 ),
CPU_REG_EX_AS("cr4", CR4, U32, 4, cpumR3RegGstGet_crX, cpumR3RegGstSet_crX, NULL, g_aCpumRegFields_cr4 ),
CPU_REG_EX_AS("dr6", DR6, U32, 6, cpumR3RegGstGet_drX, cpumR3RegGstSet_drX, NULL, g_aCpumRegFields_dr6 ),
CPU_REG_EX_AS("dr7", DR7, U32, 7, cpumR3RegGstGet_drX, cpumR3RegGstSet_drX, NULL, g_aCpumRegFields_dr7 ),
CPU_REG_EX_AS("ah", AH, U8, RT_OFFSETOF(CPUMCPU, Guest.rax) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_EX_AS("ch", CH, U8, RT_OFFSETOF(CPUMCPU, Guest.rcx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_EX_AS("dh", DH, U8, RT_OFFSETOF(CPUMCPU, Guest.rdx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_EX_AS("bh", BH, U8, RT_OFFSETOF(CPUMCPU, Guest.rbx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
#define CPU_REG_RW_AS(a_szName, a_RegSuff, a_TypeSuff, a_CpumCtxMemb, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
{ a_szName, DBGFREG_##a_RegSuff, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, RT_OFFSETOF(CPUMCPU, Hyper.a_CpumCtxMemb), a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
#define CPU_REG_RO_AS(a_szName, a_RegSuff, a_TypeSuff, a_CpumCtxMemb, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
{ a_szName, DBGFREG_##a_RegSuff, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, RT_OFFSETOF(CPUMCPU, Hyper.a_CpumCtxMemb), a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
CPU_REG_EX_AS(a_szName, MSR_##UName, a_TypeSuff, MSR_##UName, cpumR3RegHyperGet_msr, cpumR3RegHyperSet_msr, NULL, a_paSubFields)
#define CPU_REG_ST(n) \
CPU_REG_EX_AS("st" #n, ST##n, R80, n, cpumR3RegHyperGet_stN, cpumR3RegHyperSet_stN, NULL, g_aCpumRegFields_stN)
CPU_REG_RW_AS("rflags", RFLAGS, U64, rflags, cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_rflags, g_aCpumRegFields_rflags ),
CPU_REG_RW_AS("fcw", FCW, U16, fpu.FCW, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_fcw ),
CPU_REG_RW_AS("fsw", FSW, U16, fpu.FSW, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_fsw ),
CPU_REG_RO_AS("ftw", FTW, U16, fpu, cpumR3RegGet_ftw, cpumR3RegSet_ftw, NULL, g_aCpumRegFields_ftw ),
CPU_REG_RW_AS("fpuip", FPUIP, U32, fpu.FPUIP, cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_fpuip, NULL ),
CPU_REG_RW_AS("fpucs", FPUCS, U16, fpu.CS, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("fpudp", FPUDP, U32, fpu.FPUDP, cpumR3RegGet_Generic, cpumR3RegSet_Generic, g_aCpumRegAliases_fpudp, NULL ),
CPU_REG_RW_AS("fpuds", FPUDS, U16, fpu.DS, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("mxcsr", MXCSR, U32, fpu.MXCSR, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_mxcsr ),
CPU_REG_RW_AS("mxcsr_mask", MXCSR_MASK, U32, fpu.MXCSR_MASK, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, g_aCpumRegFields_mxcsr ),
CPU_REG_ST(0),
CPU_REG_MM(0),
CPU_REG_XMM(0),
CPU_REG_RW_AS("gdtr_base", GDTR_BASE, U64, gdtr.pGdt, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("gdtr_lim", GDTR_LIMIT, U16, gdtr.cbGdt, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("idtr_base", IDTR_BASE, U64, idtr.pIdt, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_RW_AS("idtr_lim", IDTR_LIMIT, U16, idtr.cbIdt, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_EX_AS("cr0", CR0, U32, 0, cpumR3RegHyperGet_crX, cpumR3RegHyperSet_crX, g_aCpumRegAliases_cr0, g_aCpumRegFields_cr0 ),
CPU_REG_EX_AS("cr3", CR3, U64, 3, cpumR3RegHyperGet_crX, cpumR3RegHyperSet_crX, NULL, g_aCpumRegFields_cr3 ),
CPU_REG_EX_AS("cr4", CR4, U32, 4, cpumR3RegHyperGet_crX, cpumR3RegHyperSet_crX, NULL, g_aCpumRegFields_cr4 ),
CPU_REG_EX_AS("dr6", DR6, U32, 6, cpumR3RegHyperGet_drX, cpumR3RegHyperSet_drX, NULL, g_aCpumRegFields_dr6 ),
CPU_REG_EX_AS("dr7", DR7, U32, 7, cpumR3RegHyperGet_drX, cpumR3RegHyperSet_drX, NULL, g_aCpumRegFields_dr7 ),
CPU_REG_EX_AS("ah", AH, U8, RT_OFFSETOF(CPUMCPU, Hyper.rax) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_EX_AS("ch", CH, U8, RT_OFFSETOF(CPUMCPU, Hyper.rcx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_EX_AS("dh", DH, U8, RT_OFFSETOF(CPUMCPU, Hyper.rdx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
CPU_REG_EX_AS("bh", BH, U8, RT_OFFSETOF(CPUMCPU, Hyper.rbx) + 1, cpumR3RegGet_Generic, cpumR3RegSet_Generic, NULL, NULL ),
return VINF_SUCCESS;