]> git.proxmox.com Git - mirror_edk2.git/blob - ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c
ArmVirtPkg/ArmVirtGicArchLib: eliminate unchecked PcdSetXX() calls
[mirror_edk2.git] / ArmVirtPkg / Library / ArmVirtGicArchLib / ArmVirtGicArchLib.c
1 /** @file
2 ArmGicArchLib library class implementation for DT based virt platforms
3
4 Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <Base.h>
17 #include <Uefi.h>
18
19 #include <Library/ArmGicLib.h>
20 #include <Library/ArmGicArchLib.h>
21 #include <Library/BaseLib.h>
22 #include <Library/DebugLib.h>
23 #include <Library/PcdLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
25
26 #include <Protocol/FdtClient.h>
27
28 STATIC ARM_GIC_ARCH_REVISION mGicArchRevision;
29
30 RETURN_STATUS
31 EFIAPI
32 ArmVirtGicArchLibConstructor (
33 VOID
34 )
35 {
36 UINT32 IccSre;
37 FDT_CLIENT_PROTOCOL *FdtClient;
38 CONST UINT64 *Reg;
39 UINT32 RegSize;
40 UINTN AddressCells, SizeCells;
41 UINTN GicRevision;
42 EFI_STATUS Status;
43 UINT64 DistBase, CpuBase, RedistBase;
44 RETURN_STATUS PcdStatus;
45
46 Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
47 (VOID **)&FdtClient);
48 ASSERT_EFI_ERROR (Status);
49
50 GicRevision = 2;
51 Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,cortex-a15-gic",
52 (CONST VOID **)&Reg, &AddressCells, &SizeCells,
53 &RegSize);
54 if (Status == EFI_NOT_FOUND) {
55 GicRevision = 3;
56 Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,gic-v3",
57 (CONST VOID **)&Reg, &AddressCells, &SizeCells,
58 &RegSize);
59 }
60 if (EFI_ERROR (Status)) {
61 return Status;
62 }
63
64 switch (GicRevision) {
65
66 case 3:
67 //
68 // The GIC v3 DT binding describes a series of at least 3 physical (base
69 // addresses, size) pairs: the distributor interface (GICD), at least one
70 // redistributor region (GICR) containing dedicated redistributor
71 // interfaces for all individual CPUs, and the CPU interface (GICC).
72 // Under virtualization, we assume that the first redistributor region
73 // listed covers the boot CPU. Also, our GICv3 driver only supports the
74 // system register CPU interface, so we can safely ignore the MMIO version
75 // which is listed after the sequence of redistributor interfaces.
76 // This means we are only interested in the first two memory regions
77 // supplied, and ignore everything else.
78 //
79 ASSERT (RegSize >= 32);
80
81 // RegProp[0..1] == { GICD base, GICD size }
82 DistBase = SwapBytes64 (Reg[0]);
83 ASSERT (DistBase < MAX_UINTN);
84
85 // RegProp[2..3] == { GICR base, GICR size }
86 RedistBase = SwapBytes64 (Reg[2]);
87 ASSERT (RedistBase < MAX_UINTN);
88
89 PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
90 ASSERT_RETURN_ERROR (PcdStatus);
91 PcdStatus = PcdSet64S (PcdGicRedistributorsBase, RedistBase);
92 ASSERT_RETURN_ERROR (PcdStatus);
93
94 DEBUG ((EFI_D_INFO, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
95 DistBase, RedistBase));
96
97 //
98 // The default implementation of ArmGicArchLib is responsible for enabling
99 // the system register interface on the GICv3 if one is found. So let's do
100 // the same here.
101 //
102 IccSre = ArmGicV3GetControlSystemRegisterEnable ();
103 if (!(IccSre & ICC_SRE_EL2_SRE)) {
104 ArmGicV3SetControlSystemRegisterEnable (IccSre | ICC_SRE_EL2_SRE);
105 IccSre = ArmGicV3GetControlSystemRegisterEnable ();
106 }
107
108 //
109 // Unlike the default implementation, there is no fall through to GICv2
110 // mode if this GICv3 cannot be driven in native mode due to the fact
111 // that the System Register interface is unavailable.
112 //
113 ASSERT (IccSre & ICC_SRE_EL2_SRE);
114
115 mGicArchRevision = ARM_GIC_ARCH_REVISION_3;
116 break;
117
118 case 2:
119 ASSERT (RegSize == 32);
120
121 DistBase = SwapBytes64 (Reg[0]);
122 CpuBase = SwapBytes64 (Reg[2]);
123 ASSERT (DistBase < MAX_UINTN);
124 ASSERT (CpuBase < MAX_UINTN);
125
126 PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
127 ASSERT_RETURN_ERROR (PcdStatus);
128 PcdStatus = PcdSet64S (PcdGicInterruptInterfaceBase, CpuBase);
129 ASSERT_RETURN_ERROR (PcdStatus);
130
131 DEBUG ((EFI_D_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));
132
133 mGicArchRevision = ARM_GIC_ARCH_REVISION_2;
134 break;
135
136 default:
137 DEBUG ((EFI_D_ERROR, "%a: No GIC revision specified!\n", __FUNCTION__));
138 return RETURN_NOT_FOUND;
139 }
140 return RETURN_SUCCESS;
141 }
142
143 ARM_GIC_ARCH_REVISION
144 EFIAPI
145 ArmGicGetSupportedArchRevision (
146 VOID
147 )
148 {
149 return mGicArchRevision;
150 }