fixed TSS and IST issues... ISR's have their own RSP now...

merge-requests/1/head
_xeroxz 3 years ago
parent 4ce8e47684
commit a475ced8b9

@ -61,7 +61,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
<TreatLinkerWarningAsErrors>false</TreatLinkerWarningAsErrors>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
<EntryPointSymbol>drv_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -71,7 +71,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<TreatLinkerWarningAsErrors>false</TreatLinkerWarningAsErrors>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
<EntryPointSymbol>drv_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>

@ -29,15 +29,15 @@
<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>
<ClCompile Include="debug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gdt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="vmxon.hpp">
@ -70,10 +70,10 @@
<ClInclude Include="invd.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="gdt.hpp">
<ClInclude Include="debug.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="debug.hpp">
<ClInclude Include="gdt.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>

@ -1,4 +1,5 @@
#include <iostream>
#include <intrin.h>
#include "hypercall.h"
int main()

@ -1,18 +1,7 @@
#include "vmxlaunch.hpp"
#include "idt.hpp"
auto driver_unload(
PDRIVER_OBJECT driver_object
) -> void
{
// no unloading this hv... restart...
__debugbreak();
}
auto driver_entry(
PDRIVER_OBJECT driver_object,
PUNICODE_STRING registry_path
) -> NTSTATUS
auto drv_entry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path) -> NTSTATUS
{
vmxon::g_vmx_ctx =
reinterpret_cast<hv::pvmx_ctx>(
@ -58,9 +47,8 @@ auto driver_entry(
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);
idt::table[general_protection] = idt::create_entry(hv::idt_addr_t{ __gp_handler }, idt::ist_idx::gp);
idt::table[page_fault] = idt::create_entry(hv::idt_addr_t{ __pf_handler }, idt::ist_idx::pf);
// used for SEH in vmxroot fault handler...
idt::image_base = driver_object->DriverStart;
@ -73,7 +61,5 @@ auto driver_entry(
// vmxlaunch for all cores...
KeIpiGenericCall((PKIPI_BROADCAST_WORKER)&vmxlaunch::launch, NULL);
driver_object->DriverUnload = &driver_unload;
return STATUS_SUCCESS;
}

@ -11,8 +11,15 @@ auto exit_handler(hv::pguest_registers regs) -> void
{
if (regs->rcx == 0xC0FFEE)
{
regs->rax = 0xC0FFEE;
*(u8*)0x0 = 0xDE;
__try
{
*(u8*)0x0 = 0xDE;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
regs->rax = 0xC0FFEE;
break;
}
}
else
{
@ -31,8 +38,6 @@ auto exit_handler(hv::pguest_registers regs) -> void
value.high = regs->rdx;
value.low = regs->rax;
// can also validate the input instead of using
// reimplimented SEH...
__try
{
/*
@ -62,8 +67,6 @@ 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
{
/*
@ -95,8 +98,6 @@ 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);

@ -1,12 +1,8 @@
#pragma once
#include "hv_types.hpp"
#pragma section(".gdt", read, write)
namespace gdt
{
// index used for GDT per-core in vmxroot...
enum idx : u8 { es, ds, cs, gs, fs, ss, tr, ldt };
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;
}

@ -2,6 +2,7 @@
#include <ntifs.h>
#include <intrin.h>
#include "ia32.hpp"
#include <minwindef.h>
using u8 = unsigned char;
using u16 = unsigned short;
@ -29,6 +30,188 @@ extern "C" void _sgdt(void*);
#define HOST_STACK_PAGES 6
#define HOST_STACK_SIZE PAGE_SIZE * HOST_STACK_PAGES
// Export Directory
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
// Import Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
// Resource Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
// Exception Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
// Security Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
// Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
// Debug Directory
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
// Description String
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
// Machine Value (MIPS GP)
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
// TLS Directory
#define IMAGE_DIRECTORY_ENTRY_TLS 9
// Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
#define UNW_FLAG_NHANDLER 0
#define UNW_FLAG_EHANDLER 1
#define UNW_FLAG_UHANDLER 2
#define UNW_FLAG_CHAININFO 4
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
USHORT e_magic; // Magic number
USHORT e_cblp; // Bytes on last page of file
USHORT e_cp; // Pages in file
USHORT e_crlc; // Relocations
USHORT e_cparhdr; // Size of header in paragraphs
USHORT e_minalloc; // Minimum extra paragraphs needed
USHORT e_maxalloc; // Maximum extra paragraphs needed
USHORT e_ss; // Initial (relative) SS value
USHORT e_sp; // Initial SP value
USHORT e_csum; // Checksum
USHORT e_ip; // Initial IP value
USHORT e_cs; // Initial (relative) CS value
USHORT e_lfarlc; // File address of relocation table
USHORT e_ovno; // Overlay number
USHORT e_res[4]; // Reserved words
USHORT e_oemid; // OEM identifier (for e_oeminfo)
USHORT e_oeminfo; // OEM information; e_oemid specific
USHORT e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER {
short Machine;
short NumberOfSections;
unsigned TimeDateStamp;
unsigned PointerToSymbolTable;
unsigned NumberOfSymbols;
short SizeOfOptionalHeader;
short Characteristics;
} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
unsigned VirtualAddress;
unsigned Size;
} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;
typedef struct _IMAGE_OPTIONAL_HEADER64 {
short Magic;
unsigned char MajorLinkerVersion;
unsigned char MinorLinkerVersion;
unsigned SizeOfCode;
unsigned SizeOfInitializedData;
unsigned SizeOfUninitializedData;
unsigned AddressOfEntryPoint;
unsigned BaseOfCode;
ULONGLONG ImageBase;
unsigned SectionAlignment;
unsigned FileAlignment;
short MajorOperatingSystemVersion;
short MinorOperatingSystemVersion;
short MajorImageVersion;
short MinorImageVersion;
short MajorSubsystemVersion;
short MinorSubsystemVersion;
unsigned Win32VersionValue;
unsigned SizeOfImage;
unsigned SizeOfHeaders;
unsigned CheckSum;
short Subsystem;
short DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
unsigned LoaderFlags;
unsigned NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
} IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64;
typedef struct _IMAGE_NT_HEADERS64 {
unsigned Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, * PIMAGE_NT_HEADERS64;
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
unsigned long Characteristics; // 0 for terminating null import descriptor
unsigned long OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
} DUMMYUNIONNAME;
unsigned long TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
unsigned long ForwarderChain; // -1 if no forwarders
unsigned long Name;
unsigned long FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED* PIMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME {
unsigned long Hint;
CHAR Name[1];
} IMAGE_IMPORT_BY_NAME, * PIMAGE_IMPORT_BY_NAME;
typedef struct _IMAGE_THUNK_DATA64 {
union {
ULONGLONG ForwarderString; // PBYTE
ULONGLONG Function; // PDWORD
ULONGLONG Ordinal;
ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA64, * PIMAGE_THUNK_DATA64;
typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA;
typedef struct _SCOPE_RECORD {
UINT32 BeginAddress;
UINT32 EndAddress;
UINT32 HandlerAddress;
UINT32 JumpTarget;
} SCOPE_RECORD;
typedef struct _SCOPE_TABLE {
UINT32 Count;
SCOPE_RECORD ScopeRecords[1];
} SCOPE_TABLE;
typedef struct _RUNTIME_FUNCTION {
UINT32 BeginAddress;
UINT32 EndAddress;
UINT32 UnwindData;
} RUNTIME_FUNCTION;
#pragma warning(push)
#pragma warning(disable : 4200)
#pragma warning(disable : 4201)
#pragma warning(disable : 4214)
typedef union _UNWIND_CODE {
UINT8 CodeOffset;
UINT8 UnwindOp : 4;
UINT8 OpInfo : 4;
UINT16 FrameOffset;
} UNWIND_CODE;
typedef struct _UNWIND_INFO {
UINT8 Version : 3;
UINT8 Flags : 5;
UINT8 SizeOfProlog;
UINT8 CountOfCodes;
UINT8 FrameRegister : 4;
UINT8 FrameOffset : 4;
UNWIND_CODE UnwindCode[1];
union {
UINT32 ExceptionHandler;
UINT32 FunctionEntry;
};
UINT32 ExceptionData[];
} UNWIND_INFO;
#pragma warning(pop)
namespace hv
{
typedef struct _guest_registers
@ -133,8 +316,7 @@ namespace hv
u64 segment_selector : 16;
u64 ist_index : 3;
u64 reserved_0 : 5;
u64 gate_type : 4;
u64 storage_segment : 1;
u64 gate_type : 5;
u64 dpl : 2;
u64 present : 1;
u64 offset_middle : 16;
@ -156,14 +338,12 @@ namespace hv
typedef struct _tss64
{
u32 reserved_0;
u64 rsp_0;
u64 rsp_1;
u64 rsp_2;
void* interrupt_stack_table[8];
u32 reserved;
u64 privilege_stacks[3];
u64 reserved_1;
u64 reserved_2;
u64 io_map_base;
u64 interrupt_stack_table[7];
u16 reserved_2;
u16 iomap_base;
} tss64, *ptss64;
union segment_descriptor_addr_t
@ -492,13 +672,12 @@ namespace hv
{
pvmxon_region_ctx vmxon;
pvmcs_ctx vmcs;
u64 vmcs_phys;
u64 vmxon_phys;
u64 host_stack;
tss64 tss;
segment_descriptor_64 gdt[8];
segment_descriptor_64* gdt;
} vcpu_ctx, * pvcpu_ctx;
typedef struct _vmx_ctx

@ -2,44 +2,46 @@
auto seh_handler(hv::pidt_regs_t regs) -> void
{
__debugbreak();
/*const auto rva = regs->rip - reinterpret_cast<u64>(idt::image_base);
IMAGE_NT_HEADERS64* nt = (IMAGE_NT_HEADERS64*)(reinterpret_cast<u64>(idt::image_base) +
reinterpret_cast<IMAGE_DOS_HEADER>(idt::image_base).e_lfanew);
IMAGE_DATA_DIRECTORY* exception =
&nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
RUNTIME_FUNCTION* functions =
(RUNTIME_FUNCTION*)((UINT64)&__ImageBase + exception->VirtualAddress);
for (UINT32 i = 0; i < exception->Size / sizeof(RUNTIME_FUNCTION); ++i) {
RUNTIME_FUNCTION* function = &functions[i];
if (!(rva >= function->BeginAddress && rva < function->EndAddress)) {
const auto rva = regs->rip - reinterpret_cast<u64>(idt::image_base);
const auto nt_headers = reinterpret_cast<IMAGE_NT_HEADERS64*>(
reinterpret_cast<u64>(idt::image_base) +
reinterpret_cast<IMAGE_DOS_HEADER*>(idt::image_base)->e_lfanew);
const auto exception =
&nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
const auto functions =
reinterpret_cast<RUNTIME_FUNCTION*>(
reinterpret_cast<u64>(idt::image_base) + exception->VirtualAddress);
for (auto idx = 0; idx < exception->Size / sizeof(RUNTIME_FUNCTION); ++idx)
{
const auto function = &functions[idx];
if (!(rva >= function->BeginAddress && rva < function->EndAddress))
continue;
}
UNWIND_INFO* unwindInfo = (UNWIND_INFO*)((UINT64)&__ImageBase + function->UnwindData);
if (!(unwindInfo->Flags & UNW_FLAG_EHANDLER)) {
continue;
}
const auto unwind_info =
reinterpret_cast<UNWIND_INFO*>(
reinterpret_cast<u64>(idt::image_base) + function->UnwindData);
SCOPE_TABLE* scopeTable =
(SCOPE_TABLE*)((UINT64)&unwindInfo->UnwindCode[(unwindInfo->CountOfCodes + 1) & ~1] +
sizeof(UINT32));
for (UINT32 e = 0; e < scopeTable->Count; ++e) {
SCOPE_RECORD* scopeRecord = &scopeTable->ScopeRecords[e];
if (!(unwind_info->Flags & UNW_FLAG_EHANDLER))
continue;
if (rva >= scopeRecord->BeginAddress && rva < scopeRecord->EndAddress) {
*rip = (UINT64)&__ImageBase + scopeRecord->JumpTarget;
const auto scope_table =
reinterpret_cast<SCOPE_TABLE*>(
reinterpret_cast<u64>(&unwind_info->UnwindCode[
(unwind_info->CountOfCodes + 1) & ~1]) + sizeof(u32));
for (auto entry = 0; entry < scope_table->Count; ++entry)
{
const auto scope_record = &scope_table->ScopeRecords[entry];
if (rva >= scope_record->BeginAddress && rva < scope_record->EndAddress)
{
regs->rip = reinterpret_cast<u64>(idt::image_base) + scope_record->JumpTarget;
return;
}
}
}
*/
}
namespace idt
@ -47,11 +49,10 @@ namespace idt
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.segment_selector = readcs();
result.gate_type = SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE;
result.present = true;
result.ist_index = NULL;
result.dpl = 0;
//result.ist_index = ist_index;
result.offset_high = idt_handler.offset_high;
result.offset_middle = idt_handler.offset_middle;

@ -6,15 +6,14 @@
#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];
inline void* image_base = nullptr; // used for SEH...
enum ist_idx : u8 { gp = 5, pf = 6, de = 7};
enum ist_idx : u8 { de = 4, pf = 5, gp = 6};
inline void* image_base = nullptr; // used for SEH...
auto create_entry(hv::idt_addr_t idt_handler, u8 ist_index) -> hv::idt_entry_t;
}

@ -2,7 +2,6 @@ extern seh_handler : proc
.code
__pf_handler proc
__de_handler proc
__gp_handler proc
push rax
push rbx
@ -20,7 +19,7 @@ __gp_handler proc
push r14
push r15
sub rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment...
sub rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment... (you dont need any of these...)
movaps [rsp], xmm0
movaps [rsp + 010h], xmm1
movaps [rsp + 020h], xmm2
@ -59,7 +58,7 @@ __gp_handler proc
movups xmm13, [rsp + 0D0h]
movups xmm14, [rsp + 0E0h]
movups xmm15, [rsp + 0F0h]
add rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment...
add rsp, 0108h ; 16 xmm registers... and +8 bytes for alignment... (you dont need any of these...)
pop r15
pop r14
@ -80,6 +79,5 @@ __gp_handler proc
iretq
__gp_handler endp
__de_handler endp
__pf_handler endp
end

@ -2,121 +2,56 @@
namespace vmcs
{
auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value) -> void
auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value, u64 gdt_base) -> void
{
segment_descriptor_register_64 gdt_value;
_sgdt(&gdt_value);
__vmx_vmwrite(VMCS_HOST_CR0, __readcr0());
__vmx_vmwrite(VMCS_HOST_CR3, cr3_value.flags);
__vmx_vmwrite(VMCS_HOST_CR4, __readcr4());
__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_GDTR_BASE, gdt_base);
__vmx_vmwrite(VMCS_HOST_IDTR_BASE, reinterpret_cast<u64>(idt::table));
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;
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);
// 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

@ -3,12 +3,12 @@
#include "segment_intrin.h"
#include "vmxexit_handler.h"
#include "vmxon.hpp"
#include "gdt.hpp"
#include "idt.hpp"
#include "gdt.hpp"
namespace vmcs
{
auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value) -> void;
auto setup_host(void* host_rip, u64 host_rsp, cr3 cr3_value, u64 gdt_base) -> void;
auto setup_guest() -> void;
auto setup_controls() -> void;
}

@ -9,7 +9,34 @@ auto vmxlaunch::init_vmcs(cr3 cr3_value) -> void
__vmx_vmclear(&vcpu->vmcs_phys);
__vmx_vmptrld(&vcpu->vmcs_phys);
vmcs::setup_host(&vmxexit_handler, vcpu->host_stack, cr3_value);
segment_descriptor_register_64 gdt_value;
_sgdt(&gdt_value);
const auto [tr_descriptor, tr_rights, tr_limit, tr_base] =
gdt::get_info(gdt_value, segment_selector{ readtr() });
// copy windows TSS and windows GDT...
// change TSS base to new TSS...
hv::segment_descriptor_addr_t tss{ &vcpu->tss };
memcpy(&vcpu->tss, (void*)tr_base, sizeof hv::tss64);
memcpy(vcpu->gdt, (void*)gdt_value.base_address, PAGE_SIZE);
vcpu->tss.interrupt_stack_table[idt::ist_idx::pf] =
reinterpret_cast<u64>(ExAllocatePool(NonPagedPool,
PAGE_SIZE * HOST_STACK_PAGES)) + (PAGE_SIZE * HOST_STACK_PAGES);
vcpu->tss.interrupt_stack_table[idt::ist_idx::gp] =
reinterpret_cast<u64>(ExAllocatePool(NonPagedPool,
PAGE_SIZE * HOST_STACK_PAGES)) + (PAGE_SIZE * HOST_STACK_PAGES);
vcpu->gdt[segment_selector{ readtr() }.idx].base_address_upper = tss.upper;
vcpu->gdt[segment_selector{ readtr() }.idx].base_address_high = tss.high;
vcpu->gdt[segment_selector{ readtr() }.idx].base_address_middle = tss.middle;
vcpu->gdt[segment_selector{ readtr() }.idx].base_address_low = tss.low;
vmcs::setup_host(&vmxexit_handler,
vcpu->host_stack, cr3_value, (u64)vcpu->gdt);
vmcs::setup_guest();
vmcs::setup_controls();
}

@ -74,6 +74,10 @@ namespace vmxon
ExAllocatePool(NonPagedPool,
PAGE_SIZE * HOST_STACK_PAGES));
vmx_ctx->vcpus[idx]->gdt =
reinterpret_cast<segment_descriptor_64*>(
ExAllocatePool(NonPagedPool, PAGE_SIZE));
RtlZeroMemory(reinterpret_cast<void*>(
vmx_ctx->vcpus[idx]->host_stack), PAGE_SIZE * HOST_STACK_PAGES);
@ -84,16 +88,10 @@ namespace vmxon
auto init_vmxon() -> void
{
hv::ia32_feature_control_msr_t feature_msr = { 0 };
hv::cr_fixed_t cr_fixed;
hv::cr0_t cr0 = { 0 };
hv::cr4_t cr4 = { 0 };
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);
cr_fixed.all = __readmsr(IA32_VMX_CR0_FIXED0);
cr0.flags = __readcr0();
cr0.flags |= cr_fixed.split.low;
@ -108,10 +106,6 @@ namespace vmxon
cr4.flags &= cr_fixed.split.low;
__writecr4(cr4.flags);
cr4.flags = __readcr4();
cr4.vmx_enable = true;
__writecr4(cr4.flags);
const auto vmxon_result =
__vmx_on((unsigned long long*)
&vmxon::g_vmx_ctx->vcpus[

Loading…
Cancel
Save