Skip to content

Commit 1ff95eb

Browse files
Alexandre Ghitipalmer-dabbelt
authored andcommitted
riscv: Fix RISCV_ALTERNATIVE_EARLY
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. 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. Reported-by: Conor Dooley <[email protected]> Closes: https://lore.kernel.org/linux-riscv/20240813-pony-truck-3e7a83e9759e@spud/ Reported-by: [email protected] Closes: https://lore.kernel.org/linux-riscv/[email protected]/ Fixes: 1745cfa ("riscv: don't use global static vars to store alternative data") Signed-off-by: Alexandre Ghiti <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 5f77108 commit 1ff95eb

File tree

4 files changed

+72
-65
lines changed

4 files changed

+72
-65
lines changed

arch/riscv/include/asm/sbi.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <linux/types.h>
1111
#include <linux/cpumask.h>
12+
#include <linux/jump_label.h>
1213

1314
#ifdef CONFIG_RISCV_SBI
1415
enum sbi_ext_id {
@@ -304,6 +305,7 @@ struct sbiret {
304305
};
305306

306307
void sbi_init(void);
308+
long __sbi_base_ecall(int fid);
307309
struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
308310
unsigned long arg2, unsigned long arg3,
309311
unsigned long arg4, unsigned long arg5,
@@ -373,7 +375,23 @@ static inline unsigned long sbi_mk_version(unsigned long major,
373375
| (minor & SBI_SPEC_VERSION_MINOR_MASK);
374376
}
375377

376-
int sbi_err_map_linux_errno(int err);
378+
static inline int sbi_err_map_linux_errno(int err)
379+
{
380+
switch (err) {
381+
case SBI_SUCCESS:
382+
return 0;
383+
case SBI_ERR_DENIED:
384+
return -EPERM;
385+
case SBI_ERR_INVALID_PARAM:
386+
return -EINVAL;
387+
case SBI_ERR_INVALID_ADDRESS:
388+
return -EFAULT;
389+
case SBI_ERR_NOT_SUPPORTED:
390+
case SBI_ERR_FAILURE:
391+
default:
392+
return -ENOTSUPP;
393+
};
394+
}
377395

378396
extern bool sbi_debug_console_available;
379397
int sbi_debug_console_write(const char *bytes, unsigned int num_bytes);

arch/riscv/kernel/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@ endif
2020
ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
2121
CFLAGS_alternative.o := -mcmodel=medany
2222
CFLAGS_cpufeature.o := -mcmodel=medany
23+
CFLAGS_sbi_ecall.o := -mcmodel=medany
2324
ifdef CONFIG_FTRACE
2425
CFLAGS_REMOVE_alternative.o = $(CC_FLAGS_FTRACE)
2526
CFLAGS_REMOVE_cpufeature.o = $(CC_FLAGS_FTRACE)
27+
CFLAGS_REMOVE_sbi_ecall.o = $(CC_FLAGS_FTRACE)
2628
endif
2729
ifdef CONFIG_RELOCATABLE
2830
CFLAGS_alternative.o += -fno-pie
2931
CFLAGS_cpufeature.o += -fno-pie
32+
CFLAGS_sbi_ecall.o += -fno-pie
3033
endif
3134
ifdef CONFIG_KASAN
3235
KASAN_SANITIZE_alternative.o := n
3336
KASAN_SANITIZE_cpufeature.o := n
37+
KASAN_SANITIZE_sbi_ecall.o := n
3438
endif
3539
endif
3640

@@ -88,7 +92,7 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
8892

8993
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
9094
obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
91-
obj-$(CONFIG_RISCV_SBI) += sbi.o
95+
obj-$(CONFIG_RISCV_SBI) += sbi.o sbi_ecall.o
9296
ifeq ($(CONFIG_RISCV_SBI), y)
9397
obj-$(CONFIG_SMP) += sbi-ipi.o
9498
obj-$(CONFIG_SMP) += cpu_ops_sbi.o

arch/riscv/kernel/sbi.c

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
#include <asm/smp.h>
1515
#include <asm/tlbflush.h>
1616

17-
#define CREATE_TRACE_POINTS
18-
#include <asm/trace.h>
19-
2017
/* default SBI version is 0.1 */
2118
unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
2219
EXPORT_SYMBOL(sbi_spec_version);
@@ -27,55 +24,6 @@ static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
2724
unsigned long start, unsigned long size,
2825
unsigned long arg4, unsigned long arg5) __ro_after_init;
2926

30-
struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
31-
unsigned long arg2, unsigned long arg3,
32-
unsigned long arg4, unsigned long arg5,
33-
int fid, int ext)
34-
{
35-
struct sbiret ret;
36-
37-
trace_sbi_call(ext, fid);
38-
39-
register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
40-
register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
41-
register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
42-
register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
43-
register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
44-
register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
45-
register uintptr_t a6 asm ("a6") = (uintptr_t)(fid);
46-
register uintptr_t a7 asm ("a7") = (uintptr_t)(ext);
47-
asm volatile ("ecall"
48-
: "+r" (a0), "+r" (a1)
49-
: "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
50-
: "memory");
51-
ret.error = a0;
52-
ret.value = a1;
53-
54-
trace_sbi_return(ext, ret.error, ret.value);
55-
56-
return ret;
57-
}
58-
EXPORT_SYMBOL(__sbi_ecall);
59-
60-
int sbi_err_map_linux_errno(int err)
61-
{
62-
switch (err) {
63-
case SBI_SUCCESS:
64-
return 0;
65-
case SBI_ERR_DENIED:
66-
return -EPERM;
67-
case SBI_ERR_INVALID_PARAM:
68-
return -EINVAL;
69-
case SBI_ERR_INVALID_ADDRESS:
70-
return -EFAULT;
71-
case SBI_ERR_NOT_SUPPORTED:
72-
case SBI_ERR_FAILURE:
73-
default:
74-
return -ENOTSUPP;
75-
};
76-
}
77-
EXPORT_SYMBOL(sbi_err_map_linux_errno);
78-
7927
#ifdef CONFIG_RISCV_SBI_V01
8028
static unsigned long __sbi_v01_cpumask_to_hartmask(const struct cpumask *cpu_mask)
8129
{
@@ -535,17 +483,6 @@ long sbi_probe_extension(int extid)
535483
}
536484
EXPORT_SYMBOL(sbi_probe_extension);
537485

538-
static long __sbi_base_ecall(int fid)
539-
{
540-
struct sbiret ret;
541-
542-
ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0);
543-
if (!ret.error)
544-
return ret.value;
545-
else
546-
return sbi_err_map_linux_errno(ret.error);
547-
}
548-
549486
static inline long sbi_get_spec_version(void)
550487
{
551488
return __sbi_base_ecall(SBI_EXT_BASE_GET_SPEC_VERSION);

arch/riscv/kernel/sbi_ecall.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2024 Rivos Inc. */
3+
4+
#include <asm/sbi.h>
5+
#define CREATE_TRACE_POINTS
6+
#include <asm/trace.h>
7+
8+
long __sbi_base_ecall(int fid)
9+
{
10+
struct sbiret ret;
11+
12+
ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0);
13+
if (!ret.error)
14+
return ret.value;
15+
else
16+
return sbi_err_map_linux_errno(ret.error);
17+
}
18+
EXPORT_SYMBOL(__sbi_base_ecall);
19+
20+
struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
21+
unsigned long arg2, unsigned long arg3,
22+
unsigned long arg4, unsigned long arg5,
23+
int fid, int ext)
24+
{
25+
struct sbiret ret;
26+
27+
trace_sbi_call(ext, fid);
28+
29+
register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
30+
register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
31+
register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
32+
register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
33+
register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
34+
register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
35+
register uintptr_t a6 asm ("a6") = (uintptr_t)(fid);
36+
register uintptr_t a7 asm ("a7") = (uintptr_t)(ext);
37+
asm volatile ("ecall"
38+
: "+r" (a0), "+r" (a1)
39+
: "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
40+
: "memory");
41+
ret.error = a0;
42+
ret.value = a1;
43+
44+
trace_sbi_return(ext, ret.error, ret.value);
45+
46+
return ret;
47+
}
48+
EXPORT_SYMBOL(__sbi_ecall);

0 commit comments

Comments
 (0)