Update comments
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Locates the image base from the current RIP value. This can be manually invoked
|
||||
# from the IDA Pro during the GDB remote debug session to load symbols (a PDB file).
|
||||
#
|
||||
# Author: Satoshi Tanda
|
||||
current_page_base = idaapi.get_reg_val('rip') & (~0xfff)
|
||||
offset = 0
|
||||
while idc.read_dbg_word(current_page_base - offset) != 0x5a4d:
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copies the lib files created by the EDK2's build command to a single specified
|
||||
# locations, so that Visual Studio can easily find and link them. Invoked as
|
||||
# part of Pre-Link Event of the MiniVisor project.
|
||||
#
|
||||
# Author: Satoshi Tanda
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
@@ -23,17 +23,17 @@ extern HandleVmExit : proc
|
||||
extern HandleVmExitFailure : proc
|
||||
|
||||
;
|
||||
; @brief An entry point for the hypervisor.
|
||||
; @brief The entry point for the hypervisor.
|
||||
;
|
||||
; @details The easiest way to understand this code is to see this as an entry
|
||||
; point of "VM-exit handler".
|
||||
;
|
||||
; Up on VM-exit, the processor starts executing this function as
|
||||
; condifured in the VmcsHostRip field of VMCS. At this time, the processor
|
||||
; is in the vmx-root mode, which allows the processor to execute any
|
||||
; instructions without causing VM-exit, and the processor is not governed
|
||||
; by EPT. The code executed from here emulates the instruction caused
|
||||
; VM-exit by, most typically, executing the same instruction on behalf of
|
||||
; configured in the Host RIP field of VMCS. When this function is executed,
|
||||
; the processor is in the vmx-root mode, which allows the processor to
|
||||
; execute any instructions without causing VM-exit, and the processor is
|
||||
; not governed by EPT. The code executed from here most typically emulates
|
||||
; the instruction caused VM-exit by executing the same instruction on behalf of
|
||||
; the guest (see HandleCpuid for example), or changing relevant processor
|
||||
; state and letting the guest retry, for example, handling EPT violation.
|
||||
;
|
||||
@@ -41,6 +41,8 @@ extern HandleVmExitFailure : proc
|
||||
; context. We also refer those code as a VM-exit handler.
|
||||
;
|
||||
AsmHypervisorEntryPoint proc frame
|
||||
;
|
||||
; Windows-specific:
|
||||
;
|
||||
; Three not-well known techniques are used in this function in oder for
|
||||
; Windbg to display the stack trace of the guest while the VM-exit
|
||||
@@ -177,9 +179,8 @@ ExitVm:
|
||||
|
||||
VmxError:
|
||||
;
|
||||
; Any of VMX instructions failed. Unrecoverble. The most useful thing
|
||||
; to do here is probably to call a C-function that does diagnostics
|
||||
; like dumping VMCS.
|
||||
; VMRESUME or VMXOFF instruction failed. Unrecoverble. The most useful
|
||||
; thing to do here is to call a C-function to diagnose the issue.
|
||||
;
|
||||
pushf
|
||||
PUSHAQ
|
||||
@@ -190,11 +191,11 @@ VmxError:
|
||||
AsmHypervisorEntryPoint endp
|
||||
|
||||
;
|
||||
; @brief Invalidate translations derived from EPT
|
||||
; @brief Invalidates translations derived from EPT
|
||||
;
|
||||
; @param[in] RCX - A type of invalidation.
|
||||
; @param[in] RCX - The type of invalidation.
|
||||
;
|
||||
; @param[in] RDX - A description of translations to invalidate.
|
||||
; @param[in] RDX - The description of translations to invalidate.
|
||||
;
|
||||
; @return An appropriate VMX_RESULT value.
|
||||
;
|
||||
@@ -221,11 +222,11 @@ ErrorWithoutCode:
|
||||
AsmInvept endp
|
||||
|
||||
;
|
||||
; @brief Invalidate translations based on VPID
|
||||
; @brief Invalidates translations based on VPID
|
||||
;
|
||||
; @param[in] RCX - A type of invalidation.
|
||||
; @param[in] RCX - The type of invalidation.
|
||||
;
|
||||
; @param[in] RDX - A description of translations to invalidate.
|
||||
; @param[in] RDX - The description of translations to invalidate.
|
||||
;
|
||||
; @return An appropriate VMX_RESULT value.
|
||||
;
|
||||
@@ -287,9 +288,9 @@ AsmVmxCall proc
|
||||
AsmVmxCall endp
|
||||
|
||||
;
|
||||
; @brief Returns the address of the return address from this function.
|
||||
; @brief Returns the return address from this function.
|
||||
;
|
||||
; @return The address of the return address from this function.
|
||||
; @return The return address from this function.
|
||||
;
|
||||
AsmGetCurrentInstructionPointer proc
|
||||
mov rax, [rsp]
|
||||
|
||||
@@ -10,28 +10,27 @@
|
||||
#pragma once
|
||||
#include "Common.h"
|
||||
|
||||
#if defined(NTDDI_VERSION)
|
||||
#if defined(MV_PLATFORM_WINDOWS)
|
||||
#include "Platform/Windows/WinAsm.h"
|
||||
#else
|
||||
#include "Platform/EFI/EfiAsm.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@brief An entry point for the hypervisor.
|
||||
@brief The entry point for the hypervisor.
|
||||
|
||||
@details See x64.asm.
|
||||
@details See Asm.asm.
|
||||
*/
|
||||
VOID
|
||||
AsmHypervisorEntryPoint (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@brief Invalidate translations derived from EPT.
|
||||
@brief Invalidates translations derived from EPT.
|
||||
|
||||
@param[in] InvEptType - A type of invalidation.
|
||||
@param[in] InvEptType - The type of invalidation.
|
||||
|
||||
@param[in] InvEptDescriptor - A description of translations to invalidate.
|
||||
@param[in] InvEptDescriptor - The description of translations to invalidate.
|
||||
|
||||
@return An appropriate VMX_RESULT value.
|
||||
*/
|
||||
@@ -42,11 +41,11 @@ AsmInvept (
|
||||
);
|
||||
|
||||
/*!
|
||||
@brief Invalidate translations based on VPID.
|
||||
@brief Invalidates translations based on VPID.
|
||||
|
||||
@param[in] InvVpidType - A type of invalidation.
|
||||
@param[in] InvVpidType - The type of invalidation.
|
||||
|
||||
@param[in] InvVpidDescriptor - A description of translations to invalidate.
|
||||
@param[in] InvVpidDescriptor - The description of translations to invalidate.
|
||||
|
||||
@return An appropriate VMX_RESULT value.
|
||||
*/
|
||||
@@ -56,7 +55,6 @@ AsmInvvpid (
|
||||
_In_ CONST INVVPID_DESCRIPTOR* InvVpidDescriptor
|
||||
);
|
||||
|
||||
|
||||
/*!
|
||||
@brief Reads the access rights byte of the segment.
|
||||
|
||||
@@ -93,13 +91,12 @@ AsmVmxCall (
|
||||
);
|
||||
|
||||
/*!
|
||||
@brief Returns the address of the return address from this function.
|
||||
@brief Returns the return address from this function.
|
||||
|
||||
@return The address of the return address from this function.
|
||||
@return The return address from this function.
|
||||
*/
|
||||
UINT64
|
||||
AsmGetCurrentInstructionPointer (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -109,5 +106,4 @@ AsmGetCurrentInstructionPointer (
|
||||
*/
|
||||
UINT64
|
||||
AsmGetCurrentStackPointer (
|
||||
VOID
|
||||
);
|
||||
|
||||
@@ -9,10 +9,17 @@
|
||||
*/
|
||||
#pragma once
|
||||
#if defined(NTDDI_VERSION)
|
||||
#define MV_PLATFORM_WINDOWS
|
||||
#else
|
||||
#define MV_PLATFORM_EFI
|
||||
#endif
|
||||
|
||||
#if defined(MV_PLATFORM_WINDOWS)
|
||||
#include "Platform/Windows/WinCommon.h"
|
||||
#else
|
||||
#include "Platform/EFI/EfiCommon.h"
|
||||
#endif
|
||||
|
||||
#include "Ia32.h"
|
||||
|
||||
//
|
||||
|
||||
@@ -37,11 +37,11 @@ typedef struct _EPT_ENTRIES
|
||||
C_ASSERT(sizeof(EPT_ENTRIES) == sizeof(VOID*) * 4);
|
||||
|
||||
/*!
|
||||
@brief Cleans up all EPT entries and the table recursively.
|
||||
@brief Cleans up all EPT entries and the tables recursively.
|
||||
|
||||
@param[in,out] EptTable - A pointer to the EPT table to clean up.
|
||||
@param[in,out] EptTable - The pointer to the EPT table to clean up.
|
||||
|
||||
@param[in] PageMapLevel - A level of the table.
|
||||
@param[in] PageMapLevel - The level of the table.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
|
||||
@@ -63,9 +63,9 @@ typedef struct _EPT_CONTEXT
|
||||
} EPT_CONTEXT;
|
||||
|
||||
/*!
|
||||
@brief Initializes EPT with pass-through style configurations.
|
||||
@brief Initializes identity-mapping EPTs.
|
||||
|
||||
@param[in,out] EptContext - A pointer to the EPT context to initialize.
|
||||
@param[in,out] EptContext - The pointer to the EPT context to initialize.
|
||||
|
||||
@return MV_STATUS_SUCCESS on success; otherwise, an appropriate error code.
|
||||
*/
|
||||
@@ -76,9 +76,9 @@ InitializeExtendedPageTables (
|
||||
);
|
||||
|
||||
/*!
|
||||
@brief Cleans up EPT context.
|
||||
@brief Cleans up the EPT context.
|
||||
|
||||
@param[in,out] EptContext - A pointer to the EPT context to clean up.
|
||||
@param[in,out] EptContext - The pointer to the EPT context to clean up.
|
||||
*/
|
||||
VOID
|
||||
CleanupExtendedPageTables (
|
||||
@@ -110,7 +110,7 @@ UpdateExtendPageTables (
|
||||
);
|
||||
|
||||
/*!
|
||||
@brief Invalidate guest-physical and combined caches.
|
||||
@brief Invalidates guest-physical and combined caches.
|
||||
|
||||
@param[in] EptPointer - The EPT pointer to invalidate associated caches. If
|
||||
0 is specified, caches associated with any EPT pointers are invalidated.
|
||||
@@ -121,10 +121,10 @@ InvalidateEptDerivedCache (
|
||||
);
|
||||
|
||||
/*!
|
||||
@brief Invalidate liner and combined caches.
|
||||
@brief Invalidates liner and combined caches.
|
||||
|
||||
@param[in] VirtualProcessorId - The VPID to invalidate associated caches. If
|
||||
0 is specified, caches associated with any VPID are invalidated.
|
||||
0 is specified, caches associated with any VPIDs are invalidated.
|
||||
*/
|
||||
VOID
|
||||
InvalidateVpidDerivedCache (
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "HostVmcall.h"
|
||||
#include "HostNesting.h"
|
||||
|
||||
//
|
||||
// Windows-specific:
|
||||
//
|
||||
// The trap frame structure for x64 systems. This is structure is used to help
|
||||
// Windbg to construct call stack while VM-exit handlers are being executed.
|
||||
@@ -53,7 +55,7 @@ typedef struct _INITIAL_HYPERVISOR_STACK
|
||||
can check the exception is #GP(0) caused by RDMSR or WRMSR, and if this
|
||||
is the case, inject it to the guest.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
|
||||
@param[in] OperationType - The type of the operation.
|
||||
*/
|
||||
@@ -110,7 +112,7 @@ HandleMsrAccess (
|
||||
/*!
|
||||
@brief Handles VM-exit due to execution of the RDMSR instruction.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -124,7 +126,7 @@ HandleMsrRead (
|
||||
/*!
|
||||
@brief Handles VM-exit due to execution of the WRMSR instruction.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -138,7 +140,7 @@ HandleMsrWrite (
|
||||
/*!
|
||||
@brief Handles VM-exit due to execution of the CPUID instruction.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -208,7 +210,7 @@ HandleCpuid (
|
||||
/*!
|
||||
@brief Handles VM-exit due to execution of the VMCALL instruction.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -245,7 +247,7 @@ Exit:
|
||||
/*!
|
||||
@brief Handles VM-exit due to execution of the XSETBV instruction.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -275,7 +277,7 @@ HandleXsetbv (
|
||||
@brief Returns the address of where the guest general purpose register that
|
||||
corresponds to the given index is stored.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
|
||||
@param[in] RegisterIndex - The index provided by VMCS up on VM-exit.
|
||||
|
||||
@@ -318,7 +320,7 @@ SelectEffectiveRegister (
|
||||
/*!
|
||||
@brief Handles VM-exit due to execution of access to the control register.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -382,7 +384,7 @@ HandleCrAccess (
|
||||
/*!
|
||||
@brief Handles VM-exit due to EPT violation.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -408,7 +410,7 @@ HandleEptViolation (
|
||||
/*!
|
||||
@brief Handles VM-exit due to EPT misconfiguration.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -444,7 +446,12 @@ HandleEptMisconfig (
|
||||
/*!
|
||||
@brief Handles VM-exit due to interrupt or exception.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@details Currently, this handler is specialized for skipping main initialization
|
||||
of PatchGuard for the demo purpose. When #DE occurs with the guest state
|
||||
that seems to be the trigger of PatchGuard initialization, suppress it.
|
||||
Otherwise, just inject the exception (pass-through).
|
||||
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -455,11 +462,6 @@ HandleExceptionOrNmi (
|
||||
static BOOLEAN isKeInitAmd64SpecificStateCalled;
|
||||
VMEXIT_INTERRUPT_INFORMATION interruptInfo;
|
||||
|
||||
//
|
||||
// This handler is specialized for skipping main initialization of PatchGuard.
|
||||
// When #DE occurs with the guest state that seems to be during initialization
|
||||
// of PatchGuard, suppress it. Otherwise, just inject the exception (pass-through).
|
||||
//
|
||||
interruptInfo.Flags = (UINT32)VmxRead(VMCS_VMEXIT_INTERRUPTION_INFORMATION);
|
||||
MV_ASSERT(interruptInfo.InterruptionType == HardwareException);
|
||||
MV_ASSERT(interruptInfo.Vector == DivideError);
|
||||
@@ -513,7 +515,7 @@ Exit:
|
||||
/*!
|
||||
@brief Handles VM-exit due to the INIT signal.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -673,7 +675,7 @@ HandleInitSignal (
|
||||
/*!
|
||||
@brief Handles VM-exit due to the Startup-IPI (SIPI) signal.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
@@ -738,12 +740,12 @@ HandleStartupIpi (
|
||||
Any hypervisor code including this and the AsmHypervisorEntryPoint
|
||||
functions are executed while interrupt is disabled via RFLAGS.IF being
|
||||
0 (See: 27.5.3 Loading Host RIP, RSP, and RFLAGS). This means IPI, if
|
||||
requested, is never delivered and causes deadlock. This condition is
|
||||
essentially equal to IRQL being HIGH_LEVEL (i.e., at a higher IRQL than
|
||||
IPI_LEVEL), and so, it is unsafe to call any Windows provided API that
|
||||
is not stated as callable at HIGH_LEVEL.
|
||||
requested, is never delivered and causes deadlock. In the Windows
|
||||
terminology, this condition is essentially equal to IRQL being HIGH_LEVEL
|
||||
(i.e., at a higher IRQL than IPI_LEVEL), and so, it is unsafe to call any
|
||||
Windows provided API that is not stated as callable at HIGH_LEVEL.
|
||||
|
||||
@param[in,out] Stack - A pointer to the hypervisor stack containing the
|
||||
@param[in,out] Stack - The pointer to the hypervisor stack containing the
|
||||
guest register values.
|
||||
|
||||
@return TRUE when virtualization should continue and the VMRESUME instruction
|
||||
@@ -785,6 +787,8 @@ HandleVmExit (
|
||||
guestContext.VmcsBasedRegisters.Rsp = VmxRead(VMCS_GUEST_RSP);
|
||||
guestContext.VmcsBasedRegisters.Rip = VmxRead(VMCS_GUEST_RIP);
|
||||
|
||||
//
|
||||
// Windows-specific:
|
||||
//
|
||||
// Update the _KTRAP_FRAME structure values in hypervisor stack, so that
|
||||
// Windbg can reconstruct call stack of the guest during debug session.
|
||||
@@ -903,7 +907,7 @@ typedef struct _EXCEPTION_STACK
|
||||
|
||||
@details On Windows, this function is unused because the host uses the same
|
||||
IDT as that of the guest. All interrupts and exceptions are handled by
|
||||
the NT kernel.
|
||||
the NT kernel allowing Windbg to work as usual.
|
||||
|
||||
@param[in] Stack - The pointer to the hypervisor stack containing the
|
||||
guest register values.
|
||||
|
||||
@@ -308,7 +308,6 @@ AdvanceGuestInstructionPointer (
|
||||
_Use_decl_annotations_
|
||||
BOOLEAN
|
||||
IsGuestInKernelMode (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
VMX_SEGMENT_ACCESS_RIGHTS accessRight;
|
||||
|
||||
@@ -107,9 +107,9 @@ DumpControl (
|
||||
/*!
|
||||
@brief Writes the value to the VMCS.
|
||||
|
||||
@param[in] Field - A VMCS field to write the value to.
|
||||
@param[in] Field - The VMCS field to write the value to.
|
||||
|
||||
@param[in] FieldValue - A value to write.
|
||||
@param[in] FieldValue - The value to write.
|
||||
*/
|
||||
VOID
|
||||
VmxWrite (
|
||||
@@ -120,7 +120,7 @@ VmxWrite (
|
||||
/*!
|
||||
@brief Read a value from the VMCS.
|
||||
|
||||
@param[in] Field - A VMCS field to read a value from.
|
||||
@param[in] Field - The VMCS field to read a value from.
|
||||
|
||||
@return A value read from the VMCS. 0 is returned when a non-existent VMCS
|
||||
field is requested for read.
|
||||
@@ -134,7 +134,7 @@ VmxRead (
|
||||
@brief Advances the guest's RIP to the address of the next instruction. This
|
||||
implies that the hypervisor completed emulation of the instruction.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
VOID
|
||||
AdvanceGuestInstructionPointer (
|
||||
@@ -150,7 +150,6 @@ AdvanceGuestInstructionPointer (
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
IsGuestInKernelMode (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -160,16 +159,16 @@ IsGuestInKernelMode (
|
||||
corresponding exception handler before executing the instruction pointed
|
||||
by Rip.
|
||||
|
||||
@param[in] InterruptionType - A type of interrupt to inject.
|
||||
@param[in] InterruptionType - The type of interrupt to inject.
|
||||
|
||||
@param[in] Vector - A vector number of interrupt to inject.
|
||||
@param[in] Vector - The vector number of interrupt to inject.
|
||||
|
||||
@param[in] DeliverErrorCode - TRUE when the interrupt should have an error
|
||||
code. Whether the interrupt should have an error code is defined by the
|
||||
Intel SDM. See comments in the EXCEPTION_VECTOR definitions for a quick
|
||||
reference.
|
||||
|
||||
@param[in] ErrorCode - An error code. Not used when DeliverErrorCode is FALSE.
|
||||
@param[in] ErrorCode - The error code. Not used when DeliverErrorCode is FALSE.
|
||||
*/
|
||||
VOID
|
||||
InjectInterruption (
|
||||
@@ -217,7 +216,7 @@ AdjustGuestCr4 (
|
||||
);
|
||||
|
||||
/*!
|
||||
@brief Find the base address of the image to which the specified address belongs.
|
||||
@brief Finds the base address of the image to which the specified address belongs.
|
||||
|
||||
@param[in] GuestContext - The pointer to the guest context.
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ HandleVmcallUninstall (
|
||||
// from the guest state fields of the VMCS. However, it is not the case when
|
||||
// the VMRESUME is not called, like here. In such a case those values must
|
||||
// be restored with normal value manually, or PatchGuard will report
|
||||
// integrity violation.
|
||||
// integrity violation on Windows.
|
||||
//
|
||||
// "The GDTR and IDTR limits are each set to FFFFH."
|
||||
// See: 27.5.2 Loading Host Segment and Descriptor-Table Registers
|
||||
|
||||
@@ -24,7 +24,7 @@ VMCALL_HANDLER (
|
||||
/*!
|
||||
@brief Handles hypercall for uninstalling the hypervisor.
|
||||
|
||||
@param[in,out] GuestContext - A pointer to the guest context.
|
||||
@param[in,out] GuestContext - The pointer to the guest context.
|
||||
*/
|
||||
VMCALL_HANDLER HandleVmcallUninstall;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
// difference of the formatting functions. Use them like the standard's PRIx macro
|
||||
// family.
|
||||
//
|
||||
#if defined(NTDDI_VERSION)
|
||||
#if defined(MV_PLATFORM_WINDOWS)
|
||||
#define LOG_PRIANSI "s"
|
||||
#define LOG_PRIUNICODE "S"
|
||||
#else
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
#include "Logger.h"
|
||||
|
||||
/*!
|
||||
@brief Split a 2MB EPT PDE to 512 EPT PTEs.
|
||||
@brief Splits a 2MB PDE to 512 PTEs.
|
||||
|
||||
@param[in,out] PdeLarge - The pointer to the 2MB EPT PDE to split.
|
||||
@param[in,out] PdeLarge - The pointer to the 2MB PDE to split.
|
||||
|
||||
@return MV_STATUS_SUCCESS on success; otherwise, an appropriate error code.
|
||||
*/
|
||||
@@ -499,11 +499,14 @@ GetPhysicalAddressForGuest (
|
||||
|
||||
Exit:
|
||||
//
|
||||
// Return the collected permission bits on success.
|
||||
// Return the collected permission bits if provided.
|
||||
//
|
||||
if ((pa != MV_INVALID_PHYSICAL_ADDRESS) &&
|
||||
ARGUMENT_PRESENT(AggregatedPagePermissions))
|
||||
if (ARGUMENT_PRESENT(AggregatedPagePermissions))
|
||||
{
|
||||
if (pa == MV_INVALID_PHYSICAL_ADDRESS)
|
||||
{
|
||||
permission.Flags = 0;
|
||||
}
|
||||
*AggregatedPagePermissions = permission;
|
||||
}
|
||||
return pa;
|
||||
|
||||
@@ -85,9 +85,9 @@ CleanupMemoryAccess (
|
||||
given virtual address and retrieves the guest physical address of it.
|
||||
This is equivalent to changing the current CR3 with the guest CR3 and
|
||||
calling GetPhysicalAddress(). This function, however, exists to avoid
|
||||
problems associated with CR3 update, for example, updating the CR3 crashes
|
||||
the system immediately if the KVA Shadow is enabled and the guest CR3
|
||||
contains the USER CR3, as it does not map our driver.
|
||||
problems associated with CR3 update, for example, on Windows, updating
|
||||
the CR3 crashes the system immediately if the KVA Shadow is enabled and
|
||||
the guest CR3 contains the USER CR3, as it does not map our code.
|
||||
|
||||
@param[in] Context - The pointer to the memory access context.
|
||||
|
||||
@@ -174,7 +174,8 @@ WriteGuestVirtualAddress (
|
||||
|
||||
@param[in] Context - The pointer to the memory access context.
|
||||
|
||||
@param[in] GuestPageNumber - See ReadOrWriteGuestVirtualAddress().
|
||||
@param[in] GuestPageNumber - The guest page number (ie, the guest virtual
|
||||
address without lower 12bits) to map to the host address space.
|
||||
|
||||
@return The virtual address mapping the same physical page as specified as
|
||||
the page number, or NULL if the specified page number does not have
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "MemoryManager.h"
|
||||
#include "Platform.h"
|
||||
#include "Logger.h"
|
||||
#if !defined(NTDDI_VERSION)
|
||||
#if defined(MV_PLATFORM_EFI)
|
||||
#include "Platform/EFI/EfiBitmap.h"
|
||||
#endif
|
||||
|
||||
@@ -78,7 +78,7 @@ MmInitializeMemoryManager (
|
||||
UINT32 lengthMapPagesCount;
|
||||
MEMORY_MANAGER_CONTEXT* memoryManager;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
memoryManager = &g_MemoryManager;
|
||||
lengthMapPagesCount = 0;
|
||||
@@ -174,7 +174,7 @@ MmCleanupMemoryManager (
|
||||
UINT32 lengthMapPagesCount;
|
||||
MEMORY_MANAGER_CONTEXT* memoryManager;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
memoryManager = &g_MemoryManager;
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
@brief Functions for memory management.
|
||||
|
||||
@details All API in this file are prefixed with Mm because naive names
|
||||
conflict with platform API, for example, AllocatePages and FreePages in
|
||||
EDK2.
|
||||
|
||||
@author Satoshi Tanda
|
||||
|
||||
@copyright Copyright (c) 2020 - , Satoshi Tanda. All rights reserved.
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "Common.h"
|
||||
#include "Ia32.h"
|
||||
|
||||
/*!
|
||||
@brief Initializes the MTRR context.
|
||||
@@ -21,12 +20,12 @@ InitializeMemoryTypeMapping (
|
||||
/*!
|
||||
@brief Returns a memory type for the given physical address range.
|
||||
|
||||
@param[in] PhysicalAddress - A physical address to retrieve its memory type.
|
||||
@param[in] PhysicalAddress - The physical address to retrieve its memory type.
|
||||
|
||||
@param[in] RangeSize - The size of the range to check.
|
||||
|
||||
@return The memory type for the given physical address. If the range contains
|
||||
more than one memory type, return MEMORY_TYPE_INVALID.
|
||||
more than one memory type, MEMORY_TYPE_INVALID.
|
||||
*/
|
||||
IA32_MEMORY_TYPE
|
||||
GetMemoryTypeForRange (
|
||||
|
||||
@@ -164,10 +164,10 @@ typedef struct _SHARED_PROCESSOR_CONTEXT
|
||||
@brief Returns the VM control value that is adjusted in consideration with
|
||||
the VMX capability MSR.
|
||||
|
||||
@param[in] VmxCapabilityMsr - A VMX capability MSR to consult to adjust the
|
||||
@param[in] VmxCapabilityMsr - The VMX capability MSR to consult to adjust the
|
||||
RequestedValue,
|
||||
|
||||
@param[in] RequestedValue - A VM control value that needs adjustment.
|
||||
@param[in] RequestedValue - The VM control value that needs adjustment.
|
||||
|
||||
@return The adjusted control value.
|
||||
*/
|
||||
@@ -220,7 +220,7 @@ AdjustControlValue (
|
||||
@brief Adjusts a pin-based control value in consideration with the VMX
|
||||
capability MSR.
|
||||
|
||||
@param[in,out] PinBasedControls - A pointer to the pin-based control value
|
||||
@param[in,out] PinBasedControls - The pointer to the pin-based control value
|
||||
to adjust.
|
||||
*/
|
||||
static
|
||||
@@ -233,9 +233,9 @@ AdjustPinBasedControls (
|
||||
IA32_VMX_BASIC_REGISTER vmxBasicMsr;
|
||||
|
||||
//
|
||||
// This determine the right VMX capability MSR based on the value of
|
||||
// This determines the right VMX capability MSR based on the value of
|
||||
// IA32_VMX_BASIC. With the right VMX capability MSR, the
|
||||
// AdjustControlValue function implements the logic described under
|
||||
// AdjustControlValue function implements the logic described as below.
|
||||
// "It is necessary for software to consult only one of the capability MSRs
|
||||
// to determine the allowed settings of the pin based VM-execution controls:"
|
||||
// See: A.3.1 Pin-Based VM-Execution Controls
|
||||
@@ -252,7 +252,7 @@ AdjustPinBasedControls (
|
||||
@brief Adjusts a processor-based control value in consideration with the VMX
|
||||
capability MSR.
|
||||
|
||||
@param[in,out] PrimaryProcBasedControls - A pointer to the processor-based
|
||||
@param[in,out] PrimaryProcBasedControls - The pointer to the processor-based
|
||||
control value to adjust.
|
||||
*/
|
||||
static
|
||||
@@ -280,7 +280,7 @@ AdjustProcessorBasedControls (
|
||||
@brief Adjusts a VM-exit control value in consideration with the VMX
|
||||
capability MSR.
|
||||
|
||||
@param[in,out] VmExitControls - A pointer to the VM-exit control value to
|
||||
@param[in,out] VmExitControls - The pointer to the VM-exit control value to
|
||||
adjust.
|
||||
*/
|
||||
static
|
||||
@@ -307,7 +307,7 @@ AdjustVmExitControls (
|
||||
@brief Adjusts a VM-entry control value in consideration with the VMX
|
||||
capability MSR.
|
||||
|
||||
@param[in,out] VmEntryControls - A pointer to the VM-entry control value to
|
||||
@param[in,out] VmEntryControls - The pointer to the VM-entry control value to
|
||||
adjust.
|
||||
*/
|
||||
static
|
||||
@@ -334,7 +334,7 @@ AdjustVmEntryControls (
|
||||
@brief Adjusts a secondary processor-based control value in consideration
|
||||
with the VMX capability MSR.
|
||||
|
||||
@param[in,out] SecondaryProcBasedControls - A pointer to the secondary
|
||||
@param[in,out] SecondaryProcBasedControls - The pointer to the secondary
|
||||
processor-based control value to adjust.
|
||||
*/
|
||||
static
|
||||
@@ -361,7 +361,6 @@ static
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
IsMiniVisorInstalled (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
int registers[4]; // EAX, EBX, ECX, and EDX
|
||||
@@ -381,11 +380,12 @@ IsMiniVisorInstalled (
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Disables hypervisor on the current processor.
|
||||
@brief Disables the hypervisor on the current processor.
|
||||
|
||||
@param[in,out] Context - A pointer to the location to receive the address of
|
||||
@param[in,out] Context - The pointer to the location to receive the address of
|
||||
the shared processor context.
|
||||
*/
|
||||
MV_SECTION_PAGED
|
||||
static
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
@@ -397,6 +397,8 @@ DisableHypervisor (
|
||||
SHARED_PROCESSOR_CONTEXT** sharedProcessorContextsAddress;
|
||||
PER_PROCESSOR_CONTEXT* processorContext;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if (IsMiniVisorInstalled() == FALSE)
|
||||
{
|
||||
goto Exit;
|
||||
@@ -404,8 +406,7 @@ DisableHypervisor (
|
||||
|
||||
//
|
||||
// Issues the hypercall to uninstall the hypervisor. This hypercall returns
|
||||
// the address of the shared processor context on success. If the hypervisor
|
||||
// is not installed, this (VMCALL instruction) raises #UD.
|
||||
// the address of the shared processor context on success.
|
||||
//
|
||||
returnedAddress = (SHARED_PROCESSOR_CONTEXT*)AsmVmxCall(VmcallUninstall, 0, 0, 0);
|
||||
MV_ASSERT(returnedAddress != NULL);
|
||||
@@ -423,7 +424,7 @@ DisableHypervisor (
|
||||
*sharedProcessorContextsAddress = returnedAddress;
|
||||
|
||||
//
|
||||
// Clean up the per-processor stuff, to be precise, EPT setup.
|
||||
// Clean up the per-processor data structures.
|
||||
//
|
||||
processorContext = &(*sharedProcessorContextsAddress)->Contexts[GetCurrentProcessorNumber()];
|
||||
CleanupExtendedPageTables(&processorContext->EptContext);
|
||||
@@ -435,19 +436,18 @@ Exit:
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Enables hypervisor on the all processors.
|
||||
@brief Disables the hypervisor on the all processors.
|
||||
*/
|
||||
MV_SECTION_PAGED
|
||||
static
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
DisableHypervisorOnAllProcessors (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
SHARED_PROCESSOR_CONTEXT* sharedProcessorContext;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
sharedProcessorContext = NULL;
|
||||
RunOnAllProcessors(DisableHypervisor, &sharedProcessorContext);
|
||||
@@ -467,7 +467,6 @@ static
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
IsVmxAvailable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
BOOLEAN vmxAvailable;
|
||||
@@ -494,7 +493,7 @@ IsVmxAvailable (
|
||||
//
|
||||
// Check the processor support the write-back type for VMCS. We do not
|
||||
// support the processor that does not support the write-back type for
|
||||
// simplicity. It is not practically an issue since
|
||||
// simplicity. It is practically not an issue since
|
||||
// "As of this writing, all processors that support VMX operation indicate
|
||||
// the write-back type."
|
||||
//
|
||||
@@ -529,19 +528,17 @@ IsVmxAvailable (
|
||||
}
|
||||
|
||||
//
|
||||
// Check the followings to confirm availability of EPT related capabilities:
|
||||
// - page walk length is 4 steps
|
||||
// - extended page tables can be laid out in write-back memory
|
||||
// - INVEPT instruction for global context is supported
|
||||
// - INVVPID instruction for global context is supported
|
||||
// Check the followings to confirm availability of EPT related capabilities.
|
||||
//
|
||||
eptVpidCapabilityMsr.Flags = __readmsr(IA32_VMX_EPT_VPID_CAP);
|
||||
if ((eptVpidCapabilityMsr.PageWalkLength4 == FALSE) ||
|
||||
(eptVpidCapabilityMsr.MemoryTypeWriteBack == FALSE) ||
|
||||
(eptVpidCapabilityMsr.Pde2MbPages == FALSE) ||
|
||||
(eptVpidCapabilityMsr.Invept == FALSE) ||
|
||||
(eptVpidCapabilityMsr.InveptSingleContext == FALSE) ||
|
||||
(eptVpidCapabilityMsr.InveptAllContexts == FALSE) ||
|
||||
(eptVpidCapabilityMsr.Invvpid == FALSE) ||
|
||||
(eptVpidCapabilityMsr.InvvpidSingleContext == FALSE) ||
|
||||
(eptVpidCapabilityMsr.InvvpidAllContexts == FALSE))
|
||||
{
|
||||
LOG_ERROR("EPT is not supported.");
|
||||
@@ -562,10 +559,10 @@ Exit:
|
||||
See: 31.5 VMM SETUP & TEAR DOWN
|
||||
See: 31.6 PREPARATION AND LAUNCHING A VIRTUAL MACHINE
|
||||
|
||||
@param[in] SharedProcessorContext - A pointer to the shared processor context.
|
||||
@param[in] SharedProcessorContext - The pointer to the shared processor context.
|
||||
|
||||
@param[in,out] ProcessorContext - A pointer to the per-processor context for this
|
||||
processor.
|
||||
@param[in,out] ProcessorContext - The pointer to the per-processor context
|
||||
for this processor.
|
||||
|
||||
@return MV_STATUS_SUCCESS on success, or an appropriate status code on error.
|
||||
*/
|
||||
@@ -618,7 +615,7 @@ SetupVmcs (
|
||||
|
||||
//
|
||||
// VMX requires TR to be configured properly (ie, non zero). This requirement
|
||||
// is not already satisfied in case of EFI environment. Set it up by updating
|
||||
// is not satisfied yet in case of EFI environment. Set it up by updating
|
||||
// GDT as necessary.
|
||||
//
|
||||
// "The selector fields for CS and TR cannot be 0000H."
|
||||
@@ -769,8 +766,7 @@ SetupVmcs (
|
||||
//
|
||||
|
||||
//
|
||||
// Initialize EPT specific data structure, which we will referred to as the
|
||||
// EPT-context.
|
||||
// Initialize EPT specific data structures.
|
||||
//
|
||||
status = InitializeExtendedPageTables(&ProcessorContext->EptContext);
|
||||
if (MV_ERROR(status))
|
||||
@@ -829,20 +825,20 @@ SetupVmcs (
|
||||
// instructions.
|
||||
//
|
||||
// - MSR bitmaps are used; this is not to cause VM-exit as much as possible.
|
||||
// We are setting the MSR bitmaps that are all cleared below (see code
|
||||
// around the "64-Bit Control Fields" comment). This prevents VM-exits from
|
||||
// occurring when 0x0 - 0x1fff and 0xc0000000 - 0xc0001fff are accessed.
|
||||
// Note that VM-exit still occurs if outside the range is accessed, and it
|
||||
// is not possible to prevent this.
|
||||
// We are setting the MSR bitmaps that are mostly cleared below (see
|
||||
// InitializeMsrBitmaps). This prevents VM-exits from occurring when
|
||||
// 0x0 - 0x1fff and 0xc0000000 - 0xc0001fff are accessed. VM-exit still
|
||||
// occurs if outside the range is accessed, and it is not possible to
|
||||
// prevent this.
|
||||
//
|
||||
// - The secondary processor-based controls are used; this is to let the
|
||||
// guest (Windows) executes RDTSCP, INVPCID and the XSAVE/XRSTORS family
|
||||
// instructions. Those instructions are used in Windows 10. If those are
|
||||
// not set, attempt to execute them causes #UD, which results in a bug
|
||||
// check. VPID is enabled, which could lead to better performance for free
|
||||
// by not flushing all TLB on every VM-exit. Finally, to enable EPT and
|
||||
// unrestricted guest which are required for the UEFI hypervisor to handle
|
||||
// the real-mode guest.
|
||||
// by not flushing all TLB on every VM-exit and VM-entry. Finally, enabling
|
||||
// EPT and unrestricted guest which are required for the UEFI hypervisor to
|
||||
// handle the real-mode guest.
|
||||
//
|
||||
primaryProcBasedControls.Flags = 0;
|
||||
primaryProcBasedControls.UseMsrBitmaps = TRUE;
|
||||
@@ -870,13 +866,20 @@ SetupVmcs (
|
||||
// RPL (bits 1:0) and the TI flag (bit 2) must be 0"
|
||||
// See: 26.2.3 Checks on Host Segment and Descriptor-Table Registers
|
||||
//
|
||||
VmxWrite(VMCS_HOST_ES_SELECTOR, AsmReadEs() & ~hostSegmentSelectorMask);
|
||||
VmxWrite(VMCS_HOST_CS_SELECTOR, AsmReadCs() & ~hostSegmentSelectorMask);
|
||||
VmxWrite(VMCS_HOST_SS_SELECTOR, AsmReadSs() & ~hostSegmentSelectorMask);
|
||||
VmxWrite(VMCS_HOST_DS_SELECTOR, AsmReadDs() & ~hostSegmentSelectorMask);
|
||||
VmxWrite(VMCS_HOST_FS_SELECTOR, AsmReadFs() & ~hostSegmentSelectorMask);
|
||||
VmxWrite(VMCS_HOST_GS_SELECTOR, AsmReadGs() & ~hostSegmentSelectorMask);
|
||||
VmxWrite(VMCS_HOST_TR_SELECTOR, AsmReadTr() & ~hostSegmentSelectorMask);
|
||||
MV_ASSERT(FlagOn(AsmReadEs(), hostSegmentSelectorMask) == FALSE);
|
||||
MV_ASSERT(FlagOn(AsmReadCs(), hostSegmentSelectorMask) == FALSE);
|
||||
MV_ASSERT(FlagOn(AsmReadSs(), hostSegmentSelectorMask) == FALSE);
|
||||
MV_ASSERT(FlagOn(AsmReadDs(), hostSegmentSelectorMask) == FALSE);
|
||||
MV_ASSERT(FlagOn(AsmReadFs(), hostSegmentSelectorMask) == FALSE);
|
||||
MV_ASSERT(FlagOn(AsmReadGs(), hostSegmentSelectorMask) == FALSE);
|
||||
MV_ASSERT(FlagOn(AsmReadTr(), hostSegmentSelectorMask) == FALSE);
|
||||
VmxWrite(VMCS_HOST_ES_SELECTOR, AsmReadEs());
|
||||
VmxWrite(VMCS_HOST_CS_SELECTOR, AsmReadCs());
|
||||
VmxWrite(VMCS_HOST_SS_SELECTOR, AsmReadSs());
|
||||
VmxWrite(VMCS_HOST_DS_SELECTOR, AsmReadDs());
|
||||
VmxWrite(VMCS_HOST_FS_SELECTOR, AsmReadFs());
|
||||
VmxWrite(VMCS_HOST_GS_SELECTOR, AsmReadGs());
|
||||
VmxWrite(VMCS_HOST_TR_SELECTOR, AsmReadTr());
|
||||
|
||||
/* 64-Bit Host-State Fields */
|
||||
VmxWrite(VMCS_HOST_EFER, __readmsr(IA32_EFER));
|
||||
@@ -1021,8 +1024,9 @@ Exit:
|
||||
/*!
|
||||
@brief Enables hypervisor on the current processor.
|
||||
|
||||
@param[in,out] Context - A pointer to the shared processor context.
|
||||
@param[in,out] Context - The pointer to the shared processor context.
|
||||
*/
|
||||
MV_SECTION_PAGED
|
||||
static
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
@@ -1037,6 +1041,8 @@ EnableHypervisor (
|
||||
UINT64 guestRip;
|
||||
BOOLEAN maCtxInitialized;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
maCtxInitialized = FALSE;
|
||||
|
||||
sharedProcessorContext = Context;
|
||||
@@ -1049,7 +1055,7 @@ EnableHypervisor (
|
||||
// host.
|
||||
//
|
||||
processorContext->Status = InitializeMemoryAccess(&processorContext->MemoryAccessContext,
|
||||
GetHostCr3());
|
||||
GetHostCr3());
|
||||
if (MV_ERROR(processorContext->Status))
|
||||
{
|
||||
LOG_ERROR("InitializeMemoryAccess failed : %08x", processorContext->Status);
|
||||
@@ -1140,6 +1146,7 @@ EnableHypervisor (
|
||||
vmxErrorStatus = (result == VmxResultErrorWithStatus) ?
|
||||
(VMX_ERROR_NUMBER)VmxRead(VMCS_VM_INSTRUCTION_ERROR) : 0;
|
||||
LOG_ERROR("__vmx_vmlaunch failed : %u", vmxErrorStatus);
|
||||
|
||||
processorContext->Status = MV_STATUS_HV_OPERATION_FAILED;
|
||||
CleanupExtendedPageTables(&processorContext->EptContext);
|
||||
__vmx_off();
|
||||
@@ -1159,8 +1166,8 @@ Exit:
|
||||
|
||||
@details This function clears the bitmaps to avoid VM-exits that do not require
|
||||
manual handling. The MSR that requires manual handling for MiniVisor is
|
||||
IA32_BIOS_SIGN_ID to prevent the guest from attempting update BIOS
|
||||
microcode. See HandleMsrAccess for more details.
|
||||
IA32_BIOS_SIGN_ID for read to prevent the guest from attempting update
|
||||
BIOS microcode which is not allowed. See HandleMsrAccess for more details.
|
||||
|
||||
@param[out] Bitmaps - The pointer to the MSR bitmaps to initialize.
|
||||
*/
|
||||
@@ -1174,7 +1181,7 @@ InitializeMsrBitmaps (
|
||||
static CONST UINT64 biosSignatureByteOffset = (IA32_BIOS_SIGN_ID / CHAR_BIT);
|
||||
static CONST UINT64 biosSignatureBitMask = (1ull << (IA32_BIOS_SIGN_ID % CHAR_BIT));
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
RtlZeroMemory(Bitmaps, sizeof(*Bitmaps));
|
||||
|
||||
@@ -1182,7 +1189,7 @@ InitializeMsrBitmaps (
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Enables hypervisor on the all processors.
|
||||
@brief Enables the hypervisor on the all processors.
|
||||
|
||||
@return MV_STATUS_SUCCESS on success; otherwise, an appropriate error code.
|
||||
*/
|
||||
@@ -1192,7 +1199,6 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
_Must_inspect_result_
|
||||
MV_STATUS
|
||||
EnableHypervisorOnAllProcessors (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
MV_STATUS status;
|
||||
@@ -1201,7 +1207,7 @@ EnableHypervisorOnAllProcessors (
|
||||
SHARED_PROCESSOR_CONTEXT* sharedProcessorContext;
|
||||
BOOLEAN virtualized;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
virtualized = FALSE;
|
||||
|
||||
@@ -1322,7 +1328,7 @@ InitializeMiniVisor (
|
||||
//
|
||||
if (IsMiniVisorInstalled() != FALSE)
|
||||
{
|
||||
LOG_ERROR("MiniVisor already installed");
|
||||
LOG_INFO("MiniVisor already installed");
|
||||
status = MV_STATUS_HV_OPERATION_FAILED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//
|
||||
// Spin lock type and state names.
|
||||
//
|
||||
#if defined(NTDDI_VERSION)
|
||||
#if defined(MV_PLATFORM_WINDOWS)
|
||||
typedef volatile LONG64 SPIN_LOCK;
|
||||
typedef enum _SPIN_LOCK_STATE
|
||||
{
|
||||
@@ -81,7 +81,7 @@ GetCurrentProcessorNumber (
|
||||
/*!
|
||||
@brief Returns the physical address of the given virtual address.
|
||||
|
||||
@param[in] VirualAddress - A virtual address to retrieve its physical
|
||||
@param[in] VirualAddress - The virtual address to retrieve its physical
|
||||
address for the current CR3. This must be non paged pool, otherwise the
|
||||
result is undefined.
|
||||
|
||||
|
||||
@@ -25,7 +25,10 @@ Index = 0
|
||||
; Index is incremented whenever this macro is used.
|
||||
;
|
||||
INTERRUPT_HANDLER macro InterruptNumber
|
||||
push 0 ; Push dummy error code for consistent stack layout.
|
||||
;
|
||||
; Push dummy error code for consistent stack layout.
|
||||
;
|
||||
push 0
|
||||
push InterruptNumber
|
||||
jmp AsmCommonExceptionHandler
|
||||
Index = Index + 1
|
||||
@@ -38,7 +41,10 @@ endm
|
||||
; Index is incremented whenever this macro is used.
|
||||
;
|
||||
INTERRUPT_HANDLER_WITH_CODE macro InterruptNumber
|
||||
nop ; Error code is expected to be pushed by the processor.
|
||||
;
|
||||
; Error code is expected to be pushed by the processor.
|
||||
;
|
||||
nop
|
||||
nop
|
||||
push InterruptNumber
|
||||
jmp AsmCommonExceptionHandler
|
||||
@@ -53,26 +59,44 @@ endm
|
||||
; works as a hendler of the corresponding interrupt/exception in the host.
|
||||
;
|
||||
AsmDefaultExceptionHandlers proc
|
||||
repeat 8
|
||||
INTERRUPT_HANDLER Index ; INT0-7
|
||||
endm
|
||||
;
|
||||
; INT0-7
|
||||
;
|
||||
repeat 8
|
||||
INTERRUPT_HANDLER Index
|
||||
endm
|
||||
|
||||
INTERRUPT_HANDLER_WITH_CODE Index ; INT8
|
||||
INTERRUPT_HANDLER Index ; INT9
|
||||
;
|
||||
; INT8, INT9
|
||||
;
|
||||
INTERRUPT_HANDLER_WITH_CODE Index
|
||||
INTERRUPT_HANDLER Index
|
||||
|
||||
repeat 5
|
||||
INTERRUPT_HANDLER_WITH_CODE Index ; INT10-14
|
||||
endm
|
||||
;
|
||||
; INT10-14
|
||||
;
|
||||
repeat 5
|
||||
INTERRUPT_HANDLER_WITH_CODE Index
|
||||
endm
|
||||
|
||||
repeat 2
|
||||
INTERRUPT_HANDLER Index ; INT15-16
|
||||
endm
|
||||
;
|
||||
; INT15-16
|
||||
;
|
||||
repeat 2
|
||||
INTERRUPT_HANDLER Index
|
||||
endm
|
||||
|
||||
INTERRUPT_HANDLER_WITH_CODE Index ; INT17
|
||||
;
|
||||
; INT17
|
||||
;
|
||||
INTERRUPT_HANDLER_WITH_CODE Index
|
||||
|
||||
repeat 238
|
||||
INTERRUPT_HANDLER Index ; INT18-255
|
||||
endm
|
||||
;
|
||||
; INT18-255
|
||||
;
|
||||
repeat 238
|
||||
INTERRUPT_HANDLER Index
|
||||
endm
|
||||
AsmDefaultExceptionHandlers endp
|
||||
|
||||
;
|
||||
@@ -88,7 +112,11 @@ AsmCommonExceptionHandler proc
|
||||
call HandleHostException
|
||||
add rsp, 20h
|
||||
POPAQ
|
||||
add rsp, 10h ; Remove the error code and interrupt number.
|
||||
|
||||
;
|
||||
; Remove the error code and interrupt number.
|
||||
;
|
||||
add rsp, 10h
|
||||
iretq
|
||||
AsmCommonExceptionHandler endp
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
VOID
|
||||
AsmDefaultExceptionHandlers (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -23,5 +22,4 @@ AsmDefaultExceptionHandlers (
|
||||
*/
|
||||
VOID
|
||||
AsmNmiExceptionHandler (
|
||||
VOID
|
||||
);
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
reused once they are set, even after they are "cleared".
|
||||
|
||||
For complete implementation, one can copy ReactOS's implementation if
|
||||
licensing the project under GPL is acceptable. hvpp by wbenny has its own
|
||||
implementation of bitmap but is actually influenced by ReactOS
|
||||
implementation and such should be treated as GPL.
|
||||
licensing the project under GPL is acceptable. hvpp by Petr Beneš has its
|
||||
own implementation of bitmap but is actually influenced by ReactOS
|
||||
implementation, and such, should be treated as GPL.
|
||||
|
||||
@author Satoshi Tanda
|
||||
|
||||
|
||||
@@ -34,21 +34,21 @@
|
||||
fault (null pointer access) when it fires in the host code. The author
|
||||
has not been able to find out the root cause and a fix.
|
||||
*/
|
||||
#if !defined(MDEPKG_NDEBUG)
|
||||
#if defined(MDEPKG_NDEBUG)
|
||||
#define MV_ASSERT(x)
|
||||
#else
|
||||
#define MV_ASSERT(x) \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
LOG_ERROR("ASSERT %a(%d): %a", __FILE__, __LINE__, #x); \
|
||||
MV_PANIC(); \
|
||||
} (VOID*)NULL
|
||||
#else
|
||||
#define MV_ASSERT(x)
|
||||
#endif
|
||||
|
||||
#if !defined(MDEPKG_NDEBUG)
|
||||
#define MV_VERIFY(x) MV_ASSERT(x)
|
||||
#else
|
||||
#if defined(MDEPKG_NDEBUG)
|
||||
#define MV_VERIFY(x) (x)
|
||||
#else
|
||||
#define MV_VERIFY(x) MV_ASSERT(x)
|
||||
#endif
|
||||
|
||||
#define MV_MAX(x, y) MAX((x), (y))
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
.code
|
||||
|
||||
;
|
||||
; @brief Read the value from LDTR.
|
||||
; @brief Reads the value of LDTR.
|
||||
;
|
||||
; @return The value of LDTR.
|
||||
;
|
||||
@@ -20,7 +20,7 @@ AsmReadLdtr proc
|
||||
AsmReadLdtr endp
|
||||
|
||||
;
|
||||
; @brief Read the value from TR.
|
||||
; @brief Reads the value of TR.
|
||||
;
|
||||
; @return The value of TR.
|
||||
;
|
||||
@@ -30,7 +30,7 @@ AsmReadTr proc
|
||||
AsmReadTr endp
|
||||
|
||||
;
|
||||
; @brief Read the value from ES.
|
||||
; @brief Reads the value of ES.
|
||||
;
|
||||
; @return The value of ES.
|
||||
;
|
||||
@@ -40,7 +40,7 @@ AsmReadEs proc
|
||||
AsmReadEs endp
|
||||
|
||||
;
|
||||
; @brief Read the value from CS.
|
||||
; @brief Reads the value of CS.
|
||||
;
|
||||
; @return The value of CS.
|
||||
;
|
||||
@@ -50,7 +50,7 @@ AsmReadCs proc
|
||||
AsmReadCs endp
|
||||
|
||||
;
|
||||
; @brief Read the value from SS.
|
||||
; @brief Reads the value of SS.
|
||||
;
|
||||
; @return The value of SS.
|
||||
;
|
||||
@@ -60,7 +60,7 @@ AsmReadSs proc
|
||||
AsmReadSs endp
|
||||
|
||||
;
|
||||
; @brief Read the value from DS.
|
||||
; @brief Reads the value of DS.
|
||||
;
|
||||
; @return The value of DS.
|
||||
;
|
||||
@@ -70,7 +70,7 @@ AsmReadDs proc
|
||||
AsmReadDs endp
|
||||
|
||||
;
|
||||
; @brief Read the value from FS.
|
||||
; @brief Reads the value of FS.
|
||||
;
|
||||
; @return The value of FS.
|
||||
;
|
||||
@@ -80,7 +80,7 @@ AsmReadFs proc
|
||||
AsmReadFs endp
|
||||
|
||||
;
|
||||
; @brief Read the value from GS.
|
||||
; @brief Reads the value of GS.
|
||||
;
|
||||
; @return The value of GS.
|
||||
;
|
||||
@@ -90,7 +90,7 @@ AsmReadGs proc
|
||||
AsmReadGs endp
|
||||
|
||||
;
|
||||
; @brief Write the value to TR.
|
||||
; @brief Writes the value to TR.
|
||||
;
|
||||
; @param[in] RCX - The new TR value to write.
|
||||
;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
UINT16
|
||||
AsmReadLdtr (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -27,7 +26,6 @@ AsmReadLdtr (
|
||||
*/
|
||||
UINT16
|
||||
AsmReadTr (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -37,7 +35,6 @@ AsmReadTr (
|
||||
*/
|
||||
UINT16
|
||||
AsmReadEs (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -47,7 +44,6 @@ AsmReadEs (
|
||||
*/
|
||||
UINT16
|
||||
AsmReadCs (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -57,7 +53,6 @@ AsmReadCs (
|
||||
*/
|
||||
UINT16
|
||||
AsmReadSs (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -67,7 +62,6 @@ AsmReadSs (
|
||||
*/
|
||||
UINT16
|
||||
AsmReadDs (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -77,7 +71,6 @@ AsmReadDs (
|
||||
*/
|
||||
UINT16
|
||||
AsmReadFs (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -87,7 +80,6 @@ AsmReadFs (
|
||||
*/
|
||||
UINT16
|
||||
AsmReadGs (
|
||||
VOID
|
||||
);
|
||||
|
||||
/*!
|
||||
|
||||
@@ -457,7 +457,7 @@ LogFlushThread (
|
||||
LOGGER_CONTEXT* logger;
|
||||
LARGE_INTEGER interval;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
logger = (LOGGER_CONTEXT*)StartContext;
|
||||
interval.QuadPart = -(10000ll * logger->FlushIntervalInMs);
|
||||
@@ -562,13 +562,6 @@ CleanupPairedLogBuffer (
|
||||
ExFreePoolWithTag(PairedLogBuffer->InactiveLogBuffer->LogEntries, LOGGER_POOL_TAG);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Initializes the global logger.
|
||||
|
||||
@param[in] Configuration - The configuration for initialization.
|
||||
|
||||
@return STATUS_SUCCESS on success; otherwise, an appropriate error code.
|
||||
*/
|
||||
LOGGER_INIT
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS
|
||||
@@ -581,7 +574,7 @@ InitializeLogger (
|
||||
HANDLE fileHandle;
|
||||
HANDLE threadHandle;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
MV_ASSERT(g_Logger == NULL);
|
||||
|
||||
@@ -615,7 +608,7 @@ InitializeLogger (
|
||||
&filePath,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL)
|
||||
NULL);
|
||||
status = ZwCreateFile(&fileHandle,
|
||||
FILE_APPEND_DATA | SYNCHRONIZE,
|
||||
&objectAttributes,
|
||||
@@ -709,7 +702,6 @@ InitializeLogger (
|
||||
//
|
||||
g_Logger = logger;
|
||||
|
||||
|
||||
Exit:
|
||||
if (NT_ERROR(status))
|
||||
{
|
||||
@@ -729,9 +721,6 @@ Exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Clean up the logger.
|
||||
*/
|
||||
LOGGER_PAGED
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
@@ -742,7 +731,7 @@ CleanupLogger (
|
||||
LOGGER_CONTEXT* logger;
|
||||
SIZE_T maxOverflowedLogSize;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
MV_ASSERT(g_Logger != NULL);
|
||||
|
||||
|
||||
@@ -69,6 +69,13 @@ typedef struct _LOGGER_CONFIGURATION
|
||||
PCWSTR FilePath;
|
||||
} LOGGER_CONFIGURATION;
|
||||
|
||||
/*!
|
||||
@brief Initializes the global logger.
|
||||
|
||||
@param[in] Configuration - The configuration for initialization.
|
||||
|
||||
@return STATUS_SUCCESS on success; otherwise, an appropriate error code.
|
||||
*/
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
@@ -76,6 +83,9 @@ InitializeLogger (
|
||||
_In_ CONST LOGGER_CONFIGURATION* Configuration
|
||||
);
|
||||
|
||||
/*!
|
||||
@brief Clean up the logger.
|
||||
*/
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
VOID
|
||||
CleanupLogger (
|
||||
|
||||
@@ -97,7 +97,7 @@ ConvertNtToMvStatus (
|
||||
|
||||
@param[in] DriverObject - The driver's driver object.
|
||||
|
||||
@param[in] RegistryPath - A path to the driver's registry key.
|
||||
@param[in] RegistryPath - The path to the driver's registry key.
|
||||
|
||||
@return STATUS_SUCCESS on success; otherwise, an appropriate error code.
|
||||
*/
|
||||
@@ -148,7 +148,7 @@ DriverUnload (
|
||||
{
|
||||
UNREFERENCED_PARAMETER(DriverObject);
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// Start cross-platform clean up.
|
||||
@@ -165,7 +165,7 @@ InitializePlatform (
|
||||
NTSTATUS status;
|
||||
LOGGER_CONFIGURATION loggerConfig;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// Initialize in-house logger. Enable all flags.
|
||||
@@ -192,7 +192,7 @@ VOID
|
||||
CleanupPlatform (
|
||||
)
|
||||
{
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
CleanupLogger();
|
||||
}
|
||||
@@ -206,7 +206,7 @@ Sleep (
|
||||
{
|
||||
LARGE_INTEGER interval;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
interval.QuadPart = -(LONGLONG)(10000 * Milliseconds);
|
||||
(VOID)KeDelayExecutionThread(KernelMode, FALSE, &interval);
|
||||
@@ -296,7 +296,7 @@ ReserveVirtualAddress (
|
||||
UINT64 PageCount
|
||||
)
|
||||
{
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
return MmAllocateMappingAddress(PageCount * PAGE_SIZE, MV_POOL_TAG);
|
||||
}
|
||||
@@ -309,7 +309,7 @@ FreeReservedVirtualAddress (
|
||||
UINT64 PageCount
|
||||
)
|
||||
{
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(PageCount);
|
||||
|
||||
@@ -326,7 +326,7 @@ RunOnAllProcessors (
|
||||
{
|
||||
UINT32 numberOfProcessors;
|
||||
|
||||
PAGED_CODE()
|
||||
PAGED_CODE();
|
||||
|
||||
numberOfProcessors = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
|
||||
for (UINT32 index = 0; index < numberOfProcessors; ++index)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*!
|
||||
@file Public.h
|
||||
|
||||
@brief Interfaces to communicate with our hypervisor.
|
||||
@brief Interfaces to communicate with the hypervisor.
|
||||
|
||||
@author Satoshi Tanda
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/*!
|
||||
@file Utils.c
|
||||
|
||||
@brief Utility functions that could be used by both on root and non-root
|
||||
operations.
|
||||
@brief Utility functions that could be used by both the host and non-host.
|
||||
|
||||
@author Satoshi Tanda
|
||||
|
||||
@@ -75,10 +74,10 @@ Exit:
|
||||
/*!
|
||||
@brief Returns the segment descriptor corresponds to the SegmentSelector.
|
||||
|
||||
@param[in] DescriptorTableBase - An address of the base of the descriptor
|
||||
@param[in] DescriptorTableBase - The address of the base of the descriptor
|
||||
table.
|
||||
|
||||
@param[in] SegmentSelector - A segment selector value.
|
||||
@param[in] SegmentSelector - The segment selector value.
|
||||
|
||||
@return The segment descriptor corresponds to the SegmentSelector.
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/*!
|
||||
@file Utils.h
|
||||
|
||||
@brief Utility functions that could be used by both on root and non-root
|
||||
operations.
|
||||
@brief Utility functions that could be used by both the host and non-host.
|
||||
|
||||
@author Satoshi Tanda
|
||||
|
||||
@@ -36,7 +35,7 @@ ComputeAddressFromIndexes (
|
||||
@brief Returns the access right of the segment specified by the SegmentSelector
|
||||
for VMX.
|
||||
|
||||
@param[in] SegmentSelector - A segment selector value.
|
||||
@param[in] SegmentSelector - The segment selector value.
|
||||
|
||||
@return The access right of the segment for VMX.
|
||||
*/
|
||||
@@ -48,7 +47,7 @@ GetSegmentAccessRight (
|
||||
/*!
|
||||
@brief Returns the base address of the segment specified by SegmentSelector.
|
||||
|
||||
@param[in] DescriptorTableBase - An address of the base of the descriptor
|
||||
@param[in] DescriptorTableBase - The address of the base of the descriptor
|
||||
table.
|
||||
|
||||
@param[in] SegmentSelector - The segment selector which points to the
|
||||
|
||||
Reference in New Issue
Block a user