[PATCH -fixes] riscv: Fix RISCV_ALTERNATIVE_EARLY
Alexandre Ghiti
alex at ghiti.fr
Mon Aug 26 22:27:55 PDT 2024
Hi Chunyan,
On 27/08/2024 06:57, Chunyan Zhang wrote:
> Hi Alex,
>
> On Mon, 26 Aug 2024 at 18:58, Alexandre Ghiti <alexghiti at rivosinc.com> wrote:
>> RISCV_ALTERNATIVE_EARLY will issue sbi_ecall() very early in the boot
>> process, before the first memory mapping is setup so we can't have any
>> instrumentation happening here.
> I also found that when CONFIG_KASAN is enabled, and either
> RISCV_ALTERNATIVE_EARLY or CONFIG_DT_IDLE_GENPD is set, the kernel
> cannot boot.
Yes, I was initially fixing this report:
https://lore.kernel.org/linux-riscv/00000000000065062c061fcec37b@google.com/
And that makes me think I forgot the syzbot tag:
Reported-by: syzbot+cfbcb82adf6d7279fd35 at syzkaller.appspotmail.com
>
> This patch fixed the issue.
>
> Tested-by: Chunyan Zhang <zhangchunyan at iscas.ac.cn>
Thanks!
Alex
>
>> In addition, when the kernel is relocatable, we must also not issue any
>> relocation this early since they would have been patched virtually only.
>>
>> So, instead of disabling instrumentation for the whole kernel/sbi.c file
>> and compiling it with -fno-pie, simply move __sbi_ecall() and
>> __sbi_base_ecall() into their own file where this is fixed.
>>
>> Fixes: 1745cfafebdf ("riscv: don't use global static vars to store alternative data")
>> Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
>> ---
>> arch/riscv/include/asm/sbi.h | 2 ++
>> arch/riscv/kernel/Makefile | 6 ++++-
>> arch/riscv/kernel/sbi.c | 44 --------------------------------
>> arch/riscv/kernel/sbi_ecall.c | 48 +++++++++++++++++++++++++++++++++++
>> 4 files changed, 55 insertions(+), 45 deletions(-)
>> create mode 100644 arch/riscv/kernel/sbi_ecall.c
>>
>> diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
>> index 7cffd4ffecd0..5843a10b380e 100644
>> --- a/arch/riscv/include/asm/sbi.h
>> +++ b/arch/riscv/include/asm/sbi.h
>> @@ -9,6 +9,7 @@
>>
>> #include <linux/types.h>
>> #include <linux/cpumask.h>
>> +#include <linux/jump_label.h>
>>
>> #ifdef CONFIG_RISCV_SBI
>> enum sbi_ext_id {
>> @@ -304,6 +305,7 @@ struct sbiret {
>> };
>>
>> void sbi_init(void);
>> +long __sbi_base_ecall(int fid);
>> struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
>> unsigned long arg2, unsigned long arg3,
>> unsigned long arg4, unsigned long arg5,
>> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
>> index 06d407f1b30b..7f88cc4931f5 100644
>> --- a/arch/riscv/kernel/Makefile
>> +++ b/arch/riscv/kernel/Makefile
>> @@ -20,17 +20,21 @@ endif
>> ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
>> CFLAGS_alternative.o := -mcmodel=medany
>> CFLAGS_cpufeature.o := -mcmodel=medany
>> +CFLAGS_sbi_ecall.o := -mcmodel=medany
>> ifdef CONFIG_FTRACE
>> CFLAGS_REMOVE_alternative.o = $(CC_FLAGS_FTRACE)
>> CFLAGS_REMOVE_cpufeature.o = $(CC_FLAGS_FTRACE)
>> +CFLAGS_REMOVE_sbi_ecall.o = $(CC_FLAGS_FTRACE)
>> endif
>> ifdef CONFIG_RELOCATABLE
>> CFLAGS_alternative.o += -fno-pie
>> CFLAGS_cpufeature.o += -fno-pie
>> +CFLAGS_sbi_ecall.o += -fno-pie
>> endif
>> ifdef CONFIG_KASAN
>> KASAN_SANITIZE_alternative.o := n
>> KASAN_SANITIZE_cpufeature.o := n
>> +KASAN_SANITIZE_sbi_ecall.o := n
>> endif
>> endif
>>
>> @@ -88,7 +92,7 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
>>
>> obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
>> obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
>> -obj-$(CONFIG_RISCV_SBI) += sbi.o
>> +obj-$(CONFIG_RISCV_SBI) += sbi.o sbi_ecall.o
>> ifeq ($(CONFIG_RISCV_SBI), y)
>> obj-$(CONFIG_SMP) += sbi-ipi.o
>> obj-$(CONFIG_SMP) += cpu_ops_sbi.o
>> diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
>> index 837bdab2601b..ace9e2f59c41 100644
>> --- a/arch/riscv/kernel/sbi.c
>> +++ b/arch/riscv/kernel/sbi.c
>> @@ -14,9 +14,6 @@
>> #include <asm/smp.h>
>> #include <asm/tlbflush.h>
>>
>> -#define CREATE_TRACE_POINTS
>> -#include <asm/trace.h>
>> -
>> /* default SBI version is 0.1 */
>> unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
>> EXPORT_SYMBOL(sbi_spec_version);
>> @@ -27,36 +24,6 @@ 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;
>>
>> -struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
>> - unsigned long arg2, unsigned long arg3,
>> - unsigned long arg4, unsigned long arg5,
>> - int fid, int ext)
>> -{
>> - struct sbiret ret;
>> -
>> - trace_sbi_call(ext, fid);
>> -
>> - register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
>> - register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
>> - register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
>> - register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
>> - register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
>> - register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
>> - register uintptr_t a6 asm ("a6") = (uintptr_t)(fid);
>> - register uintptr_t a7 asm ("a7") = (uintptr_t)(ext);
>> - asm volatile ("ecall"
>> - : "+r" (a0), "+r" (a1)
>> - : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
>> - : "memory");
>> - ret.error = a0;
>> - ret.value = a1;
>> -
>> - trace_sbi_return(ext, ret.error, ret.value);
>> -
>> - return ret;
>> -}
>> -EXPORT_SYMBOL(__sbi_ecall);
>> -
>> int sbi_err_map_linux_errno(int err)
>> {
>> switch (err) {
>> @@ -535,17 +502,6 @@ long sbi_probe_extension(int extid)
>> }
>> EXPORT_SYMBOL(sbi_probe_extension);
>>
>> -static long __sbi_base_ecall(int fid)
>> -{
>> - struct sbiret ret;
>> -
>> - ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0);
>> - if (!ret.error)
>> - return ret.value;
>> - else
>> - return sbi_err_map_linux_errno(ret.error);
>> -}
>> -
>> static inline long sbi_get_spec_version(void)
>> {
>> return __sbi_base_ecall(SBI_EXT_BASE_GET_SPEC_VERSION);
>> diff --git a/arch/riscv/kernel/sbi_ecall.c b/arch/riscv/kernel/sbi_ecall.c
>> new file mode 100644
>> index 000000000000..24aabb4fbde3
>> --- /dev/null
>> +++ b/arch/riscv/kernel/sbi_ecall.c
>> @@ -0,0 +1,48 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Copyright (c) 2024 Rivos Inc. */
>> +
>> +#include <asm/sbi.h>
>> +#define CREATE_TRACE_POINTS
>> +#include <asm/trace.h>
>> +
>> +long __sbi_base_ecall(int fid)
>> +{
>> + struct sbiret ret;
>> +
>> + ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0);
>> + if (!ret.error)
>> + return ret.value;
>> + else
>> + return sbi_err_map_linux_errno(ret.error);
>> +}
>> +EXPORT_SYMBOL(__sbi_base_ecall);
>> +
>> +struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
>> + unsigned long arg2, unsigned long arg3,
>> + unsigned long arg4, unsigned long arg5,
>> + int fid, int ext)
>> +{
>> + struct sbiret ret;
>> +
>> + trace_sbi_call(ext, fid);
>> +
>> + register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
>> + register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
>> + register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
>> + register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
>> + register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
>> + register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
>> + register uintptr_t a6 asm ("a6") = (uintptr_t)(fid);
>> + register uintptr_t a7 asm ("a7") = (uintptr_t)(ext);
>> + asm volatile ("ecall"
>> + : "+r" (a0), "+r" (a1)
>> + : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
>> + : "memory");
>> + ret.error = a0;
>> + ret.value = a1;
>> +
>> + trace_sbi_return(ext, ret.error, ret.value);
>> +
>> + return ret;
>> +}
>> +EXPORT_SYMBOL(__sbi_ecall);
>> --
>> 2.39.2
>>
>>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
More information about the linux-riscv
mailing list