To do remote FENCEs (i.e. remote TLB flushes) using IPI calls on the RISC-V kernel, we need hardware mechanism to directly inject IPI from the RISC-V kernel instead of using SBI calls. The upcoming ACLINT [M|S]SWI devices and AIA IMSIC devices allow direct IPI injection from the RISC-V kernel. To support this, we extend the riscv_ipi_set_virq_range() function so that irqchip drivers can mark IPIs as suitable for remote FENCEs. Signed-off-by: Anup Patel <anup.patel@xxxxxxx> --- arch/riscv/include/asm/smp.h | 18 ++++++++++++++++-- arch/riscv/kernel/sbi-ipi.c | 2 +- arch/riscv/kernel/smp.c | 9 ++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h index 6bdaab122ffa..f4856c911335 100644 --- a/arch/riscv/include/asm/smp.h +++ b/arch/riscv/include/asm/smp.h @@ -16,6 +16,9 @@ struct seq_file; extern unsigned long boot_cpu_hartid; #ifdef CONFIG_SMP + +#include <linux/jump_label.h> + /* * Mapping between linux logical cpu index and hartid. */ @@ -47,7 +50,12 @@ void riscv_ipi_disable(void); void riscv_ipi_setup(void); /* Set the IPI interrupt numbers for arch (called by irqchip drivers) */ -void riscv_ipi_set_virq_range(int virq, int nr_irqs); +void riscv_ipi_set_virq_range(int virq, int nr_irqs, bool use_for_rfence); + +/* Check if we can use IPIs for remote FENCEs */ +DECLARE_STATIC_KEY_FALSE(riscv_ipi_for_rfence); +#define riscv_use_ipi_for_rfence() \ + static_branch_unlikely(&riscv_ipi_for_rfence) /* Secondary hart entry */ asmlinkage void smp_callin(void); @@ -102,10 +110,16 @@ static inline void riscv_ipi_setup(void) { } -static inline void riscv_ipi_set_virq_range(int virq, int nr) +static inline void riscv_ipi_set_virq_range(int virq, int nr, + bool use_for_rfence) { } +static inline bool riscv_use_ipi_for_rfence(void) +{ + return false; +} + #endif /* CONFIG_SMP */ #if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP) diff --git a/arch/riscv/kernel/sbi-ipi.c b/arch/riscv/kernel/sbi-ipi.c index dc284ad3551c..c65daf50ff1f 100644 --- a/arch/riscv/kernel/sbi-ipi.c +++ b/arch/riscv/kernel/sbi-ipi.c @@ -149,7 +149,7 @@ static int __init sbi_ipi_set_virq(void) return -ENOMEM; } - riscv_ipi_set_virq_range(virq, BITS_PER_LONG); + riscv_ipi_set_virq_range(virq, BITS_PER_LONG, false); return 0; } diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index 6c9873b7d60e..a8ce7a0556ab 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -183,7 +183,10 @@ void riscv_ipi_setup(void) riscv_ipi_enable(); } -void riscv_ipi_set_virq_range(int virq, int nr) +DEFINE_STATIC_KEY_FALSE(riscv_ipi_for_rfence); +EXPORT_SYMBOL_GPL(riscv_ipi_for_rfence); + +void riscv_ipi_set_virq_range(int virq, int nr, bool use_for_rfence) { if (WARN_ON(ipi_virq_base)) return; @@ -191,6 +194,10 @@ void riscv_ipi_set_virq_range(int virq, int nr) WARN_ON(nr < IPI_MAX); nr_ipi = min(nr, IPI_MAX); ipi_virq_base = virq; + if (use_for_rfence) + static_branch_enable(&riscv_ipi_for_rfence); + else + static_branch_disable(&riscv_ipi_for_rfence); } EXPORT_SYMBOL_GPL(riscv_ipi_set_virq_range); -- 2.25.1