mirror of
https://github.com/momo5502/hypervisor.git
synced 2025-04-20 14:05:45 +00:00
More cleanup
This commit is contained in:
parent
e9f0a14fff
commit
17e10a93ea
@ -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
|
||||||
|
|
||||||
LEAF_ENTRY _str, _TEXT$00
|
.code
|
||||||
str word ptr [rcx] ; Store TR value
|
|
||||||
ret ; Return
|
|
||||||
LEAF_END _str, _TEXT$00
|
|
||||||
|
|
||||||
LEAF_ENTRY _sldt, _TEXT$00
|
; -----------------------------------------------------
|
||||||
sldt word ptr [rcx] ; Store LDTR value
|
|
||||||
ret ; Return
|
|
||||||
LEAF_END _sldt, _TEXT$00
|
|
||||||
|
|
||||||
LEAF_ENTRY ShvVmxCleanup, _TEXT$00
|
LEAF_ENTRY _str, _TEXT$00
|
||||||
mov ds, cx ; set DS to parameter 1
|
str word ptr [rcx]
|
||||||
mov es, cx ; set ES to parameter 1
|
ret
|
||||||
mov fs, dx ; set FS to parameter 2
|
LEAF_END _str, _TEXT$00
|
||||||
ret ; return
|
|
||||||
LEAF_END ShvVmxCleanup, _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 ShvOsRestoreContext2, _TEXT$00
|
LEAF_ENTRY _sldt, _TEXT$00
|
||||||
movaps xmm0, CxXmm0[rcx] ;
|
sldt word ptr [rcx]
|
||||||
movaps xmm1, CxXmm1[rcx] ;
|
ret
|
||||||
movaps xmm2, CxXmm2[rcx] ;
|
LEAF_END _sldt, _TEXT$00
|
||||||
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] ;
|
; -----------------------------------------------------
|
||||||
mov rdx, CxRdx[rcx] ;
|
|
||||||
mov r8, CxR8[rcx] ; Restore volatile registers
|
|
||||||
mov r9, CxR9[rcx] ;
|
|
||||||
mov r10, CxR10[rcx] ;
|
|
||||||
mov r11, CxR11[rcx] ;
|
|
||||||
|
|
||||||
mov rbx, CxRbx[rcx] ;
|
LEAF_ENTRY __lgdt, _TEXT$00
|
||||||
mov rsi, CxRsi[rcx] ;
|
lgdt fword ptr [rcx]
|
||||||
mov rdi, CxRdi[rcx] ;
|
ret
|
||||||
mov rbp, CxRbp[rcx] ; Restore non volatile regsiters
|
LEAF_END __lgdt, _TEXT$00
|
||||||
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
|
|
||||||
|
|
||||||
end
|
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]
|
||||||
|
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]
|
||||||
|
mov r12, CxR12[rcx]
|
||||||
|
mov r13, CxR13[rcx]
|
||||||
|
mov r14, CxR14[rcx]
|
||||||
|
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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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__)
|
||||||
|
@ -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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user