diff options
author | ionescu007 <aionescu+git@gmail.com> | 2016-08-28 23:07:25 +0300 |
---|---|---|
committer | ionescu007 <aionescu+git@gmail.com> | 2016-08-28 23:07:25 +0300 |
commit | bbc18f49a677f7e452c14cf614bace6131411c5b (patch) | |
tree | ea0d47f0324ea42893ee052a3bfe9e34eac69271 /shv.c | |
parent | 16b6c8ffe1beb92e250f3f094b89ce97a0f3a94a (diff) |
Fix SimpleVisor to work on VMWare, stop using KeSaveStateForHibernate and misc. cleanups
SimpleVisor was previously using the presence of *ANY* hypervisor as a
sign that it is already loaded. This breaks if the loaded hypervisor
actually supports nesting and/or isn't SimpleVisor. As such, always try
to enable SimpleVisor -- ShvVmxProbe will fail if we can't, and detect
SimpleVisor explicitly using the Hyper-V Detection Interface (used by
all hypervisors these days).
Second, stop using KeSaveStateForHibernate. While it saved us the need
for two more assembly instructions (str/sldt), it appears to have bugs
around handling of DebugControl, on top of the other bugs we already had
to work around. Instead, just use compiler instrincs to grab the
required state, which is faster anyway.
Move Intel VT-x specific structures into vmx.h instead of shv.h
Diffstat (limited to 'shv.c')
-rw-r--r-- | shv.c | 48 |
1 files changed, 35 insertions, 13 deletions
@@ -24,6 +24,39 @@ Environment: PSHV_GLOBAL_DATA ShvGlobalData; +BOOLEAN +ShvIsOurHypervisorPresent ( + VOID + ) +{ + INT cpuInfo[4]; + + // + // Check if ECX[31h] ("Hypervisor Present Bit") is set in CPUID 1h + // + __cpuid(cpuInfo, 1); + if (cpuInfo[2] & HYPERV_HYPERVISOR_PRESENT_BIT) + { + // + // Next, check if this is a compatible Hypervisor, and if it has the + // SimpleVisor signature + // + __cpuid(cpuInfo, HYPERV_CPUID_INTERFACE); + if (cpuInfo[0] == ' vhS') + { + // + // It's us! + // + return TRUE; + } + } + + // + // No Hypervisor, or someone else's + // + return FALSE; +} + VOID ShvUnload ( _In_ PDRIVER_OBJECT DriverObject @@ -71,17 +104,6 @@ ShvInitialize ( UNREFERENCED_PARAMETER(RegistryPath); // - // Detect if a hypervisor is already loaded, using the standard high bit in - // the ECX features register. Hypervisors may choose to hide from this, at - // which point entering VMX root mode will fail (unless a shadows VMCS is - // used). - // - if (HviIsAnyHypervisorPresent()) - { - return STATUS_HV_OBJECT_IN_USE; - } - - // // Next, detect if the hardware appears to support VMX root mode to start. // No attempts are made to enable this if it is lacking or disabled. // @@ -115,10 +137,10 @@ ShvInitialize ( KeGenericCallDpc(ShvVpCallbackDpc, (PVOID)__readcr3()); // - // A hypervisor should now be seen as present on this (and all other) LP, + // Our hypervisor should now be seen as present on this (and all other) LP, // as the SHV correctly handles CPUID ECX features register. // - if (HviIsAnyHypervisorPresent() == FALSE) + if (ShvIsOurHypervisorPresent() == FALSE) { MmFreeContiguousMemory(ShvGlobalData); return STATUS_HV_NOT_PRESENT; |