TianoCore EDK2 master
Loading...
Searching...
No Matches
ArmGicCommonDxe.c
1/*++
2
3Copyright (c) 2013-2023, Arm Ltd. All rights reserved.<BR>
4
5SPDX-License-Identifier: BSD-2-Clause-Patent
6
7--*/
8
9#include "ArmGicDxe.h"
10
11// Making this global saves a few bytes in image size
12EFI_HANDLE gHardwareInterruptHandle = NULL;
13
14// Notifications
15EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
16
17// Maximum Number of Interrupts
18UINTN mGicNumInterrupts = 0;
19
20HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;
21
34GicGetDistributorIcfgBaseAndBit (
35 IN HARDWARE_INTERRUPT_SOURCE Source,
36 OUT UINTN *RegAddress,
37 OUT UINTN *Config1Bit
38 )
39{
40 UINTN RegIndex;
41 UINTN Field;
42
43 if (Source >= mGicNumInterrupts) {
44 ASSERT (Source < mGicNumInterrupts);
45 return EFI_UNSUPPORTED;
46 }
47
48 RegIndex = Source / ARM_GIC_ICDICFR_F_STRIDE; // NOTE: truncation is significant
49 Field = Source % ARM_GIC_ICDICFR_F_STRIDE;
50 *RegAddress = (UINTN)PcdGet64 (PcdGicDistributorBase)
51 + ARM_GIC_ICDICFR
52 + (ARM_GIC_ICDICFR_BYTES * RegIndex);
53 *Config1Bit = ((Field * ARM_GIC_ICDICFR_F_WIDTH)
54 + ARM_GIC_ICDICFR_F_CONFIG1_BIT);
55
56 return EFI_SUCCESS;
57}
58
71EFIAPI
72RegisterInterruptSource (
74 IN HARDWARE_INTERRUPT_SOURCE Source,
76 )
77{
78 if (Source >= mGicNumInterrupts) {
79 ASSERT (FALSE);
80 return EFI_UNSUPPORTED;
81 }
82
83 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
84 return EFI_INVALID_PARAMETER;
85 }
86
87 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
88 return EFI_ALREADY_STARTED;
89 }
90
91 gRegisteredInterruptHandlers[Source] = Handler;
92
93 // If the interrupt handler is unregistered then disable the interrupt
94 if (NULL == Handler) {
95 return This->DisableInterruptSource (This, Source);
96 } else {
97 return This->EnableInterruptSource (This, Source);
98 }
99}
100
101STATIC VOID *mCpuArchProtocolNotifyEventRegistration;
102
103STATIC
104VOID
105EFIAPI
106CpuArchEventProtocolNotify (
107 IN EFI_EVENT Event,
108 IN VOID *Context
109 )
110{
112 EFI_STATUS Status;
113
114 // Get the CPU protocol that this driver requires.
115 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
116 if (EFI_ERROR (Status)) {
117 return;
118 }
119
120 // Unregister the default exception handler.
121 Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);
122 if (EFI_ERROR (Status)) {
123 DEBUG ((
124 DEBUG_ERROR,
125 "%a: Cpu->RegisterInterruptHandler() - %r\n",
126 __func__,
127 Status
128 ));
129 return;
130 }
131
132 // Register to receive interrupts
133 Status = Cpu->RegisterInterruptHandler (
134 Cpu,
135 ARM_ARCH_EXCEPTION_IRQ,
136 Context
137 );
138 if (EFI_ERROR (Status)) {
139 DEBUG ((
140 DEBUG_ERROR,
141 "%a: Cpu->RegisterInterruptHandler() - %r\n",
142 __func__,
143 Status
144 ));
145 }
146
147 gBS->CloseEvent (Event);
148}
149
151InstallAndRegisterInterruptService (
152 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,
153 IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *Interrupt2Protocol,
154 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,
156 )
157{
158 EFI_STATUS Status;
159 CONST UINTN RihArraySize =
160 (sizeof (HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
161
162 // Initialize the array for the Interrupt Handlers
163 gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize);
164 if (gRegisteredInterruptHandlers == NULL) {
165 return EFI_OUT_OF_RESOURCES;
166 }
167
168 Status = gBS->InstallMultipleProtocolInterfaces (
169 &gHardwareInterruptHandle,
170 &gHardwareInterruptProtocolGuid,
171 InterruptProtocol,
172 &gHardwareInterrupt2ProtocolGuid,
173 Interrupt2Protocol,
174 NULL
175 );
176 if (EFI_ERROR (Status)) {
177 return Status;
178 }
179
180 //
181 // Install the interrupt handler as soon as the CPU arch protocol appears.
182 //
184 &gEfiCpuArchProtocolGuid,
185 TPL_CALLBACK,
186 CpuArchEventProtocolNotify,
187 InterruptHandler,
188 &mCpuArchProtocolNotifyEventRegistration
189 );
190
191 // Register for an ExitBootServicesEvent
192 Status = gBS->CreateEvent (
193 EVT_SIGNAL_EXIT_BOOT_SERVICES,
194 TPL_NOTIFY,
196 NULL,
197 &EfiExitBootServicesEvent
198 );
199
200 return Status;
201}
UINT64 UINTN
VOID(EFIAPI * EFI_CPU_INTERRUPT_HANDLER)(IN CONST EFI_EXCEPTION_TYPE InterruptType, IN CONST EFI_SYSTEM_CONTEXT SystemContext)
Definition: Cpu.h:52
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID(EFIAPI * HARDWARE_INTERRUPT_HANDLER)(IN HARDWARE_INTERRUPT_SOURCE Source, IN EFI_SYSTEM_CONTEXT SystemContext)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
VOID EFIAPI ExitBootServicesEvent(IN EFI_EVENT Event, IN VOID *Context)
Definition: TimerDxe.c:92
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_EVENT EFIAPI EfiCreateProtocolNotifyEvent(IN EFI_GUID *ProtocolGuid, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext OPTIONAL, OUT VOID **Registration)
Definition: UefiLib.c:134
VOID(EFIAPI * EFI_EVENT_NOTIFY)(IN EFI_EVENT Event, IN VOID *Context)
Definition: UefiSpec.h:463