#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)