added idt and gdt starter code...

merge-requests/1/head
_xeroxz 4 years ago
parent 0ddabe809e
commit 0d63ad288a

@ -83,18 +83,20 @@
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="entry.cpp" />
<ClCompile Include="drv_entry.cpp" />
<ClCompile Include="exit_handler.cpp" />
<ClCompile Include="gdt.cpp" />
<ClCompile Include="idt.cpp" />
<ClCompile Include="mm.cpp" />
<ClCompile Include="segment.cpp" />
<ClCompile Include="vmcs.cpp" />
<ClCompile Include="vmxlaunch.cpp" />
<ClCompile Include="vmxon.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="gdt.hpp" />
<ClInclude Include="ia32.hpp" />
<ClInclude Include="idt.hpp" />
<ClInclude Include="invd.hpp" />
<ClInclude Include="mm.hpp" />
<ClInclude Include="segment_intrin.h" />
<ClInclude Include="hv_types.hpp" />
@ -104,7 +106,8 @@
<ClInclude Include="vmxon.hpp" />
</ItemGroup>
<ItemGroup>
<MASM Include="idt_handler.asm" />
<MASM Include="idt_handlers.asm" />
<MASM Include="invd.asm" />
<MASM Include="segment_intrin.asm" />
<MASM Include="vmxexit_handler.asm" />
</ItemGroup>

@ -11,9 +11,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="entry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="vmxon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -26,15 +23,18 @@
<ClCompile Include="vmcs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="segment.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mm.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="idt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gdt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="drv_entry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="vmxon.hpp">
@ -64,6 +64,12 @@
<ClInclude Include="idt.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="invd.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="gdt.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<MASM Include="segment_intrin.asm">
@ -72,7 +78,10 @@
<MASM Include="vmxexit_handler.asm">
<Filter>Source Files</Filter>
</MASM>
<MASM Include="idt_handler.asm">
<MASM Include="invd.asm">
<Filter>Source Files</Filter>
</MASM>
<MASM Include="idt_handlers.asm">
<Filter>Source Files</Filter>
</MASM>
</ItemGroup>

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

@ -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<hv::pvmx_ctx>(
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;
}

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

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

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

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

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

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

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

@ -0,0 +1,6 @@
.code
__invd proc
invd
ret
__invd endp
end

@ -0,0 +1,2 @@
#pragma once
extern "C" void __invd(void);

@ -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<ppte>(vmxroot_pml4)
[result.pt_index].pfn = phys_addr >> 12;
__invlpg(result.value);
result.offset = virt_addr_t{ (void*)phys_addr }.offset;
return reinterpret_cast<u64>(result.value);
}
}

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

@ -9,9 +9,3 @@ 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;
}

@ -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<mm::ppml4e>(
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);

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

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

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

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

@ -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<hv::pvcpu_ctx*>(
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<hv::pvcpu_ctx>(

Loading…
Cancel
Save