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-25 17:46:17 +0300
committerAlex Ionescu <aionescu@gmail.com>2017-03-25 17:46:17 +0300
commit64f9ae2254c10bdc984e52a34c74af7b65d662b0 (patch)
treedb65e4a6b6d90281207e7085a38f4fc1eed7118c
parent9891d1048fc6e08b3d2b5929c6def43f7112698f (diff)
Use 2MB pages. It's only a few more lines of code and avoids the perf costs of 1GB UC regions.
Also has the benefit of allowing this to run on VMWare systems now.
-rw-r--r--shv_x.h8
-rw-r--r--shvvmx.c54
-rw-r--r--vmx.h32
3 files changed, 72 insertions, 22 deletions
diff --git a/shv_x.h b/shv_x.h
index aaafe56..95eac78 100644
--- a/shv_x.h
+++ b/shv_x.h
@@ -30,7 +30,8 @@ Environment:
#define SHV_STATUS_NO_RESOURCES -2
#define SHV_STATUS_NOT_PRESENT -3
-#define _1GB (1 * 1024 * 1024 * 1024)
+#define _1GB (1 * 1024 * 1024 * 1024)
+#define _2MB (2 * 1024 * 1024)
struct _SHV_CALLBACK_CONTEXT;
@@ -85,13 +86,14 @@ typedef struct _SHV_VP_DATA
DECLSPEC_ALIGN(PAGE_SIZE) UINT8 MsrBitmap[PAGE_SIZE];
DECLSPEC_ALIGN(PAGE_SIZE) VMX_EPML4E Epml4[PML4E_ENTRY_COUNT];
- DECLSPEC_ALIGN(PAGE_SIZE) VMX_HUGE_PDPTE Epdpt[PDPTE_ENTRY_COUNT];
+ DECLSPEC_ALIGN(PAGE_SIZE) VMX_PDPTE Epdpt[PDPTE_ENTRY_COUNT];
+ DECLSPEC_ALIGN(PAGE_SIZE) VMX_LARGE_PDE Epde[PDPTE_ENTRY_COUNT][PDE_ENTRY_COUNT];
DECLSPEC_ALIGN(PAGE_SIZE) VMX_VMCS VmxOn;
DECLSPEC_ALIGN(PAGE_SIZE) VMX_VMCS Vmcs;
} SHV_VP_DATA, *PSHV_VP_DATA;
-C_ASSERT(sizeof(SHV_VP_DATA) == (KERNEL_STACK_SIZE + 5 * PAGE_SIZE));
+C_ASSERT(sizeof(SHV_VP_DATA) == (KERNEL_STACK_SIZE + (512 + 5) * PAGE_SIZE));
VOID
_sldt (
diff --git a/shvvmx.c b/shvvmx.c
index 051ac2d..4afd298 100644
--- a/shvvmx.c
+++ b/shvvmx.c
@@ -76,7 +76,7 @@ ShvVmxMtrrInitialize (
UINT32
ShvVmxMtrrAdjustEffectiveMemoryType (
_In_ PSHV_VP_DATA VpData,
- _In_ UINT64 SuperPageAddress,
+ _In_ UINT64 LargePageAddress,
_In_ UINT32 CandidateMemoryType
)
{
@@ -93,11 +93,11 @@ ShvVmxMtrrAdjustEffectiveMemoryType (
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.
+ // Check if this large page falls within the boundary. If a single
+ // physical page (4KB) touches it, we need to override the entire 2MB.
//
- if (((SuperPageAddress + _1GB) >= VpData->MtrrData[i].PhysicalAddressMin) &&
- (SuperPageAddress <= VpData->MtrrData[i].PhysicalAddressMax))
+ if (((LargePageAddress + _2MB) >= VpData->MtrrData[i].PhysicalAddressMin) &&
+ (LargePageAddress <= VpData->MtrrData[i].PhysicalAddressMax))
{
//
// Override candidate type with MTRR type
@@ -118,8 +118,9 @@ ShvVmxEptInitialize (
_In_ PSHV_VP_DATA VpData
)
{
- UINT32 i;
- VMX_HUGE_PDPTE tempEpdpte;
+ UINT32 i, j;
+ VMX_PDPTE tempEpdpte;
+ VMX_LARGE_PDE tempEpde;
//
// Fill out the EPML4E which covers the first 512GB of RAM
@@ -130,12 +131,11 @@ ShvVmxEptInitialize (
VpData->Epml4[0].PageFrameNumber = ShvOsGetPhysicalAddress(&VpData->Epdpt) / PAGE_SIZE;
//
- // Fill out a RWX Write-back 1GB EPDPTE
+ // Fill out a RWX PDPTE
//
tempEpdpte.AsUlonglong = 0;
tempEpdpte.Read = tempEpdpte.Write = tempEpdpte.Execute = 1;
- tempEpdpte.Large = 1;
-
+
//
// Construct EPT identity map for every 1GB of RAM
//
@@ -143,12 +143,34 @@ ShvVmxEptInitialize (
for (i = 0; i < PDPTE_ENTRY_COUNT; i++)
{
//
- // Set the page frame number (1GB-sized) and adjust the memory type
+ // Set the page frame number of the PDE table
//
- VpData->Epdpt[i].PageFrameNumber = i;
- VpData->Epdpt[i].Type = ShvVmxMtrrAdjustEffectiveMemoryType(VpData,
- i * _1GB,
- MTRR_TYPE_WB);
+ VpData->Epdpt[i].PageFrameNumber = ShvOsGetPhysicalAddress(&VpData->Epde[i][0]) / PAGE_SIZE;
+ }
+
+ //
+ // Fill out a RWX Large PDE
+ //
+ tempEpde.AsUlonglong = 0;
+ tempEpde.Read = tempEpde.Write = tempEpde.Execute = 1;
+ tempEpde.Large = 1;
+
+ //
+ // Loop every 1GB of RAM (described by the PDPTE)
+ //
+ __stosq((UINT64*)VpData->Epde, tempEpde.AsUlonglong, PDPTE_ENTRY_COUNT * PDE_ENTRY_COUNT);
+ for (i = 0; i < PDPTE_ENTRY_COUNT; i++)
+ {
+ //
+ // Construct EPT identity map for every 2MB of RAM
+ //
+ for (j = 0; j < PDE_ENTRY_COUNT; j++)
+ {
+ VpData->Epde[i][j].PageFrameNumber = (i * 512) + j;
+ VpData->Epde[i][j].Type = ShvVmxMtrrAdjustEffectiveMemoryType(VpData,
+ VpData->Epde[i][j].PageFrameNumber * _2MB,
+ MTRR_TYPE_WB);
+ }
}
}
@@ -188,7 +210,7 @@ ShvVmxEnterRootModeOnVp (
//
if (((VpData->MsrData[12].QuadPart & VMX_EPT_PAGE_WALK_4_BIT) != 0) &&
((VpData->MsrData[12].QuadPart & VMX_EPTP_WB_BIT) != 0) &&
- ((VpData->MsrData[12].QuadPart & VMX_EPT_1GB_PAGE_BIT) != 0))
+ ((VpData->MsrData[12].QuadPart & VMX_EPT_2MB_PAGE_BIT) != 0))
{
//
// Enable EPT if these features are supported
diff --git a/vmx.h b/vmx.h
index 2f08bcb..182c99b 100644
--- a/vmx.h
+++ b/vmx.h
@@ -615,11 +615,37 @@ typedef struct _VMX_PDPTE
};
} VMX_PDPTE, *PVMX_PDPTE;
+typedef struct _VMX_LARGE_PDE
+{
+ union
+ {
+ struct
+ {
+ UINT64 Read : 1;
+ UINT64 Write : 1;
+ UINT64 Execute : 1;
+ UINT64 Type : 3;
+ UINT64 IgnorePat : 1;
+ UINT64 Large : 1;
+ UINT64 Accessed : 1;
+ UINT64 Dirty : 1;
+ UINT64 UserModeExecute : 1;
+ UINT64 SoftwareUse : 1;
+ UINT64 Reserved : 9;
+ UINT64 PageFrameNumber : 27;
+ UINT64 ReservedHigh : 4;
+ UINT64 SoftwareUseHigh : 11;
+ UINT64 SupressVme : 1;
+ };
+ UINT64 AsUlonglong;
+ };
+} VMX_LARGE_PDE, *PVMX_LARGE_PDE;
+
static_assert(sizeof(VMX_EPTP) == sizeof(UINT64), "EPTP Size Mismatch");
static_assert(sizeof(VMX_EPML4E) == sizeof(UINT64), "EPML4E Size Mismatch");
static_assert(sizeof(VMX_PDPTE) == sizeof(UINT64), "EPDPTE Size Mismatch");
-#define PML4E_ENTRY_COUNT 512
-#define PDPTE_ENTRY_COUNT 512
-
+#define PML4E_ENTRY_COUNT 512
+#define PDPTE_ENTRY_COUNT 512
+#define PDE_ENTRY_COUNT 512