Skip to content

Commit

Permalink
Removed redundant vmexits
Browse files Browse the repository at this point in the history
  • Loading branch information
HoShiMin committed Jun 13, 2020
1 parent 3d72dd1 commit 2f55e1b
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 124 deletions.
12 changes: 11 additions & 1 deletion CommonTypes/VMX.h
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,16 @@ namespace VMX
unsigned long long RTM : 1; // #DB or #BP occured inside an RTM region
unsigned long long Reserved2 : 47;
} DebugExceptions;
struct {
unsigned long long LinearAddress;
} Invlpg;
struct {
unsigned long long InstructionDisplacementField;
} Invept, Invpcid, Invvpid,
Lgdt, Lidt, Lldt, Ltr,
Sgdt, Sidt, Sldt, Str,
Vmclear, Vmptrld, Vmptrst, Vmread, Vmwrite, Vmxon,
Xrstors, Xsaves;
struct {
unsigned long long SelectorOfTss : 16; // To which the guest attempted to switch
unsigned long long Reserved0 : 14;
Expand Down Expand Up @@ -907,7 +917,7 @@ namespace VMX
struct INVVPID_DESCRIPTOR {
unsigned long long Vpid : 16;
unsigned long long Reserved : 48;
unsigned long long LinearAddress : 64;
unsigned long long LinearAddress;
};
static_assert(sizeof(INVVPID_DESCRIPTOR) == 2 * sizeof(unsigned long long), "Size of INVVPID_DESCRIPTOR != 2 * sizeof(unsigned long long)");

Expand Down
148 changes: 28 additions & 120 deletions Kernel-Bridge/API/Hypervisor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,11 @@ namespace VMX
Info->Selector = Selector;
}

inline unsigned long long GetVpid()
{
return static_cast<unsigned long long>(KeGetCurrentProcessorNumber()) + 1ull;
}

union CONTROLS_MASK
{
unsigned long long Value;
Expand Down Expand Up @@ -1904,7 +1909,6 @@ namespace VMX
__vmx_vmwrite(VMX::VMCS_FIELD_PIN_BASED_VM_EXECUTION_CONTROLS, PinControls.Value);

PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS PrimaryControls = {};
PrimaryControls.Bitmap.RdtscExiting = TRUE;
PrimaryControls.Bitmap.UseMsrBitmaps = TRUE;
PrimaryControls.Bitmap.ActivateSecondaryControls = TRUE;
PrimaryControls = ApplyMask(PrimaryControls, GetPrimaryControlsMask(VmxBasicInfo));
Expand All @@ -1926,7 +1930,6 @@ namespace VMX
SecondaryControls.Bitmap.EnableEpt = TRUE;
SecondaryControls.Bitmap.EnableRdtscp = TRUE;
SecondaryControls.Bitmap.EnableVpid = TRUE;
SecondaryControls.Bitmap.WbinvdExiting = TRUE;
SecondaryControls.Bitmap.EnableInvpcid = TRUE;
SecondaryControls.Bitmap.EnableVmFunctions = TRUE;
SecondaryControls.Bitmap.EptViolation = FALSE;
Expand Down Expand Up @@ -2176,34 +2179,6 @@ namespace VMX
return VMM_STATUS::VMM_CONTINUE;
}

_IRQL_requires_same_
_IRQL_requires_min_(DISPATCH_LEVEL)
static VMM_STATUS InvdHandler(__inout PRIVATE_VM_DATA* Private, __inout GUEST_CONTEXT* Context, unsigned long long Rip, __inout_opt bool& RepeatInstruction)
{
UNREFERENCED_PARAMETER(Private);
UNREFERENCED_PARAMETER(Context);
UNREFERENCED_PARAMETER(Rip);
UNREFERENCED_PARAMETER(RepeatInstruction);

// Invalidate caches:
__invd();
return VMM_STATUS::VMM_CONTINUE;
}

_IRQL_requires_same_
_IRQL_requires_min_(DISPATCH_LEVEL)
static VMM_STATUS WbinvdHandler(__inout PRIVATE_VM_DATA* Private, __inout GUEST_CONTEXT* Context, unsigned long long Rip, __inout_opt bool& RepeatInstruction)
{
UNREFERENCED_PARAMETER(Private);
UNREFERENCED_PARAMETER(Context);
UNREFERENCED_PARAMETER(Rip);
UNREFERENCED_PARAMETER(RepeatInstruction);

// Write-back & invalidate caches:
__wbinvd();
return VMM_STATUS::VMM_CONTINUE;
}

_IRQL_requires_same_
_IRQL_requires_min_(DISPATCH_LEVEL)
static VMM_STATUS XsetbvHandler(__inout PRIVATE_VM_DATA* Private, __inout GUEST_CONTEXT* Context, unsigned long long Rip, __inout bool& RepeatInstruction)
Expand Down Expand Up @@ -2237,11 +2212,17 @@ namespace VMX

if (Info.EptViolations.AccessedRead)
{
unsigned long long HostCr3 = __readcr3();
unsigned long long GuestCr3 = vmread(VMX::VMCS_FIELD_GUEST_CR3);
__writecr3(GuestCr3);
unsigned long long RipPa = Supplementation::FastPhys::GetPhysAddressFast4KbUnsafe(Rip);
__writecr3(HostCr3);
unsigned long long RipPa;
if (AddressRange::IsUserAddress(reinterpret_cast<void*>(Rip)))
{
__writecr3(vmread(VMX::VMCS_FIELD_GUEST_CR3));
RipPa = Supplementation::FastPhys::GetPhysAddressFast4KbUnsafe(Rip);
__writecr3(g_Shared.KernelCr3);
}
else
{
RipPa = Supplementation::FastPhys::GetPhysAddressFast4KbUnsafe(Rip);
}

if (ALIGN_DOWN_BY(AccessedPa, PAGE_SIZE) == ALIGN_DOWN_BY(RipPa, PAGE_SIZE))
{
Expand All @@ -2263,11 +2244,17 @@ namespace VMX
{
unsigned long long InstructionLength = vmread(VMX::VMCS_FIELD_VMEXIT_INSTRUCTION_LENGTH);

unsigned long long HostCr3 = __readcr3();
unsigned long long GuestCr3 = vmread(VMX::VMCS_FIELD_GUEST_CR3);
__writecr3(GuestCr3);
unsigned long long RipPa = Supplementation::FastPhys::GetPhysAddressFast4KbUnsafe(Rip);
__writecr3(HostCr3);
unsigned long long RipPa;
if (AddressRange::IsUserAddress(reinterpret_cast<void*>(Rip)))
{
__writecr3(vmread(VMX::VMCS_FIELD_GUEST_CR3));
RipPa = Supplementation::FastPhys::GetPhysAddressFast4KbUnsafe(Rip);
__writecr3(g_Shared.KernelCr3);
}
else
{
RipPa = Supplementation::FastPhys::GetPhysAddressFast4KbUnsafe(Rip);
}

if (ALIGN_DOWN_BY(AccessedPa, PAGE_SIZE) == ALIGN_DOWN_BY(RipPa, PAGE_SIZE))
{
Expand Down Expand Up @@ -2419,36 +2406,6 @@ namespace VMX
return VMM_STATUS::VMM_CONTINUE;
}

_IRQL_requires_same_
_IRQL_requires_min_(DISPATCH_LEVEL)
static VMM_STATUS RdtscHandler(__inout PRIVATE_VM_DATA* Private, __inout GUEST_CONTEXT* Context, unsigned long long Rip, __inout_opt bool& RepeatInstruction)
{
UNREFERENCED_PARAMETER(Private);
UNREFERENCED_PARAMETER(Rip);
UNREFERENCED_PARAMETER(RepeatInstruction);

unsigned long long TSC = __rdtsc();
Context->Rax = TSC & 0xFFFFFFFF;
Context->Rdx = TSC >> 32;
return VMM_STATUS::VMM_CONTINUE;
}

_IRQL_requires_same_
_IRQL_requires_min_(DISPATCH_LEVEL)
static VMM_STATUS RdtscpHandler(__inout PRIVATE_VM_DATA* Private, __inout GUEST_CONTEXT* Context, unsigned long long Rip, __inout_opt bool& RepeatInstruction)
{
UNREFERENCED_PARAMETER(Private);
UNREFERENCED_PARAMETER(Rip);
UNREFERENCED_PARAMETER(RepeatInstruction);

unsigned int Rcx = 0;
unsigned long long TSC = __rdtscp(&Rcx);
Context->Rax = TSC & 0xFFFFFFFF;
Context->Rcx = Rcx;
Context->Rdx = TSC >> 32;
return VMM_STATUS::VMM_CONTINUE;
}

_IRQL_requires_same_
_IRQL_requires_min_(DISPATCH_LEVEL)
static VMM_STATUS RdmsrHandler(__inout PRIVATE_VM_DATA* Private, __inout GUEST_CONTEXT* Context, unsigned long long Rip, __inout_opt bool& RepeatInstruction)
Expand Down Expand Up @@ -2493,50 +2450,6 @@ namespace VMX
return VMM_STATUS::VMM_CONTINUE;
}

_IRQL_requires_same_
_IRQL_requires_min_(DISPATCH_LEVEL)
static VMM_STATUS InvpcidHandler(__inout PRIVATE_VM_DATA* Private, __inout GUEST_CONTEXT* Context, unsigned long long Rip, __inout_opt bool& RepeatInstruction)
{
UNREFERENCED_PARAMETER(Private);
UNREFERENCED_PARAMETER(Rip);
UNREFERENCED_PARAMETER(RepeatInstruction);

VMX::INSTRUCTION_INFORMATION_FIELD Instr = { static_cast<unsigned int>(vmread(VMX::VMCS_FIELD_VMEXIT_INSTRUCTION_INFORMATION)) };
unsigned long long Disp = vmread(VMX::VMCS_FIELD_EXIT_QUALIFICATION);
unsigned long long Rsp = vmread(VMX::VMCS_FIELD_GUEST_RSP);

// invpcid reg2, oword ptr [base + index * scale + disp]
// base - GP register
// index - GP register (can't be ESP/RSP)
// scale - value of 2/4/8
// disp - 8/16/32-bit value

unsigned long long InvType = 0;
unsigned long long DescAddr = 0;

unsigned long long* TypeReg = GetRegPtr(Instr.Invpcid.Reg2, Context);
InvType = TypeReg ? *TypeReg : Rsp;

if (Instr.Invpcid.BaseRegInvalid == 0)
{
unsigned long long* BaseReg = GetRegPtr(Instr.Invpcid.BaseReg, Context);
DescAddr += BaseReg ? *BaseReg : Rsp;
}

if (Instr.Invpcid.IndexRegInvalid == 0)
{
unsigned long long* IndexReg = GetRegPtr(Instr.Invpcid.IndexReg, Context);
unsigned long long Scale = 1ull < Instr.Invpcid.Scaling;
DescAddr += *IndexReg * Scale;
}

DescAddr += Disp;

_invpcid(static_cast<unsigned int>(InvType), reinterpret_cast<void*>(DescAddr));

return VMM_STATUS::VMM_CONTINUE;
}

_IRQL_requires_same_
_IRQL_requires_min_(DISPATCH_LEVEL)
static VMM_STATUS VmxRelatedHandler(__inout PRIVATE_VM_DATA* Private, __inout GUEST_CONTEXT* Context, unsigned long long Rip, __inout_opt bool& RepeatInstruction)
Expand Down Expand Up @@ -2570,19 +2483,14 @@ namespace VMX
}

InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_CPUID , CpuidHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_INVD , InvdHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_WBINVD , WbinvdHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_XSETBV , XsetbvHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_EPT_VIOLATION, EptViolationHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_EPT_MISCONFIGURATION, EptMisconfigurationHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_MONITOR_TRAP_FLAG, MonitorTrapFlagHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_EXCEPTION_OR_NMI, ExceptionOrNmiHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_VMCALL , VmcallHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_RDTSC , RdtscHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_RDTSCP , RdtscpHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_RDMSR , RdmsrHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_WRMSR , WrmsrHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_INVPCID , InvpcidHandler);

InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_VMCLEAR , VmxRelatedHandler);
InsertHandler(VMX::VMX_EXIT_REASON::EXIT_REASON_VMLAUNCH, VmxRelatedHandler);
Expand Down Expand Up @@ -2684,7 +2592,7 @@ namespace VMX
}
}

DbgPrint("%p..%p: %s\r\n", reinterpret_cast<void*>(RangeBeginning), reinterpret_cast<void*>(512ull * 1024ull * 1048576ull - 1ull), MemTypeToStr(CurrentRangeType));
DbgPrint("Physical range [%p..%p]: %s\r\n", reinterpret_cast<void*>(RangeBeginning), reinterpret_cast<void*>(512ull * 1024ull * 1048576ull - 1ull), MemTypeToStr(CurrentRangeType));

DbgPrint("EptVpidCap : 0x%I64X\r\n", MtrrInfo->EptVpidCap.Value);
DbgPrint("MaxPhysAddrBits : 0x%I64X\r\n", MtrrInfo->MaxPhysAddrBits);
Expand Down
3 changes: 0 additions & 3 deletions Kernel-Bridge/API/VMM.asm
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ __invvpid PROC PUBLIC
__invvpid ENDP

VmxVmmRun PROC PUBLIC
cli
PUSHAQ
mov rcx, [rsp + GPR_CONTEXT_SIZE + 16]
mov rdx, rsp
Expand All @@ -218,7 +217,6 @@ VmxVmmRun PROC PUBLIC
jz VmmExit

POPAQ
sti
vmresume

VmmExit:
Expand All @@ -232,7 +230,6 @@ VmmExit:

mov rsp, rcx
mov ecx, CPUID_VMM_SHUTDOWN ; Signature that says about the VM shutdown
sti
jmp rbx
VmxVmmRun ENDP

Expand Down

0 comments on commit 2f55e1b

Please sign in to comment.