]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ArmPkg / Drivers / ArmGic / ArmGicCommonDxe.c
CommitLineData
69b5dc9f
OM
1/*++\r
2\r
b0393756 3Copyright (c) 2013-2017, ARM Ltd. All rights reserved.<BR>\r
69b5dc9f 4\r
4059386c 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
69b5dc9f
OM
6\r
7--*/\r
8\r
9#include "ArmGicDxe.h"\r
10\r
11VOID\r
12EFIAPI\r
13IrqInterruptHandler (\r
429309e0
MK
14 IN EFI_EXCEPTION_TYPE InterruptType,\r
15 IN EFI_SYSTEM_CONTEXT SystemContext\r
69b5dc9f
OM
16 );\r
17\r
18VOID\r
19EFIAPI\r
20ExitBootServicesEvent (\r
21 IN EFI_EVENT Event,\r
22 IN VOID *Context\r
23 );\r
24\r
69b5dc9f 25// Making this global saves a few bytes in image size\r
69b5dc9f
OM
26EFI_HANDLE gHardwareInterruptHandle = NULL;\r
27\r
69b5dc9f 28// Notifications\r
429309e0 29EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;\r
69b5dc9f
OM
30\r
31// Maximum Number of Interrupts\r
429309e0 32UINTN mGicNumInterrupts = 0;\r
69b5dc9f
OM
33\r
34HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;\r
35\r
8659306a
AB
36/**\r
37 Calculate GICD_ICFGRn base address and corresponding bit\r
38 field Int_config[1] of the GIC distributor register.\r
39\r
40 @param Source Hardware source of the interrupt.\r
41 @param RegAddress Corresponding GICD_ICFGRn base address.\r
42 @param Config1Bit Bit number of F Int_config[1] bit in the register.\r
43\r
44 @retval EFI_SUCCESS Source interrupt supported.\r
45 @retval EFI_UNSUPPORTED Source interrupt is not supported.\r
46**/\r
47EFI_STATUS\r
48GicGetDistributorIcfgBaseAndBit (\r
429309e0
MK
49 IN HARDWARE_INTERRUPT_SOURCE Source,\r
50 OUT UINTN *RegAddress,\r
51 OUT UINTN *Config1Bit\r
8659306a
AB
52 )\r
53{\r
429309e0
MK
54 UINTN RegIndex;\r
55 UINTN Field;\r
8659306a
AB
56\r
57 if (Source >= mGicNumInterrupts) {\r
429309e0 58 ASSERT (Source < mGicNumInterrupts);\r
8659306a
AB
59 return EFI_UNSUPPORTED;\r
60 }\r
61\r
429309e0
MK
62 RegIndex = Source / ARM_GIC_ICDICFR_F_STRIDE; // NOTE: truncation is significant\r
63 Field = Source % ARM_GIC_ICDICFR_F_STRIDE;\r
8659306a
AB
64 *RegAddress = PcdGet64 (PcdGicDistributorBase)\r
65 + ARM_GIC_ICDICFR\r
66 + (ARM_GIC_ICDICFR_BYTES * RegIndex);\r
67 *Config1Bit = ((Field * ARM_GIC_ICDICFR_F_WIDTH)\r
68 + ARM_GIC_ICDICFR_F_CONFIG1_BIT);\r
69\r
70 return EFI_SUCCESS;\r
71}\r
72\r
0458b423
OM
73/**\r
74 Register Handler for the specified interrupt source.\r
75\r
76 @param This Instance pointer for this protocol\r
77 @param Source Hardware source of the interrupt\r
78 @param Handler Callback for interrupt. NULL to unregister\r
79\r
80 @retval EFI_SUCCESS Source was updated to support Handler.\r
81 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
82\r
83**/\r
84EFI_STATUS\r
85EFIAPI\r
86RegisterInterruptSource (\r
429309e0
MK
87 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
88 IN HARDWARE_INTERRUPT_SOURCE Source,\r
89 IN HARDWARE_INTERRUPT_HANDLER Handler\r
0458b423
OM
90 )\r
91{\r
599f004b 92 if (Source >= mGicNumInterrupts) {\r
429309e0 93 ASSERT (FALSE);\r
0458b423
OM
94 return EFI_UNSUPPORTED;\r
95 }\r
96\r
97 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {\r
98 return EFI_INVALID_PARAMETER;\r
99 }\r
100\r
101 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {\r
102 return EFI_ALREADY_STARTED;\r
103 }\r
104\r
105 gRegisteredInterruptHandlers[Source] = Handler;\r
106\r
107 // If the interrupt handler is unregistered then disable the interrupt\r
429309e0 108 if (NULL == Handler) {\r
0458b423
OM
109 return This->DisableInterruptSource (This, Source);\r
110 } else {\r
111 return This->EnableInterruptSource (This, Source);\r
112 }\r
113}\r
114\r
429309e0 115STATIC VOID *mCpuArchProtocolNotifyEventRegistration;\r
61a7b0ec
AB
116\r
117STATIC\r
118VOID\r
119EFIAPI\r
120CpuArchEventProtocolNotify (\r
429309e0
MK
121 IN EFI_EVENT Event,\r
122 IN VOID *Context\r
61a7b0ec
AB
123 )\r
124{\r
429309e0
MK
125 EFI_CPU_ARCH_PROTOCOL *Cpu;\r
126 EFI_STATUS Status;\r
61a7b0ec
AB
127\r
128 // Get the CPU protocol that this driver requires.\r
129 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);\r
130 if (EFI_ERROR (Status)) {\r
131 return;\r
132 }\r
133\r
134 // Unregister the default exception handler.\r
135 Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);\r
136 if (EFI_ERROR (Status)) {\r
429309e0
MK
137 DEBUG ((\r
138 DEBUG_ERROR,\r
139 "%a: Cpu->RegisterInterruptHandler() - %r\n",\r
140 __FUNCTION__,\r
141 Status\r
142 ));\r
61a7b0ec
AB
143 return;\r
144 }\r
145\r
146 // Register to receive interrupts\r
429309e0
MK
147 Status = Cpu->RegisterInterruptHandler (\r
148 Cpu,\r
149 ARM_ARCH_EXCEPTION_IRQ,\r
150 Context\r
151 );\r
61a7b0ec 152 if (EFI_ERROR (Status)) {\r
429309e0
MK
153 DEBUG ((\r
154 DEBUG_ERROR,\r
155 "%a: Cpu->RegisterInterruptHandler() - %r\n",\r
156 __FUNCTION__,\r
157 Status\r
158 ));\r
61a7b0ec
AB
159 }\r
160\r
161 gBS->CloseEvent (Event);\r
162}\r
163\r
69b5dc9f
OM
164EFI_STATUS\r
165InstallAndRegisterInterruptService (\r
166 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,\r
8659306a 167 IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *Interrupt2Protocol,\r
429309e0
MK
168 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,\r
169 IN EFI_EVENT_NOTIFY ExitBootServicesEvent\r
69b5dc9f
OM
170 )\r
171{\r
429309e0
MK
172 EFI_STATUS Status;\r
173 CONST UINTN RihArraySize =\r
174 (sizeof (HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);\r
69b5dc9f
OM
175\r
176 // Initialize the array for the Interrupt Handlers\r
b0393756 177 gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize);\r
69b5dc9f
OM
178 if (gRegisteredInterruptHandlers == NULL) {\r
179 return EFI_OUT_OF_RESOURCES;\r
180 }\r
181\r
182 Status = gBS->InstallMultipleProtocolInterfaces (\r
183 &gHardwareInterruptHandle,\r
b0393756
EL
184 &gHardwareInterruptProtocolGuid,\r
185 InterruptProtocol,\r
8659306a
AB
186 &gHardwareInterrupt2ProtocolGuid,\r
187 Interrupt2Protocol,\r
69b5dc9f
OM
188 NULL\r
189 );\r
190 if (EFI_ERROR (Status)) {\r
191 return Status;\r
192 }\r
193\r
61a7b0ec
AB
194 //\r
195 // Install the interrupt handler as soon as the CPU arch protocol appears.\r
196 //\r
197 EfiCreateProtocolNotifyEvent (\r
198 &gEfiCpuArchProtocolGuid,\r
199 TPL_CALLBACK,\r
200 CpuArchEventProtocolNotify,\r
201 InterruptHandler,\r
429309e0
MK
202 &mCpuArchProtocolNotifyEventRegistration\r
203 );\r
69b5dc9f
OM
204\r
205 // Register for an ExitBootServicesEvent\r
b0393756
EL
206 Status = gBS->CreateEvent (\r
207 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
208 TPL_NOTIFY,\r
209 ExitBootServicesEvent,\r
210 NULL,\r
211 &EfiExitBootServicesEvent\r
212 );\r
69b5dc9f
OM
213\r
214 return Status;\r
215}\r