check for hypervisor support of load and save VMCS exit and entry controls

This commit is contained in:
sina 2026-04-19 20:08:47 +02:00
parent 6e511c8368
commit 111bead68d
10 changed files with 111 additions and 12 deletions

View file

@ -412,6 +412,17 @@ VmFuncGetDebugctlVmcallOnTargetCore()
return CrossVmcallGetDebugctlVmcallOnTargetCore();
}
/**
* @brief Check if CPU support save and load debug controls on exit and load entries
*
* @return BOOLEAN
*/
BOOLEAN
VmFuncCheckCpuSupportForSaveAndLoadDebugControls()
{
return HvCheckCpuSupportForSaveAndLoadDebugControls();
}
/**
* @brief Set the guest state of IA32_DEBUGCTL
* @param Value

View file

@ -1540,6 +1540,54 @@ HvSetDebugctl(UINT64 Value)
VmxVmwrite64(VMCS_GUEST_DEBUGCTL_HIGH, Value >> 32);
}
/**
* @brief Check if CPU support save and load debug controls on exit and load entries
*
* @return BOOLEAN
*/
BOOLEAN
HvCheckCpuSupportForSaveAndLoadDebugControls()
{
IA32_VMX_BASIC_REGISTER VmxBasicMsr = {0};
//
// Reading IA32_VMX_BASIC_MSR
//
VmxBasicMsr.AsUInt = __readmsr(IA32_VMX_BASIC);
//
// Read 1-settings of save debug controls (exit controls)
//
UINT32 ExitCtls = HvAdjustControls(
IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_FLAG,
VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS);
//
// Read 1-settings of load debug controls (entry controls)
//
UINT32 EntryCtls = HvAdjustControls(
IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_FLAG,
VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS);
//
// Check if entry and exit controls are supported on this system
//
if (ExitCtls != NULL_ZERO && EntryCtls != NULL_ZERO)
{
//
// Supported
//
return TRUE;
}
else
{
//
// Not supported
//
return FALSE;
}
}
/**
* @brief Set the guest state of DR7
* @param Value The new value for DR7

View file

@ -908,15 +908,13 @@ VmxSetupVmcs(VIRTUAL_MACHINE_STATE * VCpu, PVOID GuestStack)
VmxVmwrite64(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS,
HvAdjustControls(
IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_FLAG |
IA32_VMX_EXIT_CTLS_LOAD_IA32_CET_STATE_FLAG |
IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_FLAG,
IA32_VMX_EXIT_CTLS_LOAD_IA32_CET_STATE_FLAG,
VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS));
VmxVmwrite64(VMCS_CTRL_VMENTRY_CONTROLS,
HvAdjustControls(
IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_FLAG |
IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_FLAG |
IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_FLAG,
IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_FLAG,
VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS));
VmxVmwrite64(VMCS_CTRL_CR0_GUEST_HOST_MASK, 0);

View file

@ -476,6 +476,14 @@ HvGetAndStoreDebugctl(UINT64 * StoreDebugctl);
VOID
HvSetDebugctl(UINT64 Value);
/**
* @brief Check if CPU support save and load debug controls on exit and load entries
*
* @return BOOLEAN
*/
BOOLEAN
HvCheckCpuSupportForSaveAndLoadDebugControls();
/**
* @brief Set the guest state of DR7
* @param Value The new value for DR7

View file

@ -36,10 +36,11 @@ LoaderInitHyperTrace()
//
// Fill the callbacks for using hyperhv in hypertrace
//
HyperTraceCallbacks.VmFuncGetDebugctl = VmFuncGetDebugctl;
HyperTraceCallbacks.VmFuncGetDebugctlVmcallOnTargetCore = VmFuncGetDebugctlVmcallOnTargetCore;
HyperTraceCallbacks.VmFuncSetDebugctl = VmFuncSetDebugctl;
HyperTraceCallbacks.VmFuncSetDebugctlVmcallOnTargetCore = VmFuncSetDebugctlVmcallOnTargetCore;
HyperTraceCallbacks.VmFuncGetDebugctl = VmFuncGetDebugctl;
HyperTraceCallbacks.VmFuncGetDebugctlVmcallOnTargetCore = VmFuncGetDebugctlVmcallOnTargetCore;
HyperTraceCallbacks.VmFuncSetDebugctl = VmFuncSetDebugctl;
HyperTraceCallbacks.VmFuncSetDebugctlVmcallOnTargetCore = VmFuncSetDebugctlVmcallOnTargetCore;
HyperTraceCallbacks.VmFuncCheckCpuSupportForSaveAndLoadDebugControls = VmFuncCheckCpuSupportForSaveAndLoadDebugControls;
//
// Memory callbacks

View file

@ -202,12 +202,24 @@ HyperTraceEnableLbrTracing(HYPERTRACE_OPERATION_PACKETS * HyperTraceOperationReq
return FALSE;
}
//
// Check LBR support on CPU
//
if (!LbrCheck())
{
HyperTraceOperationRequest->KernelStatus = DEBUGGER_ERROR_LBR_NOT_SUPPORTED;
return FALSE;
}
//
// Check VMCS support for LBR
//
if (!g_Callbacks.VmFuncCheckCpuSupportForSaveAndLoadDebugControls())
{
HyperTraceOperationRequest->KernelStatus = DEBUGGER_ERROR_DEBUGCTL_NOT_SUPPORTED_ON_VMCS;
return FALSE;
}
//
// Enabling LBR
//

View file

@ -611,6 +611,12 @@
*/
#define DEBUGGER_ERROR_LBR_NOT_SUPPORTED 0xc000005e
/**
* @brief error, Dubugctl not supported on VMCS
*
*/
#define DEBUGGER_ERROR_DEBUGCTL_NOT_SUPPORTED_ON_VMCS 0xc000005f
//
// WHEN YOU ADD ANYTHING TO THIS LIST OF ERRORS, THEN
// MAKE SURE TO ADD AN ERROR MESSAGE TO ShowErrorMessage(UINT32 Error)

View file

@ -229,6 +229,9 @@ VmFuncVmxGetCurrentExecutionMode();
IMPORT_EXPORT_VMM BOOLEAN
VmFuncQueryModeExecTrap();
IMPORT_EXPORT_VMM BOOLEAN
VmFuncCheckCpuSupportForSaveAndLoadDebugControls();
IMPORT_EXPORT_VMM INT32
VmFuncVmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2);

View file

@ -70,6 +70,12 @@ typedef VOID (*VM_FUNC_SET_DEBUGCTL)(UINT64 Value);
*/
typedef VOID (*VM_FUNC_SET_DEBUGCTL_VMCALL_ON_TARGET_CORE)(UINT64 Value);
/**
* @brief A function that checks whether IA32_DEBUGCTL can be used in load and save of exit and entry controls
*
*/
typedef BOOLEAN (*VM_FUNC_CHECK_CPU_SUPPORT_FOR_SAVE_AND_LOAD_DEBUG_CONTROLS)();
/**
* @brief A function that checks the validity and safety of the target address
*
@ -115,10 +121,11 @@ typedef struct _HYPERTRACE_CALLBACKS
//
// *** Hypervisor (Hyperhv) callbacks ***
//
VM_FUNC_GET_DEBUGCTL VmFuncGetDebugctl;
VM_FUNC_GET_DEBUGCTL_VMCALL_ON_TARGET_CORE VmFuncGetDebugctlVmcallOnTargetCore;
VM_FUNC_SET_DEBUGCTL VmFuncSetDebugctl;
VM_FUNC_SET_DEBUGCTL_VMCALL_ON_TARGET_CORE VmFuncSetDebugctlVmcallOnTargetCore;
VM_FUNC_GET_DEBUGCTL VmFuncGetDebugctl;
VM_FUNC_GET_DEBUGCTL_VMCALL_ON_TARGET_CORE VmFuncGetDebugctlVmcallOnTargetCore;
VM_FUNC_SET_DEBUGCTL VmFuncSetDebugctl;
VM_FUNC_SET_DEBUGCTL_VMCALL_ON_TARGET_CORE VmFuncSetDebugctlVmcallOnTargetCore;
VM_FUNC_CHECK_CPU_SUPPORT_FOR_SAVE_AND_LOAD_DEBUG_CONTROLS VmFuncCheckCpuSupportForSaveAndLoadDebugControls;
//
// *** HYPERTRACE callbacks ***

View file

@ -594,6 +594,11 @@ ShowErrorMessage(UINT32 Error)
Error);
break;
case DEBUGGER_ERROR_DEBUGCTL_NOT_SUPPORTED_ON_VMCS:
ShowMessages("err, Debugctl is not supported on VMCS (%x)\n",
Error);
break;
default:
ShowMessages("err, error not found (%x)\n",
Error);