UefiCpuPkg/PiSmmCpuDxeSmm: Add 2 function to disable/enable CR0.WP

Add two functions to disable/enable CR0.WP. These two unctions
will also be used in later commits. This commit doesn't change any
functionality.

Signed-off-by: Dun Tan <dun.tan@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Dun Tan 2023-04-20 16:06:52 +08:00 committed by Ray Ni
parent f51967280b
commit 7b6e7d0098
2 changed files with 90 additions and 49 deletions

View File

@ -1567,4 +1567,28 @@ SmmWaitForApArrival (
VOID VOID
); );
/**
Disable Write Protect on pages marked as read-only if Cr0.Bits.WP is 1.
@param[out] WpEnabled If Cr0.WP is enabled.
@param[out] CetEnabled If CET is enabled.
**/
VOID
DisableReadOnlyPageWriteProtect (
OUT BOOLEAN *WpEnabled,
OUT BOOLEAN *CetEnabled
);
/**
Enable Write Protect on pages marked as read-only.
@param[out] WpEnabled If Cr0.WP should be enabled.
@param[out] CetEnabled If CET should be enabled.
**/
VOID
EnableReadOnlyPageWriteProtect (
BOOLEAN WpEnabled,
BOOLEAN CetEnabled
);
#endif #endif

View File

@ -40,6 +40,64 @@ PAGE_TABLE_POOL *mPageTablePool = NULL;
// //
BOOLEAN mIsReadOnlyPageTable = FALSE; BOOLEAN mIsReadOnlyPageTable = FALSE;
/**
Disable Write Protect on pages marked as read-only if Cr0.Bits.WP is 1.
@param[out] WpEnabled If Cr0.WP is enabled.
@param[out] CetEnabled If CET is enabled.
**/
VOID
DisableReadOnlyPageWriteProtect (
OUT BOOLEAN *WpEnabled,
OUT BOOLEAN *CetEnabled
)
{
IA32_CR0 Cr0;
*CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
Cr0.UintN = AsmReadCr0 ();
*WpEnabled = (Cr0.Bits.WP != 0) ? TRUE : FALSE;
if (*WpEnabled) {
if (*CetEnabled) {
//
// CET must be disabled if WP is disabled. Disable CET before clearing CR0.WP.
//
DisableCet ();
}
Cr0.Bits.WP = 0;
AsmWriteCr0 (Cr0.UintN);
}
}
/**
Enable Write Protect on pages marked as read-only.
@param[out] WpEnabled If Cr0.WP should be enabled.
@param[out] CetEnabled If CET should be enabled.
**/
VOID
EnableReadOnlyPageWriteProtect (
BOOLEAN WpEnabled,
BOOLEAN CetEnabled
)
{
IA32_CR0 Cr0;
if (WpEnabled) {
Cr0.UintN = AsmReadCr0 ();
Cr0.Bits.WP = 1;
AsmWriteCr0 (Cr0.UintN);
if (CetEnabled) {
//
// re-enable CET.
//
EnableCet ();
}
}
}
/** /**
Initialize a buffer pool for page table use only. Initialize a buffer pool for page table use only.
@ -62,10 +120,9 @@ InitializePageTablePool (
IN UINTN PoolPages IN UINTN PoolPages
) )
{ {
VOID *Buffer; VOID *Buffer;
BOOLEAN CetEnabled; BOOLEAN WpEnabled;
BOOLEAN WpEnabled; BOOLEAN CetEnabled;
IA32_CR0 Cr0;
// //
// Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one page for // Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one page for
@ -102,34 +159,9 @@ InitializePageTablePool (
// If page table memory has been marked as RO, mark the new pool pages as read-only. // If page table memory has been marked as RO, mark the new pool pages as read-only.
// //
if (mIsReadOnlyPageTable) { if (mIsReadOnlyPageTable) {
CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE; DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
Cr0.UintN = AsmReadCr0 ();
WpEnabled = (Cr0.Bits.WP != 0) ? TRUE : FALSE;
if (WpEnabled) {
if (CetEnabled) {
//
// CET must be disabled if WP is disabled. Disable CET before clearing CR0.WP.
//
DisableCet ();
}
Cr0.Bits.WP = 0;
AsmWriteCr0 (Cr0.UintN);
}
SmmSetMemoryAttributes ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (PoolPages), EFI_MEMORY_RO); SmmSetMemoryAttributes ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (PoolPages), EFI_MEMORY_RO);
if (WpEnabled) { EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
Cr0.UintN = AsmReadCr0 ();
Cr0.Bits.WP = 1;
AsmWriteCr0 (Cr0.UintN);
if (CetEnabled) {
//
// re-enable CET.
//
EnableCet ();
}
}
} }
return TRUE; return TRUE;
@ -1786,6 +1818,7 @@ SetPageTableAttributes (
VOID VOID
) )
{ {
BOOLEAN WpEnabled;
BOOLEAN CetEnabled; BOOLEAN CetEnabled;
if (!IfReadOnlyPageTableNeeded ()) { if (!IfReadOnlyPageTableNeeded ()) {
@ -1799,15 +1832,7 @@ SetPageTableAttributes (
// Disable write protection, because we need mark page table to be write protected. // Disable write protection, because we need mark page table to be write protected.
// We need *write* page table memory, to mark itself to be *read only*. // We need *write* page table memory, to mark itself to be *read only*.
// //
CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE; DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
if (CetEnabled) {
//
// CET must be disabled if WP is disabled.
//
DisableCet ();
}
AsmWriteCr0 (AsmReadCr0 () & ~CR0_WP);
// Set memory used by page table as Read Only. // Set memory used by page table as Read Only.
DEBUG ((DEBUG_INFO, "Start...\n")); DEBUG ((DEBUG_INFO, "Start...\n"));
@ -1816,20 +1841,12 @@ SetPageTableAttributes (
// //
// Enable write protection, after page table attribute updated. // Enable write protection, after page table attribute updated.
// //
AsmWriteCr0 (AsmReadCr0 () | CR0_WP); EnableReadOnlyPageWriteProtect (TRUE, CetEnabled);
mIsReadOnlyPageTable = TRUE; mIsReadOnlyPageTable = TRUE;
// //
// Flush TLB after mark all page table pool as read only. // Flush TLB after mark all page table pool as read only.
// //
FlushTlbForAll (); FlushTlbForAll ();
if (CetEnabled) {
//
// re-enable CET.
//
EnableCet ();
}
PERF_FUNCTION_END (); PERF_FUNCTION_END ();
} }