cloning GDT, IDT and TSS... making modifications to the clone

merge-requests/1/head
_xeroxz 3 years ago
parent 0d63ad288a
commit 29c43d81bf

@ -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::ppte>(mm::pml4)[idx].present = true;
reinterpret_cast<mm::ppte>(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);

@ -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...

@ -25,13 +25,14 @@ namespace gdt
const auto segment_descriptor =
reinterpret_cast<segment_descriptor_64*>(
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;
}
}

@ -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;
}

@ -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;

@ -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

@ -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<u64>(idt::table);
}
}

@ -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;
}

@ -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

@ -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

@ -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<u64>(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<u64>(current_vcpu->gdt));
__vmx_vmwrite(VMCS_HOST_IDTR_BASE, reinterpret_cast<u64>(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(&current_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{ &current_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);

@ -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"

@ -58,40 +58,27 @@ namespace vmxon
KeQueryActiveProcessorCountEx(
ALL_PROCESSOR_GROUPS);
// allocate buffer for vcpu pointers...
vmx_ctx->vcpus =
reinterpret_cast<hv::pvcpu_ctx*>(
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<hv::pvcpu_ctx>(
ExAllocatePool(NonPagedPool, sizeof hv::vcpu_ctx));
// allocate host stack...
vmx_ctx->vcpus[idx]->host_stack =
reinterpret_cast<u64>(
ExAllocatePool(NonPagedPool,
PAGE_SIZE * HOST_STACK_PAGES));
// zero host stack...
RtlZeroMemory(reinterpret_cast<void*>(
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);
}
}
Loading…
Cancel
Save