Update comments

This commit is contained in:
Satoshi Tanda
2020-03-07 10:47:18 -08:00
parent adf09d85af
commit cd56f77bc0
32 changed files with 276 additions and 229 deletions

View File

@@ -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) current_page_base = idaapi.get_reg_val('rip') & (~0xfff)
offset = 0 offset = 0
while idc.read_dbg_word(current_page_base - offset) != 0x5a4d: while idc.read_dbg_word(current_page_base - offset) != 0x5a4d:

View File

@@ -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 os
import sys import sys
import shutil import shutil

View File

@@ -23,17 +23,17 @@ extern HandleVmExit : proc
extern HandleVmExitFailure : 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 ; @details The easiest way to understand this code is to see this as an entry
; point of "VM-exit handler". ; point of "VM-exit handler".
; ;
; Up on VM-exit, the processor starts executing this function as ; Up on VM-exit, the processor starts executing this function as
; condifured in the VmcsHostRip field of VMCS. At this time, the processor ; configured in the Host RIP field of VMCS. When this function is executed,
; is in the vmx-root mode, which allows the processor to execute any ; the processor is in the vmx-root mode, which allows the processor to
; instructions without causing VM-exit, and the processor is not governed ; execute any instructions without causing VM-exit, and the processor is
; by EPT. The code executed from here emulates the instruction caused ; not governed by EPT. The code executed from here most typically emulates
; VM-exit by, most typically, executing the same instruction on behalf of ; the instruction caused VM-exit by executing the same instruction on behalf of
; the guest (see HandleCpuid for example), or changing relevant processor ; the guest (see HandleCpuid for example), or changing relevant processor
; state and letting the guest retry, for example, handling EPT violation. ; 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. ; context. We also refer those code as a VM-exit handler.
; ;
AsmHypervisorEntryPoint proc frame AsmHypervisorEntryPoint proc frame
;
; Windows-specific:
; ;
; Three not-well known techniques are used in this function in oder for ; 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 ; Windbg to display the stack trace of the guest while the VM-exit
@@ -177,9 +179,8 @@ ExitVm:
VmxError: VmxError:
; ;
; Any of VMX instructions failed. Unrecoverble. The most useful thing ; VMRESUME or VMXOFF instruction failed. Unrecoverble. The most useful
; to do here is probably to call a C-function that does diagnostics ; thing to do here is to call a C-function to diagnose the issue.
; like dumping VMCS.
; ;
pushf pushf
PUSHAQ PUSHAQ
@@ -190,11 +191,11 @@ VmxError:
AsmHypervisorEntryPoint endp 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. ; @return An appropriate VMX_RESULT value.
; ;
@@ -221,11 +222,11 @@ ErrorWithoutCode:
AsmInvept endp 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. ; @return An appropriate VMX_RESULT value.
; ;
@@ -287,9 +288,9 @@ AsmVmxCall proc
AsmVmxCall endp 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 AsmGetCurrentInstructionPointer proc
mov rax, [rsp] mov rax, [rsp]

View File

@@ -10,28 +10,27 @@
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#if defined(NTDDI_VERSION) #if defined(MV_PLATFORM_WINDOWS)
#include "Platform/Windows/WinAsm.h" #include "Platform/Windows/WinAsm.h"
#else #else
#include "Platform/EFI/EfiAsm.h" #include "Platform/EFI/EfiAsm.h"
#endif #endif
/*! /*!
@brief An entry point for the hypervisor. @brief The entry point for the hypervisor.
@details See x64.asm. @details See Asm.asm.
*/ */
VOID VOID
AsmHypervisorEntryPoint ( 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. @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. @return An appropriate VMX_RESULT value.
*/ */
@@ -56,7 +55,6 @@ AsmInvvpid (
_In_ CONST INVVPID_DESCRIPTOR* InvVpidDescriptor _In_ CONST INVVPID_DESCRIPTOR* InvVpidDescriptor
); );
/*! /*!
@brief Reads the access rights byte of the segment. @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 UINT64
AsmGetCurrentInstructionPointer ( AsmGetCurrentInstructionPointer (
VOID
); );
/*! /*!
@@ -109,5 +106,4 @@ AsmGetCurrentInstructionPointer (
*/ */
UINT64 UINT64
AsmGetCurrentStackPointer ( AsmGetCurrentStackPointer (
VOID
); );

View File

@@ -9,10 +9,17 @@
*/ */
#pragma once #pragma once
#if defined(NTDDI_VERSION) #if defined(NTDDI_VERSION)
#define MV_PLATFORM_WINDOWS
#else
#define MV_PLATFORM_EFI
#endif
#if defined(MV_PLATFORM_WINDOWS)
#include "Platform/Windows/WinCommon.h" #include "Platform/Windows/WinCommon.h"
#else #else
#include "Platform/EFI/EfiCommon.h" #include "Platform/EFI/EfiCommon.h"
#endif #endif
#include "Ia32.h" #include "Ia32.h"
// //

View File

@@ -37,11 +37,11 @@ typedef struct _EPT_ENTRIES
C_ASSERT(sizeof(EPT_ENTRIES) == sizeof(VOID*) * 4); 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 static
VOID VOID

View File

@@ -63,9 +63,9 @@ typedef struct _EPT_CONTEXT
} 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. @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 VOID
CleanupExtendedPageTables ( 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 @param[in] EptPointer - The EPT pointer to invalidate associated caches. If
0 is specified, caches associated with any EPT pointers are invalidated. 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 @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 VOID
InvalidateVpidDerivedCache ( InvalidateVpidDerivedCache (

View File

@@ -15,6 +15,8 @@
#include "HostVmcall.h" #include "HostVmcall.h"
#include "HostNesting.h" #include "HostNesting.h"
//
// Windows-specific:
// //
// The trap frame structure for x64 systems. This is structure is used to help // 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. // 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 can check the exception is #GP(0) caused by RDMSR or WRMSR, and if this
is the case, inject it to the guest. 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. @param[in] OperationType - The type of the operation.
*/ */
@@ -110,7 +112,7 @@ HandleMsrAccess (
/*! /*!
@brief Handles VM-exit due to execution of the RDMSR instruction. @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 static
VOID VOID
@@ -124,7 +126,7 @@ HandleMsrRead (
/*! /*!
@brief Handles VM-exit due to execution of the WRMSR instruction. @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 static
VOID VOID
@@ -138,7 +140,7 @@ HandleMsrWrite (
/*! /*!
@brief Handles VM-exit due to execution of the CPUID instruction. @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 static
VOID VOID
@@ -208,7 +210,7 @@ HandleCpuid (
/*! /*!
@brief Handles VM-exit due to execution of the VMCALL instruction. @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 static
VOID VOID
@@ -245,7 +247,7 @@ Exit:
/*! /*!
@brief Handles VM-exit due to execution of the XSETBV instruction. @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 static
VOID VOID
@@ -275,7 +277,7 @@ HandleXsetbv (
@brief Returns the address of where the guest general purpose register that @brief Returns the address of where the guest general purpose register that
corresponds to the given index is stored. 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. @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. @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 static
VOID VOID
@@ -382,7 +384,7 @@ HandleCrAccess (
/*! /*!
@brief Handles VM-exit due to EPT violation. @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 static
VOID VOID
@@ -408,7 +410,7 @@ HandleEptViolation (
/*! /*!
@brief Handles VM-exit due to EPT misconfiguration. @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 static
VOID VOID
@@ -444,7 +446,12 @@ HandleEptMisconfig (
/*! /*!
@brief Handles VM-exit due to interrupt or exception. @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 static
VOID VOID
@@ -455,11 +462,6 @@ HandleExceptionOrNmi (
static BOOLEAN isKeInitAmd64SpecificStateCalled; static BOOLEAN isKeInitAmd64SpecificStateCalled;
VMEXIT_INTERRUPT_INFORMATION interruptInfo; 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); interruptInfo.Flags = (UINT32)VmxRead(VMCS_VMEXIT_INTERRUPTION_INFORMATION);
MV_ASSERT(interruptInfo.InterruptionType == HardwareException); MV_ASSERT(interruptInfo.InterruptionType == HardwareException);
MV_ASSERT(interruptInfo.Vector == DivideError); MV_ASSERT(interruptInfo.Vector == DivideError);
@@ -513,7 +515,7 @@ Exit:
/*! /*!
@brief Handles VM-exit due to the INIT signal. @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 static
VOID VOID
@@ -673,7 +675,7 @@ HandleInitSignal (
/*! /*!
@brief Handles VM-exit due to the Startup-IPI (SIPI) signal. @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 static
VOID VOID
@@ -738,12 +740,12 @@ HandleStartupIpi (
Any hypervisor code including this and the AsmHypervisorEntryPoint Any hypervisor code including this and the AsmHypervisorEntryPoint
functions are executed while interrupt is disabled via RFLAGS.IF being 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 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 requested, is never delivered and causes deadlock. In the Windows
essentially equal to IRQL being HIGH_LEVEL (i.e., at a higher IRQL than terminology, this condition is essentially equal to IRQL being HIGH_LEVEL
IPI_LEVEL), and so, it is unsafe to call any Windows provided API that (i.e., at a higher IRQL than IPI_LEVEL), and so, it is unsafe to call any
is not stated as callable at HIGH_LEVEL. 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. guest register values.
@return TRUE when virtualization should continue and the VMRESUME instruction @return TRUE when virtualization should continue and the VMRESUME instruction
@@ -785,6 +787,8 @@ HandleVmExit (
guestContext.VmcsBasedRegisters.Rsp = VmxRead(VMCS_GUEST_RSP); guestContext.VmcsBasedRegisters.Rsp = VmxRead(VMCS_GUEST_RSP);
guestContext.VmcsBasedRegisters.Rip = VmxRead(VMCS_GUEST_RIP); guestContext.VmcsBasedRegisters.Rip = VmxRead(VMCS_GUEST_RIP);
//
// Windows-specific:
// //
// Update the _KTRAP_FRAME structure values in hypervisor stack, so that // Update the _KTRAP_FRAME structure values in hypervisor stack, so that
// Windbg can reconstruct call stack of the guest during debug session. // 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 @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 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 @param[in] Stack - The pointer to the hypervisor stack containing the
guest register values. guest register values.

View File

@@ -308,7 +308,6 @@ AdvanceGuestInstructionPointer (
_Use_decl_annotations_ _Use_decl_annotations_
BOOLEAN BOOLEAN
IsGuestInKernelMode ( IsGuestInKernelMode (
VOID
) )
{ {
VMX_SEGMENT_ACCESS_RIGHTS accessRight; VMX_SEGMENT_ACCESS_RIGHTS accessRight;

View File

@@ -107,9 +107,9 @@ DumpControl (
/*! /*!
@brief Writes the value to the VMCS. @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 VOID
VmxWrite ( VmxWrite (
@@ -120,7 +120,7 @@ VmxWrite (
/*! /*!
@brief Read a value from the VMCS. @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 @return A value read from the VMCS. 0 is returned when a non-existent VMCS
field is requested for read. field is requested for read.
@@ -134,7 +134,7 @@ VmxRead (
@brief Advances the guest's RIP to the address of the next instruction. This @brief Advances the guest's RIP to the address of the next instruction. This
implies that the hypervisor completed emulation of the instruction. 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 VOID
AdvanceGuestInstructionPointer ( AdvanceGuestInstructionPointer (
@@ -150,7 +150,6 @@ AdvanceGuestInstructionPointer (
_Must_inspect_result_ _Must_inspect_result_
BOOLEAN BOOLEAN
IsGuestInKernelMode ( IsGuestInKernelMode (
VOID
); );
/*! /*!
@@ -160,16 +159,16 @@ IsGuestInKernelMode (
corresponding exception handler before executing the instruction pointed corresponding exception handler before executing the instruction pointed
by Rip. 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 @param[in] DeliverErrorCode - TRUE when the interrupt should have an error
code. Whether the interrupt should have an error code is defined by the 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 Intel SDM. See comments in the EXCEPTION_VECTOR definitions for a quick
reference. 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 VOID
InjectInterruption ( 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. @param[in] GuestContext - The pointer to the guest context.

View File

@@ -36,7 +36,7 @@ HandleVmcallUninstall (
// from the guest state fields of the VMCS. However, it is not the case when // 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 // the VMRESUME is not called, like here. In such a case those values must
// be restored with normal value manually, or PatchGuard will report // 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." // "The GDTR and IDTR limits are each set to FFFFH."
// See: 27.5.2 Loading Host Segment and Descriptor-Table Registers // See: 27.5.2 Loading Host Segment and Descriptor-Table Registers

View File

@@ -24,7 +24,7 @@ VMCALL_HANDLER (
/*! /*!
@brief Handles hypercall for uninstalling the hypervisor. @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; VMCALL_HANDLER HandleVmcallUninstall;

View File

@@ -19,7 +19,7 @@
// difference of the formatting functions. Use them like the standard's PRIx macro // difference of the formatting functions. Use them like the standard's PRIx macro
// family. // family.
// //
#if defined(NTDDI_VERSION) #if defined(MV_PLATFORM_WINDOWS)
#define LOG_PRIANSI "s" #define LOG_PRIANSI "s"
#define LOG_PRIUNICODE "S" #define LOG_PRIUNICODE "S"
#else #else

View File

@@ -14,9 +14,9 @@
#include "Logger.h" #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. @return MV_STATUS_SUCCESS on success; otherwise, an appropriate error code.
*/ */
@@ -499,11 +499,14 @@ GetPhysicalAddressForGuest (
Exit: Exit:
// //
// Return the collected permission bits on success. // Return the collected permission bits if provided.
// //
if ((pa != MV_INVALID_PHYSICAL_ADDRESS) && if (ARGUMENT_PRESENT(AggregatedPagePermissions))
ARGUMENT_PRESENT(AggregatedPagePermissions))
{ {
if (pa == MV_INVALID_PHYSICAL_ADDRESS)
{
permission.Flags = 0;
}
*AggregatedPagePermissions = permission; *AggregatedPagePermissions = permission;
} }
return pa; return pa;

View File

@@ -85,9 +85,9 @@ CleanupMemoryAccess (
given virtual address and retrieves the guest physical address of it. given virtual address and retrieves the guest physical address of it.
This is equivalent to changing the current CR3 with the guest CR3 and This is equivalent to changing the current CR3 with the guest CR3 and
calling GetPhysicalAddress(). This function, however, exists to avoid calling GetPhysicalAddress(). This function, however, exists to avoid
problems associated with CR3 update, for example, updating the CR3 crashes problems associated with CR3 update, for example, on Windows, updating
the system immediately if the KVA Shadow is enabled and the guest CR3 the CR3 crashes the system immediately if the KVA Shadow is enabled and
contains the USER CR3, as it does not map our driver. the guest CR3 contains the USER CR3, as it does not map our code.
@param[in] Context - The pointer to the memory access context. @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] 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 @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 the page number, or NULL if the specified page number does not have

View File

@@ -10,7 +10,7 @@
#include "MemoryManager.h" #include "MemoryManager.h"
#include "Platform.h" #include "Platform.h"
#include "Logger.h" #include "Logger.h"
#if !defined(NTDDI_VERSION) #if defined(MV_PLATFORM_EFI)
#include "Platform/EFI/EfiBitmap.h" #include "Platform/EFI/EfiBitmap.h"
#endif #endif
@@ -78,7 +78,7 @@ MmInitializeMemoryManager (
UINT32 lengthMapPagesCount; UINT32 lengthMapPagesCount;
MEMORY_MANAGER_CONTEXT* memoryManager; MEMORY_MANAGER_CONTEXT* memoryManager;
PAGED_CODE() PAGED_CODE();
memoryManager = &g_MemoryManager; memoryManager = &g_MemoryManager;
lengthMapPagesCount = 0; lengthMapPagesCount = 0;
@@ -174,7 +174,7 @@ MmCleanupMemoryManager (
UINT32 lengthMapPagesCount; UINT32 lengthMapPagesCount;
MEMORY_MANAGER_CONTEXT* memoryManager; MEMORY_MANAGER_CONTEXT* memoryManager;
PAGED_CODE() PAGED_CODE();
memoryManager = &g_MemoryManager; memoryManager = &g_MemoryManager;

View File

@@ -3,6 +3,10 @@
@brief Functions for memory management. @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 @author Satoshi Tanda
@copyright Copyright (c) 2020 - , Satoshi Tanda. All rights reserved. @copyright Copyright (c) 2020 - , Satoshi Tanda. All rights reserved.

View File

@@ -9,7 +9,6 @@
*/ */
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#include "Ia32.h"
/*! /*!
@brief Initializes the MTRR context. @brief Initializes the MTRR context.
@@ -21,12 +20,12 @@ InitializeMemoryTypeMapping (
/*! /*!
@brief Returns a memory type for the given physical address range. @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. @param[in] RangeSize - The size of the range to check.
@return The memory type for the given physical address. If the range contains @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 IA32_MEMORY_TYPE
GetMemoryTypeForRange ( GetMemoryTypeForRange (

View File

@@ -164,10 +164,10 @@ typedef struct _SHARED_PROCESSOR_CONTEXT
@brief Returns the VM control value that is adjusted in consideration with @brief Returns the VM control value that is adjusted in consideration with
the VMX capability MSR. 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, 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. @return The adjusted control value.
*/ */
@@ -220,7 +220,7 @@ AdjustControlValue (
@brief Adjusts a pin-based control value in consideration with the VMX @brief Adjusts a pin-based control value in consideration with the VMX
capability MSR. 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. to adjust.
*/ */
static static
@@ -233,9 +233,9 @@ AdjustPinBasedControls (
IA32_VMX_BASIC_REGISTER vmxBasicMsr; 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 // 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 // "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:" // to determine the allowed settings of the pin based VM-execution controls:"
// See: A.3.1 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 @brief Adjusts a processor-based control value in consideration with the VMX
capability MSR. 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. control value to adjust.
*/ */
static static
@@ -280,7 +280,7 @@ AdjustProcessorBasedControls (
@brief Adjusts a VM-exit control value in consideration with the VMX @brief Adjusts a VM-exit control value in consideration with the VMX
capability MSR. 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. adjust.
*/ */
static static
@@ -307,7 +307,7 @@ AdjustVmExitControls (
@brief Adjusts a VM-entry control value in consideration with the VMX @brief Adjusts a VM-entry control value in consideration with the VMX
capability MSR. 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. adjust.
*/ */
static static
@@ -334,7 +334,7 @@ AdjustVmEntryControls (
@brief Adjusts a secondary processor-based control value in consideration @brief Adjusts a secondary processor-based control value in consideration
with the VMX capability MSR. 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. processor-based control value to adjust.
*/ */
static static
@@ -361,7 +361,6 @@ static
_Must_inspect_result_ _Must_inspect_result_
BOOLEAN BOOLEAN
IsMiniVisorInstalled ( IsMiniVisorInstalled (
VOID
) )
{ {
int registers[4]; // EAX, EBX, ECX, and EDX 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. the shared processor context.
*/ */
MV_SECTION_PAGED
static static
_IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_max_(PASSIVE_LEVEL)
VOID VOID
@@ -397,6 +397,8 @@ DisableHypervisor (
SHARED_PROCESSOR_CONTEXT** sharedProcessorContextsAddress; SHARED_PROCESSOR_CONTEXT** sharedProcessorContextsAddress;
PER_PROCESSOR_CONTEXT* processorContext; PER_PROCESSOR_CONTEXT* processorContext;
PAGED_CODE();
if (IsMiniVisorInstalled() == FALSE) if (IsMiniVisorInstalled() == FALSE)
{ {
goto Exit; goto Exit;
@@ -404,8 +406,7 @@ DisableHypervisor (
// //
// Issues the hypercall to uninstall the hypervisor. This hypercall returns // Issues the hypercall to uninstall the hypervisor. This hypercall returns
// the address of the shared processor context on success. If the hypervisor // the address of the shared processor context on success.
// is not installed, this (VMCALL instruction) raises #UD.
// //
returnedAddress = (SHARED_PROCESSOR_CONTEXT*)AsmVmxCall(VmcallUninstall, 0, 0, 0); returnedAddress = (SHARED_PROCESSOR_CONTEXT*)AsmVmxCall(VmcallUninstall, 0, 0, 0);
MV_ASSERT(returnedAddress != NULL); MV_ASSERT(returnedAddress != NULL);
@@ -423,7 +424,7 @@ DisableHypervisor (
*sharedProcessorContextsAddress = returnedAddress; *sharedProcessorContextsAddress = returnedAddress;
// //
// Clean up the per-processor stuff, to be precise, EPT setup. // Clean up the per-processor data structures.
// //
processorContext = &(*sharedProcessorContextsAddress)->Contexts[GetCurrentProcessorNumber()]; processorContext = &(*sharedProcessorContextsAddress)->Contexts[GetCurrentProcessorNumber()];
CleanupExtendedPageTables(&processorContext->EptContext); 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 MV_SECTION_PAGED
static static
_IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_max_(PASSIVE_LEVEL)
VOID VOID
DisableHypervisorOnAllProcessors ( DisableHypervisorOnAllProcessors (
VOID
) )
{ {
SHARED_PROCESSOR_CONTEXT* sharedProcessorContext; SHARED_PROCESSOR_CONTEXT* sharedProcessorContext;
PAGED_CODE() PAGED_CODE();
sharedProcessorContext = NULL; sharedProcessorContext = NULL;
RunOnAllProcessors(DisableHypervisor, &sharedProcessorContext); RunOnAllProcessors(DisableHypervisor, &sharedProcessorContext);
@@ -467,7 +467,6 @@ static
_Must_inspect_result_ _Must_inspect_result_
BOOLEAN BOOLEAN
IsVmxAvailable ( IsVmxAvailable (
VOID
) )
{ {
BOOLEAN vmxAvailable; BOOLEAN vmxAvailable;
@@ -494,7 +493,7 @@ IsVmxAvailable (
// //
// Check the processor support the write-back type for VMCS. We do not // 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 // 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 // "As of this writing, all processors that support VMX operation indicate
// the write-back type." // the write-back type."
// //
@@ -529,19 +528,17 @@ IsVmxAvailable (
} }
// //
// Check the followings to confirm availability of EPT related capabilities: // 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
// //
eptVpidCapabilityMsr.Flags = __readmsr(IA32_VMX_EPT_VPID_CAP); eptVpidCapabilityMsr.Flags = __readmsr(IA32_VMX_EPT_VPID_CAP);
if ((eptVpidCapabilityMsr.PageWalkLength4 == FALSE) || if ((eptVpidCapabilityMsr.PageWalkLength4 == FALSE) ||
(eptVpidCapabilityMsr.MemoryTypeWriteBack == FALSE) || (eptVpidCapabilityMsr.MemoryTypeWriteBack == FALSE) ||
(eptVpidCapabilityMsr.Pde2MbPages == FALSE) || (eptVpidCapabilityMsr.Pde2MbPages == FALSE) ||
(eptVpidCapabilityMsr.Invept == FALSE) || (eptVpidCapabilityMsr.Invept == FALSE) ||
(eptVpidCapabilityMsr.InveptSingleContext == FALSE) ||
(eptVpidCapabilityMsr.InveptAllContexts == FALSE) || (eptVpidCapabilityMsr.InveptAllContexts == FALSE) ||
(eptVpidCapabilityMsr.Invvpid == FALSE) || (eptVpidCapabilityMsr.Invvpid == FALSE) ||
(eptVpidCapabilityMsr.InvvpidSingleContext == FALSE) ||
(eptVpidCapabilityMsr.InvvpidAllContexts == FALSE)) (eptVpidCapabilityMsr.InvvpidAllContexts == FALSE))
{ {
LOG_ERROR("EPT is not supported."); LOG_ERROR("EPT is not supported.");
@@ -562,10 +559,10 @@ Exit:
See: 31.5 VMM SETUP & TEAR DOWN See: 31.5 VMM SETUP & TEAR DOWN
See: 31.6 PREPARATION AND LAUNCHING A VIRTUAL MACHINE 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 @param[in,out] ProcessorContext - The pointer to the per-processor context
processor. for this processor.
@return MV_STATUS_SUCCESS on success, or an appropriate status code on error. @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 // 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. // GDT as necessary.
// //
// "The selector fields for CS and TR cannot be 0000H." // "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 // Initialize EPT specific data structures.
// EPT-context.
// //
status = InitializeExtendedPageTables(&ProcessorContext->EptContext); status = InitializeExtendedPageTables(&ProcessorContext->EptContext);
if (MV_ERROR(status)) if (MV_ERROR(status))
@@ -829,20 +825,20 @@ SetupVmcs (
// instructions. // instructions.
// //
// - MSR bitmaps are used; this is not to cause VM-exit as much as possible. // - 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 // We are setting the MSR bitmaps that are mostly cleared below (see
// around the "64-Bit Control Fields" comment). This prevents VM-exits from // InitializeMsrBitmaps). This prevents VM-exits from occurring when
// occurring when 0x0 - 0x1fff and 0xc0000000 - 0xc0001fff are accessed. // 0x0 - 0x1fff and 0xc0000000 - 0xc0001fff are accessed. VM-exit still
// Note that VM-exit still occurs if outside the range is accessed, and it // occurs if outside the range is accessed, and it is not possible to
// is not possible to prevent this. // prevent this.
// //
// - The secondary processor-based controls are used; this is to let the // - The secondary processor-based controls are used; this is to let the
// guest (Windows) executes RDTSCP, INVPCID and the XSAVE/XRSTORS family // guest (Windows) executes RDTSCP, INVPCID and the XSAVE/XRSTORS family
// instructions. Those instructions are used in Windows 10. If those are // instructions. Those instructions are used in Windows 10. If those are
// not set, attempt to execute them causes #UD, which results in a bug // 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 // 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 // by not flushing all TLB on every VM-exit and VM-entry. Finally, enabling
// unrestricted guest which are required for the UEFI hypervisor to handle // EPT and unrestricted guest which are required for the UEFI hypervisor to
// the real-mode guest. // handle the real-mode guest.
// //
primaryProcBasedControls.Flags = 0; primaryProcBasedControls.Flags = 0;
primaryProcBasedControls.UseMsrBitmaps = TRUE; primaryProcBasedControls.UseMsrBitmaps = TRUE;
@@ -870,13 +866,20 @@ SetupVmcs (
// RPL (bits 1:0) and the TI flag (bit 2) must be 0" // 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 // See: 26.2.3 Checks on Host Segment and Descriptor-Table Registers
// //
VmxWrite(VMCS_HOST_ES_SELECTOR, AsmReadEs() & ~hostSegmentSelectorMask); MV_ASSERT(FlagOn(AsmReadEs(), hostSegmentSelectorMask) == FALSE);
VmxWrite(VMCS_HOST_CS_SELECTOR, AsmReadCs() & ~hostSegmentSelectorMask); MV_ASSERT(FlagOn(AsmReadCs(), hostSegmentSelectorMask) == FALSE);
VmxWrite(VMCS_HOST_SS_SELECTOR, AsmReadSs() & ~hostSegmentSelectorMask); MV_ASSERT(FlagOn(AsmReadSs(), hostSegmentSelectorMask) == FALSE);
VmxWrite(VMCS_HOST_DS_SELECTOR, AsmReadDs() & ~hostSegmentSelectorMask); MV_ASSERT(FlagOn(AsmReadDs(), hostSegmentSelectorMask) == FALSE);
VmxWrite(VMCS_HOST_FS_SELECTOR, AsmReadFs() & ~hostSegmentSelectorMask); MV_ASSERT(FlagOn(AsmReadFs(), hostSegmentSelectorMask) == FALSE);
VmxWrite(VMCS_HOST_GS_SELECTOR, AsmReadGs() & ~hostSegmentSelectorMask); MV_ASSERT(FlagOn(AsmReadGs(), hostSegmentSelectorMask) == FALSE);
VmxWrite(VMCS_HOST_TR_SELECTOR, AsmReadTr() & ~hostSegmentSelectorMask); 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 */ /* 64-Bit Host-State Fields */
VmxWrite(VMCS_HOST_EFER, __readmsr(IA32_EFER)); VmxWrite(VMCS_HOST_EFER, __readmsr(IA32_EFER));
@@ -1021,8 +1024,9 @@ Exit:
/*! /*!
@brief Enables hypervisor on the current processor. @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 static
_IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_max_(PASSIVE_LEVEL)
VOID VOID
@@ -1037,6 +1041,8 @@ EnableHypervisor (
UINT64 guestRip; UINT64 guestRip;
BOOLEAN maCtxInitialized; BOOLEAN maCtxInitialized;
PAGED_CODE();
maCtxInitialized = FALSE; maCtxInitialized = FALSE;
sharedProcessorContext = Context; sharedProcessorContext = Context;
@@ -1049,7 +1055,7 @@ EnableHypervisor (
// host. // host.
// //
processorContext->Status = InitializeMemoryAccess(&processorContext->MemoryAccessContext, processorContext->Status = InitializeMemoryAccess(&processorContext->MemoryAccessContext,
GetHostCr3()); GetHostCr3());
if (MV_ERROR(processorContext->Status)) if (MV_ERROR(processorContext->Status))
{ {
LOG_ERROR("InitializeMemoryAccess failed : %08x", processorContext->Status); LOG_ERROR("InitializeMemoryAccess failed : %08x", processorContext->Status);
@@ -1140,6 +1146,7 @@ EnableHypervisor (
vmxErrorStatus = (result == VmxResultErrorWithStatus) ? vmxErrorStatus = (result == VmxResultErrorWithStatus) ?
(VMX_ERROR_NUMBER)VmxRead(VMCS_VM_INSTRUCTION_ERROR) : 0; (VMX_ERROR_NUMBER)VmxRead(VMCS_VM_INSTRUCTION_ERROR) : 0;
LOG_ERROR("__vmx_vmlaunch failed : %u", vmxErrorStatus); LOG_ERROR("__vmx_vmlaunch failed : %u", vmxErrorStatus);
processorContext->Status = MV_STATUS_HV_OPERATION_FAILED; processorContext->Status = MV_STATUS_HV_OPERATION_FAILED;
CleanupExtendedPageTables(&processorContext->EptContext); CleanupExtendedPageTables(&processorContext->EptContext);
__vmx_off(); __vmx_off();
@@ -1159,8 +1166,8 @@ Exit:
@details This function clears the bitmaps to avoid VM-exits that do not require @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 manual handling. The MSR that requires manual handling for MiniVisor is
IA32_BIOS_SIGN_ID to prevent the guest from attempting update BIOS IA32_BIOS_SIGN_ID for read to prevent the guest from attempting update
microcode. See HandleMsrAccess for more details. BIOS microcode which is not allowed. See HandleMsrAccess for more details.
@param[out] Bitmaps - The pointer to the MSR bitmaps to initialize. @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 biosSignatureByteOffset = (IA32_BIOS_SIGN_ID / CHAR_BIT);
static CONST UINT64 biosSignatureBitMask = (1ull << (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)); 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. @return MV_STATUS_SUCCESS on success; otherwise, an appropriate error code.
*/ */
@@ -1192,7 +1199,6 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_ _Must_inspect_result_
MV_STATUS MV_STATUS
EnableHypervisorOnAllProcessors ( EnableHypervisorOnAllProcessors (
VOID
) )
{ {
MV_STATUS status; MV_STATUS status;
@@ -1201,7 +1207,7 @@ EnableHypervisorOnAllProcessors (
SHARED_PROCESSOR_CONTEXT* sharedProcessorContext; SHARED_PROCESSOR_CONTEXT* sharedProcessorContext;
BOOLEAN virtualized; BOOLEAN virtualized;
PAGED_CODE() PAGED_CODE();
virtualized = FALSE; virtualized = FALSE;
@@ -1322,7 +1328,7 @@ InitializeMiniVisor (
// //
if (IsMiniVisorInstalled() != FALSE) if (IsMiniVisorInstalled() != FALSE)
{ {
LOG_ERROR("MiniVisor already installed"); LOG_INFO("MiniVisor already installed");
status = MV_STATUS_HV_OPERATION_FAILED; status = MV_STATUS_HV_OPERATION_FAILED;
goto Exit; goto Exit;
} }

View File

@@ -13,7 +13,7 @@
// //
// Spin lock type and state names. // Spin lock type and state names.
// //
#if defined(NTDDI_VERSION) #if defined(MV_PLATFORM_WINDOWS)
typedef volatile LONG64 SPIN_LOCK; typedef volatile LONG64 SPIN_LOCK;
typedef enum _SPIN_LOCK_STATE typedef enum _SPIN_LOCK_STATE
{ {
@@ -81,7 +81,7 @@ GetCurrentProcessorNumber (
/*! /*!
@brief Returns the physical address of the given virtual address. @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 address for the current CR3. This must be non paged pool, otherwise the
result is undefined. result is undefined.

View File

@@ -25,7 +25,10 @@ Index = 0
; Index is incremented whenever this macro is used. ; Index is incremented whenever this macro is used.
; ;
INTERRUPT_HANDLER macro InterruptNumber 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 push InterruptNumber
jmp AsmCommonExceptionHandler jmp AsmCommonExceptionHandler
Index = Index + 1 Index = Index + 1
@@ -38,7 +41,10 @@ endm
; Index is incremented whenever this macro is used. ; Index is incremented whenever this macro is used.
; ;
INTERRUPT_HANDLER_WITH_CODE macro InterruptNumber 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 nop
push InterruptNumber push InterruptNumber
jmp AsmCommonExceptionHandler jmp AsmCommonExceptionHandler
@@ -53,26 +59,44 @@ endm
; works as a hendler of the corresponding interrupt/exception in the host. ; works as a hendler of the corresponding interrupt/exception in the host.
; ;
AsmDefaultExceptionHandlers proc AsmDefaultExceptionHandlers proc
repeat 8 ;
INTERRUPT_HANDLER Index ; INT0-7 ; INT0-7
endm ;
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 ; INT10-14
endm ;
repeat 5
INTERRUPT_HANDLER_WITH_CODE Index
endm
repeat 2 ;
INTERRUPT_HANDLER Index ; INT15-16 ; INT15-16
endm ;
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 ; INT18-255
endm ;
repeat 238
INTERRUPT_HANDLER Index
endm
AsmDefaultExceptionHandlers endp AsmDefaultExceptionHandlers endp
; ;
@@ -88,7 +112,11 @@ AsmCommonExceptionHandler proc
call HandleHostException call HandleHostException
add rsp, 20h add rsp, 20h
POPAQ POPAQ
add rsp, 10h ; Remove the error code and interrupt number.
;
; Remove the error code and interrupt number.
;
add rsp, 10h
iretq iretq
AsmCommonExceptionHandler endp AsmCommonExceptionHandler endp

View File

@@ -15,7 +15,6 @@
*/ */
VOID VOID
AsmDefaultExceptionHandlers ( AsmDefaultExceptionHandlers (
VOID
); );
/*! /*!
@@ -23,5 +22,4 @@ AsmDefaultExceptionHandlers (
*/ */
VOID VOID
AsmNmiExceptionHandler ( AsmNmiExceptionHandler (
VOID
); );

View File

@@ -8,9 +8,9 @@
reused once they are set, even after they are "cleared". reused once they are set, even after they are "cleared".
For complete implementation, one can copy ReactOS's implementation if For complete implementation, one can copy ReactOS's implementation if
licensing the project under GPL is acceptable. hvpp by wbenny has its own licensing the project under GPL is acceptable. hvpp by Petr Beneš has its
implementation of bitmap but is actually influenced by ReactOS own implementation of bitmap but is actually influenced by ReactOS
implementation and such should be treated as GPL. implementation, and such, should be treated as GPL.
@author Satoshi Tanda @author Satoshi Tanda

View File

@@ -34,21 +34,21 @@
fault (null pointer access) when it fires in the host code. The author 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. 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) \ #define MV_ASSERT(x) \
if (!(x)) \ if (!(x)) \
{ \ { \
LOG_ERROR("ASSERT %a(%d): %a", __FILE__, __LINE__, #x); \ LOG_ERROR("ASSERT %a(%d): %a", __FILE__, __LINE__, #x); \
MV_PANIC(); \ MV_PANIC(); \
} (VOID*)NULL } (VOID*)NULL
#else
#define MV_ASSERT(x)
#endif #endif
#if !defined(MDEPKG_NDEBUG) #if defined(MDEPKG_NDEBUG)
#define MV_VERIFY(x) MV_ASSERT(x)
#else
#define MV_VERIFY(x) (x) #define MV_VERIFY(x) (x)
#else
#define MV_VERIFY(x) MV_ASSERT(x)
#endif #endif
#define MV_MAX(x, y) MAX((x), (y)) #define MV_MAX(x, y) MAX((x), (y))

View File

@@ -10,7 +10,7 @@
.code .code
; ;
; @brief Read the value from LDTR. ; @brief Reads the value of LDTR.
; ;
; @return The value of LDTR. ; @return The value of LDTR.
; ;
@@ -20,7 +20,7 @@ AsmReadLdtr proc
AsmReadLdtr endp AsmReadLdtr endp
; ;
; @brief Read the value from TR. ; @brief Reads the value of TR.
; ;
; @return The value of TR. ; @return The value of TR.
; ;
@@ -30,7 +30,7 @@ AsmReadTr proc
AsmReadTr endp AsmReadTr endp
; ;
; @brief Read the value from ES. ; @brief Reads the value of ES.
; ;
; @return The value of ES. ; @return The value of ES.
; ;
@@ -40,7 +40,7 @@ AsmReadEs proc
AsmReadEs endp AsmReadEs endp
; ;
; @brief Read the value from CS. ; @brief Reads the value of CS.
; ;
; @return The value of CS. ; @return The value of CS.
; ;
@@ -50,7 +50,7 @@ AsmReadCs proc
AsmReadCs endp AsmReadCs endp
; ;
; @brief Read the value from SS. ; @brief Reads the value of SS.
; ;
; @return The value of SS. ; @return The value of SS.
; ;
@@ -60,7 +60,7 @@ AsmReadSs proc
AsmReadSs endp AsmReadSs endp
; ;
; @brief Read the value from DS. ; @brief Reads the value of DS.
; ;
; @return The value of DS. ; @return The value of DS.
; ;
@@ -70,7 +70,7 @@ AsmReadDs proc
AsmReadDs endp AsmReadDs endp
; ;
; @brief Read the value from FS. ; @brief Reads the value of FS.
; ;
; @return The value of FS. ; @return The value of FS.
; ;
@@ -80,7 +80,7 @@ AsmReadFs proc
AsmReadFs endp AsmReadFs endp
; ;
; @brief Read the value from GS. ; @brief Reads the value of GS.
; ;
; @return The value of GS. ; @return The value of GS.
; ;
@@ -90,7 +90,7 @@ AsmReadGs proc
AsmReadGs endp AsmReadGs endp
; ;
; @brief Write the value to TR. ; @brief Writes the value to TR.
; ;
; @param[in] RCX - The new TR value to write. ; @param[in] RCX - The new TR value to write.
; ;

View File

@@ -17,7 +17,6 @@
*/ */
UINT16 UINT16
AsmReadLdtr ( AsmReadLdtr (
VOID
); );
/*! /*!
@@ -27,7 +26,6 @@ AsmReadLdtr (
*/ */
UINT16 UINT16
AsmReadTr ( AsmReadTr (
VOID
); );
/*! /*!
@@ -37,7 +35,6 @@ AsmReadTr (
*/ */
UINT16 UINT16
AsmReadEs ( AsmReadEs (
VOID
); );
/*! /*!
@@ -47,7 +44,6 @@ AsmReadEs (
*/ */
UINT16 UINT16
AsmReadCs ( AsmReadCs (
VOID
); );
/*! /*!
@@ -57,7 +53,6 @@ AsmReadCs (
*/ */
UINT16 UINT16
AsmReadSs ( AsmReadSs (
VOID
); );
/*! /*!
@@ -67,7 +62,6 @@ AsmReadSs (
*/ */
UINT16 UINT16
AsmReadDs ( AsmReadDs (
VOID
); );
/*! /*!
@@ -77,7 +71,6 @@ AsmReadDs (
*/ */
UINT16 UINT16
AsmReadFs ( AsmReadFs (
VOID
); );
/*! /*!
@@ -87,7 +80,6 @@ AsmReadFs (
*/ */
UINT16 UINT16
AsmReadGs ( AsmReadGs (
VOID
); );
/*! /*!

View File

@@ -457,7 +457,7 @@ LogFlushThread (
LOGGER_CONTEXT* logger; LOGGER_CONTEXT* logger;
LARGE_INTEGER interval; LARGE_INTEGER interval;
PAGED_CODE() PAGED_CODE();
logger = (LOGGER_CONTEXT*)StartContext; logger = (LOGGER_CONTEXT*)StartContext;
interval.QuadPart = -(10000ll * logger->FlushIntervalInMs); interval.QuadPart = -(10000ll * logger->FlushIntervalInMs);
@@ -562,13 +562,6 @@ CleanupPairedLogBuffer (
ExFreePoolWithTag(PairedLogBuffer->InactiveLogBuffer->LogEntries, LOGGER_POOL_TAG); 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 LOGGER_INIT
_Use_decl_annotations_ _Use_decl_annotations_
NTSTATUS NTSTATUS
@@ -581,7 +574,7 @@ InitializeLogger (
HANDLE fileHandle; HANDLE fileHandle;
HANDLE threadHandle; HANDLE threadHandle;
PAGED_CODE() PAGED_CODE();
MV_ASSERT(g_Logger == NULL); MV_ASSERT(g_Logger == NULL);
@@ -615,7 +608,7 @@ InitializeLogger (
&filePath, &filePath,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL, NULL,
NULL) NULL);
status = ZwCreateFile(&fileHandle, status = ZwCreateFile(&fileHandle,
FILE_APPEND_DATA | SYNCHRONIZE, FILE_APPEND_DATA | SYNCHRONIZE,
&objectAttributes, &objectAttributes,
@@ -709,7 +702,6 @@ InitializeLogger (
// //
g_Logger = logger; g_Logger = logger;
Exit: Exit:
if (NT_ERROR(status)) if (NT_ERROR(status))
{ {
@@ -729,9 +721,6 @@ Exit:
return status; return status;
} }
/*!
@brief Clean up the logger.
*/
LOGGER_PAGED LOGGER_PAGED
_Use_decl_annotations_ _Use_decl_annotations_
VOID VOID
@@ -742,7 +731,7 @@ CleanupLogger (
LOGGER_CONTEXT* logger; LOGGER_CONTEXT* logger;
SIZE_T maxOverflowedLogSize; SIZE_T maxOverflowedLogSize;
PAGED_CODE() PAGED_CODE();
MV_ASSERT(g_Logger != NULL); MV_ASSERT(g_Logger != NULL);

View File

@@ -69,6 +69,13 @@ typedef struct _LOGGER_CONFIGURATION
PCWSTR FilePath; PCWSTR FilePath;
} LOGGER_CONFIGURATION; } 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) _IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_ _Must_inspect_result_
NTSTATUS NTSTATUS
@@ -76,6 +83,9 @@ InitializeLogger (
_In_ CONST LOGGER_CONFIGURATION* Configuration _In_ CONST LOGGER_CONFIGURATION* Configuration
); );
/*!
@brief Clean up the logger.
*/
_IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_max_(PASSIVE_LEVEL)
VOID VOID
CleanupLogger ( CleanupLogger (

View File

@@ -97,7 +97,7 @@ ConvertNtToMvStatus (
@param[in] DriverObject - The driver's driver object. @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. @return STATUS_SUCCESS on success; otherwise, an appropriate error code.
*/ */
@@ -148,7 +148,7 @@ DriverUnload (
{ {
UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(DriverObject);
PAGED_CODE() PAGED_CODE();
// //
// Start cross-platform clean up. // Start cross-platform clean up.
@@ -165,7 +165,7 @@ InitializePlatform (
NTSTATUS status; NTSTATUS status;
LOGGER_CONFIGURATION loggerConfig; LOGGER_CONFIGURATION loggerConfig;
PAGED_CODE() PAGED_CODE();
// //
// Initialize in-house logger. Enable all flags. // Initialize in-house logger. Enable all flags.
@@ -192,7 +192,7 @@ VOID
CleanupPlatform ( CleanupPlatform (
) )
{ {
PAGED_CODE() PAGED_CODE();
CleanupLogger(); CleanupLogger();
} }
@@ -206,7 +206,7 @@ Sleep (
{ {
LARGE_INTEGER interval; LARGE_INTEGER interval;
PAGED_CODE() PAGED_CODE();
interval.QuadPart = -(LONGLONG)(10000 * Milliseconds); interval.QuadPart = -(LONGLONG)(10000 * Milliseconds);
(VOID)KeDelayExecutionThread(KernelMode, FALSE, &interval); (VOID)KeDelayExecutionThread(KernelMode, FALSE, &interval);
@@ -296,7 +296,7 @@ ReserveVirtualAddress (
UINT64 PageCount UINT64 PageCount
) )
{ {
PAGED_CODE() PAGED_CODE();
return MmAllocateMappingAddress(PageCount * PAGE_SIZE, MV_POOL_TAG); return MmAllocateMappingAddress(PageCount * PAGE_SIZE, MV_POOL_TAG);
} }
@@ -309,7 +309,7 @@ FreeReservedVirtualAddress (
UINT64 PageCount UINT64 PageCount
) )
{ {
PAGED_CODE() PAGED_CODE();
UNREFERENCED_PARAMETER(PageCount); UNREFERENCED_PARAMETER(PageCount);
@@ -326,7 +326,7 @@ RunOnAllProcessors (
{ {
UINT32 numberOfProcessors; UINT32 numberOfProcessors;
PAGED_CODE() PAGED_CODE();
numberOfProcessors = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS); numberOfProcessors = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
for (UINT32 index = 0; index < numberOfProcessors; ++index) for (UINT32 index = 0; index < numberOfProcessors; ++index)

View File

@@ -1,7 +1,7 @@
/*! /*!
@file Public.h @file Public.h
@brief Interfaces to communicate with our hypervisor. @brief Interfaces to communicate with the hypervisor.
@author Satoshi Tanda @author Satoshi Tanda

View File

@@ -1,8 +1,7 @@
/*! /*!
@file Utils.c @file Utils.c
@brief Utility functions that could be used by both on root and non-root @brief Utility functions that could be used by both the host and non-host.
operations.
@author Satoshi Tanda @author Satoshi Tanda
@@ -75,10 +74,10 @@ Exit:
/*! /*!
@brief Returns the segment descriptor corresponds to the SegmentSelector. @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. table.
@param[in] SegmentSelector - A segment selector value. @param[in] SegmentSelector - The segment selector value.
@return The segment descriptor corresponds to the SegmentSelector. @return The segment descriptor corresponds to the SegmentSelector.
*/ */

View File

@@ -1,8 +1,7 @@
/*! /*!
@file Utils.h @file Utils.h
@brief Utility functions that could be used by both on root and non-root @brief Utility functions that could be used by both the host and non-host.
operations.
@author Satoshi Tanda @author Satoshi Tanda
@@ -36,7 +35,7 @@ ComputeAddressFromIndexes (
@brief Returns the access right of the segment specified by the SegmentSelector @brief Returns the access right of the segment specified by the SegmentSelector
for VMX. 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. @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. @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. table.
@param[in] SegmentSelector - The segment selector which points to the @param[in] SegmentSelector - The segment selector which points to the