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:
authorAlex Ionescu <aionescu@gmail.com>2017-03-20 19:01:36 +0300
committerAlex Ionescu <aionescu@gmail.com>2017-03-20 19:01:36 +0300
commit9891d1048fc6e08b3d2b5929c6def43f7112698f (patch)
tree211751bc4f98699b407168775268752dcb6a5499
parente538c4b6fd8bb9587cddbc34263b03fb9a241322 (diff)
Re-enable EPT support, with correct parsing of MTRR registers to respect caching properties.
-rw-r--r--shv_x.h11
-rw-r--r--shvvmx.c115
2 files changed, 120 insertions, 6 deletions
diff --git a/shv_x.h b/shv_x.h
index 624b978..aaafe56 100644
--- a/shv_x.h
+++ b/shv_x.h
@@ -30,6 +30,8 @@ Environment:
#define SHV_STATUS_NO_RESOURCES -2
#define SHV_STATUS_NOT_PRESENT -3
+#define _1GB (1 * 1024 * 1024 * 1024)
+
struct _SHV_CALLBACK_CONTEXT;
typedef
@@ -53,6 +55,14 @@ typedef struct _SHV_SPECIAL_REGISTERS
KDESCRIPTOR Gdtr;
} SHV_SPECIAL_REGISTERS, *PSHV_SPECIAL_REGISTERS;
+typedef struct _SHV_MTRR_RANGE
+{
+ UINT32 Enabled;
+ UINT32 Type;
+ UINT64 PhysicalAddressMin;
+ UINT64 PhysicalAddressMax;
+} SHV_MTRR_RANGE, *PSHV_MTRR_RANGE;
+
typedef struct _SHV_VP_DATA
{
union
@@ -64,6 +74,7 @@ typedef struct _SHV_VP_DATA
CONTEXT ContextFrame;
UINT64 SystemDirectoryTableBase;
LARGE_INTEGER MsrData[17];
+ SHV_MTRR_RANGE MtrrData[16];
UINT64 VmxOnPhysicalAddress;
UINT64 VmcsPhysicalAddress;
UINT64 MsrBitmapPhysicalAddress;
diff --git a/shvvmx.c b/shvvmx.c
index 4e7a558..051ac2d 100644
--- a/shvvmx.c
+++ b/shvvmx.c
@@ -23,11 +23,102 @@ Environment:
#include "shv.h"
VOID
+ShvVmxMtrrInitialize (
+ _In_ PSHV_VP_DATA VpData
+ )
+{
+ UINT32 i;
+ MTRR_CAPABILITIES mtrrCapabilities;
+ MTRR_VARIABLE_BASE mtrrBase;
+ MTRR_VARIABLE_MASK mtrrMask;
+ unsigned long bit;
+
+ //
+ // Read the capabilities mask
+ //
+ mtrrCapabilities.AsUlonglong = __readmsr(MTRR_MSR_CAPABILITIES);
+
+ //
+ // Iterate over each variable MTRR
+ //
+ for (i = 0; i < mtrrCapabilities.VarCnt; i++)
+ {
+ //
+ // Capture the value
+ //
+ mtrrBase.AsUlonglong = __readmsr(MTRR_MSR_VARIABLE_BASE + i * 2);
+ mtrrMask.AsUlonglong = __readmsr(MTRR_MSR_VARIABLE_MASK + i * 2);
+
+ //
+ // Check if the MTRR is enabled
+ //
+ VpData->MtrrData[i].Type = (UINT32)mtrrBase.Type;
+ VpData->MtrrData[i].Enabled = (UINT32)mtrrMask.Enabled;
+ if (VpData->MtrrData[i].Enabled != FALSE)
+ {
+ //
+ // Set the base
+ //
+ VpData->MtrrData[i].PhysicalAddressMin = mtrrBase.PhysBase *
+ MTRR_PAGE_SIZE;
+
+ //
+ // Compute the length
+ //
+ _BitScanForward64(&bit, mtrrMask.PhysMask * MTRR_PAGE_SIZE);
+ VpData->MtrrData[i].PhysicalAddressMax = VpData->MtrrData[i].
+ PhysicalAddressMin +
+ (1ULL << bit) - 1;
+ }
+ }
+}
+
+UINT32
+ShvVmxMtrrAdjustEffectiveMemoryType (
+ _In_ PSHV_VP_DATA VpData,
+ _In_ UINT64 SuperPageAddress,
+ _In_ UINT32 CandidateMemoryType
+ )
+{
+ UINT32 i;
+
+ //
+ // Loop each MTRR range
+ //
+ for (i = 0; i < sizeof(VpData->MtrrData) / sizeof(VpData->MtrrData[0]); i++)
+ {
+ //
+ // Check if it's active
+ //
+ if (VpData->MtrrData[i].Enabled != FALSE)
+ {
+ //
+ // Check if this super page falls within the boundary. If a single
+ // physical page (4KB) touches it, we need to override the entire gig.
+ //
+ if (((SuperPageAddress + _1GB) >= VpData->MtrrData[i].PhysicalAddressMin) &&
+ (SuperPageAddress <= VpData->MtrrData[i].PhysicalAddressMax))
+ {
+ //
+ // Override candidate type with MTRR type
+ //
+ CandidateMemoryType = VpData->MtrrData[i].Type;
+ }
+ }
+ }
+
+ //
+ // Return the correct type needed
+ //
+ return CandidateMemoryType;
+}
+
+VOID
ShvVmxEptInitialize (
_In_ PSHV_VP_DATA VpData
)
{
- UINT64 i;
+ UINT32 i;
VMX_HUGE_PDPTE tempEpdpte;
//
@@ -43,14 +134,22 @@ ShvVmxEptInitialize (
//
tempEpdpte.AsUlonglong = 0;
tempEpdpte.Read = tempEpdpte.Write = tempEpdpte.Execute = 1;
- tempEpdpte.Type = MTRR_TYPE_WB;
tempEpdpte.Large = 1;
//
// Construct EPT identity map for every 1GB of RAM
//
__stosq((UINT64*)VpData->Epdpt, tempEpdpte.AsUlonglong, PDPTE_ENTRY_COUNT);
- for (i = 0; i < PDPTE_ENTRY_COUNT; i++) VpData->Epdpt[i].PageFrameNumber = i;
+ for (i = 0; i < PDPTE_ENTRY_COUNT; i++)
+ {
+ //
+ // Set the page frame number (1GB-sized) and adjust the memory type
+ //
+ VpData->Epdpt[i].PageFrameNumber = i;
+ VpData->Epdpt[i].Type = ShvVmxMtrrAdjustEffectiveMemoryType(VpData,
+ i * _1GB,
+ MTRR_TYPE_WB);
+ }
}
UINT8
@@ -93,10 +192,8 @@ ShvVmxEnterRootModeOnVp (
{
//
// Enable EPT if these features are supported
- // Temporarily Disable
//
- VpData->EptControls = 0;
- //VpData->EptControls = SECONDARY_EXEC_ENABLE_EPT | SECONDARY_EXEC_ENABLE_VPID;
+ VpData->EptControls = SECONDARY_EXEC_ENABLE_EPT | SECONDARY_EXEC_ENABLE_VPID;
}
//
@@ -460,6 +557,12 @@ ShvVmxLaunchOnVp (
}
//
+ // Initialize all the MTRR-related MSRs by reading their value and build
+ // range structures to describe their settings
+ //
+ ShvVmxMtrrInitialize(VpData);
+
+ //
// Initialize the EPT structures
//
ShvVmxEptInitialize(VpData);