123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /** @file
- Page table manipulation functions for IA-32 processors
- Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "PiSmmCpuDxeSmm.h"
- /**
- Create PageTable for SMM use.
- @return PageTable Address
- **/
- UINT32
- SmmInitPageTable (
- VOID
- )
- {
- UINTN PageFaultHandlerHookAddress;
- IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
- EFI_STATUS Status;
- //
- // Initialize spin lock
- //
- InitializeSpinLock (mPFLock);
- mPhysicalAddressBits = 32;
- if (FeaturePcdGet (PcdCpuSmmProfileEnable) ||
- HEAP_GUARD_NONSTOP_MODE ||
- NULL_DETECTION_NONSTOP_MODE)
- {
- //
- // Set own Page Fault entry instead of the default one, because SMM Profile
- // feature depends on IRET instruction to do Single Step
- //
- PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
- IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)gcSmiIdtr.Base;
- IdtEntry += EXCEPT_IA32_PAGE_FAULT;
- IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
- IdtEntry->Bits.Reserved_0 = 0;
- IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
- IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
- } else {
- //
- // Register SMM Page Fault Handler
- //
- Status = SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_PAGE_FAULT, SmiPFHandler);
- ASSERT_EFI_ERROR (Status);
- }
- //
- // Additional SMM IDT initialization for SMM stack guard
- //
- if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
- InitializeIDTSmmStackGuard ();
- }
- return Gen4GPageTable (TRUE);
- }
- /**
- Page Fault handler for SMM use.
- **/
- VOID
- SmiDefaultPFHandler (
- VOID
- )
- {
- CpuDeadLoop ();
- }
- /**
- ThePage Fault handler wrapper for SMM use.
- @param InterruptType Defines the type of interrupt or exception that
- occurred on the processor.This parameter is processor architecture specific.
- @param SystemContext A pointer to the processor context when
- the interrupt occurred on the processor.
- **/
- VOID
- EFIAPI
- SmiPFHandler (
- IN EFI_EXCEPTION_TYPE InterruptType,
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- UINTN PFAddress;
- UINTN GuardPageAddress;
- UINTN CpuIndex;
- ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
- AcquireSpinLock (mPFLock);
- PFAddress = AsmReadCr2 ();
- //
- // If a page fault occurs in SMRAM range, it might be in a SMM stack guard page,
- // or SMM page protection violation.
- //
- if ((PFAddress >= mCpuHotPlugData.SmrrBase) &&
- (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)))
- {
- DumpCpuContext (InterruptType, SystemContext);
- CpuIndex = GetCpuIndex ();
- GuardPageAddress = (mSmmStackArrayBase + EFI_PAGE_SIZE + CpuIndex * mSmmStackSize);
- if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
- (PFAddress >= GuardPageAddress) &&
- (PFAddress < (GuardPageAddress + EFI_PAGE_SIZE)))
- {
- DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n"));
- } else {
- if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
- DEBUG ((DEBUG_ERROR, "SMM exception at execution (0x%x)\n", PFAddress));
- DEBUG_CODE (
- DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
- );
- } else {
- DEBUG ((DEBUG_ERROR, "SMM exception at access (0x%x)\n", PFAddress));
- DEBUG_CODE (
- DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
- );
- }
- if (HEAP_GUARD_NONSTOP_MODE) {
- GuardPagePFHandler (SystemContext.SystemContextIa32->ExceptionData);
- goto Exit;
- }
- }
- CpuDeadLoop ();
- goto Exit;
- }
- //
- // If a page fault occurs in non-SMRAM range.
- //
- if ((PFAddress < mCpuHotPlugData.SmrrBase) ||
- (PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))
- {
- if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
- DumpCpuContext (InterruptType, SystemContext);
- DEBUG ((DEBUG_ERROR, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress));
- DEBUG_CODE (
- DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
- );
- CpuDeadLoop ();
- goto Exit;
- }
- //
- // If NULL pointer was just accessed
- //
- if (((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) &&
- (PFAddress < EFI_PAGE_SIZE))
- {
- DumpCpuContext (InterruptType, SystemContext);
- DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));
- DEBUG_CODE (
- DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
- );
- if (NULL_DETECTION_NONSTOP_MODE) {
- GuardPagePFHandler (SystemContext.SystemContextIa32->ExceptionData);
- goto Exit;
- }
- CpuDeadLoop ();
- goto Exit;
- }
- if (IsSmmCommBufferForbiddenAddress (PFAddress)) {
- DumpCpuContext (InterruptType, SystemContext);
- DEBUG ((DEBUG_ERROR, "Access SMM communication forbidden address (0x%x)!\n", PFAddress));
- DEBUG_CODE (
- DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
- );
- CpuDeadLoop ();
- goto Exit;
- }
- }
- if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
- SmmProfilePFHandler (
- SystemContext.SystemContextIa32->Eip,
- SystemContext.SystemContextIa32->ExceptionData
- );
- } else {
- DumpCpuContext (InterruptType, SystemContext);
- SmiDefaultPFHandler ();
- }
- Exit:
- ReleaseSpinLock (mPFLock);
- }
- /**
- This function returns with no action for 32 bit.
- @param[out] *Cr2 Pointer to variable to hold CR2 register value.
- **/
- VOID
- SaveCr2 (
- OUT UINTN *Cr2
- )
- {
- return;
- }
- /**
- This function returns with no action for 32 bit.
- @param[in] Cr2 Value to write into CR2 register.
- **/
- VOID
- RestoreCr2 (
- IN UINTN Cr2
- )
- {
- return;
- }
- /**
- Return whether access to non-SMRAM is restricted.
- @retval TRUE Access to non-SMRAM is restricted.
- @retval FALSE Access to non-SMRAM is not restricted.
- **/
- BOOLEAN
- IsRestrictedMemoryAccess (
- VOID
- )
- {
- return TRUE;
- }
|