| 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 |