416 lines
19 KiB
C
416 lines
19 KiB
C
/*!
|
|
@file HostUtils.c
|
|
|
|
@brief Utility functions and structures for the host.
|
|
|
|
@author Satoshi Tanda
|
|
|
|
@copyright Copyright (c) 2020 - , Satoshi Tanda. All rights reserved.
|
|
*/
|
|
#include "HostUtils.h"
|
|
#include "Logger.h"
|
|
#include "ExtendedPageTables.h"
|
|
#include "Utils.h"
|
|
|
|
/*!
|
|
@brief Dumps the segment access rights value.
|
|
|
|
@param[in] AccessRights - The segment access rights value to dump.
|
|
*/
|
|
static
|
|
VOID
|
|
DumpAccessRights (
|
|
_In_ UINT64 AccessRights
|
|
)
|
|
{
|
|
VMX_SEGMENT_ACCESS_RIGHTS rights;
|
|
|
|
rights.Flags = (UINT32)AccessRights;
|
|
LOG_ERROR(" - Type = %ul", rights.Type);
|
|
LOG_ERROR(" - S = %ul", rights.DescriptorType);
|
|
LOG_ERROR(" - DPL = %ul", rights.DescriptorPrivilegeLevel);
|
|
LOG_ERROR(" - P = %ul", rights.Present);
|
|
LOG_ERROR(" - Reserved1 = %ul", rights.Reserved1);
|
|
LOG_ERROR(" - Available = %ul", rights.AvailableBit);
|
|
LOG_ERROR(" - L = %ul", rights.LongMode);
|
|
LOG_ERROR(" - D/B = %ul", rights.DefaultBig);
|
|
LOG_ERROR(" - G = %ul", rights.Granularity);
|
|
LOG_ERROR(" - Unusable = %ul", rights.Unusable);
|
|
LOG_ERROR(" - Reserved2 = %ul", rights.Reserved2);
|
|
}
|
|
|
|
VOID
|
|
DumpHostState (
|
|
)
|
|
{
|
|
//
|
|
// 16-Bit Host-State Fields
|
|
//
|
|
LOG_ERROR("Host ES Selector = %016llx", VmxRead(VMCS_HOST_ES_SELECTOR));
|
|
LOG_ERROR("Host CS Selector = %016llx", VmxRead(VMCS_HOST_CS_SELECTOR));
|
|
LOG_ERROR("Host SS Selector = %016llx", VmxRead(VMCS_HOST_SS_SELECTOR));
|
|
LOG_ERROR("Host DS Selector = %016llx", VmxRead(VMCS_HOST_DS_SELECTOR));
|
|
LOG_ERROR("Host FS Selector = %016llx", VmxRead(VMCS_HOST_FS_SELECTOR));
|
|
LOG_ERROR("Host GS Selector = %016llx", VmxRead(VMCS_HOST_GS_SELECTOR));
|
|
LOG_ERROR("Host TR Selector = %016llx", VmxRead(VMCS_HOST_TR_SELECTOR));
|
|
|
|
//
|
|
// 64-Bit Host-State Fields
|
|
//
|
|
LOG_ERROR("Host IA32_PAT = %016llx", VmxRead(VMCS_HOST_PAT));
|
|
LOG_ERROR("Host IA32_EFER = %016llx", VmxRead(VMCS_HOST_EFER));
|
|
LOG_ERROR("Host IA32_PERF_GLOBAL_CTRL = %016llx", VmxRead(VMCS_HOST_PERF_GLOBAL_CTRL));
|
|
|
|
//
|
|
// 32-Bit Host-State Fields
|
|
//
|
|
LOG_ERROR("Host IA32_SYSENTER_CS = %016llx", VmxRead(VMCS_HOST_SYSENTER_CS));
|
|
|
|
//
|
|
// Natural-Width Host-State Fields
|
|
//
|
|
LOG_ERROR("Host CR0 = %016llx", VmxRead(VMCS_HOST_CR0));
|
|
LOG_ERROR("Host CR3 = %016llx", VmxRead(VMCS_HOST_CR3));
|
|
LOG_ERROR("Host CR4 = %016llx", VmxRead(VMCS_HOST_CR4));
|
|
LOG_ERROR("Host FS Base = %016llx", VmxRead(VMCS_HOST_FS_BASE));
|
|
LOG_ERROR("Host GS Base = %016llx", VmxRead(VMCS_HOST_GS_BASE));
|
|
LOG_ERROR("Host TR base = %016llx", VmxRead(VMCS_HOST_TR_BASE));
|
|
LOG_ERROR("Host GDTR base = %016llx", VmxRead(VMCS_HOST_GDTR_BASE));
|
|
LOG_ERROR("Host IDTR base = %016llx", VmxRead(VMCS_HOST_IDTR_BASE));
|
|
LOG_ERROR("Host IA32_SYSENTER_ESP = %016llx", VmxRead(VMCS_HOST_SYSENTER_ESP));
|
|
LOG_ERROR("Host IA32_SYSENTER_EIP = %016llx", VmxRead(VMCS_HOST_SYSENTER_EIP));
|
|
LOG_ERROR("Host RSP = %016llx", VmxRead(VMCS_HOST_RSP));
|
|
LOG_ERROR("Host RIP = %016llx", VmxRead(VMCS_HOST_RIP));
|
|
}
|
|
|
|
VOID
|
|
DumpGuestState (
|
|
)
|
|
{
|
|
//
|
|
// 16-Bit Guest-State Fields
|
|
//
|
|
LOG_ERROR("Guest ES Selector = %016llx", VmxRead(VMCS_GUEST_ES_SELECTOR));
|
|
LOG_ERROR("Guest CS Selector = %016llx", VmxRead(VMCS_GUEST_CS_SELECTOR));
|
|
LOG_ERROR("Guest SS Selector = %016llx", VmxRead(VMCS_GUEST_SS_SELECTOR));
|
|
LOG_ERROR("Guest DS Selector = %016llx", VmxRead(VMCS_GUEST_DS_SELECTOR));
|
|
LOG_ERROR("Guest FS Selector = %016llx", VmxRead(VMCS_GUEST_FS_SELECTOR));
|
|
LOG_ERROR("Guest GS Selector = %016llx", VmxRead(VMCS_GUEST_GS_SELECTOR));
|
|
LOG_ERROR("Guest LDTR Selector = %016llx", VmxRead(VMCS_GUEST_LDTR_SELECTOR));
|
|
LOG_ERROR("Guest TR Selector = %016llx", VmxRead(VMCS_GUEST_TR_SELECTOR));
|
|
LOG_ERROR("Guest interrupt status = %016llx", VmxRead(VMCS_GUEST_INTERRUPT_STATUS));
|
|
LOG_ERROR("PML index = %016llx", VmxRead(VMCS_GUEST_PML_INDEX));
|
|
|
|
//
|
|
// 64-Bit Guest-State Fields
|
|
//
|
|
LOG_ERROR("VMCS link pointer = %016llx", VmxRead(VMCS_GUEST_VMCS_LINK_POINTER));
|
|
LOG_ERROR("Guest IA32_DEBUGCTL = %016llx", VmxRead(VMCS_GUEST_DEBUGCTL));
|
|
LOG_ERROR("Guest IA32_PAT = %016llx", VmxRead(VMCS_GUEST_PAT));
|
|
LOG_ERROR("Guest IA32_EFER = %016llx", VmxRead(VMCS_GUEST_EFER));
|
|
LOG_ERROR("Guest IA32_PERF_GLOBAL_CTRL = %016llx", VmxRead(VMCS_GUEST_PERF_GLOBAL_CTRL));
|
|
LOG_ERROR("Guest PDPTE0 = %016llx", VmxRead(VMCS_GUEST_PDPTE0));
|
|
LOG_ERROR("Guest PDPTE1 = %016llx", VmxRead(VMCS_GUEST_PDPTE1));
|
|
LOG_ERROR("Guest PDPTE2 = %016llx", VmxRead(VMCS_GUEST_PDPTE2));
|
|
LOG_ERROR("Guest PDPTE3 = %016llx", VmxRead(VMCS_GUEST_PDPTE3));
|
|
LOG_ERROR("Guest IA32_BNDCFGS = %016llx", VmxRead(VMCS_GUEST_BNDCFGS));
|
|
LOG_ERROR("Guest IA32_RTIT_CTL = %016llx", VmxRead(VMCS_GUEST_RTIT_CTL));
|
|
|
|
//
|
|
// 32-Bit Guest-State Fields
|
|
//
|
|
LOG_ERROR("Guest ES Limit = %016llx", VmxRead(VMCS_GUEST_ES_LIMIT));
|
|
LOG_ERROR("Guest CS Limit = %016llx", VmxRead(VMCS_GUEST_CS_LIMIT));
|
|
LOG_ERROR("Guest SS Limit = %016llx", VmxRead(VMCS_GUEST_SS_LIMIT));
|
|
LOG_ERROR("Guest DS Limit = %016llx", VmxRead(VMCS_GUEST_DS_LIMIT));
|
|
LOG_ERROR("Guest FS Limit = %016llx", VmxRead(VMCS_GUEST_FS_LIMIT));
|
|
LOG_ERROR("Guest GS Limit = %016llx", VmxRead(VMCS_GUEST_GS_LIMIT));
|
|
LOG_ERROR("Guest LDTR Limit = %016llx", VmxRead(VMCS_GUEST_LDTR_LIMIT));
|
|
LOG_ERROR("Guest TR Limit = %016llx", VmxRead(VMCS_GUEST_TR_LIMIT));
|
|
LOG_ERROR("Guest GDTR limit = %016llx", VmxRead(VMCS_GUEST_GDTR_LIMIT));
|
|
LOG_ERROR("Guest IDTR limit = %016llx", VmxRead(VMCS_GUEST_IDTR_LIMIT));
|
|
LOG_ERROR("Guest ES access rights = %016llx", VmxRead(VMCS_GUEST_ES_ACCESS_RIGHTS));
|
|
LOG_ERROR("Guest CS access rights = %016llx", VmxRead(VMCS_GUEST_CS_ACCESS_RIGHTS));
|
|
LOG_ERROR("Guest SS access rights = %016llx", VmxRead(VMCS_GUEST_SS_ACCESS_RIGHTS));
|
|
LOG_ERROR("Guest DS access rights = %016llx", VmxRead(VMCS_GUEST_DS_ACCESS_RIGHTS));
|
|
LOG_ERROR("Guest FS access rights = %016llx", VmxRead(VMCS_GUEST_FS_ACCESS_RIGHTS));
|
|
LOG_ERROR("Guest GS access rights = %016llx", VmxRead(VMCS_GUEST_GS_ACCESS_RIGHTS));
|
|
LOG_ERROR("Guest LDTR access rights = %016llx", VmxRead(VMCS_GUEST_LDTR_ACCESS_RIGHTS));
|
|
LOG_ERROR("Guest TR access rights = %016llx", VmxRead(VMCS_GUEST_TR_ACCESS_RIGHTS));
|
|
LOG_ERROR("Guest interruptibility state = %016llx", VmxRead(VMCS_GUEST_INTERRUPTIBILITY_STATE));
|
|
LOG_ERROR("Guest activity state = %016llx", VmxRead(VMCS_GUEST_ACTIVITY_STATE));
|
|
LOG_ERROR("Guest SMBASE = %016llx", VmxRead(VMCS_GUEST_SMBASE));
|
|
LOG_ERROR("Guest IA32_SYSENTER_CS = %016llx", VmxRead(VMCS_GUEST_SYSENTER_CS));
|
|
LOG_ERROR("VMX-preemption timer value = %016llx", VmxRead(VMCS_GUEST_VMX_PREEMPTION_TIMER_VALUE));
|
|
|
|
//
|
|
// Natural-Width Guest-State Fields
|
|
//
|
|
LOG_ERROR("Guest CR0 = %016llx", VmxRead(VMCS_GUEST_CR0));
|
|
LOG_ERROR("Guest CR3 = %016llx", VmxRead(VMCS_GUEST_CR3));
|
|
LOG_ERROR("Guest CR4 = %016llx", VmxRead(VMCS_GUEST_CR4));
|
|
LOG_ERROR("Guest ES Base = %016llx", VmxRead(VMCS_GUEST_ES_BASE));
|
|
LOG_ERROR("Guest CS Base = %016llx", VmxRead(VMCS_GUEST_CS_BASE));
|
|
LOG_ERROR("Guest SS Base = %016llx", VmxRead(VMCS_GUEST_SS_BASE));
|
|
LOG_ERROR("Guest DS Base = %016llx", VmxRead(VMCS_GUEST_DS_BASE));
|
|
LOG_ERROR("Guest FS Base = %016llx", VmxRead(VMCS_GUEST_FS_BASE));
|
|
LOG_ERROR("Guest GS Base = %016llx", VmxRead(VMCS_GUEST_GS_BASE));
|
|
LOG_ERROR("Guest LDTR base = %016llx", VmxRead(VMCS_GUEST_LDTR_BASE));
|
|
LOG_ERROR("Guest TR base = %016llx", VmxRead(VMCS_GUEST_TR_BASE));
|
|
LOG_ERROR("Guest GDTR base = %016llx", VmxRead(VMCS_GUEST_GDTR_BASE));
|
|
LOG_ERROR("Guest IDTR base = %016llx", VmxRead(VMCS_GUEST_IDTR_BASE));
|
|
LOG_ERROR("Guest DR7 = %016llx", VmxRead(VMCS_GUEST_DR7));
|
|
LOG_ERROR("Guest RSP = %016llx", VmxRead(VMCS_GUEST_RSP));
|
|
LOG_ERROR("Guest RIP = %016llx", VmxRead(VMCS_GUEST_RIP));
|
|
LOG_ERROR("Guest RFLAGS = %016llx", VmxRead(VMCS_GUEST_RFLAGS));
|
|
LOG_ERROR("Guest pending debug exceptions = %016llx", VmxRead(VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS));
|
|
LOG_ERROR("Guest IA32_SYSENTER_ESP = %016llx", VmxRead(VMCS_GUEST_SYSENTER_ESP));
|
|
LOG_ERROR("Guest IA32_SYSENTER_EIP = %016llx", VmxRead(VMCS_GUEST_SYSENTER_EIP));
|
|
}
|
|
|
|
VOID
|
|
DumpControl (
|
|
)
|
|
{
|
|
//
|
|
// 16-Bit Control Fields
|
|
//
|
|
LOG_ERROR("Virtual-processor identifier = %016llx", VmxRead(VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER));
|
|
LOG_ERROR("Posted-interrupt notification vector = %016llx", VmxRead(VMCS_CTRL_POSTED_INTERRUPT_NOTIFICATION_VECTOR));
|
|
LOG_ERROR("EPTP index = %016llx", VmxRead(VMCS_CTRL_EPTP_INDEX));
|
|
|
|
//
|
|
// 64-Bit Control Fields
|
|
//
|
|
LOG_ERROR("Address of I/O bitmap A = %016llx", VmxRead(VMCS_CTRL_IO_BITMAP_A_ADDRESS));
|
|
LOG_ERROR("Address of I/O bitmap B = %016llx", VmxRead(VMCS_CTRL_IO_BITMAP_B_ADDRESS));
|
|
LOG_ERROR("Address of MSR bitmaps = %016llx", VmxRead(VMCS_CTRL_MSR_BITMAP_ADDRESS));
|
|
LOG_ERROR("VM-exit MSR-store address = %016llx", VmxRead(VMCS_CTRL_VMEXIT_MSR_STORE_ADDRESS));
|
|
LOG_ERROR("VM-exit MSR-load address = %016llx", VmxRead(VMCS_CTRL_VMEXIT_MSR_LOAD_ADDRESS));
|
|
LOG_ERROR("VM-entry MSR-load address = %016llx", VmxRead(VMCS_CTRL_VMENTRY_MSR_LOAD_ADDRESS));
|
|
LOG_ERROR("Executive-VMCS pointer = %016llx", VmxRead(VMCS_CTRL_EXECUTIVE_VMCS_POINTER));
|
|
LOG_ERROR("PML address = %016llx", VmxRead(VMCS_CTRL_PML_ADDRESS));
|
|
LOG_ERROR("TSC offset = %016llx", VmxRead(VMCS_CTRL_TSC_OFFSET));
|
|
LOG_ERROR("Virtual-APIC address = %016llx", VmxRead(VMCS_CTRL_VIRTUAL_APIC_ADDRESS));
|
|
LOG_ERROR("APIC-access address = %016llx", VmxRead(VMCS_CTRL_APIC_ACCESS_ADDRESS));
|
|
LOG_ERROR("Posted-interrupt descriptor address = %016llx", VmxRead(VMCS_CTRL_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS));
|
|
LOG_ERROR("VM-function controls = %016llx", VmxRead(VMCS_CTRL_VMFUNC_CONTROLS));
|
|
LOG_ERROR("EPT pointer = %016llx", VmxRead(VMCS_CTRL_EPT_POINTER));
|
|
LOG_ERROR("EOI-exit bitmap 0 = %016llx", VmxRead(VMCS_CTRL_EOI_EXIT_BITMAP_0));
|
|
LOG_ERROR("EOI-exit bitmap 1 = %016llx", VmxRead(VMCS_CTRL_EOI_EXIT_BITMAP_1));
|
|
LOG_ERROR("EOI-exit bitmap 2 = %016llx", VmxRead(VMCS_CTRL_EOI_EXIT_BITMAP_2));
|
|
LOG_ERROR("EOI-exit bitmap 3 = %016llx", VmxRead(VMCS_CTRL_EOI_EXIT_BITMAP_3));
|
|
LOG_ERROR("EPTP-list address = %016llx", VmxRead(VMCS_CTRL_EPT_POINTER_LIST_ADDRESS));
|
|
LOG_ERROR("VMREAD-bitmap address = %016llx", VmxRead(VMCS_CTRL_VMREAD_BITMAP_ADDRESS));
|
|
LOG_ERROR("VMWRITE-bitmap address = %016llx", VmxRead(VMCS_CTRL_VMWRITE_BITMAP_ADDRESS));
|
|
LOG_ERROR("Virtualization-exception information address = %016llx", VmxRead(VMCS_CTRL_VIRTUALIZATION_EXCEPTION_INFORMATION_ADDRESS));
|
|
LOG_ERROR("XSS-exiting bitmap = %016llx", VmxRead(VMCS_CTRL_XSS_EXITING_BITMAP));
|
|
LOG_ERROR("ENCLS-exiting bitmap = %016llx", VmxRead(VMCS_CTRL_ENCLS_EXITING_BITMAP));
|
|
LOG_ERROR("TSC multiplier = %016llx", VmxRead(VMCS_CTRL_TSC_MULTIPLIER));
|
|
|
|
//
|
|
// 32-Bit Control Fields
|
|
//
|
|
LOG_ERROR("Pin-based VM-execution controls = %016llx", VmxRead(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS));
|
|
LOG_ERROR("Primary processor-based VM-execution controls = %016llx", VmxRead(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS));
|
|
LOG_ERROR("Exception bitmap = %016llx", VmxRead(VMCS_CTRL_EXCEPTION_BITMAP));
|
|
LOG_ERROR("Page-fault error-code mask = %016llx", VmxRead(VMCS_CTRL_PAGEFAULT_ERROR_CODE_MASK));
|
|
LOG_ERROR("Page-fault error-code match = %016llx", VmxRead(VMCS_CTRL_PAGEFAULT_ERROR_CODE_MATCH));
|
|
LOG_ERROR("CR3-target count = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_COUNT));
|
|
LOG_ERROR("VM-exit controls = %016llx", VmxRead(VMCS_CTRL_VMEXIT_CONTROLS));
|
|
LOG_ERROR("VM-exit MSR-store count = %016llx", VmxRead(VMCS_CTRL_VMEXIT_MSR_STORE_COUNT));
|
|
LOG_ERROR("VM-exit MSR-load count = %016llx", VmxRead(VMCS_CTRL_VMEXIT_MSR_LOAD_COUNT));
|
|
LOG_ERROR("VM-entry controls = %016llx", VmxRead(VMCS_CTRL_VMENTRY_CONTROLS));
|
|
LOG_ERROR("VM-entry MSR-load count = %016llx", VmxRead(VMCS_CTRL_VMENTRY_MSR_LOAD_COUNT));
|
|
LOG_ERROR("VM-entry interruption-information field = %016llx", VmxRead(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD));
|
|
LOG_ERROR("VM-entry exception error code = %016llx", VmxRead(VMCS_CTRL_VMENTRY_EXCEPTION_ERROR_CODE));
|
|
LOG_ERROR("VM-entry instruction length = %016llx", VmxRead(VMCS_CTRL_VMENTRY_INSTRUCTION_LENGTH));
|
|
LOG_ERROR("TPR threshold = %016llx", VmxRead(VMCS_CTRL_TPR_THRESHOLD));
|
|
LOG_ERROR("Secondary processor-based VM-execution controls = %016llx", VmxRead(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS));
|
|
LOG_ERROR("PLE_Gap = %016llx", VmxRead(VMCS_CTRL_PLE_GAP));
|
|
LOG_ERROR("PLE_Window = %016llx", VmxRead(VMCS_CTRL_PLE_WINDOW));
|
|
|
|
//
|
|
// Natural-Width Control Fields
|
|
//
|
|
LOG_ERROR("CR0 guest/host mask = %016llx", VmxRead(VMCS_CTRL_CR0_GUEST_HOST_MASK));
|
|
LOG_ERROR("CR4 guest/host mask = %016llx", VmxRead(VMCS_CTRL_CR4_GUEST_HOST_MASK));
|
|
LOG_ERROR("CR0 read shadow = %016llx", VmxRead(VMCS_CTRL_CR0_READ_SHADOW));
|
|
LOG_ERROR("CR4 read shadow = %016llx", VmxRead(VMCS_CTRL_CR4_READ_SHADOW));
|
|
LOG_ERROR("CR3-target value 0 = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_VALUE_0));
|
|
LOG_ERROR("CR3-target value 1 = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_VALUE_1));
|
|
LOG_ERROR("CR3-target value 2 = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_VALUE_2));
|
|
LOG_ERROR("CR3-target value 3 = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_VALUE_3));
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
VOID
|
|
VmxWrite (
|
|
VMCS_FIELD Field,
|
|
UINT64 FieldValue
|
|
)
|
|
{
|
|
VMX_RESULT result;
|
|
|
|
result = __vmx_vmwrite(Field, FieldValue);
|
|
if (result != VmxResultOk)
|
|
{
|
|
VMX_ERROR_NUMBER vmxErrorStatus;
|
|
|
|
vmxErrorStatus = (result == VmxResultErrorWithStatus) ?
|
|
(VMX_ERROR_NUMBER)VmxRead(VMCS_VM_INSTRUCTION_ERROR) : 0;
|
|
if (vmxErrorStatus != VMX_ERROR_VMREAD_VMWRITE_INVALID_COMPONENT)
|
|
{
|
|
MV_PANIC();
|
|
}
|
|
}
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
UINT64
|
|
VmxRead (
|
|
VMCS_FIELD Field
|
|
)
|
|
{
|
|
VMX_RESULT result;
|
|
UINT64 fieldValue;
|
|
|
|
result = __vmx_vmread(Field, &fieldValue);
|
|
if (result != VmxResultOk)
|
|
{
|
|
VMX_ERROR_NUMBER vmxErrorStatus;
|
|
|
|
vmxErrorStatus = (result == VmxResultErrorWithStatus) ?
|
|
(VMX_ERROR_NUMBER)VmxRead(VMCS_VM_INSTRUCTION_ERROR) : 0;
|
|
if (vmxErrorStatus != VMX_ERROR_VMREAD_VMWRITE_INVALID_COMPONENT)
|
|
{
|
|
MV_PANIC();
|
|
}
|
|
fieldValue = MAXUINT64;
|
|
}
|
|
return fieldValue;
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
VOID
|
|
AdvanceGuestInstructionPointer (
|
|
GUEST_CONTEXT* GuestContext
|
|
)
|
|
{
|
|
UINT64 exitInstructionLength;
|
|
|
|
exitInstructionLength = VmxRead(VMCS_VMEXIT_INSTRUCTION_LENGTH);
|
|
GuestContext->VmcsBasedRegisters.Rip += exitInstructionLength;
|
|
VmxWrite(VMCS_GUEST_RIP, GuestContext->VmcsBasedRegisters.Rip);
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
BOOLEAN
|
|
IsGuestInKernelMode (
|
|
VOID
|
|
)
|
|
{
|
|
VMX_SEGMENT_ACCESS_RIGHTS accessRight;
|
|
|
|
accessRight.Flags = (UINT32)VmxRead(VMCS_GUEST_SS_ACCESS_RIGHTS);
|
|
return (accessRight.DescriptorPrivilegeLevel == 0);
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
VOID
|
|
InjectInterruption (
|
|
INTERRUPTION_TYPE InterruptionType,
|
|
EXCEPTION_VECTOR Vector,
|
|
BOOLEAN DeliverErrorCode,
|
|
UINT32 ErrorCode
|
|
)
|
|
{
|
|
VMENTRY_INTERRUPT_INFORMATION interruptToInject;
|
|
|
|
interruptToInject.Flags = 0;
|
|
interruptToInject.Valid = TRUE;
|
|
interruptToInject.InterruptionType = (UINT32)InterruptionType;
|
|
interruptToInject.Vector = (UINT32)Vector;
|
|
interruptToInject.DeliverErrorCode = DeliverErrorCode;
|
|
VmxWrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interruptToInject.Flags);
|
|
|
|
if (DeliverErrorCode != FALSE)
|
|
{
|
|
VmxWrite(VMCS_CTRL_VMENTRY_EXCEPTION_ERROR_CODE, ErrorCode);
|
|
}
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
VOID
|
|
SwitchGuestPagingMode (
|
|
CR0 NewGuestCr0
|
|
)
|
|
{
|
|
IA32_EFER_REGISTER guestEfer;
|
|
IA32_VMX_ENTRY_CTLS_REGISTER vmEntryControls;
|
|
|
|
//
|
|
// "Enable paging by setting CR0.PG = 1. This causes the processor to set the
|
|
// IA32_EFER.LMA bit to 1."
|
|
// See: 9.8.5 Initializing IA-32e Mode
|
|
//
|
|
// "The processor always sets IA32_EFER.LMA to CR0.PG & IA32_EFER.LME.
|
|
// Software cannot directly modify IA32_EFER.LMA; an execution of WRMSR to
|
|
// the IA32_EFER MSR ignores bit 10 of its source operand."
|
|
// See: 4.1.1 Three Paging Modes
|
|
//
|
|
guestEfer.Flags = VmxRead(VMCS_GUEST_EFER);
|
|
guestEfer.Ia32EModeActive = (NewGuestCr0.PagingEnable & guestEfer.Ia32EModeEnable);
|
|
VmxWrite(VMCS_GUEST_EFER, guestEfer.Flags);
|
|
|
|
//
|
|
// Apply the paging mode change in the VM-entry control VMCS field too.
|
|
//
|
|
vmEntryControls.Flags = VmxRead(VMCS_CTRL_VMENTRY_CONTROLS);
|
|
vmEntryControls.Ia32EModeGuest = guestEfer.Ia32EModeActive;
|
|
VmxWrite(VMCS_CTRL_VMENTRY_CONTROLS, vmEntryControls.Flags);
|
|
|
|
//
|
|
// Changing the paging mode results in invalidating TLB. Emulate this by
|
|
// invalidating combined caches (GVA to HPA translation caches).
|
|
//
|
|
InvalidateVpidDerivedCache((UINT16)VmxRead(VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER));
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
CR0
|
|
AdjustGuestCr0 (
|
|
CR0 Cr0
|
|
)
|
|
{
|
|
CR0 newCr0;
|
|
IA32_VMX_PROCBASED_CTLS2_REGISTER secondaryProcBasedControls;
|
|
|
|
newCr0 = AdjustCr0(Cr0);
|
|
|
|
//
|
|
// When the UnrestrictedGuest bit is set, ProtectionEnable and PagingEnable
|
|
// bits are allowed to be zero. Make this adjustment, by setting them 1 only
|
|
// when the guest did indeed requested them to be 1 (ie,
|
|
// Cr0.ProtectionEnable == 1) and the FIXED0 MSR indicated them to be 1 (ie,
|
|
// newCr0.ProtectionEnable == 1).
|
|
//
|
|
secondaryProcBasedControls.Flags = VmxRead(
|
|
VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS);
|
|
if (secondaryProcBasedControls.UnrestrictedGuest != FALSE)
|
|
{
|
|
newCr0.ProtectionEnable &= Cr0.ProtectionEnable;
|
|
newCr0.PagingEnable &= Cr0.PagingEnable;
|
|
}
|
|
return newCr0;
|
|
}
|
|
|
|
_Use_decl_annotations_
|
|
CR4
|
|
AdjustGuestCr4 (
|
|
CR4 Cr4
|
|
)
|
|
{
|
|
return AdjustCr4(Cr4);
|
|
}
|