]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DebugSupportDxe/Ia32/PlDebugSupport.c
IntelFsp2WrapperPkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / DebugSupportDxe / Ia32 / PlDebugSupport.c
CommitLineData
9e604fe4 1/** @file\r
509bc208 2 IA32/x64 generic functions to support Debug Support protocol.\r
c1f23d63 3\r
d1102dba 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
c1f23d63 6\r
7**/\r
8\r
6e8a984e 9#include "DebugSupport.h"\r
c1f23d63 10\r
11//\r
12// This the global main table to keep track of the interrupts\r
13//\r
c84507ab 14IDT_ENTRY *IdtEntryTable = NULL;\r
c1f23d63 15\r
9e604fe4 16/**\r
6e8a984e 17 Read IDT Gate Descriptor from IDT Table.\r
9e604fe4 18\r
6e8a984e 19 @param Vector Specifies vector number.\r
c84507ab 20 @param IdtGateDescriptor Pointer to IDT Gate Descriptor read from IDT Table.\r
9e604fe4 21\r
22**/\r
c84507ab 23VOID\r
24ReadIdtGateDescriptor (\r
6e8a984e 25 IN EFI_EXCEPTION_TYPE Vector,\r
c84507ab 26 OUT IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor\r
c1f23d63 27 )\r
c1f23d63 28{\r
6e8a984e 29 IA32_DESCRIPTOR IdtrValue;\r
30 IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
c1f23d63 31\r
6e8a984e 32 AsmReadIdtr (&IdtrValue);\r
33 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtrValue.Base;\r
c1f23d63 34\r
c84507ab 35 CopyMem ((VOID *) IdtGateDescriptor, (VOID *) &(IdtTable)[Vector], sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
6e8a984e 36}\r
c84507ab 37\r
6e8a984e 38/**\r
39 Write IDT Gate Descriptor into IDT Table.\r
c1f23d63 40\r
6e8a984e 41 @param Vector Specifies vector number.\r
c84507ab 42 @param IdtGateDescriptor Pointer to IDT Gate Descriptor written into IDT Table.\r
c1f23d63 43\r
6e8a984e 44**/\r
c84507ab 45VOID\r
46WriteIdtGateDescriptor (\r
6e8a984e 47 EFI_EXCEPTION_TYPE Vector,\r
c84507ab 48 IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor\r
6e8a984e 49 )\r
50{\r
51 IA32_DESCRIPTOR IdtrValue;\r
52 IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
c1f23d63 53\r
6e8a984e 54 AsmReadIdtr (&IdtrValue);\r
55 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtrValue.Base;\r
c1f23d63 56\r
c84507ab 57 CopyMem ((VOID *) &(IdtTable)[Vector], (VOID *) IdtGateDescriptor, sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
c1f23d63 58}\r
59\r
9e604fe4 60/**\r
c1f23d63 61 Creates a nes entry stub. Then saves the current IDT entry and replaces it\r
62 with an interrupt gate for the new entry point. The IdtEntryTable is updated\r
63 with the new registered function.\r
64\r
65 This code executes in boot services context. The stub entry executes in interrupt\r
66 context.\r
67\r
9e604fe4 68 @param ExceptionType Specifies which vector to hook.\r
69 @param NewCallback A pointer to the new function to be registered.\r
c1f23d63 70\r
9e604fe4 71**/\r
c84507ab 72VOID\r
9e604fe4 73HookEntry (\r
74 IN EFI_EXCEPTION_TYPE ExceptionType,\r
1ccdbf2a 75 IN CALLBACK_FUNC NewCallback\r
9e604fe4 76 )\r
c1f23d63 77{\r
78 BOOLEAN OldIntFlagState;\r
c1f23d63 79\r
c84507ab 80 CreateEntryStub (ExceptionType, (VOID **) &IdtEntryTable[ExceptionType].StubEntry);\r
d1102dba 81\r
c84507ab 82 //\r
83 // Disables CPU interrupts and returns the previous interrupt state\r
84 //\r
85 OldIntFlagState = SaveAndDisableInterrupts ();\r
c1f23d63 86\r
509bc208 87 //\r
88 // gets IDT Gate descriptor by index\r
89 //\r
c84507ab 90 ReadIdtGateDescriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
509bc208 91 //\r
d1102dba 92 // stores orignal interrupt handle\r
509bc208 93 //\r
c84507ab 94 IdtEntryTable[ExceptionType].OrigVector = (DEBUG_PROC) GetInterruptHandleFromIdt (&(IdtEntryTable[ExceptionType].OrigDesc));\r
c1f23d63 95\r
d1102dba
LG
96 //\r
97 // encodes new IDT Gate descriptor by stub entry\r
509bc208 98 //\r
c84507ab 99 Vect2Desc (&IdtEntryTable[ExceptionType].NewDesc, IdtEntryTable[ExceptionType].StubEntry);\r
509bc208 100 //\r
101 // stores NewCallback\r
102 //\r
c84507ab 103 IdtEntryTable[ExceptionType].RegisteredCallback = NewCallback;\r
509bc208 104\r
105 //\r
106 // writes back new IDT Gate descriptor\r
107 //\r
c84507ab 108 WriteIdtGateDescriptor (ExceptionType, &(IdtEntryTable[ExceptionType].NewDesc));\r
109\r
110 //\r
111 // restore interrupt state\r
112 //\r
113 SetInterruptState (OldIntFlagState);\r
c1f23d63 114\r
c84507ab 115 return ;\r
c1f23d63 116}\r
117\r
9e604fe4 118/**\r
c1f23d63 119 Undoes HookEntry. This code executes in boot services context.\r
120\r
9e604fe4 121 @param ExceptionType Specifies which entry to unhook\r
c1f23d63 122\r
9e604fe4 123**/\r
c84507ab 124VOID\r
9e604fe4 125UnhookEntry (\r
126 IN EFI_EXCEPTION_TYPE ExceptionType\r
127 )\r
c1f23d63 128{\r
129 BOOLEAN OldIntFlagState;\r
130\r
c84507ab 131 //\r
132 // Disables CPU interrupts and returns the previous interrupt state\r
133 //\r
134 OldIntFlagState = SaveAndDisableInterrupts ();\r
c1f23d63 135\r
c84507ab 136 //\r
137 // restore the default IDT Date Descriptor\r
138 //\r
139 WriteIdtGateDescriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
140\r
141 //\r
142 // restore interrupt state\r
143 //\r
144 SetInterruptState (OldIntFlagState);\r
145\r
146 return ;\r
c1f23d63 147}\r
148\r
9e604fe4 149/**\r
c84507ab 150 Returns the maximum value that may be used for the ProcessorIndex parameter in\r
d1102dba
LG
151 RegisterPeriodicCallback() and RegisterExceptionCallback().\r
152\r
c84507ab 153 Hard coded to support only 1 processor for now.\r
9e604fe4 154\r
c84507ab 155 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.\r
156 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the maximum supported\r
d1102dba
LG
157 processor index is returned. Always 0 returned.\r
158\r
c84507ab 159 @retval EFI_SUCCESS Always returned with **MaxProcessorIndex set to 0.\r
9e604fe4 160\r
161**/\r
c1f23d63 162EFI_STATUS\r
163EFIAPI\r
164GetMaximumProcessorIndex (\r
165 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
166 OUT UINTN *MaxProcessorIndex\r
167 )\r
c1f23d63 168{\r
169 *MaxProcessorIndex = 0;\r
c84507ab 170 return EFI_SUCCESS;\r
c1f23d63 171}\r
172\r
9e604fe4 173/**\r
c84507ab 174 Registers a function to be called back periodically in interrupt context.\r
d1102dba 175\r
c84507ab 176 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.\r
177 @param ProcessorIndex Specifies which processor the callback function applies to.\r
178 @param PeriodicCallback A pointer to a function of type PERIODIC_CALLBACK that is the main\r
179 periodic entry point of the debug agent.\r
d1102dba
LG
180\r
181 @retval EFI_SUCCESS The function completed successfully.\r
c84507ab 182 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback\r
d1102dba
LG
183 function was previously registered.\r
184 @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback\r
185 function.\r
9e604fe4 186**/\r
c1f23d63 187EFI_STATUS\r
188EFIAPI\r
189RegisterPeriodicCallback (\r
190 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
191 IN UINTN ProcessorIndex,\r
192 IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
193 )\r
9e604fe4 194{\r
195 return ManageIdtEntryTable (PeriodicCallback, SYSTEM_TIMER_VECTOR);\r
196}\r
c1f23d63 197\r
9e604fe4 198/**\r
c84507ab 199 Registers a function to be called when a given processor exception occurs.\r
c1f23d63 200\r
9e604fe4 201 This code executes in boot services context.\r
d1102dba 202\r
c84507ab 203 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.\r
204 @param ProcessorIndex Specifies which processor the callback function applies to.\r
205 @param ExceptionCallback A pointer to a function of type EXCEPTION_CALLBACK that is called\r
d1102dba
LG
206 when the processor exception specified by ExceptionType occurs.\r
207 @param ExceptionType Specifies which processor exception to hook.\r
208\r
209 @retval EFI_SUCCESS The function completed successfully.\r
c84507ab 210 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback\r
d1102dba
LG
211 function was previously registered.\r
212 @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback\r
c84507ab 213 function.\r
9e604fe4 214**/\r
c1f23d63 215EFI_STATUS\r
216EFIAPI\r
217RegisterExceptionCallback (\r
218 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
219 IN UINTN ProcessorIndex,\r
c84507ab 220 IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
c1f23d63 221 IN EFI_EXCEPTION_TYPE ExceptionType\r
222 )\r
c1f23d63 223{\r
c84507ab 224 return ManageIdtEntryTable (ExceptionCallback, ExceptionType);\r
c1f23d63 225}\r
226\r
509bc208 227\r
9e604fe4 228/**\r
c84507ab 229 Invalidates processor instruction cache for a memory range. Subsequent execution in this range\r
d1102dba
LG
230 causes a fresh memory fetch to retrieve code to be executed.\r
231\r
c84507ab 232 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.\r
233 @param ProcessorIndex Specifies which processor's instruction cache is to be invalidated.\r
d1102dba 234 @param Start Specifies the physical base of the memory range to be invalidated.\r
c84507ab 235 @param Length Specifies the minimum number of bytes in the processor's instruction\r
d1102dba
LG
236 cache to invalidate.\r
237\r
c84507ab 238 @retval EFI_SUCCESS Always returned.\r
9e604fe4 239\r
240**/\r
c1f23d63 241EFI_STATUS\r
242EFIAPI\r
243InvalidateInstructionCache (\r
244 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
245 IN UINTN ProcessorIndex,\r
246 IN VOID *Start,\r
247 IN UINT64 Length\r
248 )\r
c1f23d63 249{\r
250 AsmWbinvd ();\r
251 return EFI_SUCCESS;\r
252}\r
253\r
9e604fe4 254/**\r
c84507ab 255 Common piece of code that invokes the registered handlers.\r
9e604fe4 256\r
c84507ab 257 This code executes in exception context so no efi calls are allowed.\r
509bc208 258 This code is called from assembly file.\r
c84507ab 259\r
260 @param ExceptionType Exception type\r
261 @param ContextRecord System context\r
9e604fe4 262\r
263**/\r
c84507ab 264VOID\r
265InterruptDistrubutionHub (\r
266 EFI_EXCEPTION_TYPE ExceptionType,\r
267 EFI_SYSTEM_CONTEXT_IA32 *ContextRecord\r
c1f23d63 268 )\r
c1f23d63 269{\r
c84507ab 270 if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
271 if (ExceptionType != SYSTEM_TIMER_VECTOR) {\r
272 IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord);\r
273 } else {\r
274 OrigVector = IdtEntryTable[ExceptionType].OrigVector;\r
275 IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord);\r
c1f23d63 276 }\r
277 }\r
c1f23d63 278}\r
279\r
9e604fe4 280/**\r
c84507ab 281 This is the callback that is written to the Loaded Image protocol instance\r
c1f23d63 282 on the image handle. It uninstalls all registered handlers and frees all entry\r
283 stub memory.\r
284\r
9e604fe4 285 @param ImageHandle The firmware allocated handle for the EFI image.\r
c1f23d63 286\r
9e604fe4 287 @retval EFI_SUCCESS Always.\r
c1f23d63 288\r
9e604fe4 289**/\r
290EFI_STATUS\r
291EFIAPI\r
292PlUnloadDebugSupportDriver (\r
293 IN EFI_HANDLE ImageHandle\r
294 )\r
c1f23d63 295{\r
296 EFI_EXCEPTION_TYPE ExceptionType;\r
297\r
298 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
299 ManageIdtEntryTable (NULL, ExceptionType);\r
c84507ab 300 //\r
301 // Free space for each Interrupt Stub precedure.\r
302 //\r
303 if (IdtEntryTable[ExceptionType].StubEntry != NULL) {\r
304 FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry);\r
305 }\r
c1f23d63 306 }\r
307\r
308 FreePool (IdtEntryTable);\r
c84507ab 309\r
c1f23d63 310 return EFI_SUCCESS;\r
311}\r
312\r
9e604fe4 313/**\r
d1102dba
LG
314 Initializes driver's handler registration database.\r
315\r
c84507ab 316 This code executes in boot services context.\r
317 Must be public because it's referenced from DebugSupport.c\r
9e604fe4 318\r
c84507ab 319 @retval EFI_UNSUPPORTED If IA32/x64 processor does not support FXSTOR/FXRSTOR instructions,\r
320 the context save will fail, so these processors are not supported.\r
321 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory.\r
322 @retval EFI_SUCCESS Initializes successfully.\r
9e604fe4 323\r
324**/\r
c84507ab 325EFI_STATUS\r
326PlInitializeDebugSupportDriver (\r
327 VOID\r
c1f23d63 328 )\r
c1f23d63 329{\r
c84507ab 330 EFI_EXCEPTION_TYPE ExceptionType;\r
331\r
332 //\r
333 // Check whether FxStor instructions are supported.\r
334 //\r
335 if (!FxStorSupport ()) {\r
336 return EFI_UNSUPPORTED;\r
337 }\r
338\r
339 IdtEntryTable = AllocateZeroPool (sizeof (IDT_ENTRY) * NUM_IDT_ENTRIES);\r
340 if (IdtEntryTable == NULL) {\r
341 return EFI_OUT_OF_RESOURCES;\r
342 }\r
343\r
344 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType ++) {\r
345 IdtEntryTable[ExceptionType].StubEntry = (DEBUG_PROC) (UINTN) AllocatePool (StubSize);\r
346 if (IdtEntryTable[ExceptionType].StubEntry == NULL) {\r
347 goto ErrorCleanup;\r
348 }\r
d1102dba 349\r
c84507ab 350 //\r
351 // Copy Interrupt stub code.\r
352 //\r
353 CopyMem ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry, InterruptEntryStub, StubSize);\r
354 }\r
355 return EFI_SUCCESS;\r
356\r
357ErrorCleanup:\r
358\r
359 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
360 if (IdtEntryTable[ExceptionType].StubEntry != NULL) {\r
361 FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry);\r
c1f23d63 362 }\r
363 }\r
c84507ab 364 FreePool (IdtEntryTable);\r
365\r
366 return EFI_OUT_OF_RESOURCES;\r
c1f23d63 367}\r