Skip to content

Commit ea92b60

Browse files
avpatelKAGA-KOKO
authored andcommitted
irqchip/riscv-imsic: Add kernel parameter to disable IPIs
When injecting IPIs to a set of harts, the IMSIC IPI support will do a separate MMIO write to the SETIPNUM_LE register of each target hart. This means on a platform where IMSIC is trap-n-emulated, there will be N MMIO traps when injecting IPI to N target harts hence IMSIC IPIs will be slow on such platforms compared to the SBI IPI extension. Unfortunately, there is no DT, ACPI, or any other way of discovering whether the underlying IMSIC is trap-n-emulated. Using MMIO write to the SETIPNUM_LE register for injecting IPI is purely a software choice in the IMSIC driver hence add a kernel parameter to allow users to disable IMSIC IPIs on platforms with trap-n-emulated IMSIC. Signed-off-by: Anup Patel <apatel@ventanamicro.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/20250716123745.557585-1-apatel@ventanamicro.com
1 parent 97c03ec commit ea92b60

4 files changed

Lines changed: 31 additions & 4 deletions

File tree

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,6 +2538,13 @@
25382538
requires the kernel to be built with
25392539
CONFIG_ARM64_PSEUDO_NMI.
25402540

2541+
irqchip.riscv_imsic_noipi
2542+
[RISC-V,EARLY]
2543+
Force the kernel to not use IMSIC software injected MSIs
2544+
as IPIs. Intended for system where IMSIC is trap-n-emulated,
2545+
and thus want to reduce MMIO traps when triggering IPIs
2546+
to multiple harts.
2547+
25412548
irqfixup [HW]
25422549
When an interrupt is not handled search all handlers
25432550
for it. Intended to get systems with badly broken

drivers/irqchip/irq-riscv-imsic-early.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/acpi.h>
99
#include <linux/cpu.h>
1010
#include <linux/interrupt.h>
11+
#include <linux/init.h>
1112
#include <linux/io.h>
1213
#include <linux/irq.h>
1314
#include <linux/irqchip.h>
@@ -21,6 +22,14 @@
2122
#include "irq-riscv-imsic-state.h"
2223

2324
static int imsic_parent_irq;
25+
bool imsic_noipi __ro_after_init;
26+
27+
static int __init imsic_noipi_cfg(char *buf)
28+
{
29+
imsic_noipi = true;
30+
return 0;
31+
}
32+
early_param("irqchip.riscv_imsic_noipi", imsic_noipi_cfg);
2433

2534
#ifdef CONFIG_SMP
2635
static void imsic_ipi_send(unsigned int cpu)
@@ -32,12 +41,18 @@ static void imsic_ipi_send(unsigned int cpu)
3241

3342
static void imsic_ipi_starting_cpu(void)
3443
{
44+
if (imsic_noipi)
45+
return;
46+
3547
/* Enable IPIs for current CPU. */
3648
__imsic_id_set_enable(IMSIC_IPI_ID);
3749
}
3850

3951
static void imsic_ipi_dying_cpu(void)
4052
{
53+
if (imsic_noipi)
54+
return;
55+
4156
/* Disable IPIs for current CPU. */
4257
__imsic_id_clear_enable(IMSIC_IPI_ID);
4358
}
@@ -46,6 +61,9 @@ static int __init imsic_ipi_domain_init(void)
4661
{
4762
int virq;
4863

64+
if (imsic_noipi)
65+
return 0;
66+
4967
/* Create IMSIC IPI multiplexing */
5068
virq = ipi_mux_create(IMSIC_NR_IPI, imsic_ipi_send);
5169
if (virq <= 0)
@@ -88,7 +106,7 @@ static void imsic_handle_irq(struct irq_desc *desc)
88106
while ((local_id = csr_swap(CSR_TOPEI, 0))) {
89107
local_id >>= TOPEI_ID_SHIFT;
90108

91-
if (local_id == IMSIC_IPI_ID) {
109+
if (!imsic_noipi && local_id == IMSIC_IPI_ID) {
92110
if (IS_ENABLED(CONFIG_SMP))
93111
ipi_mux_process();
94112
continue;

drivers/irqchip/irq-riscv-imsic-state.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ static bool __imsic_local_sync(struct imsic_local_priv *lpriv)
134134
lockdep_assert_held(&lpriv->lock);
135135

136136
for_each_set_bit(i, lpriv->dirty_bitmap, imsic->global.nr_ids + 1) {
137-
if (!i || i == IMSIC_IPI_ID)
137+
if (!i || (!imsic_noipi && i == IMSIC_IPI_ID))
138138
goto skip;
139139
vec = &lpriv->vectors[i];
140140

@@ -419,7 +419,7 @@ void imsic_vector_debug_show(struct seq_file *m, struct imsic_vector *vec, int i
419419
seq_printf(m, "%*starget_cpu : %5u\n", ind, "", vec->cpu);
420420
seq_printf(m, "%*starget_local_id : %5u\n", ind, "", vec->local_id);
421421
seq_printf(m, "%*sis_reserved : %5u\n", ind, "",
422-
(vec->local_id <= IMSIC_IPI_ID) ? 1 : 0);
422+
(!imsic_noipi && vec->local_id <= IMSIC_IPI_ID) ? 1 : 0);
423423
seq_printf(m, "%*sis_enabled : %5u\n", ind, "", is_enabled ? 1 : 0);
424424
seq_printf(m, "%*sis_move_pending : %5u\n", ind, "", mvec ? 1 : 0);
425425
if (mvec) {
@@ -583,7 +583,8 @@ static int __init imsic_matrix_init(void)
583583
irq_matrix_assign_system(imsic->matrix, 0, false);
584584

585585
/* Reserve IPI ID because it is special and used internally */
586-
irq_matrix_assign_system(imsic->matrix, IMSIC_IPI_ID, false);
586+
if (!imsic_noipi)
587+
irq_matrix_assign_system(imsic->matrix, IMSIC_IPI_ID, false);
587588

588589
return 0;
589590
}

drivers/irqchip/irq-riscv-imsic-state.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct imsic_priv {
6161
struct irq_domain *base_domain;
6262
};
6363

64+
extern bool imsic_noipi;
6465
extern struct imsic_priv *imsic;
6566

6667
void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, bool val);

0 commit comments

Comments
 (0)