From 29c43d81bfad84d6bd3b450d39707b59d9ae7ee2 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Tue, 9 Feb 2021 18:46:44 -0800 Subject: [PATCH] cloning GDT, IDT and TSS... making modifications to the clone --- drv_entry.cpp | 30 ++++++++++++-- exit_handler.cpp | 13 +++--- gdt.cpp | 17 +------- gdt.hpp | 13 ++---- hv_types.hpp | 38 +++++++++++++++-- ia32.hpp | 6 +-- idt.cpp | 14 +++---- idt.hpp | 6 +-- idt_handlers.asm | 2 + mm.cpp | 6 +-- vmcs.cpp | 104 ++++++++++++++++++++++++++++++++++++----------- vmcs.hpp | 1 + vmxon.cpp | 20 --------- 13 files changed, 172 insertions(+), 98 deletions(-) diff --git a/drv_entry.cpp b/drv_entry.cpp index bc1e589..2b3e1d9 100644 --- a/drv_entry.cpp +++ b/drv_entry.cpp @@ -5,7 +5,7 @@ auto driver_unload( PDRIVER_OBJECT driver_object ) -> void { - // no unloading this hypervisor... reboot! + // no unloading this hv... restart! lol __debugbreak(); } @@ -21,7 +21,6 @@ auto driver_entry( // 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 = @@ -44,13 +43,38 @@ auto driver_entry( // 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... + // setup mapping ptes to be present, writeable, executable, and user supervisor false... for (auto idx = 0u; idx < 254; ++idx) { reinterpret_cast(mm::pml4)[idx].present = true; reinterpret_cast(mm::pml4)[idx].rw = true; } + // setup IDT for host.... + segment_descriptor_register_64 idt_value; + __sidt(&idt_value); + + // copy the guest IDT entries... + memcpy(idt::table, (void*)idt_value.base_address, idt_value.limit); + + // change gp, pf, and de to vmxroot handlers... + idt::table[general_protection] = create_entry(hv::idt_addr_t{ __gp_handler }, idt::ist_idx::gp); + idt::table[page_fault] = create_entry(hv::idt_addr_t{ __pf_handler }, idt::ist_idx::pf); + idt::table[divide_error] = create_entry(hv::idt_addr_t{ __de_handler }, idt::ist_idx::de); + + // change the segment selector to work with vmxroot gdt... + for (auto idx = 0u; idx < 255; ++idx) + { + segment_selector cs{}; + cs.idx = gdt::idx::cs; + cs.request_privilege_level = NULL; + cs.table = NULL; + idt::table[idx].segment_selector = cs.flags; + } + + // used for SEH in vmxroot fault handler... + idt::image_base = driver_object->DriverStart; + // enable vmx operation on all cores... KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxon::init_vmxon, NULL); diff --git a/exit_handler.cpp b/exit_handler.cpp index 0983c68..1620c0b 100644 --- a/exit_handler.cpp +++ b/exit_handler.cpp @@ -12,7 +12,7 @@ auto exit_handler(hv::pguest_registers regs) -> void if (regs->rcx == 0xC0FFEE) { regs->rax = 0xC0FFEE; - // just a demo... + __debugbreak(); } else { @@ -48,6 +48,7 @@ auto exit_handler(hv::pguest_registers regs) -> void If the LOCK prefix is used. */ _xsetbv(regs->rcx, value.value); + break; } __except (EXCEPTION_EXECUTE_HANDLER) { @@ -57,7 +58,7 @@ auto exit_handler(hv::pguest_registers regs) -> void interrupt.valid = true; __vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags); } - break; + return; // dont advance rip... } case VMX_EXIT_REASON_EXECUTE_RDMSR: { @@ -76,6 +77,7 @@ auto exit_handler(hv::pguest_registers regs) -> void regs->rdx = result.high; regs->rax = result.low; + break; } __except (EXCEPTION_EXECUTE_HANDLER) { @@ -85,7 +87,7 @@ auto exit_handler(hv::pguest_registers regs) -> void interrupt.valid = true; __vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags); } - break; + return; // dont advance rip... } case VMX_EXIT_REASON_EXECUTE_WRMSR: { @@ -98,6 +100,7 @@ auto exit_handler(hv::pguest_registers regs) -> void __try { __writemsr(regs->rcx, value.value); + break; } __except (EXCEPTION_EXECUTE_HANDLER) { @@ -113,7 +116,7 @@ auto exit_handler(hv::pguest_registers regs) -> void interrupt.valid = true; __vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags); } - break; + return; // dont advance rip... } case VMX_EXIT_REASON_EXECUTE_INVD: { @@ -136,7 +139,7 @@ auto exit_handler(hv::pguest_registers regs) -> void interrupt.vector = EXCEPTION_INVALID_OPCODE; interrupt.valid = true; __vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags); - break; + return; // dont advance rip... } default: // TODO: check out the vmexit reason and add support for it... diff --git a/gdt.cpp b/gdt.cpp index 3072bc4..3667704 100644 --- a/gdt.cpp +++ b/gdt.cpp @@ -25,13 +25,14 @@ namespace gdt const auto segment_descriptor = reinterpret_cast( - gdt_value.base_address + (selector.index << SEGMENT_SELECTOR_INDEX_BIT)); + gdt_value.base_address + (selector.idx << SEGMENT_SELECTOR_INDEX_BIT)); // access rights are spread out over the segment // descriptor so those need to picked out and assigned // to the vmx segment access rights variable... segment_info.limit = __segmentlimit(selector.flags); segment_info.rights = get_access_rights(segment_descriptor); + segment_info.segment_descriptor = *segment_descriptor; // base address of a segment is spread over the segment descriptor in 3 places. 2 parts of the // address are 8 bits each (1 byte each) and the lowest part of the address is 2 bytes (4 bytes in total)... @@ -55,18 +56,4 @@ namespace gdt 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 index ccfefd7..e1a5f0a 100644 --- a/gdt.hpp +++ b/gdt.hpp @@ -2,16 +2,11 @@ #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... + // index used for GDT per-core in vmxroot... + enum idx : u8 { es, ds, cs, gs, fs, ss, tr, ldt }; - 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; + auto get_info(const segment_descriptor_register_64& gdt_value, segment_selector segment) -> 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 ff78844..756b891 100644 --- a/hv_types.hpp +++ b/hv_types.hpp @@ -131,7 +131,8 @@ namespace hv { u64 offset_low : 16; u64 segment_selector : 16; - u64 reserved_0 : 8; + u64 ist_index : 3; + u64 reserved_0 : 5; u64 gate_type : 4; u64 storage_segment : 1; u64 dpl : 2; @@ -153,6 +154,30 @@ namespace hv }; }; + typedef struct _tss64 + { + u32 reserved_0; + u64 rsp_0; + u64 rsp_1; + u64 rsp_2; + void* interrupt_stack_table[8]; + u64 reserved_1; + u64 reserved_2; + u64 io_map_base; + } tss64, *ptss64; + + union segment_descriptor_addr_t + { + void* addr; + struct + { + u64 low : 16; + u64 middle : 8; + u64 high : 8; + u64 upper : 32; + }; + }; + union ia32_efer_t { unsigned __int64 control; @@ -444,6 +469,7 @@ namespace hv unsigned int shadow_vmcs_indicator : 1; } bits; } header; + unsigned int abort_indicator; char data[0x1000 - 2 * sizeof(unsigned)]; } vmcs_ctx, *pvmcs_ctx; @@ -458,18 +484,21 @@ namespace hv unsigned int revision_identifier : 31; } bits; } header; + char data[0x1000 - 1 * sizeof(unsigned)]; } vmxon_region_ctx, *pvmxon_region_ctx; typedef struct _vcpu_ctx { + pvmxon_region_ctx vmxon; pvmcs_ctx vmcs; - u64 vmcs_phys; - pvmxon_region_ctx vmxon; + u64 vmcs_phys; u64 vmxon_phys; - u64 host_stack; + + tss64 tss; + segment_descriptor_64 gdt[8]; } vcpu_ctx, * pvcpu_ctx; typedef struct _vmx_ctx @@ -480,6 +509,7 @@ namespace hv typedef struct _segment_info_ctx { + segment_descriptor_64 segment_descriptor; vmx_segment_access_rights rights; u64 limit; u64 base_addr; diff --git a/ia32.hpp b/ia32.hpp index eb01a7b..c3fd2c6 100644 --- a/ia32.hpp +++ b/ia32.hpp @@ -15872,7 +15872,7 @@ typedef union * of bytes in a segment descriptor) and adds the result to the base address of the GDT or LDT (from the GDTR or LDTR * register, respectively). */ - uint16_t index : 13; + uint16_t idx : 13; #define SEGMENT_SELECTOR_INDEX_BIT 3 #define SEGMENT_SELECTOR_INDEX_FLAG 0xFFF8 #define SEGMENT_SELECTOR_INDEX_MASK 0x1FFF @@ -19030,7 +19030,7 @@ typedef union /** * [Bits 9:1] Index. */ - uint16_t index : 9; + uint16_t idx : 9; #define VMCS_COMPONENT_ENCODING_INDEX_BIT 1 #define VMCS_COMPONENT_ENCODING_INDEX_FLAG 0x3FE #define VMCS_COMPONENT_ENCODING_INDEX_MASK 0x1FF @@ -21196,7 +21196,7 @@ typedef union * * @note The format of the error code is different for page-fault exceptions (#PF). */ - uint32_t index : 13; + uint32_t idx : 13; #define EXCEPTION_ERROR_CODE_INDEX_BIT 3 #define EXCEPTION_ERROR_CODE_INDEX_FLAG 0xFFF8 #define EXCEPTION_ERROR_CODE_INDEX_MASK 0x1FFF diff --git a/idt.cpp b/idt.cpp index 02f309a..70d30e2 100644 --- a/idt.cpp +++ b/idt.cpp @@ -2,29 +2,25 @@ void seh_handler(hv::pidt_regs_t regs) { + // probably not going to work since software interrupts are disabled? + __debugbreak(); return; } namespace idt { - auto create_entry(hv::idt_addr_t idt_handler) -> hv::idt_entry_t + auto create_entry(hv::idt_addr_t idt_handler, u8 ist_index) -> hv::idt_entry_t { hv::idt_entry_t result{}; result.segment_selector = readcs(); result.gate_type = SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE; result.present = true; + result.ist_index = ist_index; + result.dpl = 0; 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 da39154..15c12c4 100644 --- a/idt.hpp +++ b/idt.hpp @@ -12,7 +12,7 @@ namespace idt { __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; + inline void* image_base = nullptr; // used for SEH... + enum ist_idx : u8 { gp = 5, pf = 6, de = 7}; + auto create_entry(hv::idt_addr_t idt_handler, u8 ist_index) -> hv::idt_entry_t; } \ No newline at end of file diff --git a/idt_handlers.asm b/idt_handlers.asm index 228ec25..96019e3 100644 --- a/idt_handlers.asm +++ b/idt_handlers.asm @@ -4,6 +4,7 @@ extern seh_handler : proc __pf_handler proc __de_handler proc __gp_handler proc + int 3 push rax push rbx push rcx @@ -76,6 +77,7 @@ __gp_handler proc pop rcx pop rbx pop rax + add rsp, 8 iretq __gp_handler endp diff --git a/mm.cpp b/mm.cpp index 4cbe82f..7a80257 100644 --- a/mm.cpp +++ b/mm.cpp @@ -4,12 +4,12 @@ namespace mm { auto translate(virt_addr_t virt_addr) -> u64 { - + return {}; } - auto translate(virt_addr_t virt_addr, u64 pml4_phys, map_type type = map_type::src) -> u64 + auto translate(virt_addr_t virt_addr, u64 pml4_phys, map_type type) -> u64 { - + return {}; } auto map_page(u64 phys_addr, map_type type) -> u64 diff --git a/vmcs.cpp b/vmcs.cpp index dc5a929..c6060a2 100644 --- a/vmcs.cpp +++ b/vmcs.cpp @@ -5,62 +5,118 @@ namespace vmcs 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; - - __sidt(&idt_value); _sgdt(&gdt_value); __vmx_vmwrite(VMCS_HOST_CR0, __readcr0()); __vmx_vmwrite(VMCS_HOST_CR3, cr3_value.flags); __vmx_vmwrite(VMCS_HOST_CR4, __readcr4()); - // stack growns down... __vmx_vmwrite(VMCS_HOST_RSP, host_rsp + (PAGE_SIZE * HOST_STACK_PAGES)); __vmx_vmwrite(VMCS_HOST_RIP, reinterpret_cast(host_rip)); + + const auto current_vcpu = + vmxon::g_vmx_ctx->vcpus[KeGetCurrentProcessorNumber()]; - __vmx_vmwrite(VMCS_HOST_GDTR_BASE, gdt_value.base_address); - __vmx_vmwrite(VMCS_HOST_IDTR_BASE, idt_value.base_address); + __vmx_vmwrite(VMCS_HOST_GDTR_BASE, reinterpret_cast(current_vcpu->gdt)); + __vmx_vmwrite(VMCS_HOST_IDTR_BASE, reinterpret_cast(idt::table)); - // manual says that the priv level must be 0 and - // that the table flag also needs to be 0 so it uses the GDT... segment_selector es{ reades() }; es.request_privilege_level = NULL; es.table = NULL; + const auto [es_descriptor, es_rights, es_limit, es_base] = + gdt::get_info(gdt_value, es); + + es.idx = gdt::idx::es; + current_vcpu->gdt[gdt::idx::es] = es_descriptor; + __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, es.flags); + segment_selector cs{ readcs() }; cs.request_privilege_level = NULL; cs.table = NULL; + const auto [cs_descriptor, cs_rights, cs_limit, cs_base] = + gdt::get_info(gdt_value, cs); + + cs.idx = gdt::idx::cs; + current_vcpu->gdt[gdt::idx::cs] = cs_descriptor; + __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, cs.flags); + segment_selector ds{ readds() }; ds.request_privilege_level = NULL; ds.table = NULL; + const auto [ds_descriptor, ds_rights, ds_limit, ds_base] = + gdt::get_info(gdt_value, ds); + + ds.idx = gdt::idx::ds; + current_vcpu->gdt[gdt::idx::ds] = ds_descriptor; + __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, ds.flags); + segment_selector fs{ readfs() }; fs.request_privilege_level = NULL; fs.table = NULL; + const auto [fs_descriptor, fs_rights, fs_limit, fs_base] = + gdt::get_info(gdt_value, fs); + + fs.idx = gdt::idx::fs; + current_vcpu->gdt[gdt::idx::fs] = fs_descriptor; + __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, fs.flags); + __vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_FS_BASE)); + segment_selector gs{ readgs() }; gs.request_privilege_level = NULL; gs.table = NULL; + const auto [gs_descriptor, gs_rights, gs_limit, gs_base] = + gdt::get_info(gdt_value, gs); + + gs.idx = gdt::idx::gs; + current_vcpu->gdt[gdt::idx::gs] = gs_descriptor; + __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, gs.flags); + __vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE)); + segment_selector ss{ readss() }; ss.request_privilege_level = NULL; ss.table = NULL; + const auto [ss_descriptor, ss_rights, ss_limit, ss_base] = + gdt::get_info(gdt_value, ss); + + ss.idx = gdt::idx::ss; + current_vcpu->gdt[gdt::idx::ss] = ss_descriptor; + __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, ss.flags); + segment_selector tr{ readtr() }; tr.request_privilege_level = NULL; tr.table = NULL; - __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, es.flags); - __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, cs.flags); - __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, ds.flags); - __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, fs.flags); - __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, gs.flags); - __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, ss.flags); + const auto [tr_descriptor, tr_rights, tr_limit, tr_base] = + gdt::get_info(gdt_value, tr); + + tr.idx = gdt::idx::tr; + current_vcpu->gdt[gdt::idx::tr] = tr_descriptor; __vmx_vmwrite(VMCS_HOST_TR_SELECTOR, tr.flags); - // FS base is 0 on windows so no need to read it... - __vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE)); + // setup interrupt stack table... + // windows is using 1-4... im using 5-7... + memcpy(¤t_vcpu->tss, (void*)tr_base, sizeof hv::tss64); + + current_vcpu->tss.interrupt_stack_table[5] = + ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES); + + current_vcpu->tss.interrupt_stack_table[6] = + ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES); + + current_vcpu->tss.interrupt_stack_table[7] = + ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES); + + hv::segment_descriptor_addr_t tss_addr{ ¤t_vcpu->tss }; + current_vcpu->gdt[gdt::idx::tr].base_address_upper = tss_addr.upper; + current_vcpu->gdt[gdt::idx::tr].base_address_high = tss_addr.high; + current_vcpu->gdt[gdt::idx::tr].base_address_middle = tss_addr.middle; + current_vcpu->gdt[gdt::idx::tr].base_address_low = tss_addr.low; } auto setup_guest() -> void @@ -85,7 +141,7 @@ namespace vmcs __vmx_vmwrite(VMCS_GUEST_RFLAGS, __readeflags()); __vmx_vmwrite(VMCS_GUEST_DR7, __readdr(7)); - const auto [es_rights, es_limit, es_base] = + const auto [es_descriptor, es_rights, es_limit, es_base] = gdt::get_info(gdt_value, segment_selector{ reades() }); __vmx_vmwrite(VMCS_GUEST_ES_BASE, es_base); @@ -93,7 +149,7 @@ namespace vmcs __vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, reades()); __vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, es_rights.flags); - const auto [fs_rights, fs_limit, fs_base] = + const auto [fs_descriptor, fs_rights, fs_limit, fs_base] = gdt::get_info(gdt_value, segment_selector{ readfs() }); __vmx_vmwrite(VMCS_GUEST_FS_BASE, fs_base); @@ -101,7 +157,7 @@ namespace vmcs __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] = + const auto [gs_descriptor, gs_rights, gs_limit, gs_base] = gdt::get_info(gdt_value, segment_selector{ readgs() }); __vmx_vmwrite(VMCS_GUEST_GS_BASE, gs_base); @@ -109,7 +165,7 @@ namespace vmcs __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] = + const auto [ss_descriptor, ss_rights, ss_limit, ss_base] = gdt::get_info(gdt_value, segment_selector{ readss() }); __vmx_vmwrite(VMCS_GUEST_SS_BASE, ss_base); @@ -117,7 +173,7 @@ namespace vmcs __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] = + const auto [cs_descriptor, cs_rights, cs_limit, cs_base] = gdt::get_info(gdt_value, segment_selector{ readcs() }); __vmx_vmwrite(VMCS_GUEST_CS_BASE, cs_base); @@ -125,7 +181,7 @@ namespace vmcs __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, readcs()); __vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, cs_rights.flags); - const auto [ds_rights, ds_limit, ds_base] = + const auto [ds_descriptor, ds_rights, ds_limit, ds_base] = gdt::get_info(gdt_value, segment_selector{ readds() }); __vmx_vmwrite(VMCS_GUEST_DS_BASE, ds_base); @@ -133,7 +189,7 @@ namespace vmcs __vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, readds()); __vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, ds_rights.flags); - const auto [tr_rights, tr_limit, tr_base] = + const auto [tr_descriptor, tr_rights, tr_limit, tr_base] = gdt::get_info(gdt_value, segment_selector{ readtr() }); __vmx_vmwrite(VMCS_GUEST_TR_BASE, tr_base); @@ -141,7 +197,7 @@ namespace vmcs __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] = + const auto [ldt_descriptor, ldt_rights, ldt_limit, ldt_base] = gdt::get_info(gdt_value, segment_selector{ readldt() }); __vmx_vmwrite(VMCS_GUEST_LDTR_BASE, ldt_base); diff --git a/vmcs.hpp b/vmcs.hpp index 72f496d..d0fbe3b 100644 --- a/vmcs.hpp +++ b/vmcs.hpp @@ -2,6 +2,7 @@ #include "hv_types.hpp" #include "segment_intrin.h" #include "vmxexit_handler.h" +#include "vmxon.hpp" #include "gdt.hpp" #include "idt.hpp" diff --git a/vmxon.cpp b/vmxon.cpp index 4956930..361a2b3 100644 --- a/vmxon.cpp +++ b/vmxon.cpp @@ -58,40 +58,27 @@ namespace vmxon KeQueryActiveProcessorCountEx( ALL_PROCESSOR_GROUPS); - // allocate buffer for vcpu pointers... vmx_ctx->vcpus = reinterpret_cast( ExAllocatePool(NonPagedPool, 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_count; ++idx) { vmx_ctx->vcpus[idx] = reinterpret_cast( ExAllocatePool(NonPagedPool, sizeof hv::vcpu_ctx)); - // allocate host stack... vmx_ctx->vcpus[idx]->host_stack = reinterpret_cast( ExAllocatePool(NonPagedPool, PAGE_SIZE * HOST_STACK_PAGES)); - // zero host stack... RtlZeroMemory(reinterpret_cast( vmx_ctx->vcpus[idx]->host_stack), PAGE_SIZE * HOST_STACK_PAGES); - // setup VMCS and VMXON region... create_vmxon_region(vmx_ctx->vcpus[idx]); create_vmcs(vmx_ctx->vcpus[idx]); - - DBG_PRINT("setup vcpu for processor: %d\n", idx); - DBG_PRINT(" - vmxon region (virtual): 0x%p\n", vmx_ctx->vcpus[idx]->vmxon); - DBG_PRINT(" - vmxon region (physical): 0x%p\n", vmx_ctx->vcpus[idx]->vmxon_phys); - DBG_PRINT(" - vmcs (virtual): 0x%p\n", vmx_ctx->vcpus[idx]->vmcs); - DBG_PRINT(" - vmcs (physical): 0x%p\n", vmx_ctx->vcpus[idx]->vmcs_phys); - DBG_PRINT(" - host stack: 0x%p\n", vmx_ctx->vcpus[idx]->host_stack); } } @@ -102,14 +89,11 @@ namespace vmxon hv::cr0_t cr0 = { 0 }; hv::cr4_t cr4 = { 0 }; - // TODO: 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; @@ -124,7 +108,6 @@ namespace vmxon cr4.flags &= cr_fixed.split.low; __writecr4(cr4.flags); - // enable vmx instructions on this core... cr4.flags = __readcr4(); cr4.vmx_enable = true; __writecr4(cr4.flags); @@ -133,8 +116,5 @@ namespace vmxon __vmx_on((unsigned long long*) &vmxon::g_vmx_ctx->vcpus[ KeGetCurrentProcessorNumber()]->vmxon_phys); - - DBG_PRINT("vmxon for processor: %d\n", KeGetCurrentProcessorNumber()); - DBG_PRINT(" - vmxon result (0 == success): %d\n", vmxon_result); } } \ No newline at end of file