Use the dedicated scratch register for setting the pbl flags. Each mode has it's own scratch register so we are not conflicting with M-mode running firmware e.g. OpenSBI. Using the scratch register has two main advantages: 1st) It can be used in PBL and non-PBL use-case. 2nd) It is not affected by the relocation code. This commit prepares barebox to add support for the special cache ops used by several T-Head CPUs. Signed-off-by: Marco Felsch <m.felsch@xxxxxxxxxxxxxx> --- v2: - adapt switch-case to fix compile error arch/riscv/boot/entry.c | 3 +- arch/riscv/boot/entry.h | 6 ++-- arch/riscv/boot/start.c | 13 +++---- arch/riscv/boot/uncompress.c | 8 ++--- arch/riscv/include/asm/system.h | 63 ++++++++++++++++++++------------- 5 files changed, 51 insertions(+), 42 deletions(-) diff --git a/arch/riscv/boot/entry.c b/arch/riscv/boot/entry.c index e4a5c2208d..f5a536fc78 100644 --- a/arch/riscv/boot/entry.c +++ b/arch/riscv/boot/entry.c @@ -25,6 +25,7 @@ void __noreturn __naked barebox_riscv_entry(unsigned long membase, { unsigned long stack_top = riscv_mem_stack_top(membase, membase + memsize); asm volatile ("move sp, %0" : : "r"(stack_top)); - barebox_pbl_start(membase, memsize, boarddata, flags); + riscv_set_flags(flags); + barebox_pbl_start(membase, memsize, boarddata); } diff --git a/arch/riscv/boot/entry.h b/arch/riscv/boot/entry.h index fb4af5eae5..b3a24d2783 100644 --- a/arch/riscv/boot/entry.h +++ b/arch/riscv/boot/entry.h @@ -6,12 +6,10 @@ void __noreturn barebox_non_pbl_start(unsigned long membase, unsigned long memsize, - void *boarddata, - unsigned flags); + void *boarddata); void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize, - void *boarddata, - unsigned flags); + void *boarddata); #endif diff --git a/arch/riscv/boot/start.c b/arch/riscv/boot/start.c index 8b4c8bb2f0..27d9066243 100644 --- a/arch/riscv/boot/start.c +++ b/arch/riscv/boot/start.c @@ -27,7 +27,6 @@ static unsigned long riscv_barebox_size; static unsigned long riscv_endmem; static void *barebox_boarddata; static unsigned long barebox_boarddata_size; -unsigned barebox_riscv_pbl_flags; void *barebox_riscv_boot_dtb(void) { @@ -108,7 +107,7 @@ device_initcall(barebox_memory_areas_init); */ __noreturn __no_sanitize_address __section(.text_entry) void barebox_non_pbl_start(unsigned long membase, unsigned long memsize, - void *boarddata, unsigned flags) + void *boarddata) { unsigned long endmem = membase + memsize; unsigned long malloc_start, malloc_end; @@ -121,7 +120,7 @@ void barebox_non_pbl_start(unsigned long membase, unsigned long memsize, barrier(); - irq_init_vector(__riscv_mode(flags)); + irq_init_vector(riscv_mode()); pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize); @@ -171,20 +170,18 @@ void barebox_non_pbl_start(unsigned long membase, unsigned long memsize, mem_malloc_init((void *)malloc_start, (void *)malloc_end - 1); - barebox_riscv_pbl_flags = flags; - pr_debug("starting barebox...\n"); start_barebox(); } -void start(unsigned long membase, unsigned long memsize, void *boarddata, unsigned flags); +void start(unsigned long membase, unsigned long memsize, void *boarddata); /* * First function in the uncompressed image. We get here from * the pbl. The stack already has been set up by the pbl. */ void __no_sanitize_address __section(.text_entry) start(unsigned long membase, - unsigned long memsize, void *boarddata, unsigned flags) + unsigned long memsize, void *boarddata) { - barebox_non_pbl_start(membase, memsize, boarddata, flags); + barebox_non_pbl_start(membase, memsize, boarddata); } diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c index 4ed9b4d371..ee24f81e01 100644 --- a/arch/riscv/boot/uncompress.c +++ b/arch/riscv/boot/uncompress.c @@ -24,16 +24,16 @@ unsigned long free_mem_ptr; unsigned long free_mem_end_ptr; void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize, - void *fdt, unsigned flags) + void *fdt) { uint32_t pg_len, uncompressed_len; - void __noreturn (*barebox)(unsigned long, unsigned long, void *, unsigned); + void __noreturn (*barebox)(unsigned long, unsigned long, void *); unsigned long endmem = membase + memsize; unsigned long barebox_base; void *pg_start, *pg_end; unsigned long pc = get_pc(); - irq_init_vector(__riscv_mode(flags)); + irq_init_vector(riscv_mode()); /* piggy data is not relocated, so determine the bounds now */ pg_start = input_data + get_runtime_offset(); @@ -72,5 +72,5 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize, pr_debug("jumping to uncompressed image at 0x%p. dtb=0x%p\n", barebox, fdt); - barebox(membase, memsize, fdt, flags); + barebox(membase, memsize, fdt); } diff --git a/arch/riscv/include/asm/system.h b/arch/riscv/include/asm/system.h index 89516f075b..f0b6bf2945 100644 --- a/arch/riscv/include/asm/system.h +++ b/arch/riscv/include/asm/system.h @@ -15,7 +15,39 @@ enum riscv_mode { RISCV_M_MODE = 3, }; -static inline enum riscv_mode __riscv_mode(u32 flags) +static inline void riscv_set_flags(unsigned flags) +{ + switch (flags & RISCV_MODE_MASK) { + case RISCV_S_MODE: + __asm__ volatile("csrw sscratch, %0" : : "r"(flags)); + break; + case RISCV_M_MODE: + __asm__ volatile("csrw mscratch, %0" : : "r"(flags)); + break; + default: + /* Other modes are not implemented yet */ + break; + } +} + +static inline u32 riscv_get_flags(void) +{ + u32 flags = 0; + + if (IS_ENABLED(CONFIG_RISCV_S_MODE)) + __asm__ volatile("csrr %0, sscratch" : "=r"(flags)); + + /* + * Since we always set the scratch register on the very beginning, a + * empty flags indicates that we are running in M-mode. + */ + if (!flags) + __asm__ volatile("csrr %0, mscratch" : "=r"(flags)); + + return flags; +} + +static inline enum riscv_mode riscv_mode(void) { /* allow non-LTO builds to discard code for unused modes */ if (!IS_ENABLED(CONFIG_RISCV_MULTI_MODE)) { @@ -25,14 +57,14 @@ static inline enum riscv_mode __riscv_mode(u32 flags) return RISCV_S_MODE; } - return flags & RISCV_MODE_MASK; + return riscv_get_flags() & RISCV_MODE_MASK; } -static inline long __riscv_hartid(u32 flags) +static inline long riscv_hartid(void) { long hartid = -1; - switch (__riscv_mode(flags)) { + switch (riscv_mode()) { case RISCV_S_MODE: __asm__ volatile("mv %0, tp\n" : "=r"(hartid) :); break; @@ -44,12 +76,12 @@ static inline long __riscv_hartid(u32 flags) return hartid; } -static inline long __riscv_vendor_id(u32 flags) +static inline long riscv_vendor_id(void) { struct sbiret ret; long id; - switch (__riscv_mode(flags)) { + switch (riscv_mode()) { case RISCV_M_MODE: __asm__ volatile("csrr %0, mvendorid\n" : "=r"(id)); return id; @@ -68,25 +100,6 @@ static inline long __riscv_vendor_id(u32 flags) } } -#ifndef __PBL__ -extern unsigned barebox_riscv_pbl_flags; - -static inline enum riscv_mode riscv_mode(void) -{ - return __riscv_mode(barebox_riscv_pbl_flags); -} - -static inline long riscv_hartid(void) -{ - return __riscv_hartid(barebox_riscv_pbl_flags); -} - -static inline long riscv_vendor_id(void) -{ - return __riscv_vendor_id(barebox_riscv_pbl_flags); -} -#endif - #endif #endif -- 2.30.2