master
h 247 lines 7.69 KB
Raw
1 /*
2 * Common base class for GICv5 IRS
3 *
4 * Copyright (c) 2025 Linaro Limited
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #ifndef HW_INTC_ARM_GICV5_COMMON_H
10 #define HW_INTC_ARM_GICV5_COMMON_H
11
12 #include "qom/object.h"
13 #include "hw/core/sysbus.h"
14 #include "hw/intc/arm_gicv5_types.h"
15 #include "target/arm/cpu-qom.h"
16 #include "qemu/error-report.h"
17 #include "system/kvm.h"
18
19 /*
20 * QEMU interface:
21 *
22 * + QOM array property "cpus": CPUState pointers to each CPU
23 * connected to this IRS.
24 * + QOM array property "cpu-iaffids": array of uint32_t giving the
25 * IAFFID for each CPU in the "cpus" property array
26 * + QOM property "irsid": unique identifier for this IRS in the system
27 * (this is IRS_IDR0.IRSID); default is 0
28 * + QOM property "spi-range": total number of SPIs in the system
29 * IRS (this is IRS_IDR5.SPI_RANGE); must be set
30 * + QOM property "spi-base": minimum SPI INTID.ID implemented on this
31 * IRS (this is IRS_IDR7.SPI_BASE); default is 0
32 * + QOM property "spi-irs-range": number of SPI INTID.ID managed on this
33 * IRS (this is IRS_IDR6.SPI_IRS_RANGE); defaults to value of spi-range
34 * + unnamed GPIO inputs: the SPIs handled by this IRS
35 * (so GPIO input 0 is the SPI with INTID SPI_BASE, input 1 is
36 * SPI_BASE + 1, and so on up to SPI_BASE + SPI_IRS_RANGE - 1)
37 *
38 * sysbus MMIO regions (in order matching IRS_IDR0.INT_DOM encoding):
39 * - IRS config frame for the Secure Interrupt Domain
40 * - IRS config frame for the Non-secure Interrupt Domain
41 * - IRS config frame for the EL3 Interrupt Domain
42 * - IRS config frame for the Realm Interrupt Domain
43 *
44 * Note that even if this particular IRS does not implement all four
45 * interrupt domains it will still expose four sysbus MMIO regions.
46 * The regions corresponding to unimplemented domains will always fail
47 * accesses with a decode error. Generally the SoC/board should
48 * probably not map a region for a domain that it configured the IRS
49 * to not implement; the regions are only exposed so that changing
50 * which domains are implemented doesn't reorder which sysbus MMIO
51 * region is which (e.g. NS will always be 1 and EL3 will always be 2).
52 */
53
54 #define TYPE_ARM_GICV5_COMMON "arm-gicv5-common"
55
56 OBJECT_DECLARE_TYPE(GICv5Common, GICv5CommonClass, ARM_GICV5_COMMON)
57
58 /*
59 * This is where we store the state the IRS handles for an SPI.
60 * Generally this corresponds to the spec's list of state in I_JVVTZ
61 * and J_BWPPP. level is a QEMU implementation detail and is where we
62 * store the actual current state of the incoming qemu_irq line.
63 */
64 typedef struct GICv5SPIState {
65 uint32_t iaffid;
66 uint8_t priority;
67 bool level;
68 bool pending;
69 bool active;
70 bool enabled;
71 GICv5HandlingMode hm;
72 GICv5RoutingMode irm;
73 GICv5TriggerMode tm;
74 GICv5Domain domain;
75 } GICv5SPIState;
76
77 /*
78 * This class is for common state that will eventually be shared
79 * between TCG and KVM implementations of the GICv5.
80 */
81 struct GICv5Common {
82 SysBusDevice parent_obj;
83
84 MemoryRegion iomem[NUM_GICV5_DOMAINS];
85
86 uint64_t irs_ist_baser[NUM_GICV5_DOMAINS];
87 uint32_t irs_ist_cfgr[NUM_GICV5_DOMAINS];
88 uint32_t irs_spi_selr[NUM_GICV5_DOMAINS];
89 uint32_t irs_cr0[NUM_GICV5_DOMAINS];
90 uint32_t irs_cr1[NUM_GICV5_DOMAINS];
91 uint32_t irs_pe_selr[NUM_GICV5_DOMAINS];
92
93 /*
94 * Pointer to an array of state information for the SPIs. Array
95 * element 0 is SPI ID s->spi_base, and there are s->spi_irs_range
96 * elements in total. SPI state is not per-domain: SPI is
97 * configurable to a particular domain via IRS_SPI_DOMAINR.
98 */
99 GICv5SPIState *spi;
100
101 /* Bits here are set for each physical interrupt domain implemented */
102 uint8_t implemented_domains;
103
104 /* ID register values: set at realize, constant thereafter */
105 uint32_t irs_idr0;
106 uint32_t irs_idr1;
107 uint32_t irs_idr2;
108 uint32_t irs_idr3;
109 uint32_t irs_idr4;
110 uint32_t irs_idr5;
111 uint32_t irs_idr6;
112 uint32_t irs_idr7;
113 uint32_t irs_iidr;
114 uint32_t irs_aidr;
115
116 /* Properties */
117 uint32_t num_cpus;
118 ARMCPU **cpus;
119 uint32_t num_cpu_iaffids;
120 uint32_t *cpu_iaffids;
121
122 /* MemoryRegion and AS to DMA to/from for in-memory data structures */
123 MemoryRegion *dma;
124 AddressSpace dma_as;
125
126 uint32_t irsid;
127 uint32_t spi_base;
128 uint32_t spi_irs_range;
129 uint32_t spi_range;
130 };
131
132 struct GICv5CommonClass {
133 SysBusDeviceClass parent_class;
134 };
135
136
137 #define IRS_CONFIG_FRAME_SIZE 0x10000
138
139 /*
140 * The architecture allows a GICv5 to implement less than the full
141 * width for various ID fields. QEMU's implementation always supports
142 * the full width of these fields. These constants define our
143 * implementation's limits.
144 */
145
146 /* Number of INTID.ID bits we support */
147 #define QEMU_GICV5_ID_BITS 24
148 /* Min LPI_ID_BITS supported */
149 #define QEMU_GICV5_MIN_LPI_ID_BITS 14
150 /* IAFFID bits supported */
151 #define QEMU_GICV5_IAFFID_BITS 16
152 /* Number of priority bits supported in the IRS */
153 #define QEMU_GICV5_PRI_BITS 5
154
155 /*
156 * There are no TRMs currently published for hardware implementations
157 * of GICv5 that we might identify ourselves as. Instead, we borrow
158 * the Arm Implementer code and pick a fake product ID that is
159 * unlikely to be used by any real Arm hardware.
160 */
161 #define QEMU_GICV5_IMPLEMENTER 0x43b
162 #define QEMU_GICV5_PRODUCTID 0xfff
163 #define QEMU_GICV5_REVISION 0
164 #define QEMU_GICV5_VARIANT 0
165
166 /**
167 * gicv5_common_init_irqs_and_mmio: Create IRQs and MMIO regions for the GICv5
168 * @s: GIC object
169 * @ops: array of MemoryRegionOps that implement the config frames behaviour
170 *
171 * Subclasses of ARM_GICV5_COMMON should call this to create the sysbus
172 * MemoryRegions for the IRS config frames, passing in a four element array
173 * of MemoryRegionOps structs.
174 */
175 void gicv5_common_init_irqs_and_mmio(GICv5Common *cs,
176 qemu_irq_handler handler,
177 const MemoryRegionOps ops[NUM_GICV5_DOMAINS]);
178
179 /**
180 * gicv5_domain_implemented: Return true if this IRS implements this domain
181 * @s: GIC object
182 * @domain: domain to check
183 */
184 static inline bool gicv5_domain_implemented(GICv5Common *cs, GICv5Domain domain)
185 {
186 return cs->implemented_domains & (1 << domain);
187 }
188
189 /**
190 * gicv5_class_name
191 *
192 * Return name of GICv5 class to use depending on whether KVM acceleration is
193 * in use. May throw an error if the chosen implementation is not available.
194 *
195 * Returns: class name to use
196 */
197 static inline const char *gicv5_class_name(void)
198 {
199 /* When we implement KVM GICv5 we might return "kvm-arm-gicv5" here. */
200 if (kvm_enabled()) {
201 error_report("Userspace GICv5 is not supported with KVM");
202 exit(1);
203 }
204 return "arm-gicv5";
205 }
206
207 /**
208 * gicv5_raw_spi_state
209 * @cs: GIC object
210 * @id: INTID of SPI to look up
211 *
212 * Return pointer to the GICv5SPIState for this SPI, or NULL if the
213 * interrupt ID is out of range. This does not do a check that the SPI
214 * is assigned to the right domain: generally you should call it via
215 * some other wrapper that performs an appropriate further check.
216 */
217 static inline GICv5SPIState *gicv5_raw_spi_state(GICv5Common *cs, uint32_t id)
218 {
219 if (id < cs->spi_base || id >= cs->spi_base + cs->spi_irs_range) {
220 return NULL;
221 }
222
223 return cs->spi + (id - cs->spi_base);
224 }
225
226 /**
227 * gicv5_spi_state:
228 * @cs: GIC object
229 * @id: INTID of SPI to look up
230 * @domain: domain to check
231 *
232 * Return pointer to the GICv5SPIState for this SPI, or NULL if the
233 * interrupt is unreachable (which can be because the INTID is out of
234 * range, or because the SPI is configured for a different domain).
235 */
236 static inline GICv5SPIState *gicv5_spi_state(GICv5Common *cs, uint32_t id,
237 GICv5Domain domain)
238 {
239 GICv5SPIState *spi = gicv5_raw_spi_state(cs, id);
240
241 if (!spi || spi->domain != domain) {
242 return NULL;
243 }
244 return spi;
245 }
246
247 #endif