VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/ArmPkg/Drivers/ArmGicDxe/ArmGicCommonDxe.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
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;
21EFI_CPU_ARCH_PROTOCOL *gCpuArch;
22
23/**
24 Calculate GICD_ICFGRn base address and corresponding bit
25 field Int_config[1] of the GIC distributor register.
26
27 @param Source Hardware source of the interrupt.
28 @param RegAddress Corresponding GICD_ICFGRn base address.
29 @param Config1Bit Bit number of F Int_config[1] bit in the register.
30
31 @retval EFI_SUCCESS Source interrupt supported.
32 @retval EFI_UNSUPPORTED Source interrupt is not supported.
33**/
34EFI_STATUS
35GicGetDistributorIcfgBaseAndBit (
36 IN HARDWARE_INTERRUPT_SOURCE Source,
37 OUT UINTN *RegAddress,
38 OUT UINTN *Config1Bit
39 )
40{
41 UINTN RegIndex;
42 UINTN Field;
43
44 if (Source >= mGicNumInterrupts) {
45 ASSERT (Source < mGicNumInterrupts);
46 return EFI_UNSUPPORTED;
47 }
48
49 RegIndex = Source / ARM_GIC_ICDICFR_F_STRIDE; // NOTE: truncation is significant
50 Field = Source % ARM_GIC_ICDICFR_F_STRIDE;
51 *RegAddress = (UINTN)PcdGet64 (PcdGicDistributorBase)
52 + ARM_GIC_ICDICFR
53 + (ARM_GIC_ICDICFR_BYTES * RegIndex);
54 *Config1Bit = ((Field * ARM_GIC_ICDICFR_F_WIDTH)
55 + ARM_GIC_ICDICFR_F_CONFIG1_BIT);
56
57 return EFI_SUCCESS;
58}
59
60/**
61 Register Handler for the specified interrupt source.
62
63 @param This Instance pointer for this protocol
64 @param Source Hardware source of the interrupt
65 @param Handler Callback for interrupt. NULL to unregister
66
67 @retval EFI_SUCCESS Source was updated to support Handler.
68 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
69
70**/
71EFI_STATUS
72EFIAPI
73RegisterInterruptSource (
74 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
75 IN HARDWARE_INTERRUPT_SOURCE Source,
76 IN HARDWARE_INTERRUPT_HANDLER Handler
77 )
78{
79 if (Source >= mGicNumInterrupts) {
80 ASSERT (FALSE);
81 return EFI_UNSUPPORTED;
82 }
83
84 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
85 return EFI_INVALID_PARAMETER;
86 }
87
88 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
89 return EFI_ALREADY_STARTED;
90 }
91
92 gRegisteredInterruptHandlers[Source] = Handler;
93
94 // If the interrupt handler is unregistered then disable the interrupt
95 if (NULL == Handler) {
96 return This->DisableInterruptSource (This, Source);
97 } else {
98 return This->EnableInterruptSource (This, Source);
99 }
100}
101
102EFI_STATUS
103InstallAndRegisterInterruptService (
104 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,
105 IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *Interrupt2Protocol,
106 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,
107 IN EFI_EVENT_NOTIFY ExitBootServicesEvent
108 )
109{
110 EFI_STATUS Status;
111 CONST UINTN RihArraySize =
112 (sizeof (HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
113
114 // Initialize the array for the Interrupt Handlers
115 gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize);
116 if (gRegisteredInterruptHandlers == NULL) {
117 return EFI_OUT_OF_RESOURCES;
118 }
119
120 // Register to receive interrupts
121 Status = gCpuArch->RegisterInterruptHandler (gCpuArch, ARM_ARCH_EXCEPTION_IRQ, InterruptHandler);
122 if (EFI_ERROR (Status)) {
123 DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n", __func__, Status));
124 FreePool (gRegisteredInterruptHandlers);
125 return Status;
126 }
127
128 Status = gBS->InstallMultipleProtocolInterfaces (
129 &gHardwareInterruptHandle,
130 &gHardwareInterruptProtocolGuid,
131 InterruptProtocol,
132 &gHardwareInterrupt2ProtocolGuid,
133 Interrupt2Protocol,
134 NULL
135 );
136 if (EFI_ERROR (Status)) {
137 return Status;
138 }
139
140 // Register for an ExitBootServicesEvent
141 Status = gBS->CreateEvent (
142 EVT_SIGNAL_EXIT_BOOT_SERVICES,
143 TPL_NOTIFY,
144 ExitBootServicesEvent,
145 NULL,
146 &EfiExitBootServicesEvent
147 );
148
149 return Status;
150}
151
152/**
153 Return the GIC CPU Interrupt Interface ID.
154
155 @param GicInterruptInterfaceBase Base address of the GIC Interrupt Interface.
156
157 @retval CPU Interface Identification information.
158**/
159UINT32
160EFIAPI
161ArmGicGetInterfaceIdentification (
162 IN UINTN GicInterruptInterfaceBase
163 )
164{
165 // Read the GIC Identification Register
166 return MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIIDR);
167}
168
169UINTN
170EFIAPI
171ArmGicGetMaxNumInterrupts (
172 IN UINTN GicDistributorBase
173 )
174{
175 UINTN ItLines;
176
177 ItLines = MmioRead32 (GicDistributorBase + ARM_GIC_ICDICTR) & 0x1F;
178
179 //
180 // Interrupt ID 1020-1023 are reserved.
181 //
182 return (ItLines == 0x1f) ? 1020 : 32 * (ItLines + 1);
183}
184
185VOID
186EFIAPI
187ArmGicDisableDistributor (
188 IN UINTN GicDistributorBase
189 )
190{
191 // Disable Gic Distributor
192 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x0);
193}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette