summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg/CpuDxe/CpuPageTable.c
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/CpuDxe/CpuPageTable.c')
-rw-r--r--UefiCpuPkg/CpuDxe/CpuPageTable.c140
1 files changed, 105 insertions, 35 deletions
diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c b/UefiCpuPkg/CpuDxe/CpuPageTable.c
index e2595b4d89..d4e385139a 100644
--- a/UefiCpuPkg/CpuDxe/CpuPageTable.c
+++ b/UefiCpuPkg/CpuDxe/CpuPageTable.c
@@ -23,6 +23,7 @@
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/MpService.h>
+#include <Protocol/SmmBase2.h>
#include "CpuDxe.h"
#include "CpuPageTable.h"
@@ -87,7 +88,46 @@ PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {
{Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},
};
-PAGE_TABLE_POOL *mPageTablePool = NULL;
+PAGE_TABLE_POOL *mPageTablePool = NULL;
+PAGE_TABLE_LIB_PAGING_CONTEXT mPagingContext;
+EFI_SMM_BASE2_PROTOCOL *mSmmBase2 = NULL;
+
+/**
+ Check if current execution environment is in SMM mode or not, via
+ EFI_SMM_BASE2_PROTOCOL.
+
+ This is necessary because of the fact that MdePkg\Library\SmmMemoryAllocationLib
+ supports to free memory outside SMRAM. The library will call gBS->FreePool() or
+ gBS->FreePages() and then SetMemorySpaceAttributes interface in turn to change
+ memory paging attributes during free operation, if some memory related features
+ are enabled (like Heap Guard).
+
+ This means that SetMemorySpaceAttributes() has chance to run in SMM mode. This
+ will cause incorrect result because SMM mode always loads its own page tables,
+ which are usually different from DXE. This function can be used to detect such
+ situation and help to avoid further misoperations.
+
+ @retval TRUE In SMM mode.
+ @retval FALSE Not in SMM mode.
+**/
+BOOLEAN
+IsInSmm (
+ VOID
+ )
+{
+ BOOLEAN InSmm;
+
+ InSmm = FALSE;
+ if (mSmmBase2 == NULL) {
+ gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&mSmmBase2);
+ }
+
+ if (mSmmBase2 != NULL) {
+ mSmmBase2->InSmm (mSmmBase2, &InSmm);
+ }
+
+ return InSmm;
+}
/**
Return current paging context.
@@ -102,42 +142,53 @@ GetCurrentPagingContext (
UINT32 RegEax;
UINT32 RegEdx;
- ZeroMem(PagingContext, sizeof(*PagingContext));
- if (sizeof(UINTN) == sizeof(UINT64)) {
- PagingContext->MachineType = IMAGE_FILE_MACHINE_X64;
- } else {
- PagingContext->MachineType = IMAGE_FILE_MACHINE_I386;
- }
- if ((AsmReadCr0 () & BIT31) != 0) {
- PagingContext->ContextData.X64.PageTableBase = (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);
- } else {
- PagingContext->ContextData.X64.PageTableBase = 0;
- }
+ //
+ // Don't retrieve current paging context from processor if in SMM mode.
+ //
+ if (!IsInSmm ()) {
+ ZeroMem (&mPagingContext, sizeof(mPagingContext));
+ if (sizeof(UINTN) == sizeof(UINT64)) {
+ mPagingContext.MachineType = IMAGE_FILE_MACHINE_X64;
+ } else {
+ mPagingContext.MachineType = IMAGE_FILE_MACHINE_I386;
+ }
+ if ((AsmReadCr0 () & BIT31) != 0) {
+ mPagingContext.ContextData.X64.PageTableBase = (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);
+ } else {
+ mPagingContext.ContextData.X64.PageTableBase = 0;
+ }
- if ((AsmReadCr4 () & BIT4) != 0) {
- PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE;
- }
- if ((AsmReadCr4 () & BIT5) != 0) {
- PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE;
- }
- if ((AsmReadCr0 () & BIT16) != 0) {
- PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;
- }
+ if ((AsmReadCr4 () & BIT4) != 0) {
+ mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE;
+ }
+ if ((AsmReadCr4 () & BIT5) != 0) {
+ mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE;
+ }
+ if ((AsmReadCr0 () & BIT16) != 0) {
+ mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;
+ }
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax > 0x80000000) {
- AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT20) != 0) {
- // XD supported
- if ((AsmReadMsr64 (0xC0000080) & BIT11) != 0) {
- // XD activated
- PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED;
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax > 0x80000000) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT20) != 0) {
+ // XD supported
+ if ((AsmReadMsr64 (0xC0000080) & BIT11) != 0) {
+ // XD activated
+ mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED;
+ }
+ }
+ if ((RegEdx & BIT26) != 0) {
+ mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAGE_1G_SUPPORT;
}
- }
- if ((RegEdx & BIT26) != 0) {
- PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAGE_1G_SUPPORT;
}
}
+
+ //
+ // This can avoid getting SMM paging context if in SMM mode. We cannot assume
+ // SMM mode shares the same paging context as DXE.
+ //
+ CopyMem (PagingContext, &mPagingContext, sizeof (mPagingContext));
}
/**
@@ -507,7 +558,14 @@ IsReadOnlyPageWriteProtected (
VOID
)
{
- return ((AsmReadCr0 () & BIT16) != 0);
+ //
+ // To avoid unforseen consequences, don't touch paging settings in SMM mode
+ // in this driver.
+ //
+ if (!IsInSmm ()) {
+ return ((AsmReadCr0 () & BIT16) != 0);
+ }
+ return FALSE;
}
/**
@@ -518,7 +576,13 @@ DisableReadOnlyPageWriteProtect (
VOID
)
{
- AsmWriteCr0 (AsmReadCr0() & ~BIT16);
+ //
+ // To avoid unforseen consequences, don't touch paging settings in SMM mode
+ // in this driver.
+ //
+ if (!IsInSmm ()) {
+ AsmWriteCr0 (AsmReadCr0 () & ~BIT16);
+ }
}
/**
@@ -529,7 +593,13 @@ EnableReadOnlyPageWriteProtect (
VOID
)
{
- AsmWriteCr0 (AsmReadCr0() | BIT16);
+ //
+ // To avoid unforseen consequences, don't touch paging settings in SMM mode
+ // in this driver.
+ //
+ if (!IsInSmm ()) {
+ AsmWriteCr0 (AsmReadCr0 () | BIT16);
+ }
}
/**