More cleanup

This commit is contained in:
momo5502 2022-04-03 10:58:31 +02:00
parent e9f0a14fff
commit 17e10a93ea
6 changed files with 187 additions and 285 deletions

View File

@ -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 include ksamd64.inc
.code
; -----------------------------------------------------
LEAF_ENTRY _str, _TEXT$00 LEAF_ENTRY _str, _TEXT$00
str word ptr [rcx] ; Store TR value str word ptr [rcx]
ret ; Return ret
LEAF_END _str, _TEXT$00 LEAF_END _str, _TEXT$00
; -----------------------------------------------------
LEAF_ENTRY _sldt, _TEXT$00 LEAF_ENTRY _sldt, _TEXT$00
sldt word ptr [rcx] ; Store LDTR value sldt word ptr [rcx]
ret ; Return ret
LEAF_END _sldt, _TEXT$00 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 __lgdt, _TEXT$00 LEAF_ENTRY __lgdt, _TEXT$00
lgdt fword ptr [rcx] ; load the GDTR with the value in parameter 1 lgdt fword ptr [rcx]
ret ; return ret
LEAF_END __lgdt, _TEXT$00 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] ;
mov rax, CxRax[rcx] ; LEAF_ENTRY restore_context, _TEXT$00
mov rdx, CxRdx[rcx] ; movaps xmm0, CxXmm0[rcx]
mov r8, CxR8[rcx] ; Restore volatile registers movaps xmm1, CxXmm1[rcx]
mov r9, CxR9[rcx] ; movaps xmm2, CxXmm2[rcx]
mov r10, CxR10[rcx] ; movaps xmm3, CxXmm3[rcx]
mov r11, CxR11[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 rbx, CxRbx[rcx] ; mov rax, CxRax[rcx]
mov rsi, CxRsi[rcx] ; mov rdx, CxRdx[rcx]
mov rdi, CxRdi[rcx] ; mov r8, CxR8[rcx]
mov rbp, CxRbp[rcx] ; Restore non volatile regsiters mov r9, CxR9[rcx]
mov r12, CxR12[rcx] ; mov r10, CxR10[rcx]
mov r13, CxR13[rcx] ; mov r11, CxR11[rcx]
mov r14, CxR14[rcx] ;
mov r15, CxR15[rcx] ;
cli ; Disable interrupts mov rbx, CxRbx[rcx]
push CxEFlags[rcx] ; Push RFLAGS on stack mov rsi, CxRsi[rcx]
popfq ; Restore RFLAGS mov rdi, CxRdi[rcx]
mov rsp, CxRsp[rcx] ; Restore old stack mov rbp, CxRbp[rcx]
push CxRip[rcx] ; Push RIP on old stack mov r12, CxR12[rcx]
mov rcx, CxRcx[rcx] ; Restore RCX since we spilled it mov r13, CxR13[rcx]
ret ; Restore RIP mov r14, CxR14[rcx]
LEAF_END ShvOsRestoreContext2, _TEXT$00 mov r15, CxR15[rcx]
cli
push CxEFlags[rcx]
popfq
mov rsp, CxRsp[rcx]
push CxRip[rcx]
mov rcx, CxRcx[rcx]
ret
LEAF_END restore_context, _TEXT$00
; -----------------------------------------------------
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 end

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "std_include.hpp"
#include "stdint.hpp" #include "stdint.hpp"
extern "C" { extern "C" {
@ -10,4 +11,6 @@ void __lgdt(void* gdtr);
void _sgdt(void*); void _sgdt(void*);
[[ noreturn ]] void restore_context(CONTEXT* context);
} }

View File

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

View File

@ -72,10 +72,43 @@ namespace
__lidt(&launch_context.special_registers.idtr.limit); __lidt(&launch_context.special_registers.idtr.limit);
} }
vmx::vm_state* resolve_vm_state_from_context(CONTEXT& context)
{
auto* context_address = reinterpret_cast<uint8_t*>(&context);
auto* vm_state_address = context_address + sizeof(CONTEXT) - KERNEL_STACK_SIZE;
return reinterpret_cast<vmx::vm_state*>(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() [[ noreturn ]] void resume_vmx()
{ {
__vmx_vmresume(); __vmx_vmresume();
} }
int32_t launch_vmx()
{
__vmx_vmlaunch();
const auto error_code = static_cast<int32_t>(read_vmx(VMCS_VM_INSTRUCTION_ERROR));
__vmx_off();
return error_code;
}
[[ noreturn ]] void restore_post_launch()
{
auto* context = static_cast<CONTEXT*>(_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() 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_SIZE 4096
#define MTRR_PAGE_MASK (~(MTRR_PAGE_SIZE-1)) #define MTRR_PAGE_MASK (~(MTRR_PAGE_SIZE-1))
@ -569,51 +562,6 @@ ShvUtilAdjustMsr(
return DesiredValue; 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 VOID
ShvVmxHandleInvd( ShvVmxHandleInvd(
VOID) VOID)
@ -656,7 +604,7 @@ ShvVmxHandleCpuid(
// //
if ((VpState->VpRegs->Rax == 0x41414141) && if ((VpState->VpRegs->Rax == 0x41414141) &&
(VpState->VpRegs->Rcx == 0x42424242) && (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; VpState->ExitVm = TRUE;
return; return;
@ -770,7 +718,7 @@ ShvVmxHandleExit(
// caused the exit. Since we are not doing any special handling or changing // caused the exit. Since we are not doing any special handling or changing
// of execution, this can be done for any exit reason. // 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); __vmx_vmwrite(VMCS_GUEST_RIP, VpState->GuestRip);
} }
@ -799,10 +747,10 @@ ShvVmxEntryHandler()
// of the general purpose registers come from the context structure that we // of the general purpose registers come from the context structure that we
// captured on our own with RtlCaptureContext in the assembly entrypoint. // captured on our own with RtlCaptureContext in the assembly entrypoint.
// //
guestContext.GuestEFlags = ShvVmxRead(VMCS_GUEST_RFLAGS); guestContext.GuestEFlags = read_vmx(VMCS_GUEST_RFLAGS);
guestContext.GuestRip = ShvVmxRead(VMCS_GUEST_RIP); guestContext.GuestRip = read_vmx(VMCS_GUEST_RIP);
guestContext.GuestRsp = ShvVmxRead(VMCS_GUEST_RSP); guestContext.GuestRsp = read_vmx(VMCS_GUEST_RSP);
guestContext.ExitReason = ShvVmxRead(VMCS_EXIT_REASON) & 0xFFFF; guestContext.ExitReason = read_vmx(VMCS_EXIT_REASON) & 0xFFFF;
guestContext.VpRegs = Context; guestContext.VpRegs = Context;
guestContext.ExitVm = FALSE; guestContext.ExitVm = FALSE;
@ -840,7 +788,7 @@ ShvVmxEntryHandler()
// correct value of the "guest" CR3, so that the currently executing // correct value of the "guest" CR3, so that the currently executing
// process continues to run with its expected address space mappings. // 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 // 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 // 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. // 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* launch_context = &VpData->launch_context;
auto* state = &launch_context->special_registers; auto* state = &launch_context->special_registers;
PCONTEXT context = &launch_context->context_frame; auto* context = &launch_context->context_frame;
vmx_gdt_entry vmxGdtEntry;
ept_pointer vmxEptp;
// //
// Begin by setting the link pointer to the required value for 4KB VMCS. // 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) if (launch_context->ept_controls.flags != 0)
{ {
// ept_pointer vmx_eptp{};
// Configure the EPTP vmx_eptp.flags = 0;
// vmx_eptp.page_walk_length = 3;
vmxEptp.flags = 0; vmx_eptp.memory_type = MEMORY_TYPE_WRITE_BACK;
vmxEptp.page_walk_length = 3; vmx_eptp.page_frame_number = launch_context->ept_pml4_physical_address / PAGE_SIZE;
vmxEptp.memory_type = MEMORY_TYPE_WRITE_BACK;
vmxEptp.page_frame_number = launch_context->ept_pml4_physical_address / PAGE_SIZE;
// __vmx_vmwrite(VMCS_CTRL_EPT_POINTER, vmx_eptp.flags);
// Load EPT Root Pointer
//
__vmx_vmwrite(VMCS_CTRL_EPT_POINTER, vmxEptp.flags);
//
// Set VPID to one
//
__vmx_vmwrite(VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER, 1); __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) // Load the CS Segment (Ring 0 Code)
// //
ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegCs, &vmxGdtEntry); vmx_gdt_entry vmx_gdt_entry{};
__vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, vmxGdtEntry.selector); ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegCs, &vmx_gdt_entry);
__vmx_vmwrite(VMCS_GUEST_CS_LIMIT, vmxGdtEntry.limit); __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, vmx_gdt_entry.selector);
__vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); __vmx_vmwrite(VMCS_GUEST_CS_LIMIT, vmx_gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_CS_BASE, vmxGdtEntry.base); __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); __vmx_vmwrite(VMCS_HOST_CS_SELECTOR, context->SegCs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK);
// //
// Load the SS Segment (Ring 0 Data) // Load the SS Segment (Ring 0 Data)
// //
ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegSs, &vmxGdtEntry); ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegSs, &vmx_gdt_entry);
__vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, vmxGdtEntry.selector); __vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, vmx_gdt_entry.selector);
__vmx_vmwrite(VMCS_GUEST_SS_LIMIT, vmxGdtEntry.limit); __vmx_vmwrite(VMCS_GUEST_SS_LIMIT, vmx_gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); __vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_SS_BASE, vmxGdtEntry.base); __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); __vmx_vmwrite(VMCS_HOST_SS_SELECTOR, context->SegSs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK);
// //
// Load the DS Segment (Ring 3 Data) // Load the DS Segment (Ring 3 Data)
// //
ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegDs, &vmxGdtEntry); ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegDs, &vmx_gdt_entry);
__vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, vmxGdtEntry.selector); __vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, vmx_gdt_entry.selector);
__vmx_vmwrite(VMCS_GUEST_DS_LIMIT, vmxGdtEntry.limit); __vmx_vmwrite(VMCS_GUEST_DS_LIMIT, vmx_gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); __vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_DS_BASE, vmxGdtEntry.base); __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); __vmx_vmwrite(VMCS_HOST_DS_SELECTOR, context->SegDs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK);
// //
// Load the ES Segment (Ring 3 Data) // Load the ES Segment (Ring 3 Data)
// //
ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegEs, &vmxGdtEntry); ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegEs, &vmx_gdt_entry);
__vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, vmxGdtEntry.selector); __vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, vmx_gdt_entry.selector);
__vmx_vmwrite(VMCS_GUEST_ES_LIMIT, vmxGdtEntry.limit); __vmx_vmwrite(VMCS_GUEST_ES_LIMIT, vmx_gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); __vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_ES_BASE, vmxGdtEntry.base); __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); __vmx_vmwrite(VMCS_HOST_ES_SELECTOR, context->SegEs & ~SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK);
// //
// Load the FS Segment (Ring 3 Compatibility-Mode TEB) // Load the FS Segment (Ring 3 Compatibility-Mode TEB)
// //
ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegFs, &vmxGdtEntry); ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegFs, &vmx_gdt_entry);
__vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, vmxGdtEntry.selector); __vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, vmx_gdt_entry.selector);
__vmx_vmwrite(VMCS_GUEST_FS_LIMIT, vmxGdtEntry.limit); __vmx_vmwrite(VMCS_GUEST_FS_LIMIT, vmx_gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_FS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); __vmx_vmwrite(VMCS_GUEST_FS_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_FS_BASE, vmxGdtEntry.base); __vmx_vmwrite(VMCS_GUEST_FS_BASE, vmx_gdt_entry.base);
__vmx_vmwrite(VMCS_HOST_FS_BASE, vmxGdtEntry.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); __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) // Load the GS Segment (Ring 3 Data if in Compatibility-Mode, MSR-based in Long Mode)
// //
ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegGs, &vmxGdtEntry); ShvUtilConvertGdtEntry(state->gdtr.base_address, context->SegGs, &vmx_gdt_entry);
__vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, vmxGdtEntry.selector); __vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, vmx_gdt_entry.selector);
__vmx_vmwrite(VMCS_GUEST_GS_LIMIT, vmxGdtEntry.limit); __vmx_vmwrite(VMCS_GUEST_GS_LIMIT, vmx_gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_GS_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); __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_GUEST_GS_BASE, state->msr_gs_base);
__vmx_vmwrite(VMCS_HOST_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); __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) // Load the Task Register (Ring 0 TSS)
// //
ShvUtilConvertGdtEntry(state->gdtr.base_address, state->tr, &vmxGdtEntry); ShvUtilConvertGdtEntry(state->gdtr.base_address, state->tr, &vmx_gdt_entry);
__vmx_vmwrite(VMCS_GUEST_TR_SELECTOR, vmxGdtEntry.selector); __vmx_vmwrite(VMCS_GUEST_TR_SELECTOR, vmx_gdt_entry.selector);
__vmx_vmwrite(VMCS_GUEST_TR_LIMIT, vmxGdtEntry.limit); __vmx_vmwrite(VMCS_GUEST_TR_LIMIT, vmx_gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_TR_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); __vmx_vmwrite(VMCS_GUEST_TR_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_TR_BASE, vmxGdtEntry.base); __vmx_vmwrite(VMCS_GUEST_TR_BASE, vmx_gdt_entry.base);
__vmx_vmwrite(VMCS_HOST_TR_BASE, vmxGdtEntry.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); __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) // Load the Local Descriptor Table (Ring 0 LDT on Redstone)
// //
ShvUtilConvertGdtEntry(state->gdtr.base_address, state->ldtr, &vmxGdtEntry); ShvUtilConvertGdtEntry(state->gdtr.base_address, state->ldtr, &vmx_gdt_entry);
__vmx_vmwrite(VMCS_GUEST_LDTR_SELECTOR, vmxGdtEntry.selector); __vmx_vmwrite(VMCS_GUEST_LDTR_SELECTOR, vmx_gdt_entry.selector);
__vmx_vmwrite(VMCS_GUEST_LDTR_LIMIT, vmxGdtEntry.limit); __vmx_vmwrite(VMCS_GUEST_LDTR_LIMIT, vmx_gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_LDTR_ACCESS_RIGHTS, vmxGdtEntry.access_rights.flags); __vmx_vmwrite(VMCS_GUEST_LDTR_ACCESS_RIGHTS, vmx_gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_LDTR_BASE, vmxGdtEntry.base); __vmx_vmwrite(VMCS_GUEST_LDTR_BASE, vmx_gdt_entry.base);
// //
// Now load the GDT itself // Now load the GDT itself
@ -1110,7 +1048,7 @@ void ShvVmxSetupVmcsForVp(vmx::vm_state* VpData)
// to inside of ShvVpInitialize. // to inside of ShvVpInitialize.
// //
__vmx_vmwrite(VMCS_GUEST_RSP, (uintptr_t)VpData->stack_buffer + KERNEL_STACK_SIZE - sizeof(CONTEXT)); __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<size_t>(restore_post_launch));
__vmx_vmwrite(VMCS_GUEST_RFLAGS, context->EFlags); __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 // processor to jump to ShvVpRestoreAfterLaunch on success, or return
// back to the caller on failure. // back to the caller on failure.
// //
return ShvVmxLaunch(); auto error_code = launch_vmx();
throw std::runtime_error("Failed to launch vmx");
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#ifdef NDEBUG #ifdef NDEBUG__
#define debug_log(...) #define debug_log(...)
#else #else
#define debug_log(msg, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[MOMO] " msg, __VA_ARGS__) #define debug_log(msg, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[MOMO] " msg, __VA_ARGS__)

View File

@ -3,7 +3,10 @@
#include <ntddk.h> #include <ntddk.h>
#include <intrin.h> #include <intrin.h>
#pragma warning(push)
#pragma warning(disable: 4201)
#include <ia32.hpp> #include <ia32.hpp>
#pragma warning(pop)
#include "stdint.hpp" #include "stdint.hpp"
#include "nt_ext.hpp" #include "nt_ext.hpp"