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(