]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c
ArmPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / ArmPkg / Library / ArmExceptionLib / ArmExceptionLib.c
CommitLineData
2939c778
EC
1/* @file\r
2* Main file supporting the SEC Phase for Versatile Express\r
3*\r
4* Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
8b8b52ff 5* Copyright (c) 2011-2021, Arm Limited. All rights reserved.<BR>\r
2939c778
EC
6* Copyright (c) 2016 HP Development Company, L.P.\r
7*\r
4059386c 8* SPDX-License-Identifier: BSD-2-Clause-Patent\r
2939c778
EC
9*\r
10**/\r
11\r
12#include <Uefi.h>\r
13#include <Library/CpuExceptionHandlerLib.h>\r
14\r
15#include <Library/ArmLib.h>\r
16#include <Library/PcdLib.h>\r
17#include <Library/CacheMaintenanceLib.h>\r
18#include <Library/BaseLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/DefaultExceptionHandlerLib.h>\r
22\r
8a771a2e 23STATIC\r
2939c778
EC
24RETURN_STATUS\r
25CopyExceptionHandlers(\r
26 IN PHYSICAL_ADDRESS BaseAddress\r
27 );\r
28\r
29EFI_STATUS\r
30EFIAPI\r
31RegisterExceptionHandler(\r
32 IN EFI_EXCEPTION_TYPE ExceptionType,\r
33 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
34 );\r
35\r
36VOID\r
37ExceptionHandlersStart(\r
38 VOID\r
39 );\r
40\r
41VOID\r
42ExceptionHandlersEnd(\r
43 VOID\r
44 );\r
45\r
46RETURN_STATUS ArchVectorConfig(\r
47 IN UINTN VectorBaseAddress\r
48 );\r
49\r
50// these globals are provided by the architecture specific source (Arm or AArch64)\r
51extern UINTN gMaxExceptionNumber;\r
52extern EFI_EXCEPTION_CALLBACK gExceptionHandlers[];\r
53extern EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[];\r
54extern PHYSICAL_ADDRESS gExceptionVectorAlignmentMask;\r
55extern UINTN gDebuggerNoHandlerValue;\r
56\r
57// A compiler flag adjusts the compilation of this library to a variant where\r
58// the vectors are relocated (copied) to another location versus using the\r
59// vectors in-place. Since this effects an assembly .align directive we must\r
60// address this at library build time. Since this affects the build of the\r
61// library we cannot represent this in a PCD since PCDs are evaluated on\r
62// a per-module basis.\r
63#if defined(ARM_RELOCATE_VECTORS)\r
8a771a2e 64STATIC CONST BOOLEAN gArmRelocateVectorTable = TRUE;\r
2939c778 65#else\r
8a771a2e 66STATIC CONST BOOLEAN gArmRelocateVectorTable = FALSE;\r
2939c778
EC
67#endif\r
68\r
69\r
70/**\r
71Initializes all CPU exceptions entries and provides the default exception handlers.\r
72\r
73Caller should try to get an array of interrupt and/or exception vectors that are in use and need to\r
74persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.\r
75If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.\r
76If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.\r
77\r
78@param[in] VectorInfo Pointer to reserved vector list.\r
79\r
80@retval EFI_SUCCESS CPU Exception Entries have been successfully initialized\r
81with default exception handlers.\r
82@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.\r
83@retval EFI_UNSUPPORTED This function is not supported.\r
84\r
85**/\r
86EFI_STATUS\r
87EFIAPI\r
88InitializeCpuExceptionHandlers(\r
89 IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL\r
90 )\r
91{\r
92 RETURN_STATUS Status;\r
93 UINTN VectorBase;\r
94\r
95 Status = EFI_SUCCESS;\r
96\r
ff5fef14 97 // if we are requested to copy exception handlers to another location\r
2939c778
EC
98 if (gArmRelocateVectorTable) {\r
99\r
f0bbcdf8 100 VectorBase = PcdGet64(PcdCpuVectorBaseAddress);\r
2939c778
EC
101 Status = CopyExceptionHandlers(VectorBase);\r
102\r
103 }\r
104 else { // use VBAR to point to where our exception handlers are\r
105\r
106 // The vector table must be aligned for the architecture. If this\r
107 // assertion fails ensure the appropriate FFS alignment is in effect,\r
108 // which can be accomplished by ensuring the proper Align=X statement\r
109 // in the platform packaging rules. For ARM Align=32 is required and\r
110 // for AArch64 Align=4K is required. Align=Auto can be used but this\r
111 // is known to cause an issue with populating the reset vector area\r
112 // for encapsulated FVs.\r
113 ASSERT(((UINTN)ExceptionHandlersStart & gExceptionVectorAlignmentMask) == 0);\r
114\r
f0bbcdf8 115 // We do not copy the Exception Table at PcdGet64(PcdCpuVectorBaseAddress). We just set Vector\r
2939c778
EC
116 // Base Address to point into CpuDxe code.\r
117 VectorBase = (UINTN)ExceptionHandlersStart;\r
118\r
119 Status = RETURN_SUCCESS;\r
120 }\r
121\r
122 if (!RETURN_ERROR(Status)) {\r
123 // call the architecture-specific routine to prepare for the new vector\r
124 // configuration to take effect\r
125 ArchVectorConfig(VectorBase);\r
126\r
127 ArmWriteVBar(VectorBase);\r
128 }\r
129\r
130 return RETURN_SUCCESS;\r
131}\r
132\r
133/**\r
ff5fef14 134Copies exception handlers to the specified address.\r
2939c778
EC
135\r
136Caller should try to get an array of interrupt and/or exception vectors that are in use and need to\r
137persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.\r
138If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.\r
139If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.\r
140\r
141@param[in] VectorInfo Pointer to reserved vector list.\r
142\r
143@retval EFI_SUCCESS CPU Exception Entries have been successfully initialized\r
144with default exception handlers.\r
145@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.\r
146@retval EFI_UNSUPPORTED This function is not supported.\r
147\r
148**/\r
8a771a2e 149STATIC\r
2939c778
EC
150RETURN_STATUS\r
151CopyExceptionHandlers(\r
152 IN PHYSICAL_ADDRESS BaseAddress\r
153 )\r
154{\r
155 RETURN_STATUS Status;\r
156 UINTN Length;\r
157 UINTN Index;\r
158 UINT32 *VectorBase;\r
159\r
160 // ensure that the destination value specifies an address meeting the vector alignment requirements\r
161 ASSERT ((BaseAddress & gExceptionVectorAlignmentMask) == 0);\r
162\r
163 //\r
164 // Copy an implementation of the exception vectors to PcdCpuVectorBaseAddress.\r
165 //\r
166 Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
167\r
168 VectorBase = (UINT32 *)(UINTN)BaseAddress;\r
169\r
170 if (FeaturePcdGet(PcdDebuggerExceptionSupport) == TRUE) {\r
171 // Save existing vector table, in case debugger is already hooked in\r
172 CopyMem((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (EFI_EXCEPTION_CALLBACK)* (gMaxExceptionNumber+1));\r
173 }\r
174\r
175 // Copy our assembly code into the page that contains the exception vectors.\r
176 CopyMem((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\r
177\r
178 //\r
179 // Initialize the C entry points for interrupts\r
180 //\r
181 for (Index = 0; Index <= gMaxExceptionNumber; Index++) {\r
182 if (!FeaturePcdGet(PcdDebuggerExceptionSupport) ||\r
183 (gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)gDebuggerNoHandlerValue)) {\r
184\r
185 Status = RegisterExceptionHandler(Index, NULL);\r
186 ASSERT_EFI_ERROR(Status);\r
187 }\r
188 else {\r
189 // If the debugger has already hooked put its vector back\r
190 VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];\r
191 }\r
192 }\r
193\r
194 // Flush Caches since we updated executable stuff\r
195 InvalidateInstructionCacheRange((VOID *)(UINTN)BaseAddress, Length);\r
196\r
197 return RETURN_SUCCESS;\r
198}\r
199\r
200\r
201/**\r
202Initializes all CPU interrupt/exceptions entries and provides the default interrupt/exception handlers.\r
203\r
204Caller should try to get an array of interrupt and/or exception vectors that are in use and need to\r
205persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.\r
206If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL.\r
207If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly.\r
208\r
209@param[in] VectorInfo Pointer to reserved vector list.\r
210\r
211@retval EFI_SUCCESS All CPU interrupt/exception entries have been successfully initialized\r
212with default interrupt/exception handlers.\r
213@retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.\r
214@retval EFI_UNSUPPORTED This function is not supported.\r
215\r
216**/\r
217EFI_STATUS\r
218EFIAPI\r
219InitializeCpuInterruptHandlers(\r
220IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL\r
221)\r
222{\r
223 // not needed, this is what the CPU driver is for\r
224 return EFI_UNSUPPORTED;\r
225}\r
226\r
227/**\r
228Registers a function to be called from the processor exception handler. (On ARM/AArch64 this only\r
229provides exception handlers, not interrupt handling which is provided through the Hardware Interrupt\r
230Protocol.)\r
231\r
232This function registers and enables the handler specified by ExceptionHandler for a processor\r
233interrupt or exception type specified by ExceptionType. If ExceptionHandler is NULL, then the\r
234handler for the processor interrupt or exception type specified by ExceptionType is uninstalled.\r
235The installed handler is called once for each processor interrupt or exception.\r
236NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or\r
237InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned.\r
238\r
239@param[in] ExceptionType Defines which interrupt or exception to hook.\r
240@param[in] ExceptionHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called\r
241when a processor interrupt occurs. If this parameter is NULL, then the handler\r
242will be uninstalled.\r
243\r
244@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.\r
245@retval EFI_ALREADY_STARTED ExceptionHandler is not NULL, and a handler for ExceptionType was\r
246previously installed.\r
247@retval EFI_INVALID_PARAMETER ExceptionHandler is NULL, and a handler for ExceptionType was not\r
248previously installed.\r
249@retval EFI_UNSUPPORTED The interrupt specified by ExceptionType is not supported,\r
250or this function is not supported.\r
251**/\r
252RETURN_STATUS\r
253RegisterCpuInterruptHandler(\r
254 IN EFI_EXCEPTION_TYPE ExceptionType,\r
255 IN EFI_CPU_INTERRUPT_HANDLER ExceptionHandler\r
8b8b52ff
PG
256 )\r
257{\r
2939c778
EC
258 if (ExceptionType > gMaxExceptionNumber) {\r
259 return RETURN_UNSUPPORTED;\r
260 }\r
261\r
262 if ((ExceptionHandler != NULL) && (gExceptionHandlers[ExceptionType] != NULL)) {\r
263 return RETURN_ALREADY_STARTED;\r
264 }\r
265\r
266 gExceptionHandlers[ExceptionType] = ExceptionHandler;\r
267\r
268 return RETURN_SUCCESS;\r
269}\r
270\r
271/**\r
272Register exception handler.\r
273\r
274@param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.\r
275@param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and\r
276the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL\r
277of the UEFI 2.0 specification.\r
278@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER\r
279that is called when a processor interrupt occurs.\r
280If this parameter is NULL, then the handler will be uninstalled.\r
281\r
282@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.\r
283@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was previously installed.\r
284@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not previously installed.\r
285@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.\r
286\r
287**/\r
288EFI_STATUS\r
289EFIAPI\r
290RegisterExceptionHandler(\r
291 IN EFI_EXCEPTION_TYPE ExceptionType,\r
292 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
293 )\r
294{\r
295 return RegisterCpuInterruptHandler(ExceptionType, InterruptHandler);\r
296}\r
297\r
298VOID\r
299EFIAPI\r
300CommonCExceptionHandler(\r
301 IN EFI_EXCEPTION_TYPE ExceptionType,\r
302 IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
303 )\r
304{\r
305 if (ExceptionType <= gMaxExceptionNumber) {\r
306 if (gExceptionHandlers[ExceptionType]) {\r
307 gExceptionHandlers[ExceptionType](ExceptionType, SystemContext);\r
308 return;\r
309 }\r
310 }\r
311 else {\r
a4a582e1 312 DEBUG((DEBUG_ERROR, "Unknown exception type %d\n", ExceptionType));\r
2939c778
EC
313 ASSERT(FALSE);\r
314 }\r
315\r
316 DefaultExceptionHandler(ExceptionType, SystemContext);\r
317}\r
4cb21e1e
JW
318\r
319/**\r
320 Initializes all CPU exceptions entries with optional extra initializations.\r
321\r
322 By default, this method should include all functionalities implemented by\r
323 InitializeCpuExceptionHandlers(), plus extra initialization works, if any.\r
324 This could be done by calling InitializeCpuExceptionHandlers() directly\r
325 in this method besides the extra works.\r
326\r
327 InitData is optional and its use and content are processor arch dependent.\r
328 The typical usage of it is to convey resources which have to be reserved\r
329 elsewhere and are necessary for the extra initializations of exception.\r
330\r
331 @param[in] VectorInfo Pointer to reserved vector list.\r
332 @param[in] InitData Pointer to data optional for extra initializations\r
333 of exception.\r
334\r
335 @retval EFI_SUCCESS The exceptions have been successfully\r
336 initialized.\r
337 @retval EFI_INVALID_PARAMETER VectorInfo or InitData contains invalid\r
338 content.\r
339\r
340**/\r
341EFI_STATUS\r
342EFIAPI\r
343InitializeCpuExceptionHandlersEx (\r
344 IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL,\r
345 IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL\r
346 )\r
347{\r
348 return InitializeCpuExceptionHandlers (VectorInfo);\r
349}\r