// RDMSR and WRMSR _Use_decl_annotations_ static void VmmpHandleMsrAccess( GuestContext *guest_context, bool read_access) { // Apply it for VMCS instead of a real MSR if a speficied MSR is either of // them. const auto msr = static_cast<Msr>(guest_context->gp_regs->cx); bool transfer_to_vmcs = false; VmcsField vmcs_field = {}; switch (msr) { case Msr::kIa32SysenterCs: vmcs_field = VmcsField::kGuestSysenterCs; transfer_to_vmcs = true; break; case Msr::kIa32SysenterEsp: vmcs_field = VmcsField::kGuestSysenterEsp; transfer_to_vmcs = true; break; case Msr::kIa32SysenterEip: vmcs_field = VmcsField::kGuestSysenterEip; transfer_to_vmcs = true; break; case Msr::kIa32GsBase: vmcs_field = VmcsField::kGuestGsBase; transfer_to_vmcs = true; break; case Msr::kIa32FsBase: vmcs_field = VmcsField::kGuestFsBase; break; default: break; } // Do not shadow 64bit fields because the current implmentation for x86 is not // able to handle it due to a simple use of UtilVmWrite() below. NT_ASSERT(UtilIsInBounds(vmcs_field, VmcsField::kIoBitmapA, VmcsField::kHostIa32PerfGlobalCtrlHigh) == false); // This unconditional __readmsr and __writemsr may cause #GP resulting in // bug check. A proper way to solve this is check supported MSR values // beforehand and inject an exception when unsupported MSR values are given. LARGE_INTEGER msr_value = {}; if (read_access) { if (transfer_to_vmcs) { msr_value.QuadPart = UtilVmRead(vmcs_field); } else { msr_value.QuadPart = UtilReadMsr64(msr); } guest_context->gp_regs->ax = msr_value.LowPart; guest_context->gp_regs->dx = msr_value.HighPart; } else { msr_value.LowPart = static_cast<ULONG>(guest_context->gp_regs->ax); msr_value.HighPart = static_cast<ULONG>(guest_context->gp_regs->dx); if (transfer_to_vmcs) { UtilVmWrite(vmcs_field, static_cast<ULONG_PTR>(msr_value.QuadPart)); } else { UtilWriteMsr64(msr, msr_value.QuadPart); } } VmmpAdjustGuestInstructionPointer(guest_context->ip); }
// Sets 1 to the lock bit of the IA32_FEATURE_CONTROL MSR _Use_decl_annotations_ static NTSTATUS VmpSetLockBitCallback(void *context) { UNREFERENCED_PARAMETER(context); Ia32FeatureControlMsr vmx_feature_control = { UtilReadMsr64(Msr::kIa32FeatureControl)}; if (vmx_feature_control.fields.lock) { return STATUS_SUCCESS; } vmx_feature_control.fields.lock = true; UtilWriteMsr64(Msr::kIa32FeatureControl, vmx_feature_control.all); vmx_feature_control.all = UtilReadMsr64(Msr::kIa32FeatureControl); if (!vmx_feature_control.fields.lock) { HYPERPLATFORM_LOG_ERROR("The lock bit is still clear."); return STATUS_DEVICE_CONFIGURATION_ERROR; } return STATUS_SUCCESS; }