Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ionescu007/SimpleVisor.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorionescu007 <aionescu+git@gmail.com>2016-08-29 08:43:50 +0300
committerionescu007 <aionescu+git@gmail.com>2016-08-29 08:43:50 +0300
commit34472d9045d16280c9a4502ac83b383d75b7f740 (patch)
treedcedd9c86adbb914b90f230a659d9fb0911f4420
parent20e2c570c3c5ca080143fb49c2d340a66d494e04 (diff)
Death to global data!
Each routine knew exactly how to get its VP Data except the post-launch-guest-resumer. We now run it on the hypervisor stack (which shouldn't matter -- because it uses no stack variables other than the home space), which means it can essentially "containing record" its VP data based on it.
-rw-r--r--shv.c25
-rw-r--r--shv.h2
-rw-r--r--shvvmx.c2
-rw-r--r--shvvp.c29
4 files changed, 22 insertions, 36 deletions
diff --git a/shv.c b/shv.c
index 12a7038..e10973c 100644
--- a/shv.c
+++ b/shv.c
@@ -22,8 +22,6 @@ Environment:
#include "shv.h"
-PSHV_VP_DATA* ShvGlobalData;
-
VOID
ShvUnload (
_In_ PDRIVER_OBJECT DriverObject
@@ -45,12 +43,6 @@ ShvUnload (
KeGenericCallDpc(ShvVpCallbackDpc, &dpcContext);
//
- // Global data is always allocated and should be freed
- //
- NT_ASSERT(ShvGlobalData);
- ExFreePoolWithTag(ShvGlobalData, 'ShvA');
-
- //
// Indicate unload
//
DbgPrintEx(77, 0, "The SHV has been uninstalled.\n");
@@ -62,24 +54,10 @@ ShvInitialize (
_In_ PUNICODE_STRING RegistryPath
)
{
- LONG cpuCount;
SHV_DPC_CONTEXT dpcContext;
UNREFERENCED_PARAMETER(RegistryPath);
//
- // Allocate the global shared data which all virtual processors will share.
- //
- cpuCount = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
- ShvGlobalData = ExAllocatePoolWithTag(NonPagedPoolNx,
- cpuCount * sizeof(PVOID),
- 'ShvA');
- if (!ShvGlobalData)
- {
- return STATUS_HV_INSUFFICIENT_BUFFER;
- }
- __stosq((PULONG64)ShvGlobalData, 0, cpuCount);
-
- //
// Attempt to enter VMX root mode on all logical processors. This will
// broadcast a DPC interrupt which will execute the callback routine in
// parallel on the LPs. Send the callback routine the physical address of
@@ -99,12 +77,11 @@ ShvInitialize (
//
// Note that each VP is responsible for freeing its VP data on failure.
//
- if (dpcContext.InitCount != cpuCount)
+ if (dpcContext.InitCount != KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS))
{
DbgPrintEx(77, 0, "The SHV failed to initialize (0x%lX) Failed CPU: %d\n",
dpcContext.FailureStatus, dpcContext.FailedCpu);
NT_ASSERT(dpcContext.FailureStatus != STATUS_SUCCESS);
- ExFreePoolWithTag(ShvGlobalData, 'ShvA');
return dpcContext.FailureStatus;
}
diff --git a/shv.h b/shv.h
index 67218d1..7331a0c 100644
--- a/shv.h
+++ b/shv.h
@@ -151,7 +151,7 @@ ShvVpRestoreAfterLaunch (
typedef struct _SHV_DPC_CONTEXT
{
ULONG64 Cr3;
- volatile LONG InitCount;
+ volatile ULONG InitCount;
LONG FailedCpu;
NTSTATUS FailureStatus;
} SHV_DPC_CONTEXT, *PSHV_DPC_CONTEXT;
diff --git a/shvvmx.c b/shvvmx.c
index df24586..0fb4338 100644
--- a/shvvmx.c
+++ b/shvvmx.c
@@ -374,7 +374,7 @@ ShvVmxSetupVmcsForVp (
// corresponds exactly to the location where RtlCaptureContext will return
// to inside of ShvVpInitialize.
//
- __vmx_vmwrite(GUEST_RSP, context->Rsp);
+ __vmx_vmwrite(GUEST_RSP, (ULONG_PTR)VpData->ShvStackLimit + KERNEL_STACK_SIZE - sizeof(CONTEXT));
__vmx_vmwrite(GUEST_RIP, (ULONG_PTR)ShvVpRestoreAfterLaunch);
__vmx_vmwrite(GUEST_RFLAGS, context->EFlags);
diff --git a/shvvp.c b/shvvp.c
index 46fcf17..1f1f744 100644
--- a/shvvp.c
+++ b/shvvp.c
@@ -85,10 +85,20 @@ ShvVpRestoreAfterLaunch (
VOID
)
{
- PSHV_VP_DATA vpData = ShvGlobalData[KeGetCurrentProcessorNumberEx(NULL)];
+ PSHV_VP_DATA vpData;
//
- // Record that VMX is now enabled
+ // Get the per-processor data. This routine temporarily executes on the
+ // same stack as the hypervisor (using no real stack space except the home
+ // registers), so we can retrieve the VP the same way the hypervisor does.
+ //
+ vpData = (PSHV_VP_DATA)((ULONG_PTR)_AddressOfReturnAddress() +
+ sizeof(CONTEXT) -
+ KERNEL_STACK_SIZE);
+
+ //
+ // Record that VMX is now enabled by returning back to ShvVpInitialize with
+ // the Alignment Check (AC) bit set.
//
vpData->ContextFrame.EFlags |= EFLAGS_ALIGN_CHECK;
@@ -213,6 +223,7 @@ ShvVpCallbackDpc (
{
PSHV_DPC_CONTEXT dpcContext = Context;
ULONG cpuIndex;
+ PSHV_VP_DATA vpData;
UNREFERENCED_PARAMETER(Dpc);
//
@@ -234,8 +245,8 @@ ShvVpCallbackDpc (
//
// Allocate the per-VP data for this logical processor
//
- ShvGlobalData[cpuIndex] = ShvVpAllocateData();
- if (ShvGlobalData[cpuIndex] == NULL)
+ vpData = ShvVpAllocateData();
+ if (vpData == NULL)
{
dpcContext->FailureStatus = STATUS_HV_NO_RESOURCES;
goto Quickie;
@@ -246,12 +257,12 @@ ShvVpCallbackDpc (
// all virtual processors, regardless of which process the current LP
// has interrupted, can share the correct kernel address space.
//
- ShvGlobalData[cpuIndex]->SystemDirectoryTableBase = dpcContext->Cr3;
+ vpData->SystemDirectoryTableBase = dpcContext->Cr3;
//
// Initialize the virtual processor
//
- ShvVpInitialize(ShvGlobalData[cpuIndex]);
+ ShvVpInitialize(vpData);
//
// Our hypervisor should now be seen as present on this LP,
@@ -262,8 +273,7 @@ ShvVpCallbackDpc (
//
// Free the per-processor data
//
- MmFreeContiguousMemory(ShvGlobalData[cpuIndex]);
- ShvGlobalData[cpuIndex] = NULL;
+ MmFreeContiguousMemory(vpData);
dpcContext->FailureStatus = STATUS_HV_NOT_PRESENT;
dpcContext->FailedCpu = cpuIndex;
goto Quickie;
@@ -272,7 +282,7 @@ ShvVpCallbackDpc (
//
// This CPU is hyperjacked!
//
- InterlockedIncrement(&dpcContext->InitCount);
+ InterlockedIncrement((PLONG)&dpcContext->InitCount);
}
else
{
@@ -286,7 +296,6 @@ ShvVpCallbackDpc (
// Free the VP data
//
//MmFreeContiguousMemory(ShvGlobalData[cpuIndex]);
- ShvGlobalData[cpuIndex] = NULL;
}
Quickie: