Files
2026-05-09 19:19:39 +03:00

1596 lines
50 KiB
C++

#pragma once
#include "pch.h"
#include "Spinlock.h"
#pragma warning(push)
#pragma warning(disable: 4201)
// Constants
constexpr ULONG64 MAX_PROTECTED_ADDRESSES = 512;
constexpr SIZE_T VMM_STACK_SIZE = 0x8000;
constexpr SIZE_T MAX_XSAVE_AREA_SIZE = 0x3000;
constexpr ULONG64 CR4_OSXSAVE = 1ULL << 18;
constexpr SIZE_T VMCS_SIZE = 4096;
constexpr SIZE_T VMXON_SIZE = 4096;
constexpr ULONG MSR_APIC_BASE = 0x01B;
constexpr ULONG MSR_IA32_FEATURE_CONTROL = 0x03A;
constexpr ULONG RPL_MASK = 3;
constexpr ULONG MSR_IA32_VMX_BASIC = 0x480;
constexpr ULONG MSR_IA32_VMX_PINBASED_CTLS = 0x481;
constexpr ULONG MSR_IA32_VMX_PROCBASED_CTLS = 0x482;
constexpr ULONG MSR_IA32_VMX_EXIT_CTLS = 0x483;
constexpr ULONG MSR_IA32_VMX_ENTRY_CTLS = 0x484;
constexpr ULONG MSR_IA32_VMX_MISC = 0x485;
constexpr ULONG MSR_IA32_VMX_CR0_FIXED0 = 0x486;
constexpr ULONG MSR_IA32_VMX_CR0_FIXED1 = 0x487;
constexpr ULONG MSR_IA32_VMX_CR4_FIXED0 = 0x488;
constexpr ULONG MSR_IA32_VMX_CR4_FIXED1 = 0x489;
constexpr ULONG MSR_IA32_VMX_VMCS_ENUM = 0x48A;
constexpr ULONG MSR_IA32_VMX_PROCBASED_CTLS2 = 0x48B;
constexpr ULONG MSR_IA32_VMX_EPT_VPID_CAP = 0x48C;
constexpr ULONG MSR_IA32_VMX_TRUE_PINBASED_CTLS = 0x48D;
constexpr ULONG MSR_IA32_VMX_TRUE_PROCBASED_CTLS = 0x48E;
constexpr ULONG MSR_IA32_VMX_TRUE_EXIT_CTLS = 0x48F;
constexpr ULONG MSR_IA32_VMX_TRUE_ENTRY_CTLS = 0x490;
constexpr ULONG MSR_IA32_VMX_VMFUNC = 0x491;
constexpr ULONG MSR_IA32_SYSENTER_CS = 0x174;
constexpr ULONG MSR_IA32_SYSENTER_ESP = 0x175;
constexpr ULONG MSR_IA32_SYSENTER_EIP = 0x176;
constexpr ULONG MSR_IA32_DEBUGCTL = 0x1D9;
constexpr ULONG MSR_IA32_PAT = 0x277;
constexpr ULONG MSR_IA32_EFER = 0xC0000080;
constexpr ULONG MSR_LSTAR = 0xC0000082;
constexpr ULONG MSR_FS_BASE = 0xC0000100;
constexpr ULONG MSR_GS_BASE = 0xC0000101;
constexpr ULONG MSR_SHADOW_GS_BASE = 0xC0000102;
constexpr ULONG MSR_IA32_MTRR_DEF_TYPE = 0x2FF;
constexpr ULONG MSR_IA32_MTRR_CAPABILITIES = 0x000000FE;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE0 = 0x00000200;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE1 = 0x00000202;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE2 = 0x00000204;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE3 = 0x00000206;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE4 = 0x00000208;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE5 = 0x0000020A;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE6 = 0x0000020C;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE7 = 0x0000020E;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE8 = 0x00000210;
constexpr ULONG MSR_IA32_MTRR_PHYSBASE9 = 0x00000212;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK0 = 0x00000201;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK1 = 0x00000203;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK2 = 0x00000205;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK3 = 0x00000207;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK4 = 0x00000209;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK5 = 0x0000020B;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK6 = 0x0000020D;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK7 = 0x0000020F;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK8 = 0x00000211;
constexpr ULONG MSR_IA32_MTRR_PHYSMASK9 = 0x00000213;
constexpr ULONG64 HV_X64_MSR_GUEST_OS_ID = 0x40000000;
constexpr ULONG64 HV_X64_MSR_HYPERCALL = 0x40000001;
constexpr ULONG64 HV_X64_MSR_VP_INDEX = 0x40000002;
constexpr ULONG64 HV_X64_MSR_RESET = 0x40000003;
constexpr ULONG64 HV_X64_MSR_VP_RUNTIME = 0x40000010;
constexpr ULONG64 HV_X64_MSR_TIME_REF_COUNT = 0x40000020;
constexpr ULONG64 HV_X64_MSR_REFERENCE_TSC = 0x40000021;
constexpr ULONG64 HV_X64_MSR_TSC_FREQUENCY = 0x40000022;
constexpr ULONG64 HV_X64_MSR_APIC_FREQUENCY = 0x40000023;
constexpr ULONG64 HV_X64_MSR_NPIEP_CONFIG = 0x40000040;
constexpr ULONG64 HV_X64_MSR_EOI = 0x40000070;
constexpr ULONG64 HV_X64_MSR_TPR = 0x40000072;
constexpr ULONG64 HV_X64_MSR_SCONTROL = 0x40000080;
constexpr ULONG64 HV_X64_MSR_EOM = 0x40000084;
constexpr ULONG64 HV_X64_MSR_SINT0 = 0x40000090;
constexpr ULONG64 HV_X64_MSR_SINT15 = 0x4000009F;
constexpr ULONG64 HV_X64_MSR_STIMER0_CONFIG = 0x400000B0;
constexpr ULONG64 HV_X64_MSR_STIMER3_COUNT = 0x400000B7;
constexpr ULONG64 HV_X64_MSR_GUEST_IDLE = 0x400000F0;
constexpr ULONG64 HV_X64_MSR_CRASH_P0 = 0x40000100;
constexpr ULONG64 HV_X64_MSR_CRASH_CTL = 0x40000105;
constexpr ULONG64 HV_X64_MSR_REENLIGHTENMENT_CONTROL = 0x40000106;
constexpr ULONG64 HV_X64_MSR_TSC_EMULATION_CONTROL = 0x40000107;
constexpr ULONG64 HV_X64_MSR_TSC_EMULATION_STATUS = 0x40000108;
constexpr ULONG64 HV_X64_MSR_STIME_UNHALTED_TIMER_CONFIG = 0x40000114;
constexpr ULONG64 HV_X64_MSR_STIME_UNHALTED_TIMER_COUNT = 0x40000115;
constexpr ULONG64 HV_X64_MSR_NESTED_VP_INDEX = 0x40001002;
constexpr ULONG64 HV_X64_MSR_NESTED_SCONTROL = 0x40001080;
constexpr ULONG64 HV_X64_MSR_NESTED_EOM = 0x40001084;
constexpr ULONG64 HV_X64_MSR_NESTED_SINT0 = 0x40001090;
constexpr ULONG64 HV_X64_MSR_NESTED_SINT15 = 0x4000109F;
constexpr SIZE_T IA32_MTRR_FIX64K_BASE = 0x00000000;
constexpr SIZE_T IA32_MTRR_FIX64K_SIZE = 0x00010000;
constexpr SIZE_T IA32_MTRR_FIX64K_00000 = 0x00000250;
constexpr SIZE_T IA32_MTRR_FIX16K_BASE = 0x00080000;
constexpr SIZE_T IA32_MTRR_FIX16K_SIZE = 0x00004000;
constexpr SIZE_T IA32_MTRR_FIX16K_80000 = 0x00000258;
constexpr SIZE_T IA32_MTRR_FIX16K_A0000 = 0x00000259;
constexpr SIZE_T IA32_MTRR_FIX4K_BASE = 0x000C0000;
constexpr SIZE_T IA32_MTRR_FIX4K_SIZE = 0x00001000;
constexpr SIZE_T IA32_MTRR_FIX4K_C0000 = 0x00000268;
constexpr SIZE_T IA32_MTRR_FIX4K_C8000 = 0x00000269;
constexpr SIZE_T IA32_MTRR_FIX4K_D0000 = 0x0000026A;
constexpr SIZE_T IA32_MTRR_FIX4K_D8000 = 0x0000026B;
constexpr SIZE_T IA32_MTRR_FIX4K_E0000 = 0x0000026C;
constexpr SIZE_T IA32_MTRR_FIX4K_E8000 = 0x0000026D;
constexpr SIZE_T IA32_MTRR_FIX4K_F0000 = 0x0000026E;
constexpr SIZE_T IA32_MTRR_FIX4K_F8000 = 0x0000026F;
constexpr ULONG64 RESERVED_MSR_RANGE_LOW = 0x40000000;
constexpr ULONG64 RESERVED_MSR_RANGE_HIGH = 0x400000F0;
constexpr USHORT VMEXIT_STATE_BITS = 0xF8;
constexpr ULONGLONG NO_ADDITIONAL_VMCS = ~0ULL;
constexpr ULONG PIN_BASED_VM_EXECUTION_CONTROLS_EXTERNAL_INTERRUPT = 0x00000001;
constexpr ULONG PIN_BASED_VM_EXECUTION_CONTROLS_NMI_EXITING = 0x00000008;
constexpr ULONG PIN_BASED_VM_EXECUTION_CONTROLS_VIRTUAL_NMI = 0x00000020;
constexpr ULONG PIN_BASED_VM_EXECUTION_CONTROLS_ACTIVE_VMX_TIMER = 0x00000040;
constexpr ULONG PIN_BASED_VM_EXECUTION_CONTROLS_PROCESS_POSTED_INTERRUPTS = 0x00000080;
constexpr ULONG CPU_BASED_VIRTUAL_INTR_PENDING = 0x00000004;
constexpr ULONG CPU_BASED_USE_TSC_OFFSETING = 0x00000008;
constexpr ULONG CPU_BASED_HLT_EXITING = 0x00000080;
constexpr ULONG CPU_BASED_INVLPG_EXITING = 0x00000200;
constexpr ULONG CPU_BASED_MWAIT_EXITING = 0x00000400;
constexpr ULONG CPU_BASED_RDPMC_EXITING = 0x00000800;
constexpr ULONG CPU_BASED_RDTSC_EXITING = 0x00001000;
constexpr ULONG CPU_BASED_CR3_LOAD_EXITING = 0x00008000;
constexpr ULONG CPU_BASED_CR3_STORE_EXITING = 0x00010000;
constexpr ULONG CPU_BASED_CR8_LOAD_EXITING = 0x00080000;
constexpr ULONG CPU_BASED_CR8_STORE_EXITING = 0x00100000;
constexpr ULONG CPU_BASED_TPR_SHADOW = 0x00200000;
constexpr ULONG CPU_BASED_VIRTUAL_NMI_PENDING = 0x00400000;
constexpr ULONG CPU_BASED_MOV_DR_EXITING = 0x00800000;
constexpr ULONG CPU_BASED_UNCOND_IO_EXITING = 0x01000000;
constexpr ULONG CPU_BASED_ACTIVATE_IO_BITMAP = 0x02000000;
constexpr ULONG CPU_BASED_MONITOR_TRAP_FLAG = 0x08000000;
constexpr ULONG CPU_BASED_ACTIVATE_MSR_BITMAP = 0x10000000;
constexpr ULONG CPU_BASED_MONITOR_EXITING = 0x20000000;
constexpr ULONG CPU_BASED_PAUSE_EXITING = 0x40000000;
constexpr ULONG CPU_BASED_ACTIVATE_SECONDARY_CONTROLS = 0x80000000;
constexpr ULONG CPU_BASED_CTL2_ENABLE_EPT = 0x2;
constexpr ULONG CPU_BASED_CTL2_RDTSCP = 0x8;
constexpr ULONG CPU_BASED_CTL2_ENABLE_VPID = 0x20;
constexpr ULONG CPU_BASED_CTL2_UNRESTRICTED_GUEST = 0x80;
constexpr ULONG CPU_BASED_CTL2_VIRTUAL_INTERRUPT_DELIVERY = 0x200;
constexpr ULONG CPU_BASED_CTL2_ENABLE_INVPCID = 0x1000;
constexpr ULONG CPU_BASED_CTL2_ENABLE_VMFUNC = 0x2000;
constexpr ULONG CPU_BASED_CTL2_ENABLE_XSAVE_XRSTORS = 0x100000;
constexpr ULONG CPU_BASED_CTL2_ENABLE_USER_WAIT_AND_PAUSE = 0x4000000;
// VMCalls
constexpr ULONG VMCALL_TEST = 1;
constexpr ULONG VMCALL_VMXOFF = 2;
constexpr ULONG VMCALL_EXEC_HOOK_PAGE = 3;
constexpr ULONG VMCALL_INVEPT_ALL_CONTEXT = 4;
constexpr ULONG VMCALL_INVEPT_SINGLE_CONTEXT = 5;
constexpr ULONG VMCALL_UNHOOK_SINGLE_PAGE = 6;
constexpr ULONG VMCALL_UNHOOK_ALL_PAGES = 7;
// VM-exit Control Bits
constexpr ULONG VM_EXIT_IA32E_MODE = 0x00000200;
constexpr ULONG VM_EXIT_ACK_INTR_ON_EXIT = 0x00008000;
constexpr ULONG VM_EXIT_SAVE_GUEST_PAT = 0x00040000;
constexpr ULONG VM_EXIT_LOAD_HOST_PAT = 0x00080000;
constexpr ULONG VM_EXIT_SAVE_GUEST_EFER = 0x00100000;
constexpr ULONG VM_EXIT_LOAD_HOST_EFER = 0x00200000;
// VM-entry Control Bits
constexpr ULONG VM_ENTRY_IA32E_MODE = 0x00000200;
constexpr ULONG VM_ENTRY_SMM = 0x00000400;
constexpr ULONG VM_ENTRY_DEACT_DUAL_MONITOR = 0x00000800;
constexpr ULONG VM_ENTRY_LOAD_GUEST_PAT = 0x00004000;
constexpr ULONG VM_ENTRY_LOAD_GUEST_EFER = 0x00008000;
// Exit Reasons
constexpr ULONG EXIT_REASON_EXCEPTION_NMI = 0;
constexpr ULONG EXIT_REASON_EXTERNAL_INTERRUPT = 1;
constexpr ULONG EXIT_REASON_TRIPLE_FAULT = 2;
constexpr ULONG EXIT_REASON_INIT = 3;
constexpr ULONG EXIT_REASON_SIPI = 4;
constexpr ULONG EXIT_REASON_IO_SMI = 5;
constexpr ULONG EXIT_REASON_OTHER_SMI = 6;
constexpr ULONG EXIT_REASON_PENDING_VIRT_INTR = 7;
constexpr ULONG EXIT_REASON_PENDING_VIRT_NMI = 8;
constexpr ULONG EXIT_REASON_TASK_SWITCH = 9;
constexpr ULONG EXIT_REASON_CPUID = 10;
constexpr ULONG EXIT_REASON_GETSEC = 11;
constexpr ULONG EXIT_REASON_HLT = 12;
constexpr ULONG EXIT_REASON_INVD = 13;
constexpr ULONG EXIT_REASON_INVLPG = 14;
constexpr ULONG EXIT_REASON_RDPMC = 15;
constexpr ULONG EXIT_REASON_RDTSC = 16;
constexpr ULONG EXIT_REASON_RSM = 17;
constexpr ULONG EXIT_REASON_VMCALL = 18;
constexpr ULONG EXIT_REASON_VMCLEAR = 19;
constexpr ULONG EXIT_REASON_VMLAUNCH = 20;
constexpr ULONG EXIT_REASON_VMPTRLD = 21;
constexpr ULONG EXIT_REASON_VMPTRST = 22;
constexpr ULONG EXIT_REASON_VMREAD = 23;
constexpr ULONG EXIT_REASON_VMRESUME = 24;
constexpr ULONG EXIT_REASON_VMWRITE = 25;
constexpr ULONG EXIT_REASON_VMXOFF = 26;
constexpr ULONG EXIT_REASON_VMXON = 27;
constexpr ULONG EXIT_REASON_CR_ACCESS = 28;
constexpr ULONG EXIT_REASON_DR_ACCESS = 29;
constexpr ULONG EXIT_REASON_IO_INSTRUCTION = 30;
constexpr ULONG EXIT_REASON_MSR_READ = 31;
constexpr ULONG EXIT_REASON_MSR_WRITE = 32;
constexpr ULONG EXIT_REASON_INVALID_GUEST_STATE = 33;
constexpr ULONG EXIT_REASON_MSR_LOADING = 34;
constexpr ULONG EXIT_REASON_MWAIT_INSTRUCTION = 36;
constexpr ULONG EXIT_REASON_MONITOR_TRAP_FLAG = 37;
constexpr ULONG EXIT_REASON_MONITOR_INSTRUCTION = 39;
constexpr ULONG EXIT_REASON_PAUSE_INSTRUCTION = 40;
constexpr ULONG EXIT_REASON_MCE_DURING_VMENTRY = 41;
constexpr ULONG EXIT_REASON_TPR_BELOW_THRESHOLD = 43;
constexpr ULONG EXIT_REASON_APIC_ACCESS = 44;
constexpr ULONG EXIT_REASON_ACCESS_GDTR_OR_IDTR = 46;
constexpr ULONG EXIT_REASON_ACCESS_LDTR_OR_TR = 47;
constexpr ULONG EXIT_REASON_EPT_VIOLATION = 48;
constexpr ULONG EXIT_REASON_EPT_MISCONFIG = 49;
constexpr ULONG EXIT_REASON_INVEPT = 50;
constexpr ULONG EXIT_REASON_RDTSCP = 51;
constexpr ULONG EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED = 52;
constexpr ULONG EXIT_REASON_INVVPID = 53;
constexpr ULONG EXIT_REASON_WBINVD = 54;
constexpr ULONG EXIT_REASON_XSETBV = 55;
constexpr ULONG EXIT_REASON_APIC_WRITE = 56;
constexpr ULONG EXIT_REASON_RDRAND = 57;
constexpr ULONG EXIT_REASON_INVPCID = 58;
constexpr ULONG EXIT_REASON_RDSEED = 61;
constexpr ULONG EXIT_REASON_PML_FULL = 62;
constexpr ULONG EXIT_REASON_XSAVES = 63;
constexpr ULONG EXIT_REASON_XRSTORS = 64;
constexpr ULONG EXIT_REASON_PCOMMIT = 65;
constexpr ULONG EXIT_REASON_UMONITOR = 67;
constexpr ULONG EXIT_REASON_UMWAIT = 68;
// Hyperv cpuid
constexpr ULONG HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS = 0x40000000;
constexpr ULONG HYPERV_CPUID_INTERFACE = 0x40000001;
constexpr ULONG HYPERV_CPUID_VERSION = 0x40000002;
constexpr ULONG HYPERV_CPUID_FEATURES = 0x40000003;
constexpr ULONG HYPERV_CPUID_ENLIGHTMENT_INFO = 0x40000004;
constexpr ULONG HYPERV_CPUID_IMPLEMENT_LIMITS = 0x40000005;
constexpr ULONG HYPERV_HYPERVISOR_PRESENT_BIT = 0x80000000;
constexpr ULONG HYPERV_CPUID_VENDOR_MICROSOFT_EBX = 0x7263694d; // "Micr"
constexpr ULONG HYPERV_CPUID_VENDOR_MICROSOFT_ECX = 0x666f736f; // "osof"
constexpr ULONG HYPERV_CPUID_VENDOR_MICROSOFT_EDX = 0x76482074; // "t Hv"
constexpr ULONG HYPERV_CPUID_FEATURES_EDX_XMM_FAST_HYPERCALL_INPUT = 1UL << 4;
constexpr ULONG HYPERV_CPUID_FEATURES_EDX_XMM_FAST_HYPERCALL_OUTPUT = 1UL << 15;
constexpr ULONG HYPERV_CPUID_MIN = 0x40000005;
constexpr ULONG HYPERV_CPUID_MAX = 0x4000ffff;
// Exit qualification for CR accesses
constexpr ULONG TYPE_MOV_TO_CR = 0;
constexpr ULONG TYPE_MOV_FROM_CR = 1;
constexpr ULONG TYPE_CLTS = 2;
constexpr ULONG TYPE_LMSW = 3;
// DPL modes
constexpr SIZE_T DPL_USER = 3;
constexpr SIZE_T DPL_SYSTEM = 0;
// Ept definitions
constexpr SIZE_T VMM_EPT_PML4E_COUNT = 512;
constexpr SIZE_T VMM_EPT_PML3E_COUNT = 512;
constexpr SIZE_T VMM_EPT_PML2E_COUNT = 512;
constexpr SIZE_T VMM_EPT_PML1E_COUNT = 512;
constexpr UCHAR MEMORY_TYPE_UNCACHEABLE = 0x00000000;
constexpr UCHAR MEMORY_TYPE_WRITE_COMBINING = 0x00000001;
constexpr UCHAR MEMORY_TYPE_WRITE_THROUGH = 0x00000004;
constexpr UCHAR MEMORY_TYPE_WRITE_PROTECTED = 0x00000005;
constexpr UCHAR MEMORY_TYPE_WRITE_BACK = 0x00000006;
constexpr UCHAR MEMORY_TYPE_INVALID = 0x000000FF;
constexpr SIZE_T VPID_TAG_BASE = 1;
// Integer 2MB
constexpr SIZE_T SIZE_2_MB = ((SIZE_T)(512 * PAGE_SIZE));
// Offset into the 1st paging structure (4096 byte)
#define ADDRMASK_EPT_PML1_OFFSET(_VAR_) (_VAR_ & 0xFFFULL)
// Index of the 1st paging structure (4096 byte)
#define ADDRMASK_EPT_PML1_INDEX(_VAR_) ((_VAR_ & 0x1FF000ULL) >> 12)
// Index of the 2nd paging structure (2MB)
#define ADDRMASK_EPT_PML2_INDEX(_VAR_) ((_VAR_ & 0x3FE00000ULL) >> 21)
// Index of the 3rd paging structure (1GB)
#define ADDRMASK_EPT_PML3_INDEX(_VAR_) ((_VAR_ & 0x7FC0000000ULL) >> 30)
// Index of the 4th paging structure (512GB)
#define ADDRMASK_EPT_PML4_INDEX(_VAR_) ((_VAR_ & 0xFF8000000000ULL) >> 39)
constexpr ULONG64 CPUID_PROCESSOR_AND_PROCESSOR_FEATURE_IDENTIFIERS = 1;
constexpr ULONG64 CPUID_EXTENDED_STATE_ENUMERATION = 0xD;
// Type definitions
enum RegionType {
VMXON_REGION,
VMCS_REGION,
MSR_BITMAP_REGION
};
typedef union _PEPT_PML4
{
struct
{
/**
* [Bit 0] Read access; indicates whether reads are allowed from the 512-GByte region controlled by this entry.
*/
UINT64 ReadAccess : 1;
/**
* [Bit 1] Write access; indicates whether writes are allowed from the 512-GByte region controlled by this entry.
*/
UINT64 WriteAccess : 1;
/**
* [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether
* instruction fetches are allowed from the 512-GByte region controlled by this entry.
* If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are
* allowed from supervisor-mode linear addresses in the 512-GByte region controlled by this entry.
*/
UINT64 ExecuteAccess : 1;
UINT64 Reserved1 : 5;
/**
* [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 512-GByte region
* controlled by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Accessed : 1;
UINT64 Reserved2 : 1;
/**
* [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control
* is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 512-GByte region
* controlled by this entry. If that control is 0, this bit is ignored.
*/
UINT64 UserModeExecute : 1;
UINT64 Reserved3 : 1;
/**
* [Bits 47:12] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry.
*/
UINT64 PageFrameNumber : 36;
UINT64 Reserved4 : 16;
};
UINT64 Flags;
} EPT_PML4, * PEPT_PML4;
typedef union _EPDPTE_1GB
{
struct
{
/**
* [Bit 0] Read access; indicates whether reads are allowed from the 1-GByte page referenced by this entry.
*/
UINT64 ReadAccess : 1;
/**
* [Bit 1] Write access; indicates whether writes are allowed from the 1-GByte page referenced by this entry.
*/
UINT64 WriteAccess : 1;
/**
* [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether
* instruction fetches are allowed from the 1-GByte page controlled by this entry.
* If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are
* allowed from supervisor-mode linear addresses in the 1-GByte page controlled by this entry.
*/
UINT64 ExecuteAccess : 1;
/**
* [Bits 5:3] EPT memory type for this 1-GByte page.
*
* @see Vol3C[28.2.6(EPT and memory Typing)]
*/
UINT64 MemoryType : 3;
/**
* [Bit 6] Ignore PAT memory type for this 1-GByte page.
*
* @see Vol3C[28.2.6(EPT and memory Typing)]
*/
UINT64 IgnorePat : 1;
/**
* [Bit 7] Must be 1 (otherwise, this entry references an EPT page directory).
*/
UINT64 LargePage : 1;
/**
* [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 1-GByte page
* referenced by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Accessed : 1;
/**
* [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 1-GByte page referenced
* by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Dirty : 1;
/**
* [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control
* is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 1-GByte page controlled
* by this entry. If that control is 0, this bit is ignored.
*/
UINT64 UserModeExecute : 1;
UINT64 Reserved1 : 19;
/**
* [Bits 47:30] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry.
*/
UINT64 PageFrameNumber : 18;
UINT64 Reserved2 : 15;
/**
* [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this
* page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is
* 0, this bit is ignored.
*
* @see Vol3C[25.5.6.1(Convertible EPT Violations)]
*/
UINT64 SuppressVe : 1;
};
UINT64 Flags;
} EPDPTE_1GB, * PEPDPTE_1GB;
typedef union _EPDPTE
{
struct
{
/**
* [Bit 0] Read access; indicates whether reads are allowed from the 1-GByte region controlled by this entry.
*/
UINT64 ReadAccess : 1;
/**
* [Bit 1] Write access; indicates whether writes are allowed from the 1-GByte region controlled by this entry.
*/
UINT64 WriteAccess : 1;
/**
* [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether
* instruction fetches are allowed from the 1-GByte region controlled by this entry.
* If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are
* allowed from supervisor-mode linear addresses in the 1-GByte region controlled by this entry.
*/
UINT64 ExecuteAccess : 1;
UINT64 Reserved1 : 5;
/**
* [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 1-GByte region
* controlled by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Accessed : 1;
UINT64 Reserved2 : 1;
/**
* [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control
* is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 1-GByte region controlled
* by this entry. If that control is 0, this bit is ignored.
*/
UINT64 UserModeExecute : 1;
UINT64 Reserved3 : 1;
/**
* [Bits 47:12] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry.
*/
UINT64 PageFrameNumber : 36;
UINT64 Reserved4 : 16;
};
UINT64 Flags;
} EPDPTE, * PEPDPTE;
typedef union _EPDE_2MB
{
struct
{
/**
* [Bit 0] Read access; indicates whether reads are allowed from the 2-MByte page referenced by this entry.
*/
UINT64 ReadAccess : 1;
/**
* [Bit 1] Write access; indicates whether writes are allowed from the 2-MByte page referenced by this entry.
*/
UINT64 WriteAccess : 1;
/**
* [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether
* instruction fetches are allowed from the 2-MByte page controlled by this entry.
* If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are
* allowed from supervisor-mode linear addresses in the 2-MByte page controlled by this entry.
*/
UINT64 ExecuteAccess : 1;
/**
* [Bits 5:3] EPT memory type for this 2-MByte page.
*
* @see Vol3C[28.2.6(EPT and memory Typing)]
*/
UINT64 MemoryType : 3;
/**
* [Bit 6] Ignore PAT memory type for this 2-MByte page.
*
* @see Vol3C[28.2.6(EPT and memory Typing)]
*/
UINT64 IgnorePat : 1;
/**
* [Bit 7] Must be 1 (otherwise, this entry references an EPT page table).
*/
UINT64 LargePage : 1;
/**
* [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 2-MByte page
* referenced by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Accessed : 1;
/**
* [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 2-MByte page referenced
* by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Dirty : 1;
/**
* [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control
* is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 2-MByte page controlled
* by this entry. If that control is 0, this bit is ignored.
*/
UINT64 UserModeExecute : 1;
UINT64 Reserved1 : 10;
/**
* [Bits 47:21] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry.
*/
UINT64 PageFrameNumber : 27;
UINT64 Reserved2 : 15;
/**
* [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this
* page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is
* 0, this bit is ignored.
*
* @see Vol3C[25.5.6.1(Convertible EPT Violations)]
*/
UINT64 SuppressVe : 1;
};
UINT64 Flags;
} EPDE_2MB, * PEPDE_2MB;
typedef union _EPDE
{
struct
{
/**
* [Bit 0] Read access; indicates whether reads are allowed from the 2-MByte region controlled by this entry.
*/
UINT64 ReadAccess : 1;
/**
* [Bit 1] Write access; indicates whether writes are allowed from the 2-MByte region controlled by this entry.
*/
UINT64 WriteAccess : 1;
/**
* [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether
* instruction fetches are allowed from the 2-MByte region controlled by this entry.
* If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are
* allowed from supervisor-mode linear addresses in the 2-MByte region controlled by this entry.
*/
UINT64 ExecuteAccess : 1;
UINT64 Reserved1 : 5;
/**
* [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 2-MByte region
* controlled by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Accessed : 1;
UINT64 Reserved2 : 1;
/**
* [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control
* is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 2-MByte region controlled
* by this entry. If that control is 0, this bit is ignored.
*/
UINT64 UserModeExecute : 1;
UINT64 Reserved3 : 1;
/**
* [Bits 47:12] Physical address of 4-KByte aligned EPT page table referenced by this entry.
*/
UINT64 PageFrameNumber : 36;
UINT64 Reserved4 : 16;
};
UINT64 Flags;
} EPDE, * PEPDE;
typedef union _EPTE
{
struct
{
/**
* [Bit 0] Read access; indicates whether reads are allowed from the 4-KByte page referenced by this entry.
*/
UINT64 ReadAccess : 1;
/**
* [Bit 1] Write access; indicates whether writes are allowed from the 4-KByte page referenced by this entry.
*/
UINT64 WriteAccess : 1;
/**
* [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether
* instruction fetches are allowed from the 4-KByte page controlled by this entry.
* If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are
* allowed from supervisor-mode linear addresses in the 4-KByte page controlled by this entry.
*/
UINT64 ExecuteAccess : 1;
/**
* [Bits 5:3] EPT memory type for this 4-KByte page.
*
* @see Vol3C[28.2.6(EPT and memory Typing)]
*/
UINT64 MemoryType : 3;
/**
* [Bit 6] Ignore PAT memory type for this 4-KByte page.
*
* @see Vol3C[28.2.6(EPT and memory Typing)]
*/
UINT64 IgnorePat : 1;
UINT64 Reserved1 : 1;
/**
* [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 4-KByte page
* referenced by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Accessed : 1;
/**
* [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 4-KByte page referenced
* by this entry. Ignored if bit 6 of EPTP is 0.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 Dirty : 1;
/**
* [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control
* is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 4-KByte page controlled
* by this entry. If that control is 0, this bit is ignored.
*/
UINT64 UserModeExecute : 1;
UINT64 Reserved2 : 1;
/**
* [Bits 47:12] Physical address of the 4-KByte page referenced by this entry.
*/
UINT64 PageFrameNumber : 36;
UINT64 Reserved3 : 15;
/**
* [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this
* page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is
* 0, this bit is ignored.
*
* @see Vol3C[25.5.6.1(Convertible EPT Violations)]
*/
UINT64 SuppressVe : 1;
};
UINT64 Flags;
} EPTE, * PEPTE;
typedef EPT_PML4 EPT_PML4_POINTER, * PEPT_PML4_POINTER;
typedef EPDPTE EPT_PML3_POINTER, * PEPT_PML3_POINTER;
typedef EPDE_2MB EPT_PML2_ENTRY, * PEPT_PML2_ENTRY;
typedef EPDE EPT_PML2_POINTER, * PEPT_PML2_POINTER;
typedef EPTE EPT_PML1_ENTRY, * PEPT_PML1_ENTRY;
typedef struct _VMM_EPT_PAGE_TABLE
{
DECLSPEC_ALIGN(PAGE_SIZE) EPT_PML4_POINTER PML4[VMM_EPT_PML4E_COUNT];
DECLSPEC_ALIGN(PAGE_SIZE) EPT_PML3_POINTER PML3[VMM_EPT_PML3E_COUNT];
DECLSPEC_ALIGN(PAGE_SIZE) EPT_PML2_ENTRY PML2[VMM_EPT_PML3E_COUNT][VMM_EPT_PML2E_COUNT];
} VMM_EPT_PAGE_TABLE, * PVMM_EPT_PAGE_TABLE;
typedef struct _VMM_EPT_DYNAMIC_SPLIT
{
DECLSPEC_ALIGN(PAGE_SIZE) EPT_PML1_ENTRY PML1[VMM_EPT_PML1E_COUNT];
union
{
PEPT_PML2_ENTRY Entry;
PEPT_PML2_POINTER Pointer;
};
} VMM_EPT_DYNAMIC_SPLIT, * PVMM_EPT_DYNAMIC_SPLIT;
typedef struct _MTRR_RANGE_DESCRIPTOR
{
SIZE_T PhysicalBaseAddress;
SIZE_T PhysicalEndAddress;
UCHAR MemoryType;
bool FixedRange;
} MTRR_RANGE_DESCRIPTOR, * PMTRR_RANGE_DESCRIPTOR;
typedef union _IA32_VMX_EPT_VPID_CAP_REGISTER
{
struct
{
/**
* [Bit 0] When set to 1, the processor supports execute-only translations by EPT. This support allows software to
* configure EPT paging-structure entries in which bits 1:0 are clear (indicating that data accesses are not allowed) and
* bit 2 is set (indicating that instruction fetches are allowed).
*/
UINT64 ExecuteOnlyPages : 1;
UINT64 Reserved1 : 5;
/**
* [Bit 6] Indicates support for a page-walk length of 4.
*/
UINT64 PageWalkLength4 : 1;
UINT64 Reserved2 : 1;
/**
* [Bit 8] When set to 1, the logical processor allows software to configure the EPT paging-structure memory type to be
* uncacheable (UC).
*
* @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP))]
*/
UINT64 MemoryTypeUncacheable : 1;
UINT64 Reserved3 : 5;
/**
* [Bit 14] When set to 1, the logical processor allows software to configure the EPT paging-structure memory type to be
* write-back (WB).
*/
UINT64 MemoryTypeWriteBack : 1;
UINT64 Reserved4 : 1;
/**
* [Bit 16] When set to 1, the logical processor allows software to configure a EPT PDE to map a 2-Mbyte page (by setting
* bit 7 in the EPT PDE).
*/
UINT64 Pde2MbPages : 1;
/**
* [Bit 17] When set to 1, the logical processor allows software to configure a EPT PDPTE to map a 1-Gbyte page (by setting
* bit 7 in the EPT PDPTE).
*/
UINT64 Pdpte1GbPages : 1;
UINT64 Reserved5 : 2;
/**
* [Bit 20] If bit 20 is read as 1, the INVEPT instruction is supported.
*
* @see Vol3C[30(VMX INSTRUCTION REFERENCE)]
* @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)]
*/
UINT64 Invept : 1;
/**
* [Bit 21] When set to 1, accessed and dirty flags for EPT are supported.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 EptAccessedAndDirtyFlags : 1;
/**
* [Bit 22] When set to 1, the processor reports advanced VM-exit information for EPT violations. This reporting is done
* only if this bit is read as 1.
*
* @see Vol3C[27.2.1(Basic VM-Exit Information)]
*/
UINT64 AdvancedVmexitEptViolationsInformation : 1;
UINT64 Reserved6 : 2;
/**
* [Bit 25] When set to 1, the single-context INVEPT type is supported.
*
* @see Vol3C[30(VMX INSTRUCTION REFERENCE)]
* @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)]
*/
UINT64 InveptSingleContext : 1;
/**
* [Bit 26] When set to 1, the all-context INVEPT type is supported.
*
* @see Vol3C[30(VMX INSTRUCTION REFERENCE)]
* @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)]
*/
UINT64 InveptAllContexts : 1;
UINT64 Reserved7 : 5;
/**
* [Bit 32] When set to 1, the INVVPID instruction is supported.
*/
UINT64 Invvpid : 1;
UINT64 Reserved8 : 7;
/**
* [Bit 40] When set to 1, the individual-address INVVPID type is supported.
*/
UINT64 InvvpidIndividualAddress : 1;
/**
* [Bit 41] When set to 1, the single-context INVVPID type is supported.
*/
UINT64 InvvpidSingleContext : 1;
/**
* [Bit 42] When set to 1, the all-context INVVPID type is supported.
*/
UINT64 InvvpidAllContexts : 1;
/**
* [Bit 43] When set to 1, the single-context-retaining-globals INVVPID type is supported.
*/
UINT64 InvvpidSingleContextRetainGlobals : 1;
UINT64 Reserved9 : 20;
};
UINT64 Flags;
} IA32_VMX_EPT_VPID_CAP_REGISTER, * PIA32_VMX_EPT_VPID_CAP_REGISTER;
// MSR_IA32_MTRR_DEF_TYPE
typedef union
{
struct
{
/**
* [Bits 2:0] Default Memory Type.
*/
UINT64 DefaultMemoryType : 3;
#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_BIT 0
#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_FLAG 0x07
#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_MASK 0x07
#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE(_) (((_) >> 0) & 0x07)
UINT64 Reserved1 : 7;
/**
* [Bit 10] Fixed Range MTRR Enable.
*/
UINT64 FixedRangeMtrrEnable : 1;
#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_BIT 10
#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_FLAG 0x400
#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_MASK 0x01
#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE(_) (((_) >> 10) & 0x01)
/**
* [Bit 11] MTRR Enable.
*/
UINT64 MtrrEnable : 1;
#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_BIT 11
#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_FLAG 0x800
#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_MASK 0x01
#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE(_) (((_) >> 11) & 0x01)
UINT64 Reserved2 : 52;
};
UINT64 Flags;
} IA32_MTRR_DEF_TYPE_REGISTER;
typedef union _IA32_FEATURE_CONTROL_MSR
{
ULONG64 All;
struct
{
ULONG64 Lock : 1;
ULONG64 EnableSMX : 1;
ULONG64 EnableVmxon : 1;
ULONG64 Reserved2 : 5;
ULONG64 EnableLocalSENTER : 7;
ULONG64 EnableGlobalSENTER : 1;
ULONG64 Reserved3a : 16;
ULONG64 Reserved3b : 32;
} Fields;
} IA32_FEATURE_CONTROL_MSR, * PIA32_FEATURE_CONTROL_MSR;
typedef struct _CPUID {
int eax;
int ebx;
int ecx;
int edx;
} CPUID, * PCPUID;
typedef union _IA32_VMX_BASIC_MSR
{
ULONG64 All;
struct
{
ULONG32 RevisionIdentifier : 31; // [0-30]
ULONG32 Reserved1 : 1; // [31]
ULONG32 RegionSize : 12; // [32-43]
ULONG32 RegionClear : 1; // [44]
ULONG32 Reserved2 : 3; // [45-47]
ULONG32 SupportedIA64 : 1; // [48]
ULONG32 SupportedDualMoniter : 1; // [49]
ULONG32 MemoryType : 4; // [50-53]
ULONG32 VmExitReport : 1; // [54]
ULONG32 VmxCapabilityHint : 1; // [55]
ULONG32 Reserved3 : 8; // [56-63]
} Fields;
} IA32_VMX_BASIC_MSR, * PIA32_VMX_BASIC_MSR;
typedef union _EPTP
{
struct
{
/**
* [Bits 2:0] EPT paging-structure memory type:
* - 0 = Uncacheable (UC)
* - 6 = Write-back (WB)
* Other values are reserved.
*
* @see Vol3C[28.2.6(EPT and memory Typing)]
*/
UINT64 MemoryType : 3;
/**
* [Bits 5:3] This value is 1 less than the EPT page-walk length.
*
* @see Vol3C[28.2.6(EPT and memory Typing)]
*/
UINT64 PageWalkLength : 3;
/**
* [Bit 6] Setting this control to 1 enables accessed and dirty flags for EPT.
*
* @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)]
*/
UINT64 EnableAccessAndDirtyFlags : 1;
UINT64 Reserved1 : 5;
/**
* [Bits 47:12] Bits N-1:12 of the physical address of the 4-KByte aligned EPT PML4 table.
*/
UINT64 PageFrameNumber : 36;
UINT64 Reserved2 : 16;
};
UINT64 Flags;
} EPTP, * PEPTP;
typedef union _VMX_EXIT_QUALIFICATION_EPT_VIOLATION
{
struct
{
UINT64 ReadAccess : 1;
UINT64 WriteAccess : 1;
UINT64 ExecuteAccess : 1;
UINT64 EptReadable : 1;
UINT64 EptWriteable : 1;
UINT64 EptExecutable : 1;
UINT64 EptExecutableForUserMode : 1;
UINT64 ValidGuestLinearAddress : 1;
UINT64 CausedByTranslation : 1;
UINT64 UserModeLinearAddress : 1;
UINT64 ReadableWritablePage : 1;
UINT64 ExecuteDisablePage : 1;
UINT64 NmiUnblocking : 1;
UINT64 Reserved1 : 51;
};
UINT64 Flags;
} VMX_EXIT_QUALIFICATION_EPT_VIOLATION, * PVMX_EXIT_QUALIFICATION_EPT_VIOLATION;
//
// See Table 28-1.
//
typedef union _EPT_PML4E
{
ULONG64 All;
struct
{
UINT64 Read : 1; // bit 0
UINT64 Write : 1; // bit 1
UINT64 Execute : 1; // bit 2
UINT64 Reserved1 : 5; // bit 7:3 (Must be Zero)
UINT64 Accessed : 1; // bit 8
UINT64 Ignored1 : 1; // bit 9
UINT64 ExecuteForUserMode : 1; // bit 10
UINT64 Ignored2 : 1; // bit 11
UINT64 PhysicalAddress : 36; // bit (N-1):12 or Page-Frame-Number
UINT64 Reserved2 : 4; // bit 51:N
UINT64 Ignored3 : 12; // bit 63:52
} Fields;
} EPT_PML4E, * PEPT_PML4E;
//
// See Table 28-3
//
typedef union _EPT_PDPTE
{
ULONG64 All;
struct
{
UINT64 Read : 1; // bit 0
UINT64 Write : 1; // bit 1
UINT64 Execute : 1; // bit 2
UINT64 Reserved1 : 5; // bit 7:3 (Must be Zero)
UINT64 Accessed : 1; // bit 8
UINT64 Ignored1 : 1; // bit 9
UINT64 ExecuteForUserMode : 1; // bit 10
UINT64 Ignored2 : 1; // bit 11
UINT64 PhysicalAddress : 36; // bit (N-1):12 or Page-Frame-Number
UINT64 Reserved2 : 4; // bit 51:N
UINT64 Ignored3 : 12; // bit 63:52
} Fields;
} EPT_PDPTE, * PEPT_PDPTE;
//
// See Table 28-5
//
typedef union _EPT_PDE
{
ULONG64 All;
struct
{
UINT64 Read : 1; // bit 0
UINT64 Write : 1; // bit 1
UINT64 Execute : 1; // bit 2
UINT64 Reserved1 : 5; // bit 7:3 (Must be Zero)
UINT64 Accessed : 1; // bit 8
UINT64 Ignored1 : 1; // bit 9
UINT64 ExecuteForUserMode : 1; // bit 10
UINT64 Ignored2 : 1; // bit 11
UINT64 PhysicalAddress : 36; // bit (N-1):12 or Page-Frame-Number
UINT64 Reserved2 : 4; // bit 51:N
UINT64 Ignored3 : 12; // bit 63:52
} Fields;
} EPT_PDE, * PEPT_PDE;
//
// See Table 28-6
//
typedef union _EPT_PTE
{
ULONG64 All;
struct
{
UINT64 Read : 1; // bit 0
UINT64 Write : 1; // bit 1
UINT64 Execute : 1; // bit 2
UINT64 EPTMemoryType : 3; // bit 5:3 (EPT Memory type)
UINT64 IgnorePAT : 1; // bit 6
UINT64 Ignored1 : 1; // bit 7
UINT64 AccessedFlag : 1; // bit 8
UINT64 DirtyFlag : 1; // bit 9
UINT64 ExecuteForUserMode : 1; // bit 10
UINT64 Ignored2 : 1; // bit 11
UINT64 PhysicalAddress : 36; // bit (N-1):12 or Page-Frame-Number
UINT64 Reserved : 4; // bit 51:N
UINT64 Ignored3 : 11; // bit 62:52
UINT64 SuppressVE : 1; // bit 63
} Fields;
} EPT_PTE, * PEPT_PTE;
typedef union _IA32_MTRR_CAPABILITIES_REGISTER
{
struct
{
UINT64 VariableRangeCount : 8;
UINT64 FixedRangeSupported : 1;
UINT64 Reserved1 : 1;
UINT64 WcSupported : 1;
UINT64 SmrrSupported : 1;
UINT64 Reserved2 : 52;
};
UINT64 Flags;
} IA32_MTRR_CAPABILITIES_REGISTER, * PIA32_MTRR_CAPABILITIES_REGISTER;
// MSR_IA32_MTRR_PHYSBASE(0-9)
typedef union _IA32_MTRR_PHYSBASE_REGISTER
{
struct
{
UINT64 Type : 8;
UINT64 Reserved1 : 4;
UINT64 PageFrameNumber : 36;
UINT64 Reserved2 : 16;
};
UINT64 Flags;
} IA32_MTRR_PHYSBASE_REGISTER, * PIA32_MTRR_PHYSBASE_REGISTER;
typedef union _IA32_MTRR_PHYSMASK_REGISTER
{
struct
{
UINT64 Type : 8;
UINT64 Reserved1 : 3;
UINT64 Valid : 1;
UINT64 PageFrameNumber : 36;
UINT64 Reserved2 : 16;
};
UINT64 Flags;
} IA32_MTRR_PHYSMASK_REGISTER, * PIA32_MTRR_PHYSMASK_REGISTER;
enum INVEPT_TYPE
{
SINGLE_CONTEXT = 0x00000001,
ALL_CONTEXTS = 0x00000002,
};
enum VMCS_FIELDS
{
VIRTUAL_PROCESSOR_ID = 0x00000000,
GUEST_ES_SELECTOR = 0x00000800,
GUEST_CS_SELECTOR = 0x00000802,
GUEST_SS_SELECTOR = 0x00000804,
GUEST_DS_SELECTOR = 0x00000806,
GUEST_FS_SELECTOR = 0x00000808,
GUEST_GS_SELECTOR = 0x0000080a,
GUEST_LDTR_SELECTOR = 0x0000080c,
GUEST_TR_SELECTOR = 0x0000080e,
HOST_ES_SELECTOR = 0x00000c00,
HOST_CS_SELECTOR = 0x00000c02,
HOST_SS_SELECTOR = 0x00000c04,
HOST_DS_SELECTOR = 0x00000c06,
HOST_FS_SELECTOR = 0x00000c08,
HOST_GS_SELECTOR = 0x00000c0a,
HOST_TR_SELECTOR = 0x00000c0c,
IO_BITMAP_A = 0x00002000,
IO_BITMAP_A_HIGH = 0x00002001,
IO_BITMAP_B = 0x00002002,
IO_BITMAP_B_HIGH = 0x00002003,
MSR_BITMAP = 0x00002004,
MSR_BITMAP_HIGH = 0x00002005,
VM_EXIT_MSR_STORE_ADDR = 0x00002006,
VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,
VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,
VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,
TSC_OFFSET = 0x00002010,
TSC_OFFSET_HIGH = 0x00002011,
VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
VMFUNC_CONTROLS = 0x00002018,
VMFUNC_CONTROLS_HIGH = 0x00002019,
EPT_POINTER = 0x0000201A,
EPT_POINTER_HIGH = 0x0000201B,
EPTP_LIST = 0x00002024,
EPTP_LIST_HIGH = 0x00002025,
GUEST_PHYSICAL_ADDRESS = 0x2400,
GUEST_PHYSICAL_ADDRESS_HIGH = 0x2401,
VMCS_LINK_POINTER = 0x00002800,
VMCS_LINK_POINTER_HIGH = 0x00002801,
GUEST_IA32_DEBUGCTL = 0x00002802,
GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
GUEST_IA32_PAT = 0x00002804,
GUEST_IA32_PAT_HIGH = 0x00002805,
GUEST_IA32_EFER = 0x00002806,
GUEST_IA32_EFER_HIGH = 0x00002807,
HOST_IA32_PAT = 0x00002c00,
HOST_IA32_PAT_HIGH = 0x00002c01,
HOST_IA32_EFER = 0x00002c02,
HOST_IA32_EFER_HIGH = 0x00002c03,
PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
EXCEPTION_BITMAP = 0x00004004,
PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
CR3_TARGET_COUNT = 0x0000400a,
VM_EXIT_CONTROLS = 0x0000400c,
VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
VM_ENTRY_CONTROLS = 0x00004012,
VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
TPR_THRESHOLD = 0x0000401c,
SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
VM_INSTRUCTION_ERROR = 0x00004400,
VM_EXIT_REASON = 0x00004402,
VM_EXIT_INTR_INFO = 0x00004404,
VM_EXIT_INTR_ERROR_CODE = 0x00004406,
IDT_VECTORING_INFO_FIELD = 0x00004408,
IDT_VECTORING_ERROR_CODE = 0x0000440a,
VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
VMX_INSTRUCTION_INFO = 0x0000440e,
GUEST_ES_LIMIT = 0x00004800,
GUEST_CS_LIMIT = 0x00004802,
GUEST_SS_LIMIT = 0x00004804,
GUEST_DS_LIMIT = 0x00004806,
GUEST_FS_LIMIT = 0x00004808,
GUEST_GS_LIMIT = 0x0000480a,
GUEST_LDTR_LIMIT = 0x0000480c,
GUEST_TR_LIMIT = 0x0000480e,
GUEST_GDTR_LIMIT = 0x00004810,
GUEST_IDTR_LIMIT = 0x00004812,
GUEST_ES_AR_BYTES = 0x00004814,
GUEST_CS_AR_BYTES = 0x00004816,
GUEST_SS_AR_BYTES = 0x00004818,
GUEST_DS_AR_BYTES = 0x0000481a,
GUEST_FS_AR_BYTES = 0x0000481c,
GUEST_GS_AR_BYTES = 0x0000481e,
GUEST_LDTR_AR_BYTES = 0x00004820,
GUEST_TR_AR_BYTES = 0x00004822,
GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
GUEST_ACTIVITY_STATE = 0x00004826,
GUEST_SM_BASE = 0x00004828,
GUEST_SYSENTER_CS = 0x0000482A,
HOST_IA32_SYSENTER_CS = 0x00004c00,
CR0_GUEST_HOST_MASK = 0x00006000,
CR4_GUEST_HOST_MASK = 0x00006002,
CR0_READ_SHADOW = 0x00006004,
CR4_READ_SHADOW = 0x00006006,
CR3_TARGET_VALUE0 = 0x00006008,
CR3_TARGET_VALUE1 = 0x0000600a,
CR3_TARGET_VALUE2 = 0x0000600c,
CR3_TARGET_VALUE3 = 0x0000600e,
EXIT_QUALIFICATION = 0x00006400,
GUEST_LINEAR_ADDRESS = 0x0000640a,
GUEST_CR0 = 0x00006800,
GUEST_CR3 = 0x00006802,
GUEST_CR4 = 0x00006804,
GUEST_ES_BASE = 0x00006806,
GUEST_CS_BASE = 0x00006808,
GUEST_SS_BASE = 0x0000680a,
GUEST_DS_BASE = 0x0000680c,
GUEST_FS_BASE = 0x0000680e,
GUEST_GS_BASE = 0x00006810,
GUEST_LDTR_BASE = 0x00006812,
GUEST_TR_BASE = 0x00006814,
GUEST_GDTR_BASE = 0x00006816,
GUEST_IDTR_BASE = 0x00006818,
GUEST_DR7 = 0x0000681a,
GUEST_RSP = 0x0000681c,
GUEST_RIP = 0x0000681e,
GUEST_RFLAGS = 0x00006820,
GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
GUEST_SYSENTER_ESP = 0x00006824,
GUEST_SYSENTER_EIP = 0x00006826,
HOST_CR0 = 0x00006c00,
HOST_CR3 = 0x00006c02,
HOST_CR4 = 0x00006c04,
HOST_FS_BASE = 0x00006c06,
HOST_GS_BASE = 0x00006c08,
HOST_TR_BASE = 0x00006c0a,
HOST_GDTR_BASE = 0x00006c0c,
HOST_IDTR_BASE = 0x00006c0e,
HOST_IA32_SYSENTER_ESP = 0x00006c10,
HOST_IA32_SYSENTER_EIP = 0x00006c12,
HOST_RSP = 0x00006c14,
HOST_RIP = 0x00006c16,
};
typedef struct _INVEPT_DESCRIPTOR
{
UINT64 EptPointer;
UINT64 Reserved; // Must be zero.
} INVEPT_DESCRIPTOR, * PINVEPT_DESCRIPTOR;
typedef struct _INVEPT_DESC
{
EPTP EptPointer;
UINT64 Reserveds;
}INVEPT_DESC, * PINVEPT_DESC;
typedef enum _InvvpidType
{
InvvpidIndividualAddress = 0x00000000,
InvvpidSingleContext = 0x00000001,
InvvpidAllContext = 0x00000002,
InvvpidSingleContextRetainingGlobals = 0x00000003
} InvvpidType;
typedef struct _INVVPID_DESCRIPTOR {
UINT64 Vpid : 16;
UINT64 Reserved : 48;
UINT64 LinearAddress;
} INVVPID_DESCRIPTOR, * PINVVPID_DESCRIPTOR;
typedef struct _GUEST_REGS
{
ULONG64 rax; // 0x00
ULONG64 rcx;
ULONG64 rdx; // 0x10
ULONG64 rbx;
ULONG64 rsp; // 0x20 // rsp is not stored here
ULONG64 rbp;
ULONG64 rsi; // 0x30
ULONG64 rdi;
ULONG64 r8; // 0x40
ULONG64 r9;
ULONG64 r10; // 0x50
ULONG64 r11;
ULONG64 r12; // 0x60
ULONG64 r13;
ULONG64 r14; // 0x70
ULONG64 r15;
} GUEST_REGS, * PGUEST_REGS;
typedef union SEGMENT_ATTRIBUTES
{
USHORT UCHARs;
struct
{
USHORT TYPE : 4; /* 0; Bit 40-43 */
USHORT S : 1; /* 4; Bit 44 */
USHORT DPL : 2; /* 5; Bit 45-46 */
USHORT P : 1; /* 7; Bit 47 */
USHORT AVL : 1; /* 8; Bit 52 */
USHORT L : 1; /* 9; Bit 53 */
USHORT DB : 1; /* 10; Bit 54 */
USHORT G : 1; /* 11; Bit 55 */
USHORT GAP : 4;
} Fields;
} SEGMENT_ATTRIBUTES;
typedef struct SEGMENT_SELECTOR
{
USHORT SEL;
SEGMENT_ATTRIBUTES ATTRIBUTES;
ULONG32 LIMIT;
ULONG64 BASE;
} SEGMENT_SELECTOR, * PSEGMENT_SELECTOR;
typedef struct _SEGMENT_DESCRIPTOR {
USHORT LIMIT0;
USHORT BASE0;
UCHAR BASE1;
UCHAR ATTR0;
UCHAR LIMIT1ATTR1;
UCHAR BASE2;
} SEGMENT_DESCRIPTOR, * PSEGMENT_DESCRIPTOR;
enum SEGREGS
{
ES = 0,
CS,
SS,
DS,
FS,
GS,
LDTR,
TR
};
typedef union _MSR
{
struct
{
ULONG Low;
ULONG High;
};
ULONG64 Content;
} MSR, * PMSR;
typedef union _IA32_MTRR_FIXED_RANGE_TYPE
{
UINT64 All;
struct
{
UINT8 Types[8];
} s;
} IA32_MTRR_FIXED_RANGE_TYPE;
constexpr SIZE_T MAX_VARIABLE_RANGE_MTRRS = 255;
constexpr SIZE_T FIXED_RANGE_MTRRS_SIZE = ((1 + 2 + 8) * RTL_NUMBER_OF_FIELD(IA32_MTRR_FIXED_RANGE_TYPE, s.Types));
constexpr SIZE_T MTRR_ENTRIES_SIZE = MAX_VARIABLE_RANGE_MTRRS + FIXED_RANGE_MTRRS_SIZE;
typedef union _MOV_CR_QUALIFICATION
{
ULONG_PTR All;
struct
{
ULONG ControlRegister : 4;
ULONG AccessType : 2;
ULONG LMSWOperandType : 1;
ULONG Reserved1 : 1;
ULONG Register : 4;
ULONG Reserved2 : 4;
ULONG LMSWSourceData : 16;
ULONG Reserved3;
} Fields;
} MOV_CR_QUALIFICATION, * PMOV_CR_QUALIFICATION;
typedef struct _EPT_HOOKED_PAGE_DETAIL {
LIST_ENTRY Entry;
UINT64 VirtualAddress;
UINT64 PhysicalAddress;
UINT64 PhysicalBaseAddress;
PEPT_PML1_ENTRY EntryAddress;
EPT_PML1_ENTRY OriginalEntry;
EPT_PML1_ENTRY ChangedEntry;
PCHAR InlineHook;
bool IsExecutionHook;
} EPT_HOOKED_PAGE_DETAIL, * PEPT_HOOKED_PAGE_DETAIL;
typedef struct {
UINT8 Permissions;
UINT64 Address;
} HookedPage;
typedef union _HYPERCALL_INPUT_VALUE
{
UINT64 Flags;
struct
{
UINT64 CallCode : 16; // HYPERCALL_CODE
UINT64 Fast : 1;
UINT64 VariableHeaderSize : 9;
UINT64 IsNested : 1;
UINT64 Reserved0 : 5;
UINT64 RepCount : 12;
UINT64 Reserved1 : 4;
UINT64 RepStartIndex : 12;
UINT64 Reserved2 : 4;
} Fields;
} HYPERCALL_INPUT_VALUE, * PHYPERCALL_INPUT_VALUE;
enum HYPERCALL_CODE
{
HvSwitchVirtualAddressSpace = 0x0001,
HvFlushVirtualAddressSpace = 0x0002,
HvFlushVirtualAddressList = 0x0003,
HvGetLogicalProcessorRunTime = 0x0004,
// 0x0005..0x0007 are reserved
HvCallNotifyLongSpinWait = 0x0008,
HvCallParkedVirtualProcessors = 0x0009,
HvCallSyntheticClusterIpi = 0x000B,
HvCallModifyVtlProtectionMask = 0x000C,
HvCallEnablePartitionVtl = 0x000D,
HvCallDisablePartitionVtl = 0x000E,
HvCallEnableVpVtl = 0x000F,
HvCallDisableVpVtl = 0x0010,
HvCallVtlCall = 0x0011,
HvCallVtlReturn = 0x0012,
HvCallFlushVirtualAddressSpaceEx = 0x0013,
HvCallFlushVirtualAddressListEx = 0x0014,
HvCallSendSyntheticClusterIpiEx = 0x0015,
// 0x0016..0x003F are reserved
HvCreatePartition = 0x0040,
HvInitializePartition = 0x0041,
HvFinalizePartition = 0x0042,
HvDeletePartition = 0x0043,
HvGetPartitionProperty = 0x0044,
HvSetPartitionProperty = 0x0045,
HvGetPartitionId = 0x0046,
HvGetNextChildPartition = 0x0047,
HvDepositMemory = 0x0048,
HvWithdrawMemory = 0x0049,
HvGetMemoryBalance = 0x004A,
HvMapGpaPages = 0x004B,
HvUnmapGpaPages = 0x004C,
HvInstallIntercept = 0x004D,
HvCreateVp = 0x004E,
HvDeleteVp = 0x004F,
HvGetVpRegisters = 0x0050,
HvSetVpRegisters = 0x0051,
HvTranslateVirtualAddress = 0x0052,
HvReadGpa = 0x0053,
HvWriteGpa = 0x0054,
// 0x0055 is deprecated
HvClearVirtualInterrupt = 0x0056,
// 0x0057 is deprecated
HvDeletePort = 0x0058,
HvConnectPort = 0x0059,
HvGetPortProperty = 0x005A,
HvDisconnectPort = 0x005B,
HvPostMessage = 0x005C,
HvSignalEvent = 0x005D,
HvSavePartitionState = 0x005E,
HvRestorePartitionState = 0x005F,
HvInitializeEventLogBufferGroup = 0x0060,
HvFinalizeEventLogBufferGroup = 0x0061,
HvCreateEventLogBuffer = 0x0062,
HvDeleteEventLogBuffer = 0x0063,
HvMapEventLogBuffer = 0x0064,
HvUnmapEventLogBuffer = 0x0065,
HvSetEventLogGroupSources = 0x0066,
HvReleaseEventLogBuffer = 0x0067,
HvFlushEventLogBuffer = 0x0068,
HvPostDebugData = 0x0069,
HvRetrieveDebugData = 0x006A,
HvResetDebugSession = 0x006B,
HvMapStatsPage = 0x006C,
HvUnmapStatsPage = 0x006D,
HvCallMapSparseGpaPages = 0x006E,
HvCallSetSystemProperty = 0x006F,
HvCallSetPortProperty = 0x0070,
// 0x0071..0x0075 are reserved
HvCallAddLogicalProcessor = 0x0076,
HvCallRemoveLogicalProcessor = 0x0077,
HvCallQueryNumaDistance = 0x0078,
HvCallSetLogicalProcessorProperty = 0x0079,
HvCallGetLogicalProcessorProperty = 0x007A,
HvCallGetSystemProperty = 0x007B,
HvCallMapDeviceInterrupt = 0x007C,
HvCallUnmapDeviceInterrupt = 0x007D,
HvCallRetargetDeviceInterrupt = 0x007E,
// 0x007F is reserved
HvCallMapDevicePages = 0x0080,
HvCallUnmapDevicePages = 0x0081,
HvCallAttachDevice = 0x0082,
HvCallDetachDevice = 0x0083,
HvCallNotifyStandbyTransition = 0x0084,
HvCallPrepareForSleep = 0x0085,
HvCallPrepareForHibernate = 0x0086,
HvCallNotifyPartitionEvent = 0x0087,
HvCallGetLogicalProcessorRegisters = 0x0088,
HvCallSetLogicalProcessorRegisters = 0x0089,
HvCallQueryAssotiatedLpsforMca = 0x008A,
HvCallNotifyRingEmpty = 0x008B,
HvCallInjectSyntheticMachineCheck = 0x008C,
HvCallScrubPartition = 0x008D,
HvCallCollectLivedump = 0x008E,
HvCallDisableHypervisor = 0x008F,
HvCallModifySparseGpaPages = 0x0090,
HvCallRegisterInterceptResult = 0x0091,
HvCallUnregisterInterceptResult = 0x0092,
HvCallAssertVirtualInterrupt = 0x0094,
HvCallCreatePort = 0x0095,
HvCallConnectPort = 0x0096,
HvCallGetSpaPageList = 0x0097,
// 0x0098 is reserved
HvCallStartVirtualProcessor = 0x009A,
HvCallGetVpIndexFromApicId = 0x009A,
// 0x009A..0x00AE are reserved
HvCallFlushGuestPhysicalAddressSpace = 0x00AF,
HvCallFlushGuestPhysicalAddressList = 0x00B0
};
#pragma warning(pop)