Skip to content

Commit a02026b

Browse files
diandersctmarinas
authored andcommitted
irqchip/gic-v3: Enable support for SGIs to act as NMIs
As of commit 6abbd69 ("irqchip/gic, gic-v3: Make SGIs use handle_percpu_devid_irq()") SGIs are treated the same as PPIs/EPPIs and use handle_percpu_devid_irq() by default. Unfortunately, handle_percpu_devid_irq() isn't NMI safe, and so to run in an NMI context those should use handle_percpu_devid_fasteoi_nmi(). In order to accomplish this, we just have to make room for SGIs in the array of refcounts that keeps track of which interrupts are set as NMI. We also rename the array and create a new indexing scheme that accounts for SGIs. Also, enable NMI support prior to gic_smp_init() as allocation of SGIs as IRQs/NMIs happen as part of this routine. Co-developed-by: Sumit Garg <[email protected]> Signed-off-by: Sumit Garg <[email protected]> Acked-by: Mark Rutland <[email protected]> Tested-by: Chen-Yu Tsai <[email protected]> Signed-off-by: Douglas Anderson <[email protected]> Acked-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/20230906090246.v13.1.I1223c11c88937bd0cbd9b086d4ef216985797302@changeid Signed-off-by: Catalin Marinas <[email protected]>
1 parent 6465e26 commit a02026b

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

drivers/irqchip/irq-gic-v3.c

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
7878
#define GIC_LINE_NR min(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U)
7979
#define GIC_ESPI_NR GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
8080

81+
/*
82+
* There are 16 SGIs, though we only actually use 8 in Linux. The other 8 SGIs
83+
* are potentially stolen by the secure side. Some code, especially code dealing
84+
* with hwirq IDs, is simplified by accounting for all 16.
85+
*/
86+
#define SGI_NR 16
87+
8188
/*
8289
* The behaviours of RPR and PMR registers differ depending on the value of
8390
* SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the
@@ -125,8 +132,8 @@ EXPORT_SYMBOL(gic_nonsecure_priorities);
125132
__priority; \
126133
})
127134

128-
/* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */
129-
static refcount_t *ppi_nmi_refs;
135+
/* rdist_nmi_refs[n] == number of cpus having the rdist interrupt n set as NMI */
136+
static refcount_t *rdist_nmi_refs;
130137

131138
static struct gic_kvm_info gic_v3_kvm_info __initdata;
132139
static DEFINE_PER_CPU(bool, has_rss);
@@ -519,9 +526,22 @@ static u32 __gic_get_ppi_index(irq_hw_number_t hwirq)
519526
}
520527
}
521528

522-
static u32 gic_get_ppi_index(struct irq_data *d)
529+
static u32 __gic_get_rdist_index(irq_hw_number_t hwirq)
530+
{
531+
switch (__get_intid_range(hwirq)) {
532+
case SGI_RANGE:
533+
case PPI_RANGE:
534+
return hwirq;
535+
case EPPI_RANGE:
536+
return hwirq - EPPI_BASE_INTID + 32;
537+
default:
538+
unreachable();
539+
}
540+
}
541+
542+
static u32 gic_get_rdist_index(struct irq_data *d)
523543
{
524-
return __gic_get_ppi_index(d->hwirq);
544+
return __gic_get_rdist_index(d->hwirq);
525545
}
526546

527547
static int gic_irq_nmi_setup(struct irq_data *d)
@@ -545,11 +565,14 @@ static int gic_irq_nmi_setup(struct irq_data *d)
545565

546566
/* desc lock should already be held */
547567
if (gic_irq_in_rdist(d)) {
548-
u32 idx = gic_get_ppi_index(d);
568+
u32 idx = gic_get_rdist_index(d);
549569

550-
/* Setting up PPI as NMI, only switch handler for first NMI */
551-
if (!refcount_inc_not_zero(&ppi_nmi_refs[idx])) {
552-
refcount_set(&ppi_nmi_refs[idx], 1);
570+
/*
571+
* Setting up a percpu interrupt as NMI, only switch handler
572+
* for first NMI
573+
*/
574+
if (!refcount_inc_not_zero(&rdist_nmi_refs[idx])) {
575+
refcount_set(&rdist_nmi_refs[idx], 1);
553576
desc->handle_irq = handle_percpu_devid_fasteoi_nmi;
554577
}
555578
} else {
@@ -582,10 +605,10 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
582605

583606
/* desc lock should already be held */
584607
if (gic_irq_in_rdist(d)) {
585-
u32 idx = gic_get_ppi_index(d);
608+
u32 idx = gic_get_rdist_index(d);
586609

587610
/* Tearing down NMI, only switch handler for last NMI */
588-
if (refcount_dec_and_test(&ppi_nmi_refs[idx]))
611+
if (refcount_dec_and_test(&rdist_nmi_refs[idx]))
589612
desc->handle_irq = handle_percpu_devid_irq;
590613
} else {
591614
desc->handle_irq = handle_fasteoi_irq;
@@ -1279,10 +1302,10 @@ static void gic_cpu_init(void)
12791302
rbase = gic_data_rdist_sgi_base();
12801303

12811304
/* Configure SGIs/PPIs as non-secure Group-1 */
1282-
for (i = 0; i < gic_data.ppi_nr + 16; i += 32)
1305+
for (i = 0; i < gic_data.ppi_nr + SGI_NR; i += 32)
12831306
writel_relaxed(~0, rbase + GICR_IGROUPR0 + i / 8);
12841307

1285-
gic_cpu_config(rbase, gic_data.ppi_nr + 16, gic_redist_wait_for_rwp);
1308+
gic_cpu_config(rbase, gic_data.ppi_nr + SGI_NR, gic_redist_wait_for_rwp);
12861309

12871310
/* initialise system registers */
12881311
gic_cpu_sys_reg_init();
@@ -1939,12 +1962,13 @@ static void gic_enable_nmi_support(void)
19391962
return;
19401963
}
19411964

1942-
ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL);
1943-
if (!ppi_nmi_refs)
1965+
rdist_nmi_refs = kcalloc(gic_data.ppi_nr + SGI_NR,
1966+
sizeof(*rdist_nmi_refs), GFP_KERNEL);
1967+
if (!rdist_nmi_refs)
19441968
return;
19451969

1946-
for (i = 0; i < gic_data.ppi_nr; i++)
1947-
refcount_set(&ppi_nmi_refs[i], 0);
1970+
for (i = 0; i < gic_data.ppi_nr + SGI_NR; i++)
1971+
refcount_set(&rdist_nmi_refs[i], 0);
19481972

19491973
pr_info("Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation\n",
19501974
gic_has_relaxed_pmr_sync() ? "relaxed" : "forced");
@@ -2061,6 +2085,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base,
20612085

20622086
gic_dist_init();
20632087
gic_cpu_init();
2088+
gic_enable_nmi_support();
20642089
gic_smp_init();
20652090
gic_cpu_pm_init();
20662091

@@ -2073,8 +2098,6 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base,
20732098
gicv2m_init(handle, gic_data.domain);
20742099
}
20752100

2076-
gic_enable_nmi_support();
2077-
20782101
return 0;
20792102

20802103
out_free:

0 commit comments

Comments
 (0)