History

irqchip/gic-v3: Add ESPI range support

Add the required support for the ESPI range, which behave exactly like the SPIs of old, only with new funky INTIDs.

Marc Zyngier committed 7 years ago

Commit 211bddd1 parent 86624652 files · +85 −17Browse files

Unified · Split

2 files
  1. drivers/irqchip/irq-gic-v3.c +69 −16
  2. include/linux/irqchip/arm-gic-v3.h +16 −1
drivers/irqchip/irq-gic-v3.c+69−16
@@ -51,13 +51,16 @@ struct gic_chip_data { · 50 unmodified lines
51 u32 nr_redist_regions;51 u32 nr_redist_regions;
52 u64 flags;52 u64 flags;
53 bool has_rss;53 bool has_rss;
54 unsigned int irq_nr;
55 struct partition_desc *ppi_descs[16];54 struct partition_desc *ppi_descs[16];
56};55};
57 56
58static struct gic_chip_data gic_data __read_mostly;57static struct gic_chip_data gic_data __read_mostly;
59static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);58static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
60 59
60#define GIC_ID_NR (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
61#define GIC_LINE_NR max(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U)
62#define GIC_ESPI_NR GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
63
61/*64/*
62 * The behaviours of RPR and PMR registers differ depending on the value of65 * The behaviours of RPR and PMR registers differ depending on the value of
63 * SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the66 * SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the
@@ -100,6 +103,7 @@ static DEFINE_PER_CPU(bool, has_rss); · 36 unmodified lines
100enum gic_intid_range {103enum gic_intid_range {
101 PPI_RANGE,104 PPI_RANGE,
102 SPI_RANGE,105 SPI_RANGE,
106 ESPI_RANGE,
103 LPI_RANGE,107 LPI_RANGE,
104 __INVALID_RANGE__108 __INVALID_RANGE__
105};109};
@@ -111,6 +115,8 @@ static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq) · 5 unmodified lines
111 return PPI_RANGE;115 return PPI_RANGE;
112 case 32 ... 1019:116 case 32 ... 1019:
113 return SPI_RANGE;117 return SPI_RANGE;
118 case ESPI_BASE_INTID ... (ESPI_BASE_INTID + 1023):
119 return ESPI_RANGE;
114 case 8192 ... GENMASK(23, 0):120 case 8192 ... GENMASK(23, 0):
115 return LPI_RANGE;121 return LPI_RANGE;
116 default:122 default:
@@ -141,6 +147,7 @@ static inline void __iomem *gic_dist_base(struct irq_data *d) · 24 unmodified lines
141 return gic_data_rdist_sgi_base();147 return gic_data_rdist_sgi_base();
142 148
143 case SPI_RANGE:149 case SPI_RANGE:
150 case ESPI_RANGE:
144 /* SPI -> dist_base */151 /* SPI -> dist_base */
145 return gic_data.dist_base;152 return gic_data.dist_base;
146 153
@@ -234,6 +241,31 @@ static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index) · 87 unmodified lines
234 case SPI_RANGE:241 case SPI_RANGE:
235 *index = d->hwirq;242 *index = d->hwirq;
236 return offset;243 return offset;
244 case ESPI_RANGE:
245 *index = d->hwirq - ESPI_BASE_INTID;
246 switch (offset) {
247 case GICD_ISENABLER:
248 return GICD_ISENABLERnE;
249 case GICD_ICENABLER:
250 return GICD_ICENABLERnE;
251 case GICD_ISPENDR:
252 return GICD_ISPENDRnE;
253 case GICD_ICPENDR:
254 return GICD_ICPENDRnE;
255 case GICD_ISACTIVER:
256 return GICD_ISACTIVERnE;
257 case GICD_ICACTIVER:
258 return GICD_ICACTIVERnE;
259 case GICD_IPRIORITYR:
260 return GICD_IPRIORITYRnE;
261 case GICD_ICFGR:
262 return GICD_ICFGRnE;
263 case GICD_IROUTER:
264 return GICD_IROUTERnE;
265 default:
266 break;
267 }
268 break;
237 default:269 default:
238 break;270 break;
239 }271 }
@@ -316,7 +348,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d, · 76 unmodified lines
316{348{
317 u32 reg;349 u32 reg;
318 350
319 if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */351 if (d->hwirq >= 8192) /* PPI/SPI only */
320 return -EINVAL;352 return -EINVAL;
321 353
322 switch (which) {354 switch (which) {
@@ -343,7 +375,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d, · 20 unmodified lines
343static int gic_irq_get_irqchip_state(struct irq_data *d,375static int gic_irq_get_irqchip_state(struct irq_data *d,
344 enum irqchip_irq_state which, bool *val)376 enum irqchip_irq_state which, bool *val)
345{377{
346 if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */378 if (d->hwirq >= 8192) /* PPI/SPI only */
347 return -EINVAL;379 return -EINVAL;
348 380
349 switch (which) {381 switch (which) {
@@ -567,7 +599,12 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs · 217 unmodified lines
567 gic_arch_enable_irqs();599 gic_arch_enable_irqs();
568 }600 }
569 601
570 if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) {602 /* Check for special IDs first */
603 if ((irqnr >= 1020 && irqnr <= 1023))
604 return;
605
606 /* Treat anything but SGIs in a uniform way */
607 if (likely(irqnr > 15)) {
571 int err;608 int err;
572 609
573 if (static_branch_likely(&supports_deactivate_key))610 if (static_branch_likely(&supports_deactivate_key))
@@ -655,10 +692,26 @@ static void __init gic_dist_init(void) · 81 unmodified lines
655 * do the right thing if the kernel is running in secure mode,692 * do the right thing if the kernel is running in secure mode,
656 * but that's not the intended use case anyway.693 * but that's not the intended use case anyway.
657 */694 */
658 for (i = 32; i < gic_data.irq_nr; i += 32)695 for (i = 32; i < GIC_LINE_NR; i += 32)
659 writel_relaxed(~0, base + GICD_IGROUPR + i / 8);696 writel_relaxed(~0, base + GICD_IGROUPR + i / 8);
660 697
661 gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);698 /* Extended SPI range, not handled by the GICv2/GICv3 common code */
699 for (i = 0; i < GIC_ESPI_NR; i += 32) {
700 writel_relaxed(~0U, base + GICD_ICENABLERnE + i / 8);
701 writel_relaxed(~0U, base + GICD_ICACTIVERnE + i / 8);
702 }
703
704 for (i = 0; i < GIC_ESPI_NR; i += 32)
705 writel_relaxed(~0U, base + GICD_IGROUPRnE + i / 8);
706
707 for (i = 0; i < GIC_ESPI_NR; i += 16)
708 writel_relaxed(0, base + GICD_ICFGRnE + i / 4);
709
710 for (i = 0; i < GIC_ESPI_NR; i += 4)
711 writel_relaxed(GICD_INT_DEF_PRI_X4, base + GICD_IPRIORITYRnE + i);
712
713 /* Now do the common stuff, and wait for the distributor to drain */
714 gic_dist_config(base, GIC_LINE_NR, gic_dist_wait_for_rwp);
662 715
663 /* Enable distributor with ARE, Group1 */716 /* Enable distributor with ARE, Group1 */
664 writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,717 writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
@@ -669,8 +722,11 @@ static void __init gic_dist_init(void) · 4 unmodified lines
669 * enabled.722 * enabled.
670 */723 */
671 affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));724 affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
672 for (i = 32; i < gic_data.irq_nr; i++)725 for (i = 32; i < GIC_LINE_NR; i++)
673 gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);726 gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);
727
728 for (i = 0; i < GIC_ESPI_NR; i++)
729 gic_write_irouter(affinity, base + GICD_IROUTERnE + i * 8);
674}730}
675 731
676static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *))732static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *))
@@ -1134,8 +1190,6 @@ static struct irq_chip gic_eoimode1_chip = { · 457 unmodified lines
1134 IRQCHIP_MASK_ON_SUSPEND,1190 IRQCHIP_MASK_ON_SUSPEND,
1135};1191};
1136 1192
1137#define GIC_ID_NR (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
1138
1139static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,1193static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
1140 irq_hw_number_t hw)1194 irq_hw_number_t hw)
1141{1195{
@@ -1153,6 +1207,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, · 11 unmodified lines
1153 break;1207 break;
1154 1208
1155 case SPI_RANGE:1209 case SPI_RANGE:
1210 case ESPI_RANGE:
1156 irq_domain_set_info(d, irq, hw, chip, d->host_data,1211 irq_domain_set_info(d, irq, hw, chip, d->host_data,
1157 handle_fasteoi_irq, NULL, NULL);1212 handle_fasteoi_irq, NULL, NULL);
1158 irq_set_probe(irq);1213 irq_set_probe(irq);
@@ -1192,6 +1247,9 @@ static int gic_irq_domain_translate(struct irq_domain *d, · 33 unmodified lines
1192 case GIC_IRQ_TYPE_PARTITION:1247 case GIC_IRQ_TYPE_PARTITION:
1193 *hwirq = fwspec->param[1] + 16;1248 *hwirq = fwspec->param[1] + 16;
1194 break;1249 break;
1250 case 2: /* ESPI */
1251 *hwirq = fwspec->param[1] + ESPI_BASE_INTID;
1252 break;
1195 case GIC_IRQ_TYPE_LPI: /* LPI */1253 case GIC_IRQ_TYPE_LPI: /* LPI */
1196 *hwirq = fwspec->param[1];1254 *hwirq = fwspec->param[1];
1197 break;1255 break;
@@ -1346,7 +1404,6 @@ static int __init gic_init_bases(void __iomem *dist_base, · 148 unmodified lines
1346 struct fwnode_handle *handle)1404 struct fwnode_handle *handle)
1347{1405{
1348 u32 typer;1406 u32 typer;
1349 int gic_irqs;
1350 int err;1407 int err;
1351 1408
1352 if (!is_hyp_mode_available())1409 if (!is_hyp_mode_available())
@@ -1363,15 +1420,11 @@ static int __init gic_init_bases(void __iomem *dist_base, · 10 unmodified lines
1363 1420
1364 /*1421 /*
1365 * Find out how many interrupts are supported.1422 * Find out how many interrupts are supported.
1366 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
1367 */1423 */
1368 typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);1424 typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
1369 gic_data.rdists.gicd_typer = typer;1425 gic_data.rdists.gicd_typer = typer;
1370 gic_irqs = GICD_TYPER_IRQS(typer);1426 pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32);
1371 if (gic_irqs > 1020)1427 pr_info("%d Extended SPIs implemented\n", GIC_ESPI_NR);
1372 gic_irqs = 1020;
1373 gic_data.irq_nr = gic_irqs;
1374
1375 gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,1428 gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
1376 &gic_data);1429 &gic_data);
1377 irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);1430 irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);
include/linux/irqchip/arm-gic-v3.h+16−1
@@ -30,10 +30,22 @@ · 29 unmodified lines
30#define GICD_ICFGR 0x0C0030#define GICD_ICFGR 0x0C00
31#define GICD_IGRPMODR 0x0D0031#define GICD_IGRPMODR 0x0D00
32#define GICD_NSACR 0x0E0032#define GICD_NSACR 0x0E00
33#define GICD_IGROUPRnE 0x1000
34#define GICD_ISENABLERnE 0x1200
35#define GICD_ICENABLERnE 0x1400
36#define GICD_ISPENDRnE 0x1600
37#define GICD_ICPENDRnE 0x1800
38#define GICD_ISACTIVERnE 0x1A00
39#define GICD_ICACTIVERnE 0x1C00
40#define GICD_IPRIORITYRnE 0x2000
41#define GICD_ICFGRnE 0x3000
33#define GICD_IROUTER 0x600042#define GICD_IROUTER 0x6000
43#define GICD_IROUTERnE 0x8000
34#define GICD_IDREGS 0xFFD044#define GICD_IDREGS 0xFFD0
35#define GICD_PIDR2 0xFFE845#define GICD_PIDR2 0xFFE8
36 46
47#define ESPI_BASE_INTID 4096
48
37/*49/*
38 * Those registers are actually from GICv2, but the spec demands that they50 * Those registers are actually from GICv2, but the spec demands that they
39 * are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3).51 * are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3).
@@ -69,10 +81,13 @@ · 29 unmodified lines
69#define GICD_TYPER_RSS (1U << 26)81#define GICD_TYPER_RSS (1U << 26)
70#define GICD_TYPER_LPIS (1U << 17)82#define GICD_TYPER_LPIS (1U << 17)
71#define GICD_TYPER_MBIS (1U << 16)83#define GICD_TYPER_MBIS (1U << 16)
84#define GICD_TYPER_ESPI (1U << 8)
72 85
73#define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1)86#define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1)
74#define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1)87#define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1)
75#define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32)88#define GICD_TYPER_SPIS(typer) ((((typer) & 0x1f) + 1) * 32)
89#define GICD_TYPER_ESPIS(typer) \
90 (((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
76 91
77#define GICD_IROUTER_SPI_MODE_ONE (0U << 31)92#define GICD_IROUTER_SPI_MODE_ONE (0U << 31)
78#define GICD_IROUTER_SPI_MODE_ANY (1U << 31)93#define GICD_IROUTER_SPI_MODE_ANY (1U << 31)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t