TianoCore EDK2 master
Loading...
Searching...
No Matches
ArmVirtGicArchLib.c
Go to the documentation of this file.
1
10#include <Base.h>
11#include <Uefi.h>
12
13#include <Library/ArmGicLib.h>
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
17#include <Library/PcdLib.h>
19
20#include <Protocol/FdtClient.h>
21
22STATIC ARM_GIC_ARCH_REVISION mGicArchRevision;
23
24RETURN_STATUS
25EFIAPI
26ArmVirtGicArchLibConstructor (
27 VOID
28 )
29{
30 UINT32 IccSre;
31 FDT_CLIENT_PROTOCOL *FdtClient;
32 CONST UINT64 *Reg;
33 UINT32 RegSize;
34 UINTN AddressCells, SizeCells;
35 UINTN GicRevision;
36 EFI_STATUS Status;
37 UINT64 DistBase, CpuBase, RedistBase;
38 RETURN_STATUS PcdStatus;
39
40 Status = gBS->LocateProtocol (
41 &gFdtClientProtocolGuid,
42 NULL,
43 (VOID **)&FdtClient
44 );
45 ASSERT_EFI_ERROR (Status);
46
47 GicRevision = 2;
48 Status = FdtClient->FindCompatibleNodeReg (
49 FdtClient,
50 "arm,cortex-a15-gic",
51 (CONST VOID **)&Reg,
52 &AddressCells,
53 &SizeCells,
54 &RegSize
55 );
56 if (Status == EFI_NOT_FOUND) {
57 GicRevision = 3;
58 Status = FdtClient->FindCompatibleNodeReg (
59 FdtClient,
60 "arm,gic-v3",
61 (CONST VOID **)&Reg,
62 &AddressCells,
63 &SizeCells,
64 &RegSize
65 );
66 }
67
68 if (EFI_ERROR (Status)) {
69 return Status;
70 }
71
72 switch (GicRevision) {
73 case 3:
74 //
75 // The GIC v3 DT binding describes a series of at least 3 physical (base
76 // addresses, size) pairs: the distributor interface (GICD), at least one
77 // redistributor region (GICR) containing dedicated redistributor
78 // interfaces for all individual CPUs, and the CPU interface (GICC).
79 // Under virtualization, we assume that the first redistributor region
80 // listed covers the boot CPU. Also, our GICv3 driver only supports the
81 // system register CPU interface, so we can safely ignore the MMIO version
82 // which is listed after the sequence of redistributor interfaces.
83 // This means we are only interested in the first two memory regions
84 // supplied, and ignore everything else.
85 //
86 ASSERT (RegSize >= 32);
87
88 // RegProp[0..1] == { GICD base, GICD size }
89 DistBase = SwapBytes64 (Reg[0]);
90 ASSERT (DistBase < MAX_UINTN);
91
92 // RegProp[2..3] == { GICR base, GICR size }
93 RedistBase = SwapBytes64 (Reg[2]);
94 ASSERT (RedistBase < MAX_UINTN);
95
96 PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
97 ASSERT_RETURN_ERROR (PcdStatus);
98 PcdStatus = PcdSet64S (PcdGicRedistributorsBase, RedistBase);
99 ASSERT_RETURN_ERROR (PcdStatus);
100
101 DEBUG ((
102 DEBUG_INFO,
103 "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
104 DistBase,
105 RedistBase
106 ));
107
108 //
109 // The default implementation of ArmGicArchLib is responsible for enabling
110 // the system register interface on the GICv3 if one is found. So let's do
111 // the same here.
112 //
113 IccSre = ArmGicV3GetControlSystemRegisterEnable ();
114 if (!(IccSre & ICC_SRE_EL2_SRE)) {
115 ArmGicV3SetControlSystemRegisterEnable (IccSre | ICC_SRE_EL2_SRE);
116 IccSre = ArmGicV3GetControlSystemRegisterEnable ();
117 }
118
119 //
120 // Unlike the default implementation, there is no fall through to GICv2
121 // mode if this GICv3 cannot be driven in native mode due to the fact
122 // that the System Register interface is unavailable.
123 //
124 ASSERT (IccSre & ICC_SRE_EL2_SRE);
125
126 mGicArchRevision = ARM_GIC_ARCH_REVISION_3;
127 break;
128
129 case 2:
130 //
131 // When the GICv2 is emulated with virtualization=on, it adds a virtual
132 // set of control registers. This means the register property can be
133 // either 32 or 64 bytes in size.
134 //
135 ASSERT ((RegSize == 32) || (RegSize == 64));
136
137 DistBase = SwapBytes64 (Reg[0]);
138 CpuBase = SwapBytes64 (Reg[2]);
139 ASSERT (DistBase < MAX_UINTN);
140 ASSERT (CpuBase < MAX_UINTN);
141
142 PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
143 ASSERT_RETURN_ERROR (PcdStatus);
144 PcdStatus = PcdSet64S (PcdGicInterruptInterfaceBase, CpuBase);
145 ASSERT_RETURN_ERROR (PcdStatus);
146
147 DEBUG ((DEBUG_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));
148
149 mGicArchRevision = ARM_GIC_ARCH_REVISION_2;
150 break;
151
152 default:
153 DEBUG ((DEBUG_ERROR, "%a: No GIC revision specified!\n", __func__));
154 return RETURN_NOT_FOUND;
155 }
156
157 return RETURN_SUCCESS;
158}
159
160ARM_GIC_ARCH_REVISION
161EFIAPI
162ArmGicGetSupportedArchRevision (
163 VOID
164 )
165{
166 return mGicArchRevision;
167}
UINT64 UINTN
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define RETURN_NOT_FOUND
Definition: Base.h:1142
#define RETURN_SUCCESS
Definition: Base.h:1066
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define ASSERT_RETURN_ERROR(StatusParameter)
Definition: DebugLib.h:493
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdSet64S(TokenName, Value)
Definition: PcdLib.h:511
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
EFI_BOOT_SERVICES * gBS