diff --git a/bluepill.vcxproj b/bluepill.vcxproj
index 9555dbd..e62f178 100644
--- a/bluepill.vcxproj
+++ b/bluepill.vcxproj
@@ -56,6 +56,8 @@
+
+
@@ -63,6 +65,7 @@
+
diff --git a/bluepill.vcxproj.filters b/bluepill.vcxproj.filters
index 816cf7c..85c041b 100644
--- a/bluepill.vcxproj.filters
+++ b/bluepill.vcxproj.filters
@@ -23,6 +23,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -43,6 +49,9 @@
Header Files
+
+ Header Files
+
diff --git a/entry.cpp b/entry.cpp
index 44698fd..564ad15 100644
--- a/entry.cpp
+++ b/entry.cpp
@@ -53,7 +53,7 @@ auto driver_entry(
KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::init_vmcs, NULL);
// vmxlaunch for all cores...
- // KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL);
+ KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL);
driver_object->DriverUnload = &driver_unload;
return STATUS_SUCCESS;
diff --git a/exit_handler.cpp b/exit_handler.cpp
index a3d9ebc..40ac66d 100644
--- a/exit_handler.cpp
+++ b/exit_handler.cpp
@@ -19,6 +19,6 @@ auto exit_handler(hv::pguest_registers regs) -> void
case VMX_EXIT_REASON_EXECUTE_VMCLEAR:
case VMX_EXIT_REASON_EXECUTE_RDTSC:
default:
- __vmx_off();
+ break;
}
}
\ No newline at end of file
diff --git a/hv_types.hpp b/hv_types.hpp
index 21e7e09..3fb6156 100644
--- a/hv_types.hpp
+++ b/hv_types.hpp
@@ -14,6 +14,11 @@ using s16 = short;
using s32 = int;
using s64 = long long;
+// didnt find it in intrin.h... ?
+extern "C" void _sgdt(void*);
+#pragma intrinsic(_sgdt);
+
+
#define DBG_PRINT(...) DbgPrintEx( DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, "[hv]" __VA_ARGS__)
#define HOST_STACK_PAGES 6
@@ -378,4 +383,11 @@ namespace hv
u32 vcpu_num;
pvcpu_ctx* vcpus;
} vmx_ctx, *pvmx_ctx;
+
+ typedef struct _segment_info_ctx
+ {
+ vmx_segment_access_rights rights;
+ u64 limit;
+ u64 base_addr;
+ } segment_info_ctx, *psegment_info_ctx;
}
\ No newline at end of file
diff --git a/ia32.hpp b/ia32.hpp
index 39d6427..80c01f6 100644
--- a/ia32.hpp
+++ b/ia32.hpp
@@ -9936,6 +9936,7 @@ typedef union
#define IA32_VMX_BASIC 0x00000480
typedef union
{
+ uint64_t flags;
struct
{
/**
@@ -10054,8 +10055,6 @@ typedef union
#define IA32_VMX_BASIC_VMX_CONTROLS(_) (((_) >> 55) & 0x01)
uint64_t reserved2 : 8;
};
-
- uint64_t flags;
} ia32_vmx_basic_register;
@@ -10069,6 +10068,7 @@ typedef union
#define IA32_VMX_PINBASED_CTLS 0x00000481
typedef union
{
+ uint64_t flags;
struct
{
/**
@@ -10144,8 +10144,6 @@ typedef union
#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS(_) (((_) >> 7) & 0x01)
uint64_t reserved3 : 56;
};
-
- uint64_t flags;
} ia32_vmx_pinbased_ctls_register;
@@ -15458,7 +15456,7 @@ typedef struct
* [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details.
*/
uint32_t base_address_middle : 8;
-#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 0
+#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 16
#define SEGMENT__BASE_ADDRESS_MIDDLE_FLAG 0xFF
#define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF
#define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 0xFF)
@@ -15611,6 +15609,7 @@ typedef struct
* Base address field (32:63); see description of $BASE_LOW for more details.
*/
uint32_t base_address_upper;
+#define SEGMENT__BASE_ADDRESS_SHIFT 32
/**
* Base address field (32:63); see description of $BASE_LOW for more details.
@@ -15844,6 +15843,8 @@ typedef struct
*/
typedef union
{
+ uint16_t flags;
+
struct
{
/**
@@ -15879,8 +15880,6 @@ typedef union
#define SEGMENT_SELECTOR_INDEX_MASK 0x1FFF
#define SEGMENT_SELECTOR_INDEX(_) (((_) >> 3) & 0x1FFF)
};
-
- uint16_t flags;
} segment_selector;
/**
diff --git a/segment.cpp b/segment.cpp
new file mode 100644
index 0000000..b991148
--- /dev/null
+++ b/segment.cpp
@@ -0,0 +1,38 @@
+#include "segment_intrin.h"
+
+namespace segment
+{
+ auto get_access_rights(segment_descriptor_64* segment_descriptor) -> vmx_segment_access_rights
+ {
+ vmx_segment_access_rights result;
+ result.granularity = segment_descriptor->granularity;
+ result.type = segment_descriptor->type;
+ result.descriptor_type = segment_descriptor->descriptor_type;
+ result.present = segment_descriptor->present;
+ result.long_mode = segment_descriptor->long_mode;
+ result.available_bit = segment_descriptor->system;
+ result.default_big = segment_descriptor->default_big;
+ return result;
+ }
+
+ auto get_info(segment_descriptor_register_64 gdt_value, segment_selector segment_selector) -> hv::segment_info_ctx
+ {
+ hv::segment_info_ctx segment_info;
+ const auto segment_descriptor =
+ reinterpret_cast(
+ gdt_value.base_address + (segment_selector.index << SEGMENT_SELECTOR_INDEX_BIT));
+
+ segment_info.limit = __segmentlimit(segment_selector.flags);
+ segment_info.rights = get_access_rights(segment_descriptor);
+
+ segment_info.base_addr = (u32)((segment_descriptor->base_address_high << SEGMENT__BASE_ADDRESS_HIGH_BIT) |
+ (segment_descriptor->base_address_middle << SEGMENT__BASE_ADDRESS_MIDDLE_BIT) |
+ (segment_descriptor->base_address_low));
+
+ segment_info.base_addr &= 0xFFFFFFFF;
+ if (!segment_descriptor->descriptor_type)
+ segment_info.base_addr |= ((u64)segment_descriptor->base_address_upper << SEGMENT__BASE_ADDRESS_SHIFT);
+
+ return segment_info;
+ }
+}
\ No newline at end of file
diff --git a/segment_intrin.asm b/segment_intrin.asm
index 9719f2b..8742a4c 100644
--- a/segment_intrin.asm
+++ b/segment_intrin.asm
@@ -28,4 +28,14 @@ readcs proc
mov rax, cs
ret
readcs endp
+
+readtr proc
+ str ax
+ ret
+readtr endp
+
+readldt proc
+ sldt ax
+ ret
+readldt endp
end
\ No newline at end of file
diff --git a/segment_intrin.h b/segment_intrin.h
index 3e30b52..49c07ca 100644
--- a/segment_intrin.h
+++ b/segment_intrin.h
@@ -1,9 +1,17 @@
#pragma once
#include "hv_types.hpp"
-extern "C" u64 readfs(void);
-extern "C" u64 readgs(void);
-extern "C" u64 reades(void);
-extern "C" u64 readds(void);
-extern "C" u64 readss(void);
-extern "C" u64 readcs(void);
\ No newline at end of file
+extern "C" u16 readfs(void);
+extern "C" u16 readgs(void);
+extern "C" u16 reades(void);
+extern "C" u16 readds(void);
+extern "C" u16 readss(void);
+extern "C" u16 readcs(void);
+extern "C" u16 readtr(void);
+extern "C" u16 readldt(void);
+
+namespace segment
+{
+ auto get_info(segment_descriptor_register_64 gdt_value, segment_selector segment_selector) -> hv::segment_info_ctx;
+ auto get_access_rights(segment_descriptor_64* segment_descriptor) -> vmx_segment_access_rights;
+}
\ No newline at end of file
diff --git a/vmcs.cpp b/vmcs.cpp
new file mode 100644
index 0000000..8e261d7
--- /dev/null
+++ b/vmcs.cpp
@@ -0,0 +1,216 @@
+#include "vmcs.hpp"
+
+namespace vmcs
+{
+ auto setup_host(void* host_rip, u64 host_rsp) -> void
+ {
+ segment_descriptor_register_64 gdt_value;
+ segment_descriptor_register_64 idt_value;
+
+ __sidt(&idt_value);
+ _sgdt(&gdt_value);
+
+ __vmx_vmwrite(VMCS_HOST_CR0, __readcr0());
+ __vmx_vmwrite(VMCS_HOST_CR3, __readcr3());
+ __vmx_vmwrite(VMCS_HOST_CR4, __readcr4());
+
+ __vmx_vmwrite(VMCS_HOST_RIP, reinterpret_cast(host_rip));
+ __vmx_vmwrite(VMCS_HOST_RSP, host_rsp);
+
+ __vmx_vmwrite(VMCS_HOST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS));
+ __vmx_vmwrite(VMCS_HOST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP));
+ __vmx_vmwrite(VMCS_HOST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP));
+
+ __vmx_vmwrite(VMCS_HOST_GDTR_BASE, gdt_value.base_address);
+ __vmx_vmwrite(VMCS_HOST_IDTR_BASE, idt_value.base_address);
+
+ __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, reades());
+ __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, readcs());
+ __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, readds());
+ __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, readfs());
+ __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, readgs());
+ __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, readss());
+ __vmx_vmwrite(VMCS_HOST_TR_SELECTOR, readtr());
+
+ __vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE));
+ __vmx_vmwrite(VMCS_HOST_FS_BASE, __readmsr(IA32_FS_BASE));
+ }
+
+ auto setup_guest() -> void
+ {
+ segment_descriptor_register_64 gdt_value;
+ segment_descriptor_register_64 idt_value;
+
+ __sidt(&idt_value);
+ _sgdt(&gdt_value);
+
+ __vmx_vmwrite(VMCS_GUEST_CR0, __readcr0());
+ __vmx_vmwrite(VMCS_GUEST_CR3, __readcr3());
+ __vmx_vmwrite(VMCS_GUEST_CR4, __readcr4());
+
+ __vmx_vmwrite(VMCS_GUEST_VMCS_LINK_POINTER, ~0ULL);
+ __vmx_vmwrite(VMCS_GUEST_DEBUGCTL, __readmsr(IA32_DEBUGCTL));
+
+ __vmx_vmwrite(VMCS_GUEST_DEBUGCTL, __readmsr(IA32_DEBUGCTL));
+ __vmx_vmwrite(VMCS_GUEST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS));
+ __vmx_vmwrite(VMCS_GUEST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP));
+ __vmx_vmwrite(VMCS_GUEST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP));
+
+ __vmx_vmwrite(VMCS_GUEST_GDTR_BASE, gdt_value.base_address);
+ __vmx_vmwrite(VMCS_GUEST_GDTR_LIMIT, gdt_value.limit);
+
+ __vmx_vmwrite(VMCS_GUEST_IDTR_BASE, idt_value.base_address);
+ __vmx_vmwrite(VMCS_GUEST_IDTR_LIMIT, idt_value.limit);
+
+ __vmx_vmwrite(VMCS_GUEST_RFLAGS, __readeflags());
+ __vmx_vmwrite(VMCS_GUEST_DR7, __readdr(7));
+
+ const auto [es_rights, es_limit, es_base] =
+ segment::get_info(gdt_value, segment_selector{ reades() });
+
+ __vmx_vmwrite(VMCS_GUEST_ES_BASE, es_base);
+ __vmx_vmwrite(VMCS_GUEST_ES_LIMIT, es_limit);
+ __vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, reades());
+ __vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, es_rights.flags);
+
+ const auto [ds_rights, ds_limit, ds_base] =
+ segment::get_info(gdt_value, segment_selector{ readds() });
+
+ __vmx_vmwrite(VMCS_GUEST_DS_BASE, ds_base);
+ __vmx_vmwrite(VMCS_GUEST_DS_LIMIT, ds_limit);
+ __vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, readds());
+ __vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, ds_rights.flags);
+
+ const auto [fs_rights, fs_limit, fs_base] =
+ segment::get_info(gdt_value, segment_selector{ readfs() });
+
+ __vmx_vmwrite(VMCS_GUEST_FS_BASE, fs_base);
+ __vmx_vmwrite(VMCS_GUEST_FS_LIMIT, fs_limit);
+ __vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, readfs());
+ __vmx_vmwrite(VMCS_GUEST_FS_ACCESS_RIGHTS, fs_rights.flags);
+
+ const auto [gs_rights, gs_limit, gs_base] =
+ segment::get_info(gdt_value, segment_selector{ readgs() });
+
+ __vmx_vmwrite(VMCS_GUEST_GS_BASE, gs_base);
+ __vmx_vmwrite(VMCS_GUEST_GS_LIMIT, gs_limit);
+ __vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, readgs());
+ __vmx_vmwrite(VMCS_GUEST_GS_ACCESS_RIGHTS, gs_rights.flags);
+
+ const auto [ss_rights, ss_limit, ss_base] =
+ segment::get_info(gdt_value, segment_selector{ readss() });
+
+ __vmx_vmwrite(VMCS_GUEST_SS_BASE, ss_base);
+ __vmx_vmwrite(VMCS_GUEST_SS_LIMIT, ss_limit);
+ __vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, readss());
+ __vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, ss_rights.flags);
+
+ const auto [cs_rights, cs_limit, cs_base] =
+ segment::get_info(gdt_value, segment_selector{ readcs() });
+
+ __vmx_vmwrite(VMCS_GUEST_CS_BASE, cs_base);
+ __vmx_vmwrite(VMCS_GUEST_CS_LIMIT, cs_limit);
+ __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, readcs());
+ __vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, cs_rights.flags);
+
+ const auto [tr_rights, tr_limit, tr_base] =
+ segment::get_info(gdt_value, segment_selector{ readtr() });
+
+ __vmx_vmwrite(VMCS_GUEST_TR_BASE, tr_base);
+ __vmx_vmwrite(VMCS_GUEST_TR_LIMIT, tr_limit);
+ __vmx_vmwrite(VMCS_GUEST_TR_SELECTOR, readtr());
+ __vmx_vmwrite(VMCS_GUEST_TR_ACCESS_RIGHTS, tr_rights.flags);
+
+ const auto [ldt_rights, ldt_limit, ldt_base] =
+ segment::get_info(gdt_value, segment_selector{ readldt() });
+
+ __vmx_vmwrite(VMCS_GUEST_LDTR_BASE, ldt_base);
+ __vmx_vmwrite(VMCS_GUEST_LDTR_LIMIT, ldt_limit);
+ __vmx_vmwrite(VMCS_GUEST_LDTR_SELECTOR, readldt());
+ __vmx_vmwrite(VMCS_GUEST_LDTR_ACCESS_RIGHTS, ldt_rights.flags);
+
+ __vmx_vmwrite(VMCS_GUEST_GS_BASE, __readmsr(IA32_GS_BASE));
+ __vmx_vmwrite(VMCS_GUEST_FS_BASE, __readmsr(IA32_FS_BASE));
+ }
+
+ auto setup_controls() -> void
+ {
+ ia32_vmx_true_ctls_register msr_fix_value;
+ ia32_vmx_pinbased_ctls_register pinbased_ctls;
+ ia32_vmx_procbased_ctls_register procbased_ctls;
+ ia32_vmx_procbased_ctls2_register procbased_ctls2;
+ ia32_vmx_entry_ctls_register entry_ctls;
+ ia32_vmx_exit_ctls_register exit_ctls;
+ ia32_vmx_basic_register vmx_basic;
+
+ vmx_basic.flags = __readmsr(IA32_VMX_BASIC);
+ pinbased_ctls.flags = NULL;
+ procbased_ctls.flags = NULL;
+ procbased_ctls2.flags = NULL;
+ entry_ctls.flags = NULL;
+ exit_ctls.flags = NULL;
+
+ if (vmx_basic.vmx_controls)
+ {
+ msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PINBASED_CTLS);
+ pinbased_ctls.flags &= msr_fix_value.allowed_1_settings;
+ pinbased_ctls.flags |= msr_fix_value.allowed_0_settings;
+ __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
+
+ msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PROCBASED_CTLS);
+ procbased_ctls.flags &= msr_fix_value.allowed_1_settings;
+ procbased_ctls.flags |= msr_fix_value.allowed_0_settings;
+ procbased_ctls.activate_secondary_controls = true;
+ __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
+
+ msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_ENTRY_CTLS);
+ entry_ctls.flags &= msr_fix_value.allowed_1_settings;
+ entry_ctls.flags |= msr_fix_value.allowed_0_settings;
+ entry_ctls.ia32e_mode_guest = true;
+ entry_ctls.conceal_vmx_from_pt = true;
+ __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags);
+
+ msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_EXIT_CTLS);
+ exit_ctls.flags &= msr_fix_value.allowed_1_settings;
+ exit_ctls.flags |= msr_fix_value.allowed_0_settings;
+ exit_ctls.host_address_space_size = true;
+ exit_ctls.conceal_vmx_from_pt = true;
+ __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags);
+ }
+ else
+ {
+ msr_fix_value.flags = __readmsr(IA32_VMX_PINBASED_CTLS);
+ pinbased_ctls.flags &= msr_fix_value.allowed_1_settings;
+ pinbased_ctls.flags |= msr_fix_value.allowed_0_settings;
+ __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
+
+ msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS);
+ procbased_ctls.flags &= msr_fix_value.allowed_1_settings;
+ procbased_ctls.flags |= msr_fix_value.allowed_0_settings;
+ procbased_ctls.activate_secondary_controls = true;
+ __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
+
+ msr_fix_value.flags = __readmsr(IA32_VMX_ENTRY_CTLS);
+ entry_ctls.flags &= msr_fix_value.allowed_1_settings;
+ entry_ctls.flags |= msr_fix_value.allowed_0_settings;
+ entry_ctls.ia32e_mode_guest = true;
+ entry_ctls.conceal_vmx_from_pt = true;
+ __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags);
+
+ msr_fix_value.flags = __readmsr(IA32_VMX_EXIT_CTLS);
+ exit_ctls.flags &= msr_fix_value.allowed_1_settings;
+ exit_ctls.flags |= msr_fix_value.allowed_0_settings;
+ exit_ctls.host_address_space_size = true;
+ exit_ctls.conceal_vmx_from_pt = true;
+ __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags);
+ }
+
+ msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS2);
+ procbased_ctls2.flags &= msr_fix_value.allowed_1_settings;
+ procbased_ctls2.flags |= msr_fix_value.allowed_0_settings;
+ procbased_ctls2.enable_rdtscp = true;
+ procbased_ctls2.enable_xsaves = true;
+ procbased_ctls2.conceal_vmx_from_pt = true;
+ __vmx_vmwrite(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls2.flags);
+ }
+}
\ No newline at end of file
diff --git a/vmcs.hpp b/vmcs.hpp
new file mode 100644
index 0000000..b54014c
--- /dev/null
+++ b/vmcs.hpp
@@ -0,0 +1,11 @@
+#pragma once
+#include "hv_types.hpp"
+#include "segment_intrin.h"
+#include "vmxexit_handler.h"
+
+namespace vmcs
+{
+ auto setup_host(void* host_rip, u64 host_rsp) -> void;
+ auto setup_guest() -> void;
+ auto setup_controls() -> void;
+}
\ No newline at end of file
diff --git a/vmxexit_handler.asm b/vmxexit_handler.asm
index 1bd1a7f..d5602d7 100644
--- a/vmxexit_handler.asm
+++ b/vmxexit_handler.asm
@@ -2,6 +2,7 @@ extern exit_handler : proc
.code
vmxexit_handler proc
+ int 3 ; see if vmexit get called...
push rax
push rbx
push rcx
@@ -38,9 +39,9 @@ vmxexit_handler proc
movaps [rsp + 0F0h], xmm15
mov rcx, rsp
- sub rsp, 28h ; shadow space or some shit MSVC does it so i do it...
+ sub rsp, 20h
call exit_handler
- add rsp, 28h
+ add rsp, 20h
movaps xmm0, [rsp]
movaps xmm1, [rsp + 010h]
@@ -76,6 +77,6 @@ vmxexit_handler proc
pop rcx
pop rax
- vmresume ; resume guest execution...
+ vmresume
vmxexit_handler endp
end
\ No newline at end of file
diff --git a/vmxlaunch.cpp b/vmxlaunch.cpp
index 03399af..c1c11e9 100644
--- a/vmxlaunch.cpp
+++ b/vmxlaunch.cpp
@@ -2,104 +2,28 @@
auto vmxlaunch::init_vmcs() -> void
{
- __vmx_vmclear(&vmxon::g_vmx_ctx->vcpus[
- KeGetCurrentProcessorNumber()]->vmcs_phys);
-
- __vmx_vmptrld(&vmxon::g_vmx_ctx->vcpus[
- KeGetCurrentProcessorNumber()]->vmcs_phys);
-
- // setup host VMCS fields...
- __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, readcs() & 0xF8);
- __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, readds() & 0xF8);
- __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, reades() & 0xF8);
- __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, readgs() & 0xF8);
- __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, readss() & 0xF8);
- __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, readfs() & 0xF8);
-
- // TODO IDT, TR, GDT (base and limit for each segment register), and LDT...
-
- __vmx_vmwrite(VMCS_HOST_CR0, __readcr0());
- __vmx_vmwrite(VMCS_HOST_CR3, __readcr3());
- __vmx_vmwrite(VMCS_HOST_CR4, __readcr4());
-
- __vmx_vmwrite(VMCS_HOST_RIP,
- reinterpret_cast(&::vmxexit_handler));
-
- __vmx_vmwrite(VMCS_HOST_RSP,
+ const auto vcpu =
vmxon::g_vmx_ctx->vcpus[
- KeGetCurrentProcessorNumber()]->host_stack);
-
- // setup guest VMCS fields...
- __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, readcs());
- __vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, readds());
- __vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, reades());
- __vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, readgs());
- __vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, readss());
- __vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, readfs());
- __vmx_vmwrite(VMCS_GUEST_VMCS_LINK_POINTER, ~0ULL);
-
- ia32_vmx_exit_ctls_register exit_ctls;
- exit_ctls.save_ia32_efer = true;
- exit_ctls.conceal_vmx_from_pt = false;
- exit_ctls.host_address_space_size = true;
- exit_ctls.load_ia32_efer = false; // TODO readup on this...
- exit_ctls.load_ia32_pat = true; // TODO ask daax about this...
- exit_ctls.save_debug_controls = true;
- exit_ctls.load_ia32_perf_global_ctrl = true;
- exit_ctls.save_vmx_preemption_timer_value = true;
- __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags);
-
- ia32_vmx_procbased_ctls2_register procbased_ctls;
- procbased_ctls.apic_register_virtualization = false;
- procbased_ctls.conceal_vmx_from_pt = true;
- procbased_ctls.descriptor_table_exiting = false;
- procbased_ctls.enable_encls_exiting = false;
- procbased_ctls.enable_ept = false;
- procbased_ctls.enable_invpcid = false;
- procbased_ctls.enable_pml = false;
- procbased_ctls.enable_rdtscp = false; // might need to enable this...
- procbased_ctls.enable_vm_functions = false;
- procbased_ctls.enable_vpid = true; // TODO read up on this...
- procbased_ctls.enable_xsaves = false; // TODO not sure if i need this enabled...
- procbased_ctls.ept_violation = false;
- procbased_ctls.mode_based_execute_control_for_ept = false;
- procbased_ctls.pause_loop_exiting = false;
- procbased_ctls.rdrand_exiting = false;
- procbased_ctls.rdseed_exiting = false;
- procbased_ctls.unrestricted_guest = false; // TODO read up on this...
- procbased_ctls.use_tsc_scaling = true; // TODO read up on this...
- procbased_ctls.virtualize_apic_accesses = false;
- procbased_ctls.virtualize_x2apic_mode = false;
- procbased_ctls.virtual_interrupt_delivery = false;
- procbased_ctls.vmcs_shadowing = false;
- procbased_ctls.wbinvd_exiting = false; //TODO not sure if i need this to be true...
- __vmx_vmwrite(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
+ KeGetCurrentProcessorNumber()];
- ia32_vmx_pinbased_ctls_register pinbased_ctls;
- pinbased_ctls.activate_vmx_preemption_timer = false;
- pinbased_ctls.external_interrupt_exiting = false;
- pinbased_ctls.nmi_exiting = false;
- pinbased_ctls.process_posted_interrupts = false;
- pinbased_ctls.virtual_nmi = false;
- __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
+ __vmx_vmclear(&vcpu->vmcs_phys);
+ __vmx_vmptrld(&vcpu->vmcs_phys);
- ia32_vmx_entry_ctls_register entry_ctls;
- entry_ctls.conceal_vmx_from_pt = true;
- entry_ctls.deactivate_dual_monitor_treatment = false;
- entry_ctls.entry_to_smm = false; // TODO ask daax about this...
- entry_ctls.ia32e_mode_guest = true;
- entry_ctls.load_cet_state = true; // TODO ask daax...
- entry_ctls.load_debug_controls = true; // TODO ask daax about this...
- entry_ctls.load_ia32_bndcfgs = false; // TODO ask daax about this...
- entry_ctls.load_ia32_efer = true; // TODO ask daax about this...
- entry_ctls.load_ia32_pat = true;
- entry_ctls.load_ia32_perf_global_ctrl = true; // TODO ask daax...
- entry_ctls.load_ia32_rtit_ctl = true; // TODO ask daax...
- __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags);
+ vmcs::setup_host(&vmxexit_handler, vcpu->host_stack);
+ vmcs::setup_guest();
+ vmcs::setup_controls();
}
auto vmxlaunch::launch() -> void
{
+ const auto vmlaunch_result = __vmx_vmlaunch();
DBG_PRINT("vmxlaunch for processor: %d\n", KeGetCurrentProcessorNumber());
- DBG_PRINT(" - vmxlaunch result (0 == success): %d\n", __vmx_vmlaunch());
+ DBG_PRINT(" - vmxlaunch result (0 == success): %d\n", vmlaunch_result);
+
+ if (vmlaunch_result)
+ {
+ u64 vmxerror;
+ __vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &vmxerror);
+ DBG_PRINT("vmxerror: %d\n", vmxerror);
+ }
}
\ No newline at end of file
diff --git a/vmxlaunch.hpp b/vmxlaunch.hpp
index 1ad673e..6095d35 100644
--- a/vmxlaunch.hpp
+++ b/vmxlaunch.hpp
@@ -2,6 +2,7 @@
#include "segment_intrin.h"
#include "vmxexit_handler.h"
#include "vmxon.hpp"
+#include "vmcs.hpp"
namespace vmxlaunch
{
diff --git a/vmxon.cpp b/vmxon.cpp
index d10f06a..cd7b364 100644
--- a/vmxon.cpp
+++ b/vmxon.cpp
@@ -95,11 +95,14 @@ namespace vmxon
hv::cr0_t cr0 = { 0 };
hv::cr4_t cr4 = { 0 };
+ // should check to see if this is locked or not...
feature_msr.control = __readmsr(IA32_FEATURE_CONTROL);
feature_msr.bits.vmxon_outside_smx = true;
feature_msr.bits.lock = true;
__writemsr(IA32_FEATURE_CONTROL, feature_msr.control);
+ // not sure if did this in the wrong order, i think maybe cr4.vmx_enable bit needs
+ // to be flipped before i fixed cr0 and cr4 registers? TODO: read up on dat sheet...
cr_fixed.all = __readmsr(IA32_VMX_CR0_FIXED0);
cr0.flags = __readcr0();
cr0.flags |= cr_fixed.split.low;
@@ -118,17 +121,10 @@ namespace vmxon
cr4.vmx_enable = true;
__writecr4(cr4.flags);
- __try
- {
- DBG_PRINT("vmxon for processor: %d\n", KeGetCurrentProcessorNumber());
-
+ DBG_PRINT("vmxon for processor: %d\n", KeGetCurrentProcessorNumber());
+ DBG_PRINT(" - vmxon result (0 == success): %d\n",
__vmx_on((unsigned long long*)
&vmxon::g_vmx_ctx->vcpus[
- KeGetCurrentProcessorNumber()]->vmxon_phys);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- DBG_PRINT("vmxon failed for processor: %d\n", KeGetCurrentProcessorNumber());
- }
+ KeGetCurrentProcessorNumber()]->vmxon_phys));
}
}
\ No newline at end of file