[RFC PATCH v1 1/3] RISC-V: IPI provider should specify if we can use IPI for remote FENCE

From: Anup Patel
Date: Thu Mar 11 2021 - 11:48:47 EST


We extend riscv_set_ipi_ops() so that IPI providers (such as SBI, CLINT
driver, etc) can specify whether IPIs are suitable for doing remote
FENCEs (i.e remote TLB shoot down).

The upcoming AIA specification allows IPI injection directly from S-mode
(or VS-mode) using IMSIC controller so the extended riscv_set_ipi_ops()
will be useful to AIA IMSIC driver as well.

Signed-off-by: Anup Patel <anup.patel@xxxxxxx>
---
arch/riscv/include/asm/smp.h | 13 +++++++++++--
arch/riscv/kernel/sbi.c | 2 +-
arch/riscv/kernel/smp.c | 10 +++++++++-
arch/riscv/mm/cacheflush.c | 2 +-
drivers/clocksource/timer-clint.c | 2 +-
5 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
index df1f7c4cd433..82c23e5f22f6 100644
--- a/arch/riscv/include/asm/smp.h
+++ b/arch/riscv/include/asm/smp.h
@@ -45,8 +45,11 @@ void arch_send_call_function_single_ipi(int cpu);
int riscv_hartid_to_cpuid(int hartid);
void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out);

+/* Check if we can use IPIs for remote FENCE */
+bool riscv_use_ipi_for_rfence(void);
+
/* Set custom IPI operations */
-void riscv_set_ipi_ops(struct riscv_ipi_ops *ops);
+void riscv_set_ipi_ops(struct riscv_ipi_ops *ops, bool use_for_rfence);

/* Clear IPI for current CPU */
void riscv_clear_ipi(void);
@@ -92,7 +95,13 @@ static inline void riscv_cpuid_to_hartid_mask(const struct cpumask *in,
cpumask_set_cpu(boot_cpu_hartid, out);
}

-static inline void riscv_set_ipi_ops(struct riscv_ipi_ops *ops)
+static inline bool riscv_use_ipi_for_rfence(void)
+{
+ return false;
+}
+
+static inline void riscv_set_ipi_ops(struct riscv_ipi_ops *ops,
+ bool use_for_rfence)
{
}

diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index 49155588e56c..15a09680fdb6 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -634,5 +634,5 @@ void __init sbi_init(void)
__sbi_rfence = __sbi_rfence_v01;
}

- riscv_set_ipi_ops(&sbi_ipi_ops);
+ riscv_set_ipi_ops(&sbi_ipi_ops, false);
}
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
index ea028d9e0d24..9258e3eaa8c6 100644
--- a/arch/riscv/kernel/smp.c
+++ b/arch/riscv/kernel/smp.c
@@ -85,11 +85,19 @@ static void ipi_stop(void)
wait_for_interrupt();
}

+static bool ipi_for_rfence;
static struct riscv_ipi_ops *ipi_ops;

-void riscv_set_ipi_ops(struct riscv_ipi_ops *ops)
+bool riscv_use_ipi_for_rfence(void)
+{
+ return ipi_for_rfence;
+}
+EXPORT_SYMBOL_GPL(riscv_use_ipi_for_rfence);
+
+void riscv_set_ipi_ops(struct riscv_ipi_ops *ops, bool use_for_rfence)
{
ipi_ops = ops;
+ ipi_for_rfence = use_for_rfence;
}
EXPORT_SYMBOL_GPL(riscv_set_ipi_ops);

diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c
index 094118663285..0ffe7d560dc8 100644
--- a/arch/riscv/mm/cacheflush.c
+++ b/arch/riscv/mm/cacheflush.c
@@ -16,7 +16,7 @@ static void ipi_remote_fence_i(void *info)

void flush_icache_all(void)
{
- if (IS_ENABLED(CONFIG_RISCV_SBI))
+ if (!riscv_use_ipi_for_rfence())
sbi_remote_fence_i(NULL);
else
on_each_cpu(ipi_remote_fence_i, NULL, 1);
diff --git a/drivers/clocksource/timer-clint.c b/drivers/clocksource/timer-clint.c
index 6cfe2ab73eb0..fe018a2c008f 100644
--- a/drivers/clocksource/timer-clint.c
+++ b/drivers/clocksource/timer-clint.c
@@ -228,7 +228,7 @@ static int __init clint_timer_init_dt(struct device_node *np)
goto fail_free_irq;
}

- riscv_set_ipi_ops(&clint_ipi_ops);
+ riscv_set_ipi_ops(&clint_ipi_ops, true);
clint_clear_ipi();

return 0;
--
2.25.1