riscv: prevent null-pointer dereference with

A patch from »SVPBMT + T-Head memory types next try« in state Mainline for linux-kernel

From: Heiko Stuebner <heiko@...> Date: Fri, 10 Dec 2021 16:19:19 +0100

Commit-Message

The callback used inside sbi_remote_fence_i is set at sbi probe time to the needed variant. Before that it is a NULL pointer. flush_icache_all is from its name a pretty generic functionality so probably shoudln't get a "only call after boot-step X" limit. To prevent running into a null pointer dereference, add a default __sbi_rfence_none returning an error code and adapt flush_icache_all to check for an error from the remote fence to then fall back to a simple local_icache_flush(), as that could really only happen if called before other cpu cores are brought up. Signed-off-by: Heiko Stuebner <heiko@...>

Patch-Comment

arch/riscv/kernel/sbi.c | 10 +++++++++- arch/riscv/mm/cacheflush.c | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-)

Statistics

  • 21 lines added
  • 4 lines removed

Changes

--------------------------- arch/riscv/kernel/sbi.c ----------------------------
index 2438d6fdb788..7f7a9630dc89 100644
@@ -14,11 +14,19 @@
unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
EXPORT_SYMBOL(sbi_spec_version);
+static int __sbi_rfence_none(int fid, const struct cpumask *cpu_mask,
+ unsigned long start, unsigned long size,
+ unsigned long arg4, unsigned long arg5)
+{
+ return -EOPNOTSUPP;
+}
+
static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
static int (*__sbi_send_ipi)(const struct cpumask *cpu_mask) __ro_after_init;
static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
unsigned long start, unsigned long size,
- unsigned long arg4, unsigned long arg5) __ro_after_init;
+ unsigned long arg4, unsigned long arg5)
+ __ro_after_init = __sbi_rfence_none;
struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
unsigned long arg1, unsigned long arg2,
-------------------------- arch/riscv/mm/cacheflush.c --------------------------
index 6cb7d96ad9c7..ea9634450557 100644
@@ -18,10 +18,19 @@ void flush_icache_all(void)
{
local_flush_icache_all();
- if (IS_ENABLED(CONFIG_RISCV_SBI))
- sbi_remote_fence_i(NULL);
- else
+ if (IS_ENABLED(CONFIG_RISCV_SBI)) {
+ int ret = sbi_remote_fence_i(NULL);
+
+ /*
+ * Only fails when sbi-init hasn't run yet, so the kernel
+ * also is before SMP init, so flushing the local cpu
+ * is enough.
+ */
+ if (ret)
+ local_flush_icache_all();
+ } else {
on_each_cpu(ipi_remote_fence_i, NULL, 1);
+ }
}
EXPORT_SYMBOL(flush_icache_all);
 
 

Recent Patches

About Us

Sed lacus. Donec lectus. Nullam pretium nibh ut turpis. Nam bibendum. In nulla tortor, elementum vel, tempor at, varius non, purus. Mauris vitae nisl nec metus placerat consectetuer.

Read More...