Commit 832f15f4 authored by Anup Patel's avatar Anup Patel Committed by Marc Zyngier
Browse files

RISC-V: Treat IPIs as normal Linux IRQs



Currently, the RISC-V kernel provides arch specific hooks (i.e.
struct riscv_ipi_ops) to register IPI handling methods. The stats
gathering of IPIs is also arch specific in the RISC-V kernel.

Other architectures (such as ARM, ARM64, and MIPS) have moved away
from custom arch specific IPI handling methods. Currently, these
architectures have Linux irqchip drivers providing a range of Linux
IRQ numbers to be used as IPIs and IPI triggering is done using
generic IPI APIs. This approach allows architectures to treat IPIs
as normal Linux IRQs and IPI stats gathering is done by the generic
Linux IRQ subsystem.

We extend the RISC-V IPI handling as-per above approach so that arch
specific IPI handling methods (struct riscv_ipi_ops) can be removed
and the IPI handling is done through the Linux IRQ subsystem.

Signed-off-by: default avatarAnup Patel <apatel@ventanamicro.com>
Acked-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230328035223.1480939-4-apatel@ventanamicro.com
parent 0c60a31c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ config RISCV
	select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
	select GENERIC_IDLE_POLL_SETUP
	select GENERIC_IOREMAP if MMU
	select GENERIC_IRQ_IPI if SMP
	select GENERIC_IRQ_IPI_MUX if SMP
	select GENERIC_IRQ_MULTI_HANDLER
	select GENERIC_IRQ_SHOW
	select GENERIC_IRQ_SHOW_LEVEL
+7 −2
Original line number Diff line number Diff line
@@ -271,8 +271,7 @@ long sbi_get_marchid(void);
long sbi_get_mimpid(void);
void sbi_set_timer(uint64_t stime_value);
void sbi_shutdown(void);
void sbi_clear_ipi(void);
int sbi_send_ipi(const struct cpumask *cpu_mask);
void sbi_send_ipi(unsigned int cpu);
int sbi_remote_fence_i(const struct cpumask *cpu_mask);
int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
			   unsigned long start,
@@ -335,4 +334,10 @@ unsigned long riscv_cached_mvendorid(unsigned int cpu_id);
unsigned long riscv_cached_marchid(unsigned int cpu_id);
unsigned long riscv_cached_mimpid(unsigned int cpu_id);

#if IS_ENABLED(CONFIG_SMP) && IS_ENABLED(CONFIG_RISCV_SBI)
void sbi_ipi_init(void);
#else
static inline void sbi_ipi_init(void) { }
#endif

#endif /* _ASM_RISCV_SBI_H */
+21 −14
Original line number Diff line number Diff line
@@ -15,11 +15,6 @@
struct seq_file;
extern unsigned long boot_cpu_hartid;

struct riscv_ipi_ops {
	void (*ipi_inject)(const struct cpumask *target);
	void (*ipi_clear)(void);
};

#ifdef CONFIG_SMP
/*
 * Mapping between linux logical cpu index and hartid.
@@ -33,9 +28,6 @@ void show_ipi_stats(struct seq_file *p, int prec);
/* SMP initialization hook for setup_arch */
void __init setup_smp(void);

/* Called from C code, this handles an IPI. */
void handle_IPI(struct pt_regs *regs);

/* Hook for the generic smp_call_function_many() routine. */
void arch_send_call_function_ipi_mask(struct cpumask *mask);

@@ -44,11 +36,17 @@ void arch_send_call_function_single_ipi(int cpu);

int riscv_hartid_to_cpuid(unsigned long hartid);

/* Set custom IPI operations */
void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops);
/* Enable IPI for CPU hotplug */
void riscv_ipi_enable(void);

/* Disable IPI for CPU hotplug */
void riscv_ipi_disable(void);

/* Clear IPI for current CPU */
void riscv_clear_ipi(void);
/* Check if IPI interrupt numbers are available */
bool riscv_ipi_have_virq_range(void);

/* Set the IPI interrupt numbers for arch (called by irqchip drivers) */
void riscv_ipi_set_virq_range(int virq, int nr);

/* Check other CPUs stop or not */
bool smp_crash_stop_failed(void);
@@ -85,11 +83,20 @@ static inline unsigned long cpuid_to_hartid_map(int cpu)
	return boot_cpu_hartid;
}

static inline void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
static inline void riscv_ipi_enable(void)
{
}

static inline void riscv_clear_ipi(void)
static inline void riscv_ipi_disable(void)
{
}

static inline bool riscv_ipi_have_virq_range(void)
{
	return false;
}

static inline void riscv_ipi_set_virq_range(int virq, int nr)
{
}

+1 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
obj-$(CONFIG_HAVE_PERF_REGS)	+= perf_regs.o
obj-$(CONFIG_RISCV_SBI)		+= sbi.o
ifeq ($(CONFIG_RISCV_SBI), y)
obj-$(CONFIG_SMP)		+= sbi-ipi.o
obj-$(CONFIG_SMP) += cpu_ops_sbi.o
endif
obj-$(CONFIG_HOTPLUG_CPU)	+= cpu-hotplug.o
+2 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@
#include <asm/irq.h>
#include <asm/cpu_ops.h>
#include <asm/numa.h>
#include <asm/sbi.h>
#include <asm/smp.h>

bool cpu_has_hotplug(unsigned int cpu)
{
@@ -43,6 +43,7 @@ int __cpu_disable(void)
	remove_cpu_topology(cpu);
	numa_remove_cpu(cpu);
	set_cpu_online(cpu, false);
	riscv_ipi_disable();
	irq_migrate_all_off_this_cpu();

	return ret;
Loading