]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
UefiCpuPkg: Add PiSmmCpuDxeSmm module IA32 files
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / PageTbl.c
1 /** @file
2 Page table manipulation functions for IA-32 processors
3
4 Copyright (c) 2009 - 2015, 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 SPIN_LOCK mPFLock;
18
19 /**
20 Create PageTable for SMM use.
21
22 @return PageTable Address
23
24 **/
25 UINT32
26 SmmInitPageTable (
27 VOID
28 )
29 {
30 UINTN PageFaultHandlerHookAddress;
31 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
32
33 //
34 // Initialize spin lock
35 //
36 InitializeSpinLock (&mPFLock);
37
38 if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
39 //
40 // Set own Page Fault entry instead of the default one, because SMM Profile
41 // feature depends on IRET instruction to do Single Step
42 //
43 PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
44 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base;
45 IdtEntry += EXCEPT_IA32_PAGE_FAULT;
46 IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
47 IdtEntry->Bits.Reserved_0 = 0;
48 IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
49 IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
50 } else {
51 //
52 // Register SMM Page Fault Handler
53 //
54 SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_PAGE_FAULT, SmiPFHandler);
55 }
56
57 //
58 // Additional SMM IDT initialization for SMM stack guard
59 //
60 if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
61 InitializeIDTSmmStackGuard ();
62 }
63 return Gen4GPageTable (0);
64 }
65
66 /**
67 Page Fault handler for SMM use.
68
69 **/
70 VOID
71 SmiDefaultPFHandler (
72 VOID
73 )
74 {
75 CpuDeadLoop ();
76 }
77
78 /**
79 ThePage Fault handler wrapper for SMM use.
80
81 @param InterruptType Defines the type of interrupt or exception that
82 occurred on the processor.This parameter is processor architecture specific.
83 @param SystemContext A pointer to the processor context when
84 the interrupt occurred on the processor.
85 **/
86 VOID
87 EFIAPI
88 SmiPFHandler (
89 IN EFI_EXCEPTION_TYPE InterruptType,
90 IN EFI_SYSTEM_CONTEXT SystemContext
91 )
92 {
93 UINTN PFAddress;
94
95 ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
96
97 AcquireSpinLock (&mPFLock);
98
99 PFAddress = AsmReadCr2 ();
100
101 if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
102 (PFAddress >= mCpuHotPlugData.SmrrBase) &&
103 (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) {
104 DEBUG ((EFI_D_ERROR, "SMM stack overflow!\n"));
105 CpuDeadLoop ();
106 }
107
108 //
109 // If a page fault occurs in SMM range
110 //
111 if ((PFAddress < mCpuHotPlugData.SmrrBase) ||
112 (PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {
113 if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
114 DEBUG ((EFI_D_ERROR, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress));
115 DEBUG_CODE (
116 DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
117 );
118 CpuDeadLoop ();
119 }
120 }
121
122 if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
123 SmmProfilePFHandler (
124 SystemContext.SystemContextIa32->Eip,
125 SystemContext.SystemContextIa32->ExceptionData
126 );
127 } else {
128 SmiDefaultPFHandler ();
129 }
130
131 ReleaseSpinLock (&mPFLock);
132 }