]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
a871bef4e28f9c32202a32d5ea1e675cc08a6984
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / PageTbl.c
1 /** @file
2 Page table manipulation functions for IA-32 processors
3
4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "PiSmmCpuDxeSmm.h"
16
17 /**
18 Create PageTable for SMM use.
19
20 @return PageTable Address
21
22 **/
23 UINT32
24 SmmInitPageTable (
25 VOID
26 )
27 {
28 UINTN PageFaultHandlerHookAddress;
29 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
30
31 //
32 // Initialize spin lock
33 //
34 InitializeSpinLock (mPFLock);
35
36 if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
37 //
38 // Set own Page Fault entry instead of the default one, because SMM Profile
39 // feature depends on IRET instruction to do Single Step
40 //
41 PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
42 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base;
43 IdtEntry += EXCEPT_IA32_PAGE_FAULT;
44 IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
45 IdtEntry->Bits.Reserved_0 = 0;
46 IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
47 IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
48 } else {
49 //
50 // Register SMM Page Fault Handler
51 //
52 SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_PAGE_FAULT, SmiPFHandler);
53 }
54
55 //
56 // Additional SMM IDT initialization for SMM stack guard
57 //
58 if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
59 InitializeIDTSmmStackGuard ();
60 }
61 return Gen4GPageTable (0, TRUE);
62 }
63
64 /**
65 Page Fault handler for SMM use.
66
67 **/
68 VOID
69 SmiDefaultPFHandler (
70 VOID
71 )
72 {
73 CpuDeadLoop ();
74 }
75
76 /**
77 ThePage Fault handler wrapper for SMM use.
78
79 @param InterruptType Defines the type of interrupt or exception that
80 occurred on the processor.This parameter is processor architecture specific.
81 @param SystemContext A pointer to the processor context when
82 the interrupt occurred on the processor.
83 **/
84 VOID
85 EFIAPI
86 SmiPFHandler (
87 IN EFI_EXCEPTION_TYPE InterruptType,
88 IN EFI_SYSTEM_CONTEXT SystemContext
89 )
90 {
91 UINTN PFAddress;
92
93 ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
94
95 AcquireSpinLock (mPFLock);
96
97 PFAddress = AsmReadCr2 ();
98
99 if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
100 (PFAddress >= mCpuHotPlugData.SmrrBase) &&
101 (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) {
102 DEBUG ((EFI_D_ERROR, "SMM stack overflow!\n"));
103 CpuDeadLoop ();
104 }
105
106 //
107 // If a page fault occurs in SMM range
108 //
109 if ((PFAddress < mCpuHotPlugData.SmrrBase) ||
110 (PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {
111 if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
112 DEBUG ((EFI_D_ERROR, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress));
113 DEBUG_CODE (
114 DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
115 );
116 CpuDeadLoop ();
117 }
118 }
119
120 if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
121 SmmProfilePFHandler (
122 SystemContext.SystemContextIa32->Eip,
123 SystemContext.SystemContextIa32->ExceptionData
124 );
125 } else {
126 SmiDefaultPFHandler ();
127 }
128
129 ReleaseSpinLock (mPFLock);
130 }