1*67730e6cSSean Christopherson // SPDX-License-Identifier: GPL-2.0 2*67730e6cSSean Christopherson /* 3*67730e6cSSean Christopherson * ARM Generic Interrupt Controller (GIC) v3 support 4*67730e6cSSean Christopherson */ 5*67730e6cSSean Christopherson 6*67730e6cSSean Christopherson #include <linux/sizes.h> 7*67730e6cSSean Christopherson 8*67730e6cSSean Christopherson #include "kvm_util.h" 9*67730e6cSSean Christopherson #include "processor.h" 10*67730e6cSSean Christopherson #include "delay.h" 11*67730e6cSSean Christopherson 12*67730e6cSSean Christopherson #include "gic.h" 13*67730e6cSSean Christopherson #include "gic_v3.h" 14*67730e6cSSean Christopherson #include "gic_private.h" 15*67730e6cSSean Christopherson 16*67730e6cSSean Christopherson #define GICV3_MAX_CPUS 512 17*67730e6cSSean Christopherson 18*67730e6cSSean Christopherson #define GICD_INT_DEF_PRI 0xa0 19*67730e6cSSean Christopherson #define GICD_INT_DEF_PRI_X4 ((GICD_INT_DEF_PRI << 24) |\ 20*67730e6cSSean Christopherson (GICD_INT_DEF_PRI << 16) |\ 21*67730e6cSSean Christopherson (GICD_INT_DEF_PRI << 8) |\ 22*67730e6cSSean Christopherson GICD_INT_DEF_PRI) 23*67730e6cSSean Christopherson 24*67730e6cSSean Christopherson #define ICC_PMR_DEF_PRIO 0xf0 25*67730e6cSSean Christopherson 26*67730e6cSSean Christopherson struct gicv3_data { 27*67730e6cSSean Christopherson unsigned int nr_cpus; 28*67730e6cSSean Christopherson unsigned int nr_spis; 29*67730e6cSSean Christopherson }; 30*67730e6cSSean Christopherson 31*67730e6cSSean Christopherson #define sgi_base_from_redist(redist_base) (redist_base + SZ_64K) 32*67730e6cSSean Christopherson #define DIST_BIT (1U << 31) 33*67730e6cSSean Christopherson 34*67730e6cSSean Christopherson enum gicv3_intid_range { 35*67730e6cSSean Christopherson SGI_RANGE, 36*67730e6cSSean Christopherson PPI_RANGE, 37*67730e6cSSean Christopherson SPI_RANGE, 38*67730e6cSSean Christopherson INVALID_RANGE, 39*67730e6cSSean Christopherson }; 40*67730e6cSSean Christopherson 41*67730e6cSSean Christopherson static struct gicv3_data gicv3_data; 42*67730e6cSSean Christopherson 43*67730e6cSSean Christopherson static void gicv3_gicd_wait_for_rwp(void) 44*67730e6cSSean Christopherson { 45*67730e6cSSean Christopherson unsigned int count = 100000; /* 1s */ 46*67730e6cSSean Christopherson 47*67730e6cSSean Christopherson while (readl(GICD_BASE_GVA + GICD_CTLR) & GICD_CTLR_RWP) { 48*67730e6cSSean Christopherson GUEST_ASSERT(count--); 49*67730e6cSSean Christopherson udelay(10); 50*67730e6cSSean Christopherson } 51*67730e6cSSean Christopherson } 52*67730e6cSSean Christopherson 53*67730e6cSSean Christopherson static inline volatile void *gicr_base_cpu(uint32_t cpu) 54*67730e6cSSean Christopherson { 55*67730e6cSSean Christopherson /* Align all the redistributors sequentially */ 56*67730e6cSSean Christopherson return GICR_BASE_GVA + cpu * SZ_64K * 2; 57*67730e6cSSean Christopherson } 58*67730e6cSSean Christopherson 59*67730e6cSSean Christopherson static void gicv3_gicr_wait_for_rwp(uint32_t cpu) 60*67730e6cSSean Christopherson { 61*67730e6cSSean Christopherson unsigned int count = 100000; /* 1s */ 62*67730e6cSSean Christopherson 63*67730e6cSSean Christopherson while (readl(gicr_base_cpu(cpu) + GICR_CTLR) & GICR_CTLR_RWP) { 64*67730e6cSSean Christopherson GUEST_ASSERT(count--); 65*67730e6cSSean Christopherson udelay(10); 66*67730e6cSSean Christopherson } 67*67730e6cSSean Christopherson } 68*67730e6cSSean Christopherson 69*67730e6cSSean Christopherson static void gicv3_wait_for_rwp(uint32_t cpu_or_dist) 70*67730e6cSSean Christopherson { 71*67730e6cSSean Christopherson if (cpu_or_dist & DIST_BIT) 72*67730e6cSSean Christopherson gicv3_gicd_wait_for_rwp(); 73*67730e6cSSean Christopherson else 74*67730e6cSSean Christopherson gicv3_gicr_wait_for_rwp(cpu_or_dist); 75*67730e6cSSean Christopherson } 76*67730e6cSSean Christopherson 77*67730e6cSSean Christopherson static enum gicv3_intid_range get_intid_range(unsigned int intid) 78*67730e6cSSean Christopherson { 79*67730e6cSSean Christopherson switch (intid) { 80*67730e6cSSean Christopherson case 0 ... 15: 81*67730e6cSSean Christopherson return SGI_RANGE; 82*67730e6cSSean Christopherson case 16 ... 31: 83*67730e6cSSean Christopherson return PPI_RANGE; 84*67730e6cSSean Christopherson case 32 ... 1019: 85*67730e6cSSean Christopherson return SPI_RANGE; 86*67730e6cSSean Christopherson } 87*67730e6cSSean Christopherson 88*67730e6cSSean Christopherson /* We should not be reaching here */ 89*67730e6cSSean Christopherson GUEST_ASSERT(0); 90*67730e6cSSean Christopherson 91*67730e6cSSean Christopherson return INVALID_RANGE; 92*67730e6cSSean Christopherson } 93*67730e6cSSean Christopherson 94*67730e6cSSean Christopherson static uint64_t gicv3_read_iar(void) 95*67730e6cSSean Christopherson { 96*67730e6cSSean Christopherson uint64_t irqstat = read_sysreg_s(SYS_ICC_IAR1_EL1); 97*67730e6cSSean Christopherson 98*67730e6cSSean Christopherson dsb(sy); 99*67730e6cSSean Christopherson return irqstat; 100*67730e6cSSean Christopherson } 101*67730e6cSSean Christopherson 102*67730e6cSSean Christopherson static void gicv3_write_eoir(uint32_t irq) 103*67730e6cSSean Christopherson { 104*67730e6cSSean Christopherson write_sysreg_s(irq, SYS_ICC_EOIR1_EL1); 105*67730e6cSSean Christopherson isb(); 106*67730e6cSSean Christopherson } 107*67730e6cSSean Christopherson 108*67730e6cSSean Christopherson static void gicv3_write_dir(uint32_t irq) 109*67730e6cSSean Christopherson { 110*67730e6cSSean Christopherson write_sysreg_s(irq, SYS_ICC_DIR_EL1); 111*67730e6cSSean Christopherson isb(); 112*67730e6cSSean Christopherson } 113*67730e6cSSean Christopherson 114*67730e6cSSean Christopherson static void gicv3_set_priority_mask(uint64_t mask) 115*67730e6cSSean Christopherson { 116*67730e6cSSean Christopherson write_sysreg_s(mask, SYS_ICC_PMR_EL1); 117*67730e6cSSean Christopherson } 118*67730e6cSSean Christopherson 119*67730e6cSSean Christopherson static void gicv3_set_eoi_split(bool split) 120*67730e6cSSean Christopherson { 121*67730e6cSSean Christopherson uint32_t val; 122*67730e6cSSean Christopherson 123*67730e6cSSean Christopherson /* 124*67730e6cSSean Christopherson * All other fields are read-only, so no need to read CTLR first. In 125*67730e6cSSean Christopherson * fact, the kernel does the same. 126*67730e6cSSean Christopherson */ 127*67730e6cSSean Christopherson val = split ? (1U << 1) : 0; 128*67730e6cSSean Christopherson write_sysreg_s(val, SYS_ICC_CTLR_EL1); 129*67730e6cSSean Christopherson isb(); 130*67730e6cSSean Christopherson } 131*67730e6cSSean Christopherson 132*67730e6cSSean Christopherson uint32_t gicv3_reg_readl(uint32_t cpu_or_dist, uint64_t offset) 133*67730e6cSSean Christopherson { 134*67730e6cSSean Christopherson volatile void *base = cpu_or_dist & DIST_BIT ? GICD_BASE_GVA 135*67730e6cSSean Christopherson : sgi_base_from_redist(gicr_base_cpu(cpu_or_dist)); 136*67730e6cSSean Christopherson return readl(base + offset); 137*67730e6cSSean Christopherson } 138*67730e6cSSean Christopherson 139*67730e6cSSean Christopherson void gicv3_reg_writel(uint32_t cpu_or_dist, uint64_t offset, uint32_t reg_val) 140*67730e6cSSean Christopherson { 141*67730e6cSSean Christopherson volatile void *base = cpu_or_dist & DIST_BIT ? GICD_BASE_GVA 142*67730e6cSSean Christopherson : sgi_base_from_redist(gicr_base_cpu(cpu_or_dist)); 143*67730e6cSSean Christopherson writel(reg_val, base + offset); 144*67730e6cSSean Christopherson } 145*67730e6cSSean Christopherson 146*67730e6cSSean Christopherson uint32_t gicv3_getl_fields(uint32_t cpu_or_dist, uint64_t offset, uint32_t mask) 147*67730e6cSSean Christopherson { 148*67730e6cSSean Christopherson return gicv3_reg_readl(cpu_or_dist, offset) & mask; 149*67730e6cSSean Christopherson } 150*67730e6cSSean Christopherson 151*67730e6cSSean Christopherson void gicv3_setl_fields(uint32_t cpu_or_dist, uint64_t offset, 152*67730e6cSSean Christopherson uint32_t mask, uint32_t reg_val) 153*67730e6cSSean Christopherson { 154*67730e6cSSean Christopherson uint32_t tmp = gicv3_reg_readl(cpu_or_dist, offset) & ~mask; 155*67730e6cSSean Christopherson 156*67730e6cSSean Christopherson tmp |= (reg_val & mask); 157*67730e6cSSean Christopherson gicv3_reg_writel(cpu_or_dist, offset, tmp); 158*67730e6cSSean Christopherson } 159*67730e6cSSean Christopherson 160*67730e6cSSean Christopherson /* 161*67730e6cSSean Christopherson * We use a single offset for the distributor and redistributor maps as they 162*67730e6cSSean Christopherson * have the same value in both. The only exceptions are registers that only 163*67730e6cSSean Christopherson * exist in one and not the other, like GICR_WAKER that doesn't exist in the 164*67730e6cSSean Christopherson * distributor map. Such registers are conveniently marked as reserved in the 165*67730e6cSSean Christopherson * map that doesn't implement it; like GICR_WAKER's offset of 0x0014 being 166*67730e6cSSean Christopherson * marked as "Reserved" in the Distributor map. 167*67730e6cSSean Christopherson */ 168*67730e6cSSean Christopherson static void gicv3_access_reg(uint32_t intid, uint64_t offset, 169*67730e6cSSean Christopherson uint32_t reg_bits, uint32_t bits_per_field, 170*67730e6cSSean Christopherson bool write, uint32_t *val) 171*67730e6cSSean Christopherson { 172*67730e6cSSean Christopherson uint32_t cpu = guest_get_vcpuid(); 173*67730e6cSSean Christopherson enum gicv3_intid_range intid_range = get_intid_range(intid); 174*67730e6cSSean Christopherson uint32_t fields_per_reg, index, mask, shift; 175*67730e6cSSean Christopherson uint32_t cpu_or_dist; 176*67730e6cSSean Christopherson 177*67730e6cSSean Christopherson GUEST_ASSERT(bits_per_field <= reg_bits); 178*67730e6cSSean Christopherson GUEST_ASSERT(!write || *val < (1U << bits_per_field)); 179*67730e6cSSean Christopherson /* 180*67730e6cSSean Christopherson * This function does not support 64 bit accesses. Just asserting here 181*67730e6cSSean Christopherson * until we implement readq/writeq. 182*67730e6cSSean Christopherson */ 183*67730e6cSSean Christopherson GUEST_ASSERT(reg_bits == 32); 184*67730e6cSSean Christopherson 185*67730e6cSSean Christopherson fields_per_reg = reg_bits / bits_per_field; 186*67730e6cSSean Christopherson index = intid % fields_per_reg; 187*67730e6cSSean Christopherson shift = index * bits_per_field; 188*67730e6cSSean Christopherson mask = ((1U << bits_per_field) - 1) << shift; 189*67730e6cSSean Christopherson 190*67730e6cSSean Christopherson /* Set offset to the actual register holding intid's config. */ 191*67730e6cSSean Christopherson offset += (intid / fields_per_reg) * (reg_bits / 8); 192*67730e6cSSean Christopherson 193*67730e6cSSean Christopherson cpu_or_dist = (intid_range == SPI_RANGE) ? DIST_BIT : cpu; 194*67730e6cSSean Christopherson 195*67730e6cSSean Christopherson if (write) 196*67730e6cSSean Christopherson gicv3_setl_fields(cpu_or_dist, offset, mask, *val << shift); 197*67730e6cSSean Christopherson *val = gicv3_getl_fields(cpu_or_dist, offset, mask) >> shift; 198*67730e6cSSean Christopherson } 199*67730e6cSSean Christopherson 200*67730e6cSSean Christopherson static void gicv3_write_reg(uint32_t intid, uint64_t offset, 201*67730e6cSSean Christopherson uint32_t reg_bits, uint32_t bits_per_field, uint32_t val) 202*67730e6cSSean Christopherson { 203*67730e6cSSean Christopherson gicv3_access_reg(intid, offset, reg_bits, 204*67730e6cSSean Christopherson bits_per_field, true, &val); 205*67730e6cSSean Christopherson } 206*67730e6cSSean Christopherson 207*67730e6cSSean Christopherson static uint32_t gicv3_read_reg(uint32_t intid, uint64_t offset, 208*67730e6cSSean Christopherson uint32_t reg_bits, uint32_t bits_per_field) 209*67730e6cSSean Christopherson { 210*67730e6cSSean Christopherson uint32_t val; 211*67730e6cSSean Christopherson 212*67730e6cSSean Christopherson gicv3_access_reg(intid, offset, reg_bits, 213*67730e6cSSean Christopherson bits_per_field, false, &val); 214*67730e6cSSean Christopherson return val; 215*67730e6cSSean Christopherson } 216*67730e6cSSean Christopherson 217*67730e6cSSean Christopherson static void gicv3_set_priority(uint32_t intid, uint32_t prio) 218*67730e6cSSean Christopherson { 219*67730e6cSSean Christopherson gicv3_write_reg(intid, GICD_IPRIORITYR, 32, 8, prio); 220*67730e6cSSean Christopherson } 221*67730e6cSSean Christopherson 222*67730e6cSSean Christopherson /* Sets the intid to be level-sensitive or edge-triggered. */ 223*67730e6cSSean Christopherson static void gicv3_irq_set_config(uint32_t intid, bool is_edge) 224*67730e6cSSean Christopherson { 225*67730e6cSSean Christopherson uint32_t val; 226*67730e6cSSean Christopherson 227*67730e6cSSean Christopherson /* N/A for private interrupts. */ 228*67730e6cSSean Christopherson GUEST_ASSERT(get_intid_range(intid) == SPI_RANGE); 229*67730e6cSSean Christopherson val = is_edge ? 2 : 0; 230*67730e6cSSean Christopherson gicv3_write_reg(intid, GICD_ICFGR, 32, 2, val); 231*67730e6cSSean Christopherson } 232*67730e6cSSean Christopherson 233*67730e6cSSean Christopherson static void gicv3_irq_enable(uint32_t intid) 234*67730e6cSSean Christopherson { 235*67730e6cSSean Christopherson bool is_spi = get_intid_range(intid) == SPI_RANGE; 236*67730e6cSSean Christopherson uint32_t cpu = guest_get_vcpuid(); 237*67730e6cSSean Christopherson 238*67730e6cSSean Christopherson gicv3_write_reg(intid, GICD_ISENABLER, 32, 1, 1); 239*67730e6cSSean Christopherson gicv3_wait_for_rwp(is_spi ? DIST_BIT : cpu); 240*67730e6cSSean Christopherson } 241*67730e6cSSean Christopherson 242*67730e6cSSean Christopherson static void gicv3_irq_disable(uint32_t intid) 243*67730e6cSSean Christopherson { 244*67730e6cSSean Christopherson bool is_spi = get_intid_range(intid) == SPI_RANGE; 245*67730e6cSSean Christopherson uint32_t cpu = guest_get_vcpuid(); 246*67730e6cSSean Christopherson 247*67730e6cSSean Christopherson gicv3_write_reg(intid, GICD_ICENABLER, 32, 1, 1); 248*67730e6cSSean Christopherson gicv3_wait_for_rwp(is_spi ? DIST_BIT : cpu); 249*67730e6cSSean Christopherson } 250*67730e6cSSean Christopherson 251*67730e6cSSean Christopherson static void gicv3_irq_set_active(uint32_t intid) 252*67730e6cSSean Christopherson { 253*67730e6cSSean Christopherson gicv3_write_reg(intid, GICD_ISACTIVER, 32, 1, 1); 254*67730e6cSSean Christopherson } 255*67730e6cSSean Christopherson 256*67730e6cSSean Christopherson static void gicv3_irq_clear_active(uint32_t intid) 257*67730e6cSSean Christopherson { 258*67730e6cSSean Christopherson gicv3_write_reg(intid, GICD_ICACTIVER, 32, 1, 1); 259*67730e6cSSean Christopherson } 260*67730e6cSSean Christopherson 261*67730e6cSSean Christopherson static bool gicv3_irq_get_active(uint32_t intid) 262*67730e6cSSean Christopherson { 263*67730e6cSSean Christopherson return gicv3_read_reg(intid, GICD_ISACTIVER, 32, 1); 264*67730e6cSSean Christopherson } 265*67730e6cSSean Christopherson 266*67730e6cSSean Christopherson static void gicv3_irq_set_pending(uint32_t intid) 267*67730e6cSSean Christopherson { 268*67730e6cSSean Christopherson gicv3_write_reg(intid, GICD_ISPENDR, 32, 1, 1); 269*67730e6cSSean Christopherson } 270*67730e6cSSean Christopherson 271*67730e6cSSean Christopherson static void gicv3_irq_clear_pending(uint32_t intid) 272*67730e6cSSean Christopherson { 273*67730e6cSSean Christopherson gicv3_write_reg(intid, GICD_ICPENDR, 32, 1, 1); 274*67730e6cSSean Christopherson } 275*67730e6cSSean Christopherson 276*67730e6cSSean Christopherson static bool gicv3_irq_get_pending(uint32_t intid) 277*67730e6cSSean Christopherson { 278*67730e6cSSean Christopherson return gicv3_read_reg(intid, GICD_ISPENDR, 32, 1); 279*67730e6cSSean Christopherson } 280*67730e6cSSean Christopherson 281*67730e6cSSean Christopherson static void gicv3_enable_redist(volatile void *redist_base) 282*67730e6cSSean Christopherson { 283*67730e6cSSean Christopherson uint32_t val = readl(redist_base + GICR_WAKER); 284*67730e6cSSean Christopherson unsigned int count = 100000; /* 1s */ 285*67730e6cSSean Christopherson 286*67730e6cSSean Christopherson val &= ~GICR_WAKER_ProcessorSleep; 287*67730e6cSSean Christopherson writel(val, redist_base + GICR_WAKER); 288*67730e6cSSean Christopherson 289*67730e6cSSean Christopherson /* Wait until the processor is 'active' */ 290*67730e6cSSean Christopherson while (readl(redist_base + GICR_WAKER) & GICR_WAKER_ChildrenAsleep) { 291*67730e6cSSean Christopherson GUEST_ASSERT(count--); 292*67730e6cSSean Christopherson udelay(10); 293*67730e6cSSean Christopherson } 294*67730e6cSSean Christopherson } 295*67730e6cSSean Christopherson 296*67730e6cSSean Christopherson static void gicv3_cpu_init(unsigned int cpu) 297*67730e6cSSean Christopherson { 298*67730e6cSSean Christopherson volatile void *sgi_base; 299*67730e6cSSean Christopherson unsigned int i; 300*67730e6cSSean Christopherson volatile void *redist_base_cpu; 301*67730e6cSSean Christopherson 302*67730e6cSSean Christopherson GUEST_ASSERT(cpu < gicv3_data.nr_cpus); 303*67730e6cSSean Christopherson 304*67730e6cSSean Christopherson redist_base_cpu = gicr_base_cpu(cpu); 305*67730e6cSSean Christopherson sgi_base = sgi_base_from_redist(redist_base_cpu); 306*67730e6cSSean Christopherson 307*67730e6cSSean Christopherson gicv3_enable_redist(redist_base_cpu); 308*67730e6cSSean Christopherson 309*67730e6cSSean Christopherson /* 310*67730e6cSSean Christopherson * Mark all the SGI and PPI interrupts as non-secure Group-1. 311*67730e6cSSean Christopherson * Also, deactivate and disable them. 312*67730e6cSSean Christopherson */ 313*67730e6cSSean Christopherson writel(~0, sgi_base + GICR_IGROUPR0); 314*67730e6cSSean Christopherson writel(~0, sgi_base + GICR_ICACTIVER0); 315*67730e6cSSean Christopherson writel(~0, sgi_base + GICR_ICENABLER0); 316*67730e6cSSean Christopherson 317*67730e6cSSean Christopherson /* Set a default priority for all the SGIs and PPIs */ 318*67730e6cSSean Christopherson for (i = 0; i < 32; i += 4) 319*67730e6cSSean Christopherson writel(GICD_INT_DEF_PRI_X4, 320*67730e6cSSean Christopherson sgi_base + GICR_IPRIORITYR0 + i); 321*67730e6cSSean Christopherson 322*67730e6cSSean Christopherson gicv3_gicr_wait_for_rwp(cpu); 323*67730e6cSSean Christopherson 324*67730e6cSSean Christopherson /* Enable the GIC system register (ICC_*) access */ 325*67730e6cSSean Christopherson write_sysreg_s(read_sysreg_s(SYS_ICC_SRE_EL1) | ICC_SRE_EL1_SRE, 326*67730e6cSSean Christopherson SYS_ICC_SRE_EL1); 327*67730e6cSSean Christopherson 328*67730e6cSSean Christopherson /* Set a default priority threshold */ 329*67730e6cSSean Christopherson write_sysreg_s(ICC_PMR_DEF_PRIO, SYS_ICC_PMR_EL1); 330*67730e6cSSean Christopherson 331*67730e6cSSean Christopherson /* Enable non-secure Group-1 interrupts */ 332*67730e6cSSean Christopherson write_sysreg_s(ICC_IGRPEN1_EL1_MASK, SYS_ICC_IGRPEN1_EL1); 333*67730e6cSSean Christopherson } 334*67730e6cSSean Christopherson 335*67730e6cSSean Christopherson static void gicv3_dist_init(void) 336*67730e6cSSean Christopherson { 337*67730e6cSSean Christopherson unsigned int i; 338*67730e6cSSean Christopherson 339*67730e6cSSean Christopherson /* Disable the distributor until we set things up */ 340*67730e6cSSean Christopherson writel(0, GICD_BASE_GVA + GICD_CTLR); 341*67730e6cSSean Christopherson gicv3_gicd_wait_for_rwp(); 342*67730e6cSSean Christopherson 343*67730e6cSSean Christopherson /* 344*67730e6cSSean Christopherson * Mark all the SPI interrupts as non-secure Group-1. 345*67730e6cSSean Christopherson * Also, deactivate and disable them. 346*67730e6cSSean Christopherson */ 347*67730e6cSSean Christopherson for (i = 32; i < gicv3_data.nr_spis; i += 32) { 348*67730e6cSSean Christopherson writel(~0, GICD_BASE_GVA + GICD_IGROUPR + i / 8); 349*67730e6cSSean Christopherson writel(~0, GICD_BASE_GVA + GICD_ICACTIVER + i / 8); 350*67730e6cSSean Christopherson writel(~0, GICD_BASE_GVA + GICD_ICENABLER + i / 8); 351*67730e6cSSean Christopherson } 352*67730e6cSSean Christopherson 353*67730e6cSSean Christopherson /* Set a default priority for all the SPIs */ 354*67730e6cSSean Christopherson for (i = 32; i < gicv3_data.nr_spis; i += 4) 355*67730e6cSSean Christopherson writel(GICD_INT_DEF_PRI_X4, 356*67730e6cSSean Christopherson GICD_BASE_GVA + GICD_IPRIORITYR + i); 357*67730e6cSSean Christopherson 358*67730e6cSSean Christopherson /* Wait for the settings to sync-in */ 359*67730e6cSSean Christopherson gicv3_gicd_wait_for_rwp(); 360*67730e6cSSean Christopherson 361*67730e6cSSean Christopherson /* Finally, enable the distributor globally with ARE */ 362*67730e6cSSean Christopherson writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | 363*67730e6cSSean Christopherson GICD_CTLR_ENABLE_G1, GICD_BASE_GVA + GICD_CTLR); 364*67730e6cSSean Christopherson gicv3_gicd_wait_for_rwp(); 365*67730e6cSSean Christopherson } 366*67730e6cSSean Christopherson 367*67730e6cSSean Christopherson static void gicv3_init(unsigned int nr_cpus) 368*67730e6cSSean Christopherson { 369*67730e6cSSean Christopherson GUEST_ASSERT(nr_cpus <= GICV3_MAX_CPUS); 370*67730e6cSSean Christopherson 371*67730e6cSSean Christopherson gicv3_data.nr_cpus = nr_cpus; 372*67730e6cSSean Christopherson gicv3_data.nr_spis = GICD_TYPER_SPIS( 373*67730e6cSSean Christopherson readl(GICD_BASE_GVA + GICD_TYPER)); 374*67730e6cSSean Christopherson if (gicv3_data.nr_spis > 1020) 375*67730e6cSSean Christopherson gicv3_data.nr_spis = 1020; 376*67730e6cSSean Christopherson 377*67730e6cSSean Christopherson /* 378*67730e6cSSean Christopherson * Initialize only the distributor for now. 379*67730e6cSSean Christopherson * The redistributor and CPU interfaces are initialized 380*67730e6cSSean Christopherson * later for every PE. 381*67730e6cSSean Christopherson */ 382*67730e6cSSean Christopherson gicv3_dist_init(); 383*67730e6cSSean Christopherson } 384*67730e6cSSean Christopherson 385*67730e6cSSean Christopherson const struct gic_common_ops gicv3_ops = { 386*67730e6cSSean Christopherson .gic_init = gicv3_init, 387*67730e6cSSean Christopherson .gic_cpu_init = gicv3_cpu_init, 388*67730e6cSSean Christopherson .gic_irq_enable = gicv3_irq_enable, 389*67730e6cSSean Christopherson .gic_irq_disable = gicv3_irq_disable, 390*67730e6cSSean Christopherson .gic_read_iar = gicv3_read_iar, 391*67730e6cSSean Christopherson .gic_write_eoir = gicv3_write_eoir, 392*67730e6cSSean Christopherson .gic_write_dir = gicv3_write_dir, 393*67730e6cSSean Christopherson .gic_set_priority_mask = gicv3_set_priority_mask, 394*67730e6cSSean Christopherson .gic_set_eoi_split = gicv3_set_eoi_split, 395*67730e6cSSean Christopherson .gic_set_priority = gicv3_set_priority, 396*67730e6cSSean Christopherson .gic_irq_set_active = gicv3_irq_set_active, 397*67730e6cSSean Christopherson .gic_irq_clear_active = gicv3_irq_clear_active, 398*67730e6cSSean Christopherson .gic_irq_get_active = gicv3_irq_get_active, 399*67730e6cSSean Christopherson .gic_irq_set_pending = gicv3_irq_set_pending, 400*67730e6cSSean Christopherson .gic_irq_clear_pending = gicv3_irq_clear_pending, 401*67730e6cSSean Christopherson .gic_irq_get_pending = gicv3_irq_get_pending, 402*67730e6cSSean Christopherson .gic_irq_set_config = gicv3_irq_set_config, 403*67730e6cSSean Christopherson }; 404*67730e6cSSean Christopherson 405*67730e6cSSean Christopherson void gic_rdist_enable_lpis(vm_paddr_t cfg_table, size_t cfg_table_size, 406*67730e6cSSean Christopherson vm_paddr_t pend_table) 407*67730e6cSSean Christopherson { 408*67730e6cSSean Christopherson volatile void *rdist_base = gicr_base_cpu(guest_get_vcpuid()); 409*67730e6cSSean Christopherson 410*67730e6cSSean Christopherson u32 ctlr; 411*67730e6cSSean Christopherson u64 val; 412*67730e6cSSean Christopherson 413*67730e6cSSean Christopherson val = (cfg_table | 414*67730e6cSSean Christopherson GICR_PROPBASER_InnerShareable | 415*67730e6cSSean Christopherson GICR_PROPBASER_RaWaWb | 416*67730e6cSSean Christopherson ((ilog2(cfg_table_size) - 1) & GICR_PROPBASER_IDBITS_MASK)); 417*67730e6cSSean Christopherson writeq_relaxed(val, rdist_base + GICR_PROPBASER); 418*67730e6cSSean Christopherson 419*67730e6cSSean Christopherson val = (pend_table | 420*67730e6cSSean Christopherson GICR_PENDBASER_InnerShareable | 421*67730e6cSSean Christopherson GICR_PENDBASER_RaWaWb); 422*67730e6cSSean Christopherson writeq_relaxed(val, rdist_base + GICR_PENDBASER); 423*67730e6cSSean Christopherson 424*67730e6cSSean Christopherson ctlr = readl_relaxed(rdist_base + GICR_CTLR); 425*67730e6cSSean Christopherson ctlr |= GICR_CTLR_ENABLE_LPIS; 426*67730e6cSSean Christopherson writel_relaxed(ctlr, rdist_base + GICR_CTLR); 427*67730e6cSSean Christopherson } 428