diff options
author | Alex Ionescu <aionescu@gmail.com> | 2017-03-20 19:01:36 +0300 |
---|---|---|
committer | Alex Ionescu <aionescu@gmail.com> | 2017-03-20 19:01:36 +0300 |
commit | 9891d1048fc6e08b3d2b5929c6def43f7112698f (patch) | |
tree | 211751bc4f98699b407168775268752dcb6a5499 | |
parent | e538c4b6fd8bb9587cddbc34263b03fb9a241322 (diff) |
Re-enable EPT support, with correct parsing of MTRR registers to respect caching properties.
-rw-r--r-- | shv_x.h | 11 | ||||
-rw-r--r-- | shvvmx.c | 115 |
2 files changed, 120 insertions, 6 deletions
@@ -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; @@ -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); |