Files
MiniVisorPkg/Sources/HostUtils.c
2020-03-08 20:46:45 -07:00

534 lines
22 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 "Ia32Utils.h"
#include "MemoryAccess.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 = %u", rights.Type);
LOG_ERROR(" - S = %u", rights.DescriptorType);
LOG_ERROR(" - DPL = %u", rights.DescriptorPrivilegeLevel);
LOG_ERROR(" - P = %u", rights.Present);
LOG_ERROR(" - Reserved1 = %u", rights.Reserved1);
LOG_ERROR(" - Available = %u", rights.AvailableBit);
LOG_ERROR(" - L = %u", rights.LongMode);
LOG_ERROR(" - D/B = %u", rights.DefaultBig);
LOG_ERROR(" - G = %u", rights.Granularity);
LOG_ERROR(" - Unusable = %u", rights.Unusable);
LOG_ERROR(" - Reserved2 = %u", 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 = 0;
}
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 (
)
{
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);
}
_Use_decl_annotations_
UINT64
FindImageBase (
GUEST_CONTEXT* GuestContext,
UINT64 GuestVirtualAddress
)
{
UINT64 imageBase;
//
// Starting with the page aligned address, and search up IMAGE_DOS_SIGNATURE
// every page up to 16MB (0x1000000). Ntoskrnl.exe can be mapped at the page
// boundary and not the 64KB boundary unlike other images.
//
imageBase = (GuestVirtualAddress & ~(PAGE_SIZE - 1));
for (int i = 0; i < 0x1000; i++, imageBase -= PAGE_SIZE)
{
BOOLEAN ok;
UINT16 contents;
MEMORY_ACCESS_ERROR_INFORMATION errorInfo;
ok = ReadGuestVirtualAddress(GuestContext->Contexts->MemoryAccessContext,
TRUE,
imageBase,
&contents,
sizeof(contents),
&errorInfo);
if (ok == FALSE)
{
continue;
}
if (contents == 0x5A4D)
{
goto Exit;
}
}
imageBase = 0;
Exit:
return imageBase;
}
_Use_decl_annotations_
VOID
UpdateMsrBitmaps (
MSR_BITMAPS* Bitmaps,
IA32_MSR_ADDRESS Msr,
OPERATION_TYPE InterOperation,
BOOLEAN Intercept
)
{
IA32_MSR_ADDRESS msrTemp;
BOOLEAN highValue;
UINT64 byteOffset;
UINT64 bitMask;
UINT8* msrBitmap;
//
// MSR must be within either 0x0 - 0x1fff or 0xc0000000 - 0xc0001fff
// inclusive, and at least read or write intercept must be specified.
//
MV_ASSERT((Msr <= 0x1fff) ||
((Msr >= 0xc0000000) && (Msr <= 0xc0001fff)));
//
// Check if the MSR belongs to high bitmaps.
//
highValue = BooleanFlagOn(Msr, 0xc0000000);
//
// Computes offsets and bitmaps to update the bitmaps.
//
msrTemp = (Msr & ~0xc0000000);
byteOffset = (msrTemp / CHAR_BIT);
bitMask = (1ull << (msrTemp % CHAR_BIT));
//
// Select the bitmap to work on.
//
if (InterOperation == OperationRead)
{
if (highValue == FALSE)
{
msrBitmap = Bitmaps->ReadBitmapLow;
}
else
{
msrBitmap = Bitmaps->ReadBitmapHigh;
}
}
else
{
if (highValue == FALSE)
{
msrBitmap = Bitmaps->WriteBitmapLow;
}
else
{
msrBitmap = Bitmaps->WriteBitmapHigh;
}
}
//
// Set of clear the bit.
//
if (Intercept != FALSE)
{
SetFlag(msrBitmap[byteOffset], bitMask);
}
else
{
ClearFlag(msrBitmap[byteOffset], bitMask);
}
}