]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c
NetworkPkg: fix an error lead building crash
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / BootScriptExecutorDxe / X64 / SetIdtEntry.c
CommitLineData
be46cd5f 1/** @file\r
2 Set a IDT entry for debug purpose\r
3\r
4 Set a IDT entry for interrupt vector 3 for debug purpose for x64 platform\r
5\r
73f0127f 6Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
be46cd5f 7\r
8This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
12\r
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17#include "ScriptExecute.h"\r
d0bf5623
JY
18\r
19#define IA32_PG_P BIT0\r
20#define IA32_PG_RW BIT1\r
21#define IA32_PG_PS BIT7\r
22\r
23UINT64 mPhyMask;\r
d0bf5623
JY
24VOID *mOriginalHandler;\r
25UINTN mS3NvsPageTableAddress;\r
26\r
54e27ada
JY
27/**\r
28 Page fault handler.\r
29\r
30**/\r
d0bf5623
JY
31VOID\r
32EFIAPI\r
33PageFaultHandlerHook (\r
34 VOID\r
35 );\r
36\r
54e27ada
JY
37/**\r
38 Hook IDT with our page fault handler so that the on-demand paging works on page fault.\r
39\r
40 @param IdtEntry a pointer to IDT entry\r
41\r
42**/\r
d0bf5623
JY
43VOID\r
44HookPageFaultHandler (\r
68cc1ba3 45 IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry\r
d0bf5623
JY
46 )\r
47{\r
48 UINT32 RegEax;\r
59cc677c 49 UINT8 PhysicalAddressBits;\r
73f0127f 50 UINTN PageFaultHandlerHookAddress;\r
d0bf5623 51\r
59cc677c
SZ
52 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
53 if (RegEax >= 0x80000008) {\r
54 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
55 PhysicalAddressBits = (UINT8) RegEax;\r
56 } else {\r
57 PhysicalAddressBits = 36;\r
d0bf5623 58 }\r
59cc677c
SZ
59 mPhyMask = LShiftU64 (1, PhysicalAddressBits) - 1;\r
60 mPhyMask &= (1ull << 48) - SIZE_4KB;\r
d0bf5623
JY
61\r
62 //\r
63 // Set Page Fault entry to catch >4G access\r
64 //\r
73f0127f 65 PageFaultHandlerHookAddress = (UINTN)PageFaultHandlerHook;\r
68cc1ba3 66 mOriginalHandler = (VOID *)(UINTN)(LShiftU64 (IdtEntry->Bits.OffsetUpper, 32) + IdtEntry->Bits.OffsetLow + (IdtEntry->Bits.OffsetHigh << 16));\r
73f0127f 67 IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;\r
68cc1ba3
SZ
68 IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();\r
69 IdtEntry->Bits.Reserved_0 = 0;\r
70 IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
73f0127f
SZ
71 IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);\r
72 IdtEntry->Bits.OffsetUpper = (UINT32)(PageFaultHandlerHookAddress >> 32);\r
68cc1ba3 73 IdtEntry->Bits.Reserved_1 = 0;\r
d0bf5623
JY
74\r
75 if (mPage1GSupport) {\r
76 mS3NvsPageTableAddress = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE(2);\r
77 }else {\r
78 mS3NvsPageTableAddress = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE(6);\r
79 }\r
80}\r
81\r
be46cd5f 82/**\r
83 Set a IDT entry for interrupt vector 3 for debug purpose.\r
84\r
85 @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT\r
86\r
87**/\r
88VOID\r
89SetIdtEntry (\r
90 IN ACPI_S3_CONTEXT *AcpiS3Context\r
91 )\r
92{\r
68cc1ba3 93 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;\r
be46cd5f 94 IA32_DESCRIPTOR *IdtDescriptor;\r
95 UINTN S3DebugBuffer;\r
57f360f2 96 EFI_STATUS Status;\r
be46cd5f 97\r
98 //\r
99 // Restore IDT for debug\r
100 //\r
101 IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);\r
1e172d6b 102 AsmWriteIdtr (IdtDescriptor);\r
103\r
104 //\r
105 // Setup the default CPU exception handlers\r
106 //\r
57f360f2
JF
107 Status = InitializeCpuExceptionHandlers (NULL);\r
108 ASSERT_EFI_ERROR (Status);\r
1e172d6b 109\r
f4a25e81 110 DEBUG_CODE (\r
111 //\r
112 // Update IDT entry INT3 if the instruction is valid in it\r
113 //\r
114 S3DebugBuffer = (UINTN) (AcpiS3Context->S3DebugBufferAddress);\r
115 if (*(UINTN *)S3DebugBuffer != (UINTN) -1) {\r
68cc1ba3
SZ
116 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));\r
117 IdtEntry->Bits.OffsetLow = (UINT16)S3DebugBuffer;\r
118 IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();\r
119 IdtEntry->Bits.Reserved_0 = 0;\r
120 IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
121 IdtEntry->Bits.OffsetHigh = (UINT16)(S3DebugBuffer >> 16);\r
122 IdtEntry->Bits.OffsetUpper = (UINT32)(S3DebugBuffer >> 32);\r
123 IdtEntry->Bits.Reserved_1 = 0;\r
f4a25e81 124 }\r
125 );\r
be46cd5f 126\r
68cc1ba3 127 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (14 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));\r
d0bf5623 128 HookPageFaultHandler (IdtEntry);\r
d0bf5623
JY
129}\r
130\r
54e27ada
JY
131/**\r
132 Get new page address.\r
133\r
134 @param PageNum new page number needed\r
135\r
136 @return new page address\r
137**/\r
d0bf5623
JY
138UINTN\r
139GetNewPage (\r
140 IN UINTN PageNum\r
141 )\r
142{\r
143 UINTN NewPage;\r
144 NewPage = mS3NvsPageTableAddress;\r
145 ZeroMem ((VOID *)NewPage, EFI_PAGES_TO_SIZE(PageNum));\r
146 mS3NvsPageTableAddress += EFI_PAGES_TO_SIZE(PageNum);\r
147 return NewPage;\r
be46cd5f 148}\r
149\r
54e27ada
JY
150/**\r
151 The page fault handler that on-demand read >4G memory/MMIO.\r
152 \r
153 @retval TRUE The page fault is correctly handled.\r
154 @retval FALSE The page fault is not handled and is passed through to original handler.\r
155\r
156**/\r
d0bf5623
JY
157BOOLEAN\r
158EFIAPI\r
159PageFaultHandler (\r
160 VOID\r
161 )\r
162{\r
163 UINT64 *PageTable;\r
164 UINT64 PFAddress;\r
165 UINTN PTIndex;\r
166\r
167 PFAddress = AsmReadCr2 ();\r
168 DEBUG ((EFI_D_ERROR, "BootScript - PageFaultHandler: Cr2 - %lx\n", PFAddress));\r
169\r
170 if (PFAddress >= mPhyMask + SIZE_4KB) {\r
171 return FALSE;\r
172 }\r
173 PFAddress &= mPhyMask;\r
174\r
175 PageTable = (UINT64*)(UINTN)(AsmReadCr3 () & mPhyMask);\r
176\r
177 PTIndex = BitFieldRead64 (PFAddress, 39, 47);\r
178 // PML4E\r
179 if ((PageTable[PTIndex] & IA32_PG_P) == 0) {\r
180 PageTable[PTIndex] = GetNewPage (1) | IA32_PG_P | IA32_PG_RW;\r
181 }\r
182 PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & mPhyMask);\r
183 PTIndex = BitFieldRead64 (PFAddress, 30, 38);\r
184 // PDPTE\r
185 if (mPage1GSupport) {\r
186 PageTable[PTIndex] = PFAddress | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;\r
187 } else {\r
188 if ((PageTable[PTIndex] & IA32_PG_P) == 0) {\r
189 PageTable[PTIndex] = GetNewPage (1) | IA32_PG_P | IA32_PG_RW;\r
190 }\r
191 PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & mPhyMask);\r
192 PTIndex = BitFieldRead64 (PFAddress, 21, 29);\r
193 // PD\r
194 PageTable[PTIndex] = PFAddress | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;\r
195 }\r
196\r
197 return TRUE;\r
198}\r