diff --git a/64-ia-32-architectures-software-developer-vol-3c-part-3-manual.pdf b/64-ia-32-architectures-software-developer-vol-3c-part-3-manual.pdf
deleted file mode 100644
index d09619e..0000000
Binary files a/64-ia-32-architectures-software-developer-vol-3c-part-3-manual.pdf and /dev/null differ
diff --git a/bluepill.vcxproj b/bluepill.vcxproj
index 9dc78fe..e663bbd 100644
--- a/bluepill.vcxproj
+++ b/bluepill.vcxproj
@@ -83,18 +83,20 @@
-
+
+
-
+
+
@@ -104,7 +106,8 @@
-
+
+
diff --git a/bluepill.vcxproj.filters b/bluepill.vcxproj.filters
index f4b14c8..84c41df 100644
--- a/bluepill.vcxproj.filters
+++ b/bluepill.vcxproj.filters
@@ -11,9 +11,6 @@
-
- Source Files
-
Source Files
@@ -26,15 +23,18 @@
Source Files
-
- Source Files
-
Source Files
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -64,6 +64,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
@@ -72,7 +78,10 @@
Source Files
-
+
+ Source Files
+
+
Source Files
diff --git a/drv_entry.cpp b/drv_entry.cpp
new file mode 100644
index 0000000..bc1e589
--- /dev/null
+++ b/drv_entry.cpp
@@ -0,0 +1,65 @@
+#include "vmxlaunch.hpp"
+#include "idt.hpp"
+
+auto driver_unload(
+ PDRIVER_OBJECT driver_object
+) -> void
+{
+ // no unloading this hypervisor... reboot!
+ __debugbreak();
+}
+
+auto driver_entry(
+ PDRIVER_OBJECT driver_object,
+ PUNICODE_STRING registry_path
+) -> NTSTATUS
+{
+ vmxon::g_vmx_ctx =
+ reinterpret_cast(
+ ExAllocatePool(NonPagedPool, sizeof hv::vmx_ctx));
+
+ // setup vcpu structures (vmx on region and vmcs...)
+ vmxon::create_vcpus(vmxon::g_vmx_ctx);
+
+ // setup host address space...
+ cr3 cr3_value;
+ cr3_value.flags = __readcr3();
+ cr3_value.address_of_page_directory =
+ (MmGetPhysicalAddress(mm::pml4).QuadPart >> 12);
+
+ memset(mm::pml4, NULL, sizeof mm::pml4);
+ mm::pml4[PML4_SELF_REF].pfn = cr3_value.address_of_page_directory;
+ mm::pml4[PML4_SELF_REF].present = true;
+ mm::pml4[PML4_SELF_REF].rw = true;
+ mm::pml4[PML4_SELF_REF].user_supervisor = false;
+
+ PHYSICAL_ADDRESS current_pml4;
+ current_pml4.QuadPart =
+ (cr3{ __readcr3() }.address_of_page_directory << 12);
+
+ const auto kernel_pml4 =
+ reinterpret_cast(
+ MmGetVirtualForPhysical(current_pml4));
+
+ // vmxroot will have the same "address space" as the current one being executed in...
+ memcpy(&mm::pml4[255], &kernel_pml4[255], sizeof(mm::pml4e) * 255);
+
+ // setup mapping ptes to be present and writable...
+ for (auto idx = 0u; idx < 254; ++idx)
+ {
+ reinterpret_cast(mm::pml4)[idx].present = true;
+ reinterpret_cast(mm::pml4)[idx].rw = true;
+ }
+
+ // enable vmx operation on all cores...
+ KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxon::init_vmxon, NULL);
+
+ // setup VMCS for all logical cores...
+ KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::init_vmcs, cr3_value.flags);
+
+ // vmxlaunch for all cores...
+ KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL);
+
+ driver_object->DriverUnload = &driver_unload;
+ return STATUS_SUCCESS;
+}
\ No newline at end of file
diff --git a/entry.cpp b/entry.cpp
deleted file mode 100644
index e9dd4e9..0000000
--- a/entry.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "vmxlaunch.hpp"
-
-auto driver_unload(
- PDRIVER_OBJECT driver_object
-) -> void
-{
- // test to see if invalid opcode happens...
- __vmx_off();
-}
-
-auto driver_entry(
- PDRIVER_OBJECT driver_object,
- PUNICODE_STRING registry_path
-) -> NTSTATUS
-{
- vmxon::g_vmx_ctx =
- reinterpret_cast(
- ExAllocatePool(NonPagedPool, sizeof hv::vmx_ctx));
-
- // setup vcpu structures (vmx on region and vmcs...)
- vmxon::create_vcpus(vmxon::g_vmx_ctx);
-
- // enable vmx operation on all cores...
- KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxon::init_vmxon, NULL);
-
- // setup VMCS for all logical cores...
- KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::init_vmcs, NULL);
-
- // vmxlaunch for all cores...
- KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL);
-
- driver_object->DriverUnload = &driver_unload;
- return STATUS_SUCCESS;
-}
\ No newline at end of file
diff --git a/exit_handler.cpp b/exit_handler.cpp
index cceca94..0983c68 100644
--- a/exit_handler.cpp
+++ b/exit_handler.cpp
@@ -27,14 +27,16 @@ auto exit_handler(hv::pguest_registers regs) -> void
}
case VMX_EXIT_REASON_EXECUTE_XSETBV:
{
- hv::msr_split value;
+ hv::msr_split value{};
value.high = regs->rdx;
value.low = regs->rax;
+ // can also validate the input instead of using
+ // reimplimented SEH...
__try
{
/*
- EXCEPTION WARNING!: (will need to handle SEH in my IDT)
+ EXCEPTION WARNING:
#GP If the current privilege level is not 0.
If an invalid XCR is specified in ECX.
If the value in EDX:EAX sets bits that are reserved in the XCR specified by ECX.
@@ -50,7 +52,7 @@ auto exit_handler(hv::pguest_registers regs) -> void
__except (EXCEPTION_EXECUTE_HANDLER)
{
vmentry_interrupt_information interrupt{};
- interrupt.flags = interruption_type::software_interrupt;
+ interrupt.flags = interruption_type::hardware_exception;
interrupt.vector = EXCEPTION_GP_FAULT;
interrupt.valid = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
@@ -59,10 +61,12 @@ auto exit_handler(hv::pguest_registers regs) -> void
}
case VMX_EXIT_REASON_EXECUTE_RDMSR:
{
+ // can also validate the input instead of using
+ // reimplimented SEH...
__try
{
/*
- EXCEPTION WARNING!: (will need to handle SEH in my IDT)
+ EXCEPTION WARNING:
#GP(0) If the current privilege level is not 0.
If the value in ECX specifies a reserved or unimplemented MSR address.
#UD If the LOCK prefix is used.
@@ -76,7 +80,7 @@ auto exit_handler(hv::pguest_registers regs) -> void
__except (EXCEPTION_EXECUTE_HANDLER)
{
vmentry_interrupt_information interrupt{};
- interrupt.flags = interruption_type::software_interrupt;
+ interrupt.flags = interruption_type::hardware_exception;
interrupt.vector = EXCEPTION_GP_FAULT;
interrupt.valid = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
@@ -89,6 +93,8 @@ auto exit_handler(hv::pguest_registers regs) -> void
value.low = regs->rax;
value.high = regs->rdx;
+ // can also validate the input instead of using
+ // reimplimented SEH...
__try
{
__writemsr(regs->rcx, value.value);
@@ -96,19 +102,26 @@ auto exit_handler(hv::pguest_registers regs) -> void
__except (EXCEPTION_EXECUTE_HANDLER)
{
/*
- EXCEPTION WARNING!: (will need to handle SEH in my IDT)
+ EXCEPTION WARNING:
#GP(0) If the current privilege level is not 0.
If the value in ECX specifies a reserved or unimplemented MSR address.
#UD If the LOCK prefix is used.
*/
vmentry_interrupt_information interrupt{};
- interrupt.flags = interruption_type::software_interrupt;
+ interrupt.flags = interruption_type::hardware_exception;
interrupt.vector = EXCEPTION_GP_FAULT;
interrupt.valid = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
}
break;
}
+ case VMX_EXIT_REASON_EXECUTE_INVD:
+ {
+ // couldnt find the intrin for this so i just made one...
+ // probably could have used __wbinvd?
+ __invd();
+ break;
+ }
case VMX_EXIT_REASON_EXECUTE_VMWRITE:
case VMX_EXIT_REASON_EXECUTE_VMREAD:
case VMX_EXIT_REASON_EXECUTE_VMPTRST:
@@ -119,7 +132,7 @@ auto exit_handler(hv::pguest_registers regs) -> void
case VMX_EXIT_REASON_EXECUTE_VMCALL:
{
vmentry_interrupt_information interrupt{};
- interrupt.flags = interruption_type::software_interrupt;
+ interrupt.flags = interruption_type::hardware_exception;
interrupt.vector = EXCEPTION_INVALID_OPCODE;
interrupt.valid = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
diff --git a/segment.cpp b/gdt.cpp
similarity index 77%
rename from segment.cpp
rename to gdt.cpp
index 6a6b564..3072bc4 100644
--- a/segment.cpp
+++ b/gdt.cpp
@@ -1,6 +1,6 @@
-#include "segment_intrin.h"
+#include "gdt.hpp"
-namespace segment
+namespace gdt
{
auto get_access_rights(segment_descriptor_64* segment_descriptor) -> vmx_segment_access_rights
{
@@ -23,7 +23,7 @@ namespace segment
{
hv::segment_info_ctx segment_info{};
- const auto segment_descriptor =
+ const auto segment_descriptor =
reinterpret_cast(
gdt_value.base_address + (selector.index << SEGMENT_SELECTOR_INDEX_BIT));
@@ -55,4 +55,18 @@ namespace segment
return segment_info;
}
+
+ // TODO: make your own GDT.... (and TSS so you can have an IST for each IDT handler...)
+ auto init() -> void
+ {
+ gdt::table[GDT_CS_INDEX].present = true;
+ gdt::table[GDT_CS_INDEX].long_mode = true;
+ gdt::table[GDT_CS_INDEX].descriptor_type = SEGMENT_DESCRIPTOR_TYPE_CODE_OR_DATA;
+ gdt::table[GDT_CS_INDEX].type = SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ;
+
+ gdt::table[GDT_DS_INDEX].present = true;
+ gdt::table[GDT_DS_INDEX].long_mode = true;
+ gdt::table[GDT_DS_INDEX].descriptor_type = SEGMENT_DESCRIPTOR_TYPE_CODE_OR_DATA;
+ gdt::table[GDT_DS_INDEX].type = SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE;
+ }
}
\ No newline at end of file
diff --git a/gdt.hpp b/gdt.hpp
new file mode 100644
index 0000000..ccfefd7
--- /dev/null
+++ b/gdt.hpp
@@ -0,0 +1,17 @@
+#pragma once
+#include "hv_types.hpp"
+#pragma section(".gdt", read, write)
+
+#define GDT_CS_INDEX 0
+#define GDT_DS_INDEX 1
+#define GDT_TSS_INDEX 2
+
+namespace gdt
+{
+ __declspec(allocate(".gdt"))
+ inline segment_descriptor_64 table[3]; // TODO...
+
+ auto init()->void;
+ auto get_info(const 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/hv_types.hpp b/hv_types.hpp
index 6baf6dd..ff78844 100644
--- a/hv_types.hpp
+++ b/hv_types.hpp
@@ -69,6 +69,51 @@ namespace hv
u64 rax;
} guest_registers, * pguest_registers;
+ typedef struct _idt_regs_t
+ {
+ u128 xmm0;
+ u128 xmm1;
+ u128 xmm2;
+ u128 xmm3;
+ u128 xmm4;
+ u128 xmm5;
+ u128 xmm6;
+ u128 xmm7;
+ u128 xmm8;
+ u128 xmm9;
+ u128 xmm10;
+ u128 xmm11;
+ u128 xmm12;
+ u128 xmm13;
+ u128 xmm14;
+ u128 xmm15;
+
+ u64 padding_8b;
+
+ u64 r15;
+ u64 r14;
+ u64 r13;
+ u64 r12;
+ u64 r11;
+ u64 r10;
+ u64 r9;
+ u64 r8;
+ u64 rbp;
+ u64 rdi;
+ u64 rsi;
+ u64 rdx;
+ u64 rcx;
+ u64 rbx;
+ u64 rax;
+
+ u64 error_code;
+ u64 rip;
+ u64 cs_selector;
+ ::rflags rflags;
+ u64 rsp;
+ u64 ss_selector;
+ } idt_regs_t, *pidt_regs_t;
+
union msr_split
{
u64 value;
@@ -99,7 +144,7 @@ namespace hv
union idt_addr_t
{
- u64 addr;
+ void* addr;
struct
{
u64 offset_low : 16;
@@ -429,7 +474,7 @@ namespace hv
typedef struct _vmx_ctx
{
- u32 vcpu_num;
+ u32 vcpu_count;
pvcpu_ctx* vcpus;
} vmx_ctx, *pvmx_ctx;
diff --git a/idt.cpp b/idt.cpp
index a54bf22..02f309a 100644
--- a/idt.cpp
+++ b/idt.cpp
@@ -1,20 +1,30 @@
#include "idt.hpp"
+void seh_handler(hv::pidt_regs_t regs)
+{
+ return;
+}
+
namespace idt
{
- auto create_entry(void* address) -> hv::idt_entry_t
+ auto create_entry(hv::idt_addr_t idt_handler) -> hv::idt_entry_t
{
- hv::idt_addr_t idt_addr{ (u64) address };
hv::idt_entry_t result{};
-
- result.dpl = 0;
- result.storage_segment = 0;
result.segment_selector = readcs();
result.gate_type = SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE;
- result.present = 1;
- result.offset_high = idt_addr.offset_high;
- result.offset_middle = idt_addr.offset_middle;
- result.offset_low = idt_addr.offset_low;
+ result.present = true;
+
+ result.offset_high = idt_handler.offset_high;
+ result.offset_middle = idt_handler.offset_middle;
+ result.offset_low = idt_handler.offset_low;
return result;
}
+
+ auto init() -> u64
+ {
+ idt::table[general_protection] = create_entry(hv::idt_addr_t{ __gp_handler });
+ idt::table[page_fault] = create_entry(hv::idt_addr_t{ __pf_handler });
+ idt::table[divide_error] = create_entry(hv::idt_addr_t{ __de_handler });
+ return reinterpret_cast(idt::table);
+ }
}
\ No newline at end of file
diff --git a/idt.hpp b/idt.hpp
index b4a1575..da39154 100644
--- a/idt.hpp
+++ b/idt.hpp
@@ -3,8 +3,16 @@
#include "segment_intrin.h"
#pragma section(".idt", read, write)
+extern "C" void __gp_handler(void);
+extern "C" void __pf_handler(void);
+extern "C" void __de_handler(void);
+extern "C" void seh_handler(hv::pidt_regs_t regs);
+
namespace idt
{
- __declspec(allocate(".idt")) inline hv::idt_entry_t table[256];
- auto create_entry(void* address) -> hv::idt_entry_t;
+ __declspec(allocate(".idt"))
+ inline hv::idt_entry_t table[256];
+
+ auto create_entry(hv::idt_addr_t idt_handler) -> hv::idt_entry_t;
+ auto init() -> u64;
}
\ No newline at end of file
diff --git a/idt_handler.asm b/idt_handler.asm
deleted file mode 100644
index e69de29..0000000
diff --git a/idt_handlers.asm b/idt_handlers.asm
new file mode 100644
index 0000000..228ec25
--- /dev/null
+++ b/idt_handlers.asm
@@ -0,0 +1,84 @@
+extern seh_handler : proc
+
+.code
+__pf_handler proc
+__de_handler proc
+__gp_handler proc
+ push rax
+ push rbx
+ push rcx
+ push rdx
+ push rsi
+ push rdi
+ push rbp
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+
+ sub rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment...
+ movaps [rsp], xmm0
+ movaps [rsp + 010h], xmm1
+ movaps [rsp + 020h], xmm2
+ movaps [rsp + 030h], xmm3
+ movaps [rsp + 040h], xmm4
+ movaps [rsp + 050h], xmm5
+ movaps [rsp + 060h], xmm6
+ movaps [rsp + 070h], xmm7
+ movaps [rsp + 080h], xmm8
+ movaps [rsp + 090h], xmm9
+ movaps [rsp + 0A0h], xmm10
+ movaps [rsp + 0B0h], xmm11
+ movaps [rsp + 0C0h], xmm12
+ movaps [rsp + 0D0h], xmm13
+ movaps [rsp + 0E0h], xmm14
+ movaps [rsp + 0F0h], xmm15
+
+ mov rcx, rsp
+ sub rsp, 20h
+ call seh_handler
+ add rsp, 20h
+
+ movups xmm0, [rsp]
+ movups xmm1, [rsp + 010h]
+ movups xmm2, [rsp + 020h]
+ movups xmm3, [rsp + 030h]
+ movups xmm4, [rsp + 040h]
+ movups xmm5, [rsp + 050h]
+ movups xmm6, [rsp + 060h]
+ movups xmm7, [rsp + 070h]
+ movups xmm8, [rsp + 080h]
+ movups xmm9, [rsp + 090h]
+ movups xmm10, [rsp + 0A0h]
+ movups xmm11, [rsp + 0B0h]
+ movups xmm12, [rsp + 0C0h]
+ movups xmm13, [rsp + 0D0h]
+ movups xmm14, [rsp + 0E0h]
+ movups xmm15, [rsp + 0F0h]
+ add rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment...
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rbp
+ pop rdi
+ pop rsi
+ pop rdx
+ pop rcx
+ pop rbx
+ pop rax
+
+ iretq
+__gp_handler endp
+__de_handler endp
+__pf_handler endp
+end
\ No newline at end of file
diff --git a/invd.asm b/invd.asm
new file mode 100644
index 0000000..6075711
--- /dev/null
+++ b/invd.asm
@@ -0,0 +1,6 @@
+.code
+__invd proc
+ invd
+ ret
+__invd endp
+end
\ No newline at end of file
diff --git a/invd.hpp b/invd.hpp
new file mode 100644
index 0000000..fd580a1
--- /dev/null
+++ b/invd.hpp
@@ -0,0 +1,2 @@
+#pragma once
+extern "C" void __invd(void);
\ No newline at end of file
diff --git a/mm.cpp b/mm.cpp
index b739c2f..4cbe82f 100644
--- a/mm.cpp
+++ b/mm.cpp
@@ -2,5 +2,32 @@
namespace mm
{
+ auto translate(virt_addr_t virt_addr) -> u64
+ {
+ }
+
+ auto translate(virt_addr_t virt_addr, u64 pml4_phys, map_type type = map_type::src) -> u64
+ {
+
+ }
+
+ auto map_page(u64 phys_addr, map_type type) -> u64
+ {
+ cpuid_eax_01 cpuid_value;
+ virt_addr_t result{ vmxroot_pml4 };
+ __cpuid((int*)&cpuid_value, 1);
+
+ result.pt_index = (cpuid_value
+ .cpuid_additional_information
+ .initial_apic_id * 2)
+ + (unsigned)type;
+
+ reinterpret_cast(vmxroot_pml4)
+ [result.pt_index].pfn = phys_addr >> 12;
+
+ __invlpg(result.value);
+ result.offset = virt_addr_t{ (void*)phys_addr }.offset;
+ return reinterpret_cast(result.value);
+ }
}
\ No newline at end of file
diff --git a/mm.hpp b/mm.hpp
index b117685..f44f6af 100644
--- a/mm.hpp
+++ b/mm.hpp
@@ -1,5 +1,7 @@
#pragma once
#include "hv_types.hpp"
+
+#define PML4_SELF_REF 254
#pragma section(".pml4", read, write)
namespace mm
@@ -105,12 +107,11 @@ namespace mm
} pte, * ppte;
enum class map_type{ dest, src };
-
- constexpr auto self_ref_index = 254;
inline const ppml4e vmxroot_pml4 = reinterpret_cast(0x7f0000000000);
// make sure this is 4kb aligned or you are going to be meeting allah...
- __declspec(allocate(".pml4")) inline pml4e pml4[512];
+ __declspec(allocate(".pml4"))
+ inline pml4e pml4[512];
// translate vmxroot address's...
auto translate(virt_addr_t virt_addr) -> u64;
diff --git a/segment_intrin.h b/segment_intrin.h
index 3dc8974..dec57cb 100644
--- a/segment_intrin.h
+++ b/segment_intrin.h
@@ -8,10 +8,4 @@ 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(const 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
+extern "C" u16 readldt(void);
\ No newline at end of file
diff --git a/vmcs.cpp b/vmcs.cpp
index 53c6f3d..dc5a929 100644
--- a/vmcs.cpp
+++ b/vmcs.cpp
@@ -1,9 +1,8 @@
#include "vmcs.hpp"
-#include "mm.hpp"
namespace vmcs
{
- auto setup_host(void* host_rip, u64 host_rsp) -> void
+ auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value) -> void
{
segment_descriptor_register_64 gdt_value;
segment_descriptor_register_64 idt_value;
@@ -11,28 +10,6 @@ namespace vmcs
__sidt(&idt_value);
_sgdt(&gdt_value);
- cr3 cr3_value;
- cr3_value.flags = __readcr3();
- cr3_value.address_of_page_directory =
- (MmGetPhysicalAddress(mm::pml4).QuadPart >> 12);
-
- memset(mm::pml4, NULL, sizeof mm::pml4);
- mm::pml4[mm::self_ref_index].pfn = cr3_value.address_of_page_directory;
- mm::pml4[mm::self_ref_index].present = true;
- mm::pml4[mm::self_ref_index].rw = true;
- mm::pml4[mm::self_ref_index].user_supervisor = false;
-
- PHYSICAL_ADDRESS current_pml4;
- current_pml4.QuadPart =
- (cr3{ __readcr3() }.address_of_page_directory << 12);
-
- const auto kernel_pml4 =
- reinterpret_cast(
- MmGetVirtualForPhysical(current_pml4));
-
- // vmxroot will have the same "address space" as the current one being executed in...
- memcpy(&mm::pml4[255], &kernel_pml4[255], sizeof(mm::pml4e) * 255);
-
__vmx_vmwrite(VMCS_HOST_CR0, __readcr0());
__vmx_vmwrite(VMCS_HOST_CR3, cr3_value.flags);
__vmx_vmwrite(VMCS_HOST_CR4, __readcr4());
@@ -109,7 +86,7 @@ namespace vmcs
__vmx_vmwrite(VMCS_GUEST_DR7, __readdr(7));
const auto [es_rights, es_limit, es_base] =
- segment::get_info(gdt_value, segment_selector{ reades() });
+ gdt::get_info(gdt_value, segment_selector{ reades() });
__vmx_vmwrite(VMCS_GUEST_ES_BASE, es_base);
__vmx_vmwrite(VMCS_GUEST_ES_LIMIT, es_limit);
@@ -117,7 +94,7 @@ namespace vmcs
__vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, es_rights.flags);
const auto [fs_rights, fs_limit, fs_base] =
- segment::get_info(gdt_value, segment_selector{ readfs() });
+ gdt::get_info(gdt_value, segment_selector{ readfs() });
__vmx_vmwrite(VMCS_GUEST_FS_BASE, fs_base);
__vmx_vmwrite(VMCS_GUEST_FS_LIMIT, fs_limit);
@@ -125,7 +102,7 @@ namespace vmcs
__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() });
+ gdt::get_info(gdt_value, segment_selector{ readgs() });
__vmx_vmwrite(VMCS_GUEST_GS_BASE, gs_base);
__vmx_vmwrite(VMCS_GUEST_GS_LIMIT, gs_limit);
@@ -133,7 +110,7 @@ namespace vmcs
__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() });
+ gdt::get_info(gdt_value, segment_selector{ readss() });
__vmx_vmwrite(VMCS_GUEST_SS_BASE, ss_base);
__vmx_vmwrite(VMCS_GUEST_SS_LIMIT, ss_limit);
@@ -141,7 +118,7 @@ namespace vmcs
__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() });
+ gdt::get_info(gdt_value, segment_selector{ readcs() });
__vmx_vmwrite(VMCS_GUEST_CS_BASE, cs_base);
__vmx_vmwrite(VMCS_GUEST_CS_LIMIT, cs_limit);
@@ -149,7 +126,7 @@ namespace vmcs
__vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, cs_rights.flags);
const auto [ds_rights, ds_limit, ds_base] =
- segment::get_info(gdt_value, segment_selector{ readds() });
+ gdt::get_info(gdt_value, segment_selector{ readds() });
__vmx_vmwrite(VMCS_GUEST_DS_BASE, ds_base);
__vmx_vmwrite(VMCS_GUEST_DS_LIMIT, ds_limit);
@@ -157,7 +134,7 @@ namespace vmcs
__vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, ds_rights.flags);
const auto [tr_rights, tr_limit, tr_base] =
- segment::get_info(gdt_value, segment_selector{ readtr() });
+ gdt::get_info(gdt_value, segment_selector{ readtr() });
__vmx_vmwrite(VMCS_GUEST_TR_BASE, tr_base);
__vmx_vmwrite(VMCS_GUEST_TR_LIMIT, tr_limit);
@@ -165,7 +142,7 @@ namespace vmcs
__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() });
+ gdt::get_info(gdt_value, segment_selector{ readldt() });
__vmx_vmwrite(VMCS_GUEST_LDTR_BASE, ldt_base);
__vmx_vmwrite(VMCS_GUEST_LDTR_LIMIT, ldt_limit);
diff --git a/vmcs.hpp b/vmcs.hpp
index b54014c..72f496d 100644
--- a/vmcs.hpp
+++ b/vmcs.hpp
@@ -2,10 +2,12 @@
#include "hv_types.hpp"
#include "segment_intrin.h"
#include "vmxexit_handler.h"
+#include "gdt.hpp"
+#include "idt.hpp"
namespace vmcs
{
- auto setup_host(void* host_rip, u64 host_rsp) -> void;
+ auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value) -> void;
auto setup_guest() -> void;
auto setup_controls() -> void;
}
\ No newline at end of file
diff --git a/vmxexit_handler.h b/vmxexit_handler.h
index 28b6381..5a818b3 100644
--- a/vmxexit_handler.h
+++ b/vmxexit_handler.h
@@ -1,5 +1,6 @@
#pragma once
#include "hv_types.hpp"
+#include "invd.hpp"
extern "C" auto vmxexit_handler() -> void;
extern "C" auto exit_handler(hv::pguest_registers regs) -> void;
\ No newline at end of file
diff --git a/vmxlaunch.cpp b/vmxlaunch.cpp
index d5b0efe..afbe3a5 100644
--- a/vmxlaunch.cpp
+++ b/vmxlaunch.cpp
@@ -1,6 +1,6 @@
#include "vmxlaunch.hpp"
-auto vmxlaunch::init_vmcs() -> void
+auto vmxlaunch::init_vmcs(cr3 cr3_value) -> void
{
const auto vcpu =
vmxon::g_vmx_ctx->vcpus[
@@ -9,7 +9,7 @@ auto vmxlaunch::init_vmcs() -> void
__vmx_vmclear(&vcpu->vmcs_phys);
__vmx_vmptrld(&vcpu->vmcs_phys);
- vmcs::setup_host(&vmxexit_handler, vcpu->host_stack);
+ vmcs::setup_host(&vmxexit_handler, vcpu->host_stack, cr3_value);
vmcs::setup_guest();
vmcs::setup_controls();
}
diff --git a/vmxlaunch.hpp b/vmxlaunch.hpp
index 2f62571..653c5e0 100644
--- a/vmxlaunch.hpp
+++ b/vmxlaunch.hpp
@@ -3,12 +3,13 @@
#include "vmxexit_handler.h"
#include "vmxon.hpp"
#include "vmcs.hpp"
+#include "mm.hpp"
#define VMX_LAUNCH_SUCCESS 0xC0FFEE
extern "C" u32 vmxlaunch_processor(void);
namespace vmxlaunch
{
- auto init_vmcs() -> void;
+ auto init_vmcs(cr3 cr3_value) -> void;
auto launch() -> void;
}
\ No newline at end of file
diff --git a/vmxon.cpp b/vmxon.cpp
index 6a25880..4956930 100644
--- a/vmxon.cpp
+++ b/vmxon.cpp
@@ -54,7 +54,7 @@ namespace vmxon
auto create_vcpus(hv::pvmx_ctx vmx_ctx) -> void
{
- vmx_ctx->vcpu_num =
+ vmx_ctx->vcpu_count =
KeQueryActiveProcessorCountEx(
ALL_PROCESSOR_GROUPS);
@@ -62,11 +62,11 @@ namespace vmxon
vmx_ctx->vcpus =
reinterpret_cast(
ExAllocatePool(NonPagedPool,
- sizeof(hv::pvcpu_ctx) * vmx_ctx->vcpu_num));
+ sizeof(hv::pvcpu_ctx) * vmx_ctx->vcpu_count));
// allocate vcpu for each logical processor along with
// vmxon region and vmcs memory for each logical processor...
- for (auto idx = 0u; idx < g_vmx_ctx->vcpu_num; ++idx)
+ for (auto idx = 0u; idx < g_vmx_ctx->vcpu_count; ++idx)
{
vmx_ctx->vcpus[idx] =
reinterpret_cast(