TianoCore EDK2 master
Loading...
Searching...
No Matches
ArmExceptionLib.c
1/* @file
2* Main file supporting the SEC Phase for Versatile Express
3*
4* Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
5* Copyright (c) 2011-2021, Arm Limited. All rights reserved.<BR>
6* Copyright (c) 2016 HP Development Company, L.P.
7* Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
8*
9* SPDX-License-Identifier: BSD-2-Clause-Patent
10*
11**/
12
13#include <Uefi.h>
15
16#include <Library/ArmLib.h>
17#include <Library/PcdLib.h>
19#include <Library/BaseLib.h>
21#include <Library/DebugLib.h>
23
25RETURN_STATUS
26CopyExceptionHandlers (
27 IN PHYSICAL_ADDRESS BaseAddress
28 );
29
31EFIAPI
32RegisterExceptionHandler (
33 IN EFI_EXCEPTION_TYPE ExceptionType,
34 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
35 );
36
37VOID
38ExceptionHandlersStart (
39 VOID
40 );
41
42VOID
43ExceptionHandlersEnd (
44 VOID
45 );
46
47RETURN_STATUS
48ArchVectorConfig (
49 IN UINTN VectorBaseAddress
50 );
51
52// these globals are provided by the architecture specific source (Arm or AArch64)
53extern UINTN gMaxExceptionNumber;
54extern EFI_EXCEPTION_CALLBACK gExceptionHandlers[];
55extern EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[];
56extern PHYSICAL_ADDRESS gExceptionVectorAlignmentMask;
57extern UINTN gDebuggerNoHandlerValue;
58
59// A compiler flag adjusts the compilation of this library to a variant where
60// the vectors are relocated (copied) to another location versus using the
61// vectors in-place. Since this effects an assembly .align directive we must
62// address this at library build time. Since this affects the build of the
63// library we cannot represent this in a PCD since PCDs are evaluated on
64// a per-module basis.
65#if defined (ARM_RELOCATE_VECTORS)
66STATIC CONST BOOLEAN gArmRelocateVectorTable = TRUE;
67#else
68STATIC CONST BOOLEAN gArmRelocateVectorTable = FALSE;
69#endif
70
88EFIAPI
89InitializeCpuExceptionHandlers (
90 IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
91 )
92{
93 RETURN_STATUS Status;
94 UINTN VectorBase;
95
96 Status = EFI_SUCCESS;
97
98 // if we are requested to copy exception handlers to another location
99 if (gArmRelocateVectorTable) {
100 VectorBase = PcdGet64 (PcdCpuVectorBaseAddress);
101 Status = CopyExceptionHandlers (VectorBase);
102 } else {
103 // use VBAR to point to where our exception handlers are
104
105 // The vector table must be aligned for the architecture. If this
106 // assertion fails ensure the appropriate FFS alignment is in effect,
107 // which can be accomplished by ensuring the proper Align=X statement
108 // in the platform packaging rules. For ARM Align=32 is required and
109 // for AArch64 Align=4K is required. Align=Auto can be used but this
110 // is known to cause an issue with populating the reset vector area
111 // for encapsulated FVs.
112 ASSERT (((UINTN)ExceptionHandlersStart & gExceptionVectorAlignmentMask) == 0);
113
114 // We do not copy the Exception Table at PcdGet64(PcdCpuVectorBaseAddress). We just set Vector
115 // Base Address to point into CpuDxe code.
116 VectorBase = (UINTN)ExceptionHandlersStart;
117
118 Status = RETURN_SUCCESS;
119 }
120
121 if (!RETURN_ERROR (Status)) {
122 // call the architecture-specific routine to prepare for the new vector
123 // configuration to take effect
124 ArchVectorConfig (VectorBase);
125
126 ArmWriteVBar (VectorBase);
127 }
128
129 return RETURN_SUCCESS;
130}
131
148STATIC
149RETURN_STATUS
150CopyExceptionHandlers (
151 IN PHYSICAL_ADDRESS BaseAddress
152 )
153{
154 RETURN_STATUS Status;
155 UINTN Length;
156 UINTN Index;
157 UINT32 *VectorBase;
158
159 // ensure that the destination value specifies an address meeting the vector alignment requirements
160 ASSERT ((BaseAddress & gExceptionVectorAlignmentMask) == 0);
161
162 //
163 // Copy an implementation of the exception vectors to PcdCpuVectorBaseAddress.
164 //
165 Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
166
167 VectorBase = (UINT32 *)(UINTN)BaseAddress;
168
169 if (FeaturePcdGet (PcdDebuggerExceptionSupport) == TRUE) {
170 // Save existing vector table, in case debugger is already hooked in
171 CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (EFI_EXCEPTION_CALLBACK)* (gMaxExceptionNumber+1));
172 }
173
174 // Copy our assembly code into the page that contains the exception vectors.
175 CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);
176
177 //
178 // Initialize the C entry points for interrupts
179 //
180 for (Index = 0; Index <= gMaxExceptionNumber; Index++) {
181 if (!FeaturePcdGet (PcdDebuggerExceptionSupport) ||
182 (gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)gDebuggerNoHandlerValue))
183 {
184 Status = RegisterExceptionHandler (Index, NULL);
185 ASSERT_EFI_ERROR (Status);
186 } else {
187 // If the debugger has already hooked put its vector back
188 VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];
189 }
190 }
191
192 // Flush Caches since we updated executable stuff
193 InvalidateInstructionCacheRange ((VOID *)(UINTN)BaseAddress, Length);
194
195 return RETURN_SUCCESS;
196}
197
223RETURN_STATUS
224RegisterCpuInterruptHandler (
225 IN EFI_EXCEPTION_TYPE ExceptionType,
226 IN EFI_CPU_INTERRUPT_HANDLER ExceptionHandler
227 )
228{
229 if (ExceptionType > gMaxExceptionNumber) {
230 return RETURN_UNSUPPORTED;
231 }
232
233 if ((ExceptionHandler != NULL) && (gExceptionHandlers[ExceptionType] != NULL)) {
235 }
236
237 gExceptionHandlers[ExceptionType] = ExceptionHandler;
238
239 return RETURN_SUCCESS;
240}
241
260EFIAPI
261RegisterExceptionHandler (
262 IN EFI_EXCEPTION_TYPE ExceptionType,
263 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
264 )
265{
266 return RegisterCpuInterruptHandler (ExceptionType, InterruptHandler);
267}
268
269VOID
270EFIAPI
271CommonCExceptionHandler (
272 IN EFI_EXCEPTION_TYPE ExceptionType,
273 IN OUT EFI_SYSTEM_CONTEXT SystemContext
274 )
275{
276 if (ExceptionType <= gMaxExceptionNumber) {
277 if (gExceptionHandlers[ExceptionType]) {
278 gExceptionHandlers[ExceptionType](ExceptionType, SystemContext);
279 return;
280 }
281 } else {
282 DEBUG ((DEBUG_ERROR, "Unknown exception type %d\n", ExceptionType));
283 ASSERT (FALSE);
284 }
285
286 DefaultExceptionHandler (ExceptionType, SystemContext);
287}
288
304EFIAPI
305InitializeSeparateExceptionStacks (
306 IN VOID *Buffer,
307 IN OUT UINTN *BufferSize
308 )
309{
310 return EFI_SUCCESS;
311}
UINT64 UINTN
VOID *EFIAPI InvalidateInstructionCacheRange(IN VOID *Address, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID(EFIAPI * EFI_CPU_INTERRUPT_HANDLER)(IN CONST EFI_EXCEPTION_TYPE InterruptType, IN CONST EFI_SYSTEM_CONTEXT SystemContext)
Definition: Cpu.h:52
VOID DefaultExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN OUT EFI_SYSTEM_CONTEXT SystemContext)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define RETURN_ALREADY_STARTED
Definition: Base.h:1172
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
VOID(EFIAPI * EFI_EXCEPTION_CALLBACK)(IN EFI_EXCEPTION_TYPE ExceptionType, IN OUT EFI_SYSTEM_CONTEXT SystemContext)
Definition: DebugSupport.h:816
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112