diff --git a/src/driver/assembly.asm b/src/driver/assembly.asm index 2717d80..9bc5a53 100644 --- a/src/driver/assembly.asm +++ b/src/driver/assembly.asm @@ -1,91 +1,97 @@ -;++ -; -; Copyright (c) Alex Ionescu. All rights reserved. -; -; Module: -; -; shvvmxhvx64.asm -; -; Abstract: -; -; This module implements AMD64-specific code for NT support of SimpleVisor. -; -; Author: -; -; Alex Ionescu (@aionescu) 16-Mar-2016 - Initial version -; -; Environment: -; -; Kernel mode only. -; -;-- - include ksamd64.inc - LEAF_ENTRY _str, _TEXT$00 - str word ptr [rcx] ; Store TR value - ret ; Return - LEAF_END _str, _TEXT$00 +.code - LEAF_ENTRY _sldt, _TEXT$00 - sldt word ptr [rcx] ; Store LDTR value - ret ; Return - LEAF_END _sldt, _TEXT$00 +; ----------------------------------------------------- - LEAF_ENTRY ShvVmxCleanup, _TEXT$00 - mov ds, cx ; set DS to parameter 1 - mov es, cx ; set ES to parameter 1 - mov fs, dx ; set FS to parameter 2 - ret ; return - LEAF_END ShvVmxCleanup, _TEXT$00 +LEAF_ENTRY _str, _TEXT$00 + str word ptr [rcx] + ret +LEAF_END _str, _TEXT$00 - LEAF_ENTRY __lgdt, _TEXT$00 - lgdt fword ptr [rcx] ; load the GDTR with the value in parameter 1 - ret ; return - LEAF_END __lgdt, _TEXT$00 +; ----------------------------------------------------- + +LEAF_ENTRY _sldt, _TEXT$00 + sldt word ptr [rcx] + ret +LEAF_END _sldt, _TEXT$00 + +; ----------------------------------------------------- + +LEAF_ENTRY __lgdt, _TEXT$00 + lgdt fword ptr [rcx] + ret +LEAF_END __lgdt, _TEXT$00 + +; ----------------------------------------------------- - LEAF_ENTRY ShvOsRestoreContext2, _TEXT$00 - movaps xmm0, CxXmm0[rcx] ; - movaps xmm1, CxXmm1[rcx] ; - movaps xmm2, CxXmm2[rcx] ; - movaps xmm3, CxXmm3[rcx] ; - movaps xmm4, CxXmm4[rcx] ; - movaps xmm5, CxXmm5[rcx] ; - movaps xmm6, CxXmm6[rcx] ; Restore all XMM registers - movaps xmm7, CxXmm7[rcx] ; - movaps xmm8, CxXmm8[rcx] ; - movaps xmm9, CxXmm9[rcx] ; - movaps xmm10, CxXmm10[rcx] ; - movaps xmm11, CxXmm11[rcx] ; - movaps xmm12, CxXmm12[rcx] ; - movaps xmm13, CxXmm13[rcx] ; - movaps xmm14, CxXmm14[rcx] ; - movaps xmm15, CxXmm15[rcx] ; - ldmxcsr CxMxCsr[rcx] ; +LEAF_ENTRY restore_context, _TEXT$00 + movaps xmm0, CxXmm0[rcx] + movaps xmm1, CxXmm1[rcx] + movaps xmm2, CxXmm2[rcx] + movaps xmm3, CxXmm3[rcx] + movaps xmm4, CxXmm4[rcx] + movaps xmm5, CxXmm5[rcx] + movaps xmm6, CxXmm6[rcx] + movaps xmm7, CxXmm7[rcx] + movaps xmm8, CxXmm8[rcx] + movaps xmm9, CxXmm9[rcx] + movaps xmm10, CxXmm10[rcx] + movaps xmm11, CxXmm11[rcx] + movaps xmm12, CxXmm12[rcx] + movaps xmm13, CxXmm13[rcx] + movaps xmm14, CxXmm14[rcx] + movaps xmm15, CxXmm15[rcx] + ldmxcsr CxMxCsr[rcx] - mov rax, CxRax[rcx] ; - mov rdx, CxRdx[rcx] ; - mov r8, CxR8[rcx] ; Restore volatile registers - mov r9, CxR9[rcx] ; - mov r10, CxR10[rcx] ; - mov r11, CxR11[rcx] ; + mov rax, CxRax[rcx] + mov rdx, CxRdx[rcx] + mov r8, CxR8[rcx] + mov r9, CxR9[rcx] + mov r10, CxR10[rcx] + mov r11, CxR11[rcx] - mov rbx, CxRbx[rcx] ; - mov rsi, CxRsi[rcx] ; - mov rdi, CxRdi[rcx] ; - mov rbp, CxRbp[rcx] ; Restore non volatile regsiters - mov r12, CxR12[rcx] ; - mov r13, CxR13[rcx] ; - mov r14, CxR14[rcx] ; - mov r15, CxR15[rcx] ; + mov rbx, CxRbx[rcx] + mov rsi, CxRsi[rcx] + mov rdi, CxRdi[rcx] + mov rbp, CxRbp[rcx] + mov r12, CxR12[rcx] + mov r13, CxR13[rcx] + mov r14, CxR14[rcx] + mov r15, CxR15[rcx] - cli ; Disable interrupts - push CxEFlags[rcx] ; Push RFLAGS on stack - popfq ; Restore RFLAGS - mov rsp, CxRsp[rcx] ; Restore old stack - push CxRip[rcx] ; Push RIP on old stack - mov rcx, CxRcx[rcx] ; Restore RCX since we spilled it - ret ; Restore RIP - LEAF_END ShvOsRestoreContext2, _TEXT$00 + cli + push CxEFlags[rcx] + popfq + mov rsp, CxRsp[rcx] + push CxRip[rcx] + mov rcx, CxRcx[rcx] + ret +LEAF_END restore_context, _TEXT$00 - end \ No newline at end of file +; ----------------------------------------------------- + +extern ShvVmxEntryHandler:proc +extern RtlCaptureContext:proc + +; ----------------------------------------------------- + +ShvVmxEntry PROC + push rcx + lea rcx, [rsp+8h] + + sub rsp, 30h + call RtlCaptureContext + add rsp, 30h + + mov rcx, [rsp+CxRsp+8h] + add rcx, 8h + mov [rsp+CxRsp+8h], rcx + + pop rcx + mov [rsp+CxRcx], rcx + + jmp ShvVmxEntryHandler +ShvVmxEntry ENDP + +end diff --git a/src/driver/assembly.hpp b/src/driver/assembly.hpp index 2c8b917..d1fb185 100644 --- a/src/driver/assembly.hpp +++ b/src/driver/assembly.hpp @@ -1,4 +1,5 @@ #pragma once +#include "std_include.hpp" #include "stdint.hpp" extern "C" { @@ -10,4 +11,6 @@ void __lgdt(void* gdtr); void _sgdt(void*); +[[ noreturn ]] void restore_context(CONTEXT* context); + } diff --git a/src/driver/assembly2.asm b/src/driver/assembly2.asm deleted file mode 100644 index a5550a9..0000000 --- a/src/driver/assembly2.asm +++ /dev/null @@ -1,49 +0,0 @@ -;++ -; -; Copyright (c) Alex Ionescu. All rights reserved. -; -; Module: -; -; shvvmxhvx64.asm -; -; Abstract: -; -; This module implements the AMD64-specific SimpleVisor VMENTRY routine. -; -; Author: -; -; Alex Ionescu (@aionescu) 16-Mar-2016 - Initial version -; -; Environment: -; -; Kernel mode only. -; -;-- - -include ksamd64.inc - - .code - - extern ShvVmxEntryHandler:proc - extern ShvOsCaptureContext:proc - - ShvVmxEntry PROC - push rcx ; save the RCX register, which we spill below - lea rcx, [rsp+8h] ; store the context in the stack, bias for - ; the return address and the push we just did. - sub rsp, 30h - call ShvOsCaptureContext - add rsp, 30h - mov rcx, [rsp+CxRsp+8h] - add rcx, 8h - mov [rsp+CxRsp+8h], rcx - - pop rcx - mov [rsp+CxRcx], rcx - - jmp ShvVmxEntryHandler ; jump to the C code handler. we assume that it - ; compiled with optimizations and does not use - ; home space, which is true of release builds. - ShvVmxEntry ENDP - - end diff --git a/src/driver/hypervisor.cpp b/src/driver/hypervisor.cpp index f9d4c80..ae87071 100644 --- a/src/driver/hypervisor.cpp +++ b/src/driver/hypervisor.cpp @@ -72,10 +72,43 @@ namespace __lidt(&launch_context.special_registers.idtr.limit); } + vmx::vm_state* resolve_vm_state_from_context(CONTEXT& context) + { + auto* context_address = reinterpret_cast(&context); + auto* vm_state_address = context_address + sizeof(CONTEXT) - KERNEL_STACK_SIZE; + return reinterpret_cast(vm_state_address); + } + + uintptr_t read_vmx(const uint32_t vmcs_field_id) + { + size_t data{}; + __vmx_vmread(vmcs_field_id, &data); + return data; + } + [[ noreturn ]] void resume_vmx() { __vmx_vmresume(); } + + int32_t launch_vmx() + { + __vmx_vmlaunch(); + + const auto error_code = static_cast(read_vmx(VMCS_VM_INSTRUCTION_ERROR)); + __vmx_off(); + + return error_code; + } + + [[ noreturn ]] void restore_post_launch() + { + auto* context = static_cast(_AddressOfReturnAddress()); + auto* vm_state = resolve_vm_state_from_context(*context); + + vm_state->launch_context.context_frame.EFlags |= EFLAGS_ALIGNMENT_CHECK_FLAG_FLAG; + restore_context(&vm_state->launch_context.context_frame); + } } hypervisor::hypervisor() @@ -167,46 +200,6 @@ bool hypervisor::try_enable_core(const uint64_t system_directory_table_base) } } -uintptr_t -FORCEINLINE -ShvVmxRead( - _In_ UINT32 VmcsFieldId -) -{ - size_t FieldData; - - // - // Because VMXREAD returns an error code, and not the data, it is painful - // to use in most circumstances. This simple function simplifies it use. - // - __vmx_vmread(VmcsFieldId, &FieldData); - return FieldData; -} - -INT32 -ShvVmxLaunch( - VOID) -{ - INT32 failureCode; - - // - // Launch the VMCS - // - __vmx_vmlaunch(); - - // - // If we got here, either VMCS setup failed in some way, or the launch - // did not proceed as planned. - // - failureCode = (INT32)ShvVmxRead(VMCS_VM_INSTRUCTION_ERROR); - __vmx_off(); - - // - // Return the error back to the caller - // - return failureCode; -} - #define MTRR_PAGE_SIZE 4096 #define MTRR_PAGE_MASK (~(MTRR_PAGE_SIZE-1)) @@ -569,51 +562,6 @@ ShvUtilAdjustMsr( return DesiredValue; } -extern "C" VOID -ShvOsCaptureContext( - _In_ PCONTEXT ContextRecord -) -{ - // - // Windows provides a nice OS function to do this - // - RtlCaptureContext(ContextRecord); -} - -extern "C" DECLSPEC_NORETURN -VOID -__cdecl -ShvOsRestoreContext2( - _In_ PCONTEXT ContextRecord, - _In_opt_ struct _EXCEPTION_RECORD* ExceptionRecord -); - -DECLSPEC_NORETURN -VOID -ShvVpRestoreAfterLaunch( - VOID) -{ - // - // Get the per-processor data. This routine temporarily executes on the - // same stack as the hypervisor (using no real stack space except the home - // registers), so we can retrieve the VP the same way the hypervisor does. - // - auto* vpData = (vmx::vm_state*)((uintptr_t)_AddressOfReturnAddress() + sizeof(CONTEXT) - KERNEL_STACK_SIZE); - - // - // Record that VMX is now enabled by returning back to ShvVpInitialize with - // the Alignment Check (AC) bit set. - // - vpData->launch_context.context_frame.EFlags |= EFLAGS_ALIGNMENT_CHECK_FLAG_FLAG; - - // - // And finally, restore the context, so that all register and stack - // state is finally restored. - // - ShvOsRestoreContext2(&vpData->launch_context.context_frame, nullptr); -} - - VOID ShvVmxHandleInvd( VOID) @@ -656,7 +604,7 @@ ShvVmxHandleCpuid( // if ((VpState->VpRegs->Rax == 0x41414141) && (VpState->VpRegs->Rcx == 0x42424242) && - ((ShvVmxRead(VMCS_GUEST_CS_SELECTOR) & SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM)) + ((read_vmx(VMCS_GUEST_CS_SELECTOR) & SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM)) { VpState->ExitVm = TRUE; return; @@ -770,7 +718,7 @@ ShvVmxHandleExit( // caused the exit. Since we are not doing any special handling or changing // of execution, this can be done for any exit reason. // - VpState->GuestRip += ShvVmxRead(VMCS_VMEXIT_INSTRUCTION_LENGTH); + VpState->GuestRip += read_vmx(VMCS_VMEXIT_INSTRUCTION_LENGTH); __vmx_vmwrite(VMCS_GUEST_RIP, VpState->GuestRip); } @@ -799,10 +747,10 @@ ShvVmxEntryHandler() // of the general purpose registers come from the context structure that we // captured on our own with RtlCaptureContext in the assembly entrypoint. // - guestContext.GuestEFlags = ShvVmxRead(VMCS_GUEST_RFLAGS); - guestContext.GuestRip = ShvVmxRead(VMCS_GUEST_RIP); - guestContext.GuestRsp = ShvVmxRead(VMCS_GUEST_RSP); - guestContext.ExitReason = ShvVmxRead(VMCS_EXIT_REASON) & 0xFFFF; + guestContext.GuestEFlags = read_vmx(VMCS_GUEST_RFLAGS); + guestContext.GuestRip = read_vmx(VMCS_GUEST_RIP); + guestContext.GuestRsp = read_vmx(VMCS_GUEST_RSP); + guestContext.ExitReason = read_vmx(VMCS_EXIT_REASON) & 0xFFFF; guestContext.VpRegs = Context; guestContext.ExitVm = FALSE; @@ -840,7 +788,7 @@ ShvVmxEntryHandler() // correct value of the "guest" CR3, so that the currently executing // process continues to run with its expected address space mappings. // - __writecr3(ShvVmxRead(VMCS_GUEST_CR3)); + __writecr3(read_vmx(VMCS_GUEST_CR3)); // // Finally, restore the stack, instruction pointer and EFLAGS to the @@ -875,7 +823,7 @@ ShvVmxEntryHandler() // which we use in case an exit was requested. In this case VMX must now be // off, and this will look like a longjmp to the original stack and RIP. // - ShvOsRestoreContext2(Context, nullptr); + restore_context(Context); } @@ -887,9 +835,7 @@ void ShvVmxSetupVmcsForVp(vmx::vm_state* VpData) { auto* launch_context = &VpData->launch_context; auto* state = &launch_context->special_registers; - PCONTEXT context = &launch_context->context_frame; - vmx_gdt_entry vmxGdtEntry; - ept_pointer vmxEptp; + auto* context = &launch_context->context_frame; // // Begin by setting the link pointer to the required value for 4KB VMCS. @@ -901,22 +847,13 @@ void ShvVmxSetupVmcsForVp(vmx::vm_state* VpData) // if (launch_context->ept_controls.flags != 0) { - // - // Configure the EPTP - // - vmxEptp.flags = 0; - vmxEptp.page_walk_length = 3; - vmxEptp.memory_type = MEMORY_TYPE_WRITE_BACK; - vmxEptp.page_frame_number = launch_context->ept_pml4_physical_address / PAGE_SIZE; + ept_pointer vmx_eptp{}; + vmx_eptp.flags = 0; + vmx_eptp.page_walk_length = 3; + vmx_eptp.memory_type = MEMORY_TYPE_WRITE_BACK; + vmx_eptp.page_frame_number = launch_context->ept_pml4_physical_address / PAGE_SIZE; - // - // Load EPT Root Pointer - // - __vmx_vmwrite(VMCS_CTRL_EPT_POINTER, vmxEptp.flags); - - // - // Set VPID to one - // + __vmx_vmwrite(VMCS_CTRL_EPT_POINTER, vmx_eptp.flags); __vmx_vmwrite(VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER, 1); } @@ -983,61 +920,62 @@ void ShvVmxSetupVmcsForVp(vmx::vm_state* VpData) // // Load the CS Segment (Ring 0 Code) // - ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegCs, &vmxGdtEntry); - __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, vmxGdtEntry.selector); - __vmx_vmwrite(VMCS_GUEST_CS_LIMIT, vmxGdtEntry.limit); - __vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); - __vmx_vmwrite(VMCS_GUEST_CS_BASE, vmxGdtEntry.base); + vmx_gdt_entry vmx_gdt_entry{}; + ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegCs, &vmx_gdt_entry); + __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, vmx_gdt_entry.selector); + __vmx_vmwrite(VMCS_GUEST_CS_LIMIT, vmx_gdt_entry.limit); + __vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags); + __vmx_vmwrite(VMCS_GUEST_CS_BASE, vmx_gdt_entry.base); __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, context->SegCs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK); // // Load the SS Segment (Ring 0 Data) // - ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegSs, &vmxGdtEntry); - __vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, vmxGdtEntry.selector); - __vmx_vmwrite(VMCS_GUEST_SS_LIMIT, vmxGdtEntry.limit); - __vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); - __vmx_vmwrite(VMCS_GUEST_SS_BASE, vmxGdtEntry.base); + ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegSs, &vmx_gdt_entry); + __vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, vmx_gdt_entry.selector); + __vmx_vmwrite(VMCS_GUEST_SS_LIMIT, vmx_gdt_entry.limit); + __vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags); + __vmx_vmwrite(VMCS_GUEST_SS_BASE, vmx_gdt_entry.base); __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, context->SegSs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK); // // Load the DS Segment (Ring 3 Data) // - ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegDs, &vmxGdtEntry); - __vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, vmxGdtEntry.selector); - __vmx_vmwrite(VMCS_GUEST_DS_LIMIT, vmxGdtEntry.limit); - __vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); - __vmx_vmwrite(VMCS_GUEST_DS_BASE, vmxGdtEntry.base); + ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegDs, &vmx_gdt_entry); + __vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, vmx_gdt_entry.selector); + __vmx_vmwrite(VMCS_GUEST_DS_LIMIT, vmx_gdt_entry.limit); + __vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags); + __vmx_vmwrite(VMCS_GUEST_DS_BASE, vmx_gdt_entry.base); __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, context->SegDs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK); // // Load the ES Segment (Ring 3 Data) // - ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegEs, &vmxGdtEntry); - __vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, vmxGdtEntry.selector); - __vmx_vmwrite(VMCS_GUEST_ES_LIMIT, vmxGdtEntry.limit); - __vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); - __vmx_vmwrite(VMCS_GUEST_ES_BASE, vmxGdtEntry.base); + ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegEs, &vmx_gdt_entry); + __vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, vmx_gdt_entry.selector); + __vmx_vmwrite(VMCS_GUEST_ES_LIMIT, vmx_gdt_entry.limit); + __vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags); + __vmx_vmwrite(VMCS_GUEST_ES_BASE, vmx_gdt_entry.base); __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, context->SegEs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK); // // Load the FS Segment (Ring 3 Compatibility-Mode TEB) // - ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegFs, &vmxGdtEntry); - __vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, vmxGdtEntry.selector); - __vmx_vmwrite(VMCS_GUEST_FS_LIMIT, vmxGdtEntry.limit); - __vmx_vmwrite(VMCS_GUEST_FS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); - __vmx_vmwrite(VMCS_GUEST_FS_BASE, vmxGdtEntry.base); - __vmx_vmwrite(VMCS_HOST_FS_BASE, vmxGdtEntry.base); + ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegFs, &vmx_gdt_entry); + __vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, vmx_gdt_entry.selector); + __vmx_vmwrite(VMCS_GUEST_FS_LIMIT, vmx_gdt_entry.limit); + __vmx_vmwrite(VMCS_GUEST_FS_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags); + __vmx_vmwrite(VMCS_GUEST_FS_BASE, vmx_gdt_entry.base); + __vmx_vmwrite(VMCS_HOST_FS_BASE, vmx_gdt_entry.base); __vmx_vmwrite(VMCS_HOST_FS_SELECTOR, context->SegFs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK); // // Load the GS Segment (Ring 3 Data if in Compatibility-Mode, MSR-based in Long Mode) // - ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegGs, &vmxGdtEntry); - __vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, vmxGdtEntry.selector); - __vmx_vmwrite(VMCS_GUEST_GS_LIMIT, vmxGdtEntry.limit); - __vmx_vmwrite(VMCS_GUEST_GS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); + ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegGs, &vmx_gdt_entry); + __vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, vmx_gdt_entry.selector); + __vmx_vmwrite(VMCS_GUEST_GS_LIMIT, vmx_gdt_entry.limit); + __vmx_vmwrite(VMCS_GUEST_GS_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags); __vmx_vmwrite(VMCS_GUEST_GS_BASE, state->msr_gs_base); __vmx_vmwrite(VMCS_HOST_GS_BASE, state->msr_gs_base); __vmx_vmwrite(VMCS_HOST_GS_SELECTOR, context->SegGs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK); @@ -1045,22 +983,22 @@ void ShvVmxSetupVmcsForVp(vmx::vm_state* VpData) // // Load the Task Register (Ring 0 TSS) // - ShvUtilConvertGdtEntry(state->gdtr.base_address, state->tr, &vmxGdtEntry); - __vmx_vmwrite(VMCS_GUEST_TR_SELECTOR, vmxGdtEntry.selector); - __vmx_vmwrite(VMCS_GUEST_TR_LIMIT, vmxGdtEntry.limit); - __vmx_vmwrite(VMCS_GUEST_TR_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); - __vmx_vmwrite(VMCS_GUEST_TR_BASE, vmxGdtEntry.base); - __vmx_vmwrite(VMCS_HOST_TR_BASE, vmxGdtEntry.base); + ShvUtilConvertGdtEntry(state->gdtr.base_address, state->tr, &vmx_gdt_entry); + __vmx_vmwrite(VMCS_GUEST_TR_SELECTOR, vmx_gdt_entry.selector); + __vmx_vmwrite(VMCS_GUEST_TR_LIMIT, vmx_gdt_entry.limit); + __vmx_vmwrite(VMCS_GUEST_TR_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags); + __vmx_vmwrite(VMCS_GUEST_TR_BASE, vmx_gdt_entry.base); + __vmx_vmwrite(VMCS_HOST_TR_BASE, vmx_gdt_entry.base); __vmx_vmwrite(VMCS_HOST_TR_SELECTOR, state->tr & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK); // // Load the Local Descriptor Table (Ring 0 LDT on Redstone) // - ShvUtilConvertGdtEntry(state->gdtr.base_address, state->ldtr, &vmxGdtEntry); - __vmx_vmwrite(VMCS_GUEST_LDTR_SELECTOR, vmxGdtEntry.selector); - __vmx_vmwrite(VMCS_GUEST_LDTR_LIMIT, vmxGdtEntry.limit); - __vmx_vmwrite(VMCS_GUEST_LDTR_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); - __vmx_vmwrite(VMCS_GUEST_LDTR_BASE, vmxGdtEntry.base); + ShvUtilConvertGdtEntry(state->gdtr.base_address, state->ldtr, &vmx_gdt_entry); + __vmx_vmwrite(VMCS_GUEST_LDTR_SELECTOR, vmx_gdt_entry.selector); + __vmx_vmwrite(VMCS_GUEST_LDTR_LIMIT, vmx_gdt_entry.limit); + __vmx_vmwrite(VMCS_GUEST_LDTR_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags); + __vmx_vmwrite(VMCS_GUEST_LDTR_BASE, vmx_gdt_entry.base); // // Now load the GDT itself @@ -1110,7 +1048,7 @@ void ShvVmxSetupVmcsForVp(vmx::vm_state* VpData) // to inside of ShvVpInitialize. // __vmx_vmwrite(VMCS_GUEST_RSP, (uintptr_t)VpData->stack_buffer + KERNEL_STACK_SIZE - sizeof(CONTEXT)); - __vmx_vmwrite(VMCS_GUEST_RIP, (uintptr_t)ShvVpRestoreAfterLaunch); + __vmx_vmwrite(VMCS_GUEST_RIP, reinterpret_cast(restore_post_launch)); __vmx_vmwrite(VMCS_GUEST_RFLAGS, context->EFlags); // @@ -1167,7 +1105,8 @@ INT32 ShvVmxLaunchOnVp(vmx::vm_state* VpData) // processor to jump to ShvVpRestoreAfterLaunch on success, or return // back to the caller on failure. // - return ShvVmxLaunch(); + auto error_code = launch_vmx(); + throw std::runtime_error("Failed to launch vmx"); } diff --git a/src/driver/logging.hpp b/src/driver/logging.hpp index 3217732..e13d1d4 100644 --- a/src/driver/logging.hpp +++ b/src/driver/logging.hpp @@ -1,6 +1,6 @@ #pragma once -#ifdef NDEBUG +#ifdef NDEBUG__ #define debug_log(...) #else #define debug_log(msg, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[MOMO] " msg, __VA_ARGS__) diff --git a/src/driver/std_include.hpp b/src/driver/std_include.hpp index cff740a..e3c7e22 100644 --- a/src/driver/std_include.hpp +++ b/src/driver/std_include.hpp @@ -3,7 +3,10 @@ #include #include +#pragma warning(push) +#pragma warning(disable: 4201) #include +#pragma warning(pop) #include "stdint.hpp" #include "nt_ext.hpp"