]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c
Add missing function comments
[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
1e172d6b 6Copyright (c) 2006 - 2012, 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
18//\r
19// INTERRUPT_GATE_DESCRIPTOR and SetIdtEntry () are used to setup IDT to do debug\r
20//\r
21\r
22#pragma pack(1)\r
23\r
24typedef struct {\r
25 UINT16 Offset15To0;\r
26 UINT16 SegmentSelector;\r
27 UINT16 Attributes;\r
28 UINT16 Offset31To16;\r
29 UINT32 Offset63To32;\r
30 UINT32 Reserved;\r
31} INTERRUPT_GATE_DESCRIPTOR;\r
32\r
33#define INTERRUPT_GATE_ATTRIBUTE 0x8e00\r
34\r
35#pragma pack()\r
d0bf5623
JY
36\r
37#define IA32_PG_P BIT0\r
38#define IA32_PG_RW BIT1\r
39#define IA32_PG_PS BIT7\r
40\r
41UINT64 mPhyMask;\r
42BOOLEAN mPage1GSupport;\r
43VOID *mOriginalHandler;\r
44UINTN mS3NvsPageTableAddress;\r
45\r
54e27ada
JY
46/**\r
47 Page fault handler.\r
48\r
49**/\r
d0bf5623
JY
50VOID\r
51EFIAPI\r
52PageFaultHandlerHook (\r
53 VOID\r
54 );\r
55\r
54e27ada
JY
56/**\r
57 Hook IDT with our page fault handler so that the on-demand paging works on page fault.\r
58\r
59 @param IdtEntry a pointer to IDT entry\r
60\r
61**/\r
d0bf5623
JY
62VOID\r
63HookPageFaultHandler (\r
64 IN INTERRUPT_GATE_DESCRIPTOR *IdtEntry\r
65 )\r
66{\r
67 UINT32 RegEax;\r
68 UINT32 RegEdx;\r
69\r
70 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
71 mPhyMask = LShiftU64 (1, (UINT8)RegEax) - 1;\r
72 mPhyMask &= (1ull << 48) - SIZE_4KB;\r
73\r
74 mPage1GSupport = FALSE;\r
75 if (PcdGetBool(PcdUse1GPageTable)) {\r
76 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
77 if (RegEax >= 0x80000001) {\r
78 AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
79 if ((RegEdx & BIT26) != 0) {\r
80 mPage1GSupport = TRUE;\r
81 }\r
82 }\r
83 }\r
84\r
85 //\r
86 // Set Page Fault entry to catch >4G access\r
87 //\r
88 mOriginalHandler = (VOID *)(UINTN)(LShiftU64 (IdtEntry->Offset63To32, 32) + IdtEntry->Offset15To0 + (IdtEntry->Offset31To16 << 16));\r
89 IdtEntry->Offset15To0 = (UINT16)((UINTN)PageFaultHandlerHook);\r
90 IdtEntry->SegmentSelector = (UINT16)AsmReadCs ();\r
91 IdtEntry->Attributes = (UINT16)INTERRUPT_GATE_ATTRIBUTE;\r
92 IdtEntry->Offset31To16 = (UINT16)((UINTN)PageFaultHandlerHook >> 16);\r
93 IdtEntry->Offset63To32 = (UINT32)((UINTN)PageFaultHandlerHook >> 32);\r
94 IdtEntry->Reserved = 0;\r
95\r
96 if (mPage1GSupport) {\r
97 mS3NvsPageTableAddress = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE(2);\r
98 }else {\r
99 mS3NvsPageTableAddress = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE(6);\r
100 }\r
101}\r
102\r
be46cd5f 103/**\r
104 Set a IDT entry for interrupt vector 3 for debug purpose.\r
105\r
106 @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT\r
107\r
108**/\r
109VOID\r
110SetIdtEntry (\r
111 IN ACPI_S3_CONTEXT *AcpiS3Context\r
112 )\r
113{\r
114 INTERRUPT_GATE_DESCRIPTOR *IdtEntry;\r
115 IA32_DESCRIPTOR *IdtDescriptor;\r
116 UINTN S3DebugBuffer;\r
117\r
118 //\r
119 // Restore IDT for debug\r
120 //\r
121 IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);\r
1e172d6b 122 AsmWriteIdtr (IdtDescriptor);\r
123\r
124 //\r
125 // Setup the default CPU exception handlers\r
126 //\r
127 SetupCpuExceptionHandlers ();\r
128\r
129 //\r
130 // Update IDT entry INT3\r
131 //\r
be46cd5f 132 IdtEntry = (INTERRUPT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (INTERRUPT_GATE_DESCRIPTOR)));\r
133 S3DebugBuffer = (UINTN) (AcpiS3Context->S3DebugBufferAddress);\r
134\r
135 IdtEntry->Offset15To0 = (UINT16)S3DebugBuffer;\r
d0bf5623 136 IdtEntry->SegmentSelector = (UINT16)AsmReadCs ();\r
be46cd5f 137 IdtEntry->Attributes = (UINT16)INTERRUPT_GATE_ATTRIBUTE;\r
138 IdtEntry->Offset31To16 = (UINT16)(S3DebugBuffer >> 16);\r
139 IdtEntry->Offset63To32 = (UINT32)(S3DebugBuffer >> 32);\r
140 IdtEntry->Reserved = 0;\r
141\r
d0bf5623
JY
142 IdtEntry = (INTERRUPT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (14 * sizeof (INTERRUPT_GATE_DESCRIPTOR)));\r
143 HookPageFaultHandler (IdtEntry);\r
144\r
145 AsmWriteIdtr (IdtDescriptor);\r
146}\r
147\r
54e27ada
JY
148/**\r
149 Get new page address.\r
150\r
151 @param PageNum new page number needed\r
152\r
153 @return new page address\r
154**/\r
d0bf5623
JY
155UINTN\r
156GetNewPage (\r
157 IN UINTN PageNum\r
158 )\r
159{\r
160 UINTN NewPage;\r
161 NewPage = mS3NvsPageTableAddress;\r
162 ZeroMem ((VOID *)NewPage, EFI_PAGES_TO_SIZE(PageNum));\r
163 mS3NvsPageTableAddress += EFI_PAGES_TO_SIZE(PageNum);\r
164 return NewPage;\r
be46cd5f 165}\r
166\r
54e27ada
JY
167/**\r
168 The page fault handler that on-demand read >4G memory/MMIO.\r
169 \r
170 @retval TRUE The page fault is correctly handled.\r
171 @retval FALSE The page fault is not handled and is passed through to original handler.\r
172\r
173**/\r
d0bf5623
JY
174BOOLEAN\r
175EFIAPI\r
176PageFaultHandler (\r
177 VOID\r
178 )\r
179{\r
180 UINT64 *PageTable;\r
181 UINT64 PFAddress;\r
182 UINTN PTIndex;\r
183\r
184 PFAddress = AsmReadCr2 ();\r
185 DEBUG ((EFI_D_ERROR, "BootScript - PageFaultHandler: Cr2 - %lx\n", PFAddress));\r
186\r
187 if (PFAddress >= mPhyMask + SIZE_4KB) {\r
188 return FALSE;\r
189 }\r
190 PFAddress &= mPhyMask;\r
191\r
192 PageTable = (UINT64*)(UINTN)(AsmReadCr3 () & mPhyMask);\r
193\r
194 PTIndex = BitFieldRead64 (PFAddress, 39, 47);\r
195 // PML4E\r
196 if ((PageTable[PTIndex] & IA32_PG_P) == 0) {\r
197 PageTable[PTIndex] = GetNewPage (1) | IA32_PG_P | IA32_PG_RW;\r
198 }\r
199 PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & mPhyMask);\r
200 PTIndex = BitFieldRead64 (PFAddress, 30, 38);\r
201 // PDPTE\r
202 if (mPage1GSupport) {\r
203 PageTable[PTIndex] = PFAddress | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;\r
204 } else {\r
205 if ((PageTable[PTIndex] & IA32_PG_P) == 0) {\r
206 PageTable[PTIndex] = GetNewPage (1) | IA32_PG_P | IA32_PG_RW;\r
207 }\r
208 PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & mPhyMask);\r
209 PTIndex = BitFieldRead64 (PFAddress, 21, 29);\r
210 // PD\r
211 PageTable[PTIndex] = PFAddress | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;\r
212 }\r
213\r
214 return TRUE;\r
215}\r