From 8226166da3d6740882a2092c348fc0c31006d1d4 Mon Sep 17 00:00:00 2001 From: Sven Ginka Date: Mon, 4 Mar 2024 19:38:04 +0100 Subject: [PATCH] arch: riscv: core: run zephyr completely in user/supervisor mode Before that fix, zephyr was able to start only in machine mode. With that fix, zephyr can start (as guest) in user or supervisor mode. Defined new board type qemu_riscv32/qemu_virt_riscv32/opensbi Drivers for running zephyr in supervisor with qemu included. Fixes #68133 Signed-off-by: Sven Ginka Signed-off-by: Sven Ginka --- arch/riscv/Kconfig | 19 + arch/riscv/core/cpu_idle.c | 2 +- arch/riscv/core/fatal.c | 8 +- arch/riscv/core/irq_manage.c | 8 +- arch/riscv/core/isr.S | 35 +- arch/riscv/core/offsets/offsets.c | 6 +- arch/riscv/core/reset.S | 6 +- arch/riscv/core/stacktrace.c | 2 +- arch/riscv/core/thread.c | 6 +- boards/qemu/riscv32/board.yml | 1 + ...qemu_riscv32_qemu_virt_riscv32_opensbi.dts | 40 ++ ...emu_riscv32_qemu_virt_riscv32_opensbi.yaml | 15 + ...iscv32_qemu_virt_riscv32_opensbi_defconfig | 32 ++ drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig | 2 + drivers/serial/Kconfig.opensbi_console | 17 + drivers/serial/uart_opensbi_console.c | 79 ++++ drivers/timer/CMakeLists.txt | 1 + drivers/timer/Kconfig | 1 + drivers/timer/Kconfig.riscv_opensbi | 15 + drivers/timer/riscv_opensbi_timer.c | 97 ++++ dts/bindings/serial/opensbi,console-uart.yaml | 10 + dts/riscv/qemu/virt-riscv.dtsi | 2 +- include/zephyr/arch/riscv/arch.h | 20 +- include/zephyr/arch/riscv/csr.h | 71 +++ include/zephyr/arch/riscv/exception.h | 4 +- soc/common/CMakeLists.txt | 2 + soc/common/Kconfig | 2 + soc/common/riscv-opensbi/CMakeLists.txt | 7 + soc/common/riscv-opensbi/Kconfig | 11 + soc/common/riscv-opensbi/opensbi.c | 46 ++ soc/common/riscv-opensbi/opensbi.h | 53 +++ .../riscv-opensbi/sbi_ecall_interface.h | 436 ++++++++++++++++++ soc/common/riscv-privileged/Kconfig | 9 + soc/common/riscv-privileged/soc_common_irq.c | 10 +- soc/common/riscv-privileged/soc_irq.S | 3 +- soc/common/riscv-privileged/vector.S | 9 +- soc/nordic/common/vpr/soc_isr_stacking.h | 6 +- soc/qemu/virt_riscv/Kconfig | 2 +- 39 files changed, 1040 insertions(+), 56 deletions(-) create mode 100644 boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.dts create mode 100644 boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.yaml create mode 100644 boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi_defconfig create mode 100644 drivers/serial/Kconfig.opensbi_console create mode 100644 drivers/serial/uart_opensbi_console.c create mode 100644 drivers/timer/Kconfig.riscv_opensbi create mode 100644 drivers/timer/riscv_opensbi_timer.c create mode 100644 dts/bindings/serial/opensbi,console-uart.yaml create mode 100644 soc/common/riscv-opensbi/CMakeLists.txt create mode 100644 soc/common/riscv-opensbi/Kconfig create mode 100644 soc/common/riscv-opensbi/opensbi.c create mode 100644 soc/common/riscv-opensbi/opensbi.h create mode 100644 soc/common/riscv-opensbi/sbi_ecall_interface.h diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index e731b12af3dc673..65d3d0610ae25ed 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -206,6 +206,25 @@ config RISCV_GENERIC_TOOLCHAIN Allow SOCs that have custom extended riscv ISA to still compile with generic riscv32 toolchain. +config RISCV_KERNEL_IN_USER_MODE + bool "Start zephyr in user mode" + help + Replaces CSR access from machine mode to user mode. + Allows zephyr to run as guest in user mode only + +config RISCV_KERNEL_IN_SUPERVISOR_MODE + bool "Start zephyr in supervisor mode" + help + Replaces CSR access from machine mode to supervisor mode. + Allows zephyr to run as guest in supervisor mode only + +config RISCV_KERNEL_IN_MACHINE_MODE + bool "Start zephyr in supervisor mode" + default y if (!RISCV_KERNEL_IN_SUPERVISOR_MODE) && (!RISCV_KERNEL_IN_USER_MODE) + help + Presets CSR access to machine mode registers. + Allows zephyr to run in machine mode (default for riscv). + config GEN_ISR_TABLES default y diff --git a/arch/riscv/core/cpu_idle.c b/arch/riscv/core/cpu_idle.c index 413b911a53e31e5..6dd82f770bbf871 100644 --- a/arch/riscv/core/cpu_idle.c +++ b/arch/riscv/core/cpu_idle.c @@ -12,7 +12,7 @@ void arch_cpu_idle(void) { sys_trace_idle(); __asm__ volatile("wfi"); - irq_unlock(MSTATUS_IEN); + irq_unlock(XSTATUS_IEN); } #endif diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 3eeb169725079aa..1d62a375287d910 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -79,8 +79,8 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const struct arc #endif /* CONFIG_RISCV_ISA_RV32E */ LOG_ERR(" sp: " PR_REG, z_riscv_get_sp_before_exc(esf)); LOG_ERR(" ra: " PR_REG, esf->ra); - LOG_ERR(" mepc: " PR_REG, esf->mepc); - LOG_ERR("mstatus: " PR_REG, esf->mstatus); + LOG_ERR(" xepc: " PR_REG, esf->xepc); + LOG_ERR("xstatus: " PR_REG, esf->xstatus); LOG_ERR(""); } @@ -209,11 +209,11 @@ void _Fault(struct arch_esf *esf) unsigned long mcause; - __asm__ volatile("csrr %0, mcause" : "=r" (mcause)); + __asm__ volatile("csrr %0," STRINGIFY(xcause) : "=r" (mcause)); #ifndef CONFIG_SOC_OPENISA_RV32M1 unsigned long mtval; - __asm__ volatile("csrr %0, mtval" : "=r" (mtval)); + __asm__ volatile("csrr %0," STRINGIFY(xtval) : "=r" (mtval)); #endif mcause &= CONFIG_RISCV_MCAUSE_EXCEPTION_MASK; diff --git a/arch/riscv/core/irq_manage.c b/arch/riscv/core/irq_manage.c index 358b07534be69b5..6b4ecd7bb35a71f 100644 --- a/arch/riscv/core/irq_manage.c +++ b/arch/riscv/core/irq_manage.c @@ -19,15 +19,15 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); FUNC_NORETURN void z_irq_spurious(const void *unused) { - unsigned long mcause; + unsigned long xcause; ARG_UNUSED(unused); - mcause = csr_read(mcause); + xcause = csr_read(xcause); - mcause &= CONFIG_RISCV_MCAUSE_EXCEPTION_MASK; + xcause &= CONFIG_RISCV_MCAUSE_EXCEPTION_MASK; - LOG_ERR("Spurious interrupt detected! IRQ: %ld", mcause); + LOG_ERR("Spurious interrupt detected! IRQ: %ld", xcause); #if defined(CONFIG_RISCV_HAS_PLIC) if (mcause == RISCV_IRQ_MEXT) { unsigned int save_irq = riscv_plic_get_irq(); diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index bd21fed6b558793..1f8284abca3324c 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -2,6 +2,7 @@ * Copyright (c) 2016 Jean-Paul Etienne * Copyright (c) 2018 Foundries.io Ltd * Copyright (c) 2020 BayLibre, SAS + * Copyright (c) 2024 sensry.io * * SPDX-License-Identifier: Apache-2.0 */ @@ -189,12 +190,12 @@ SECTION_FUNC(exception.entry, _isr_wrapper) get_current_cpu s0 /* Save MEPC register */ - csrr t0, mepc - sr t0, __struct_arch_esf_mepc_OFFSET(sp) + csrr t0, xepc + sr t0, __struct_arch_esf_xepc_OFFSET(sp) /* Save MSTATUS register */ - csrr t2, mstatus - sr t2, __struct_arch_esf_mstatus_OFFSET(sp) + csrr t2, xstatus + sr t2, __struct_arch_esf_xstatus_OFFSET(sp) #if defined(CONFIG_FPU_SHARING) /* determine if FPU access was disabled */ @@ -319,7 +320,7 @@ no_fp: /* increment _current->arch.exception_depth */ jal ra, __soc_is_irq bnez a0, is_interrupt #else - csrr t0, mcause + csrr t0, xcause srli t0, t0, RISCV_MCAUSE_IRQ_POS bnez t0, is_interrupt #endif @@ -329,7 +330,7 @@ no_fp: /* increment _current->arch.exception_depth */ * perform a context-switch or an IRQ offload. Otherwise call _Fault * to report the exception. */ - csrr t0, mcause + csrr t0, xcause li t2, CONFIG_RISCV_MCAUSE_EXCEPTION_MASK and t0, t0, t2 @@ -385,9 +386,9 @@ is_kernel_syscall: * It's safe to always increment by 4, even with compressed * instructions, because the ecall instruction is always 4 bytes. */ - lr t0, __struct_arch_esf_mepc_OFFSET(sp) + lr t0, __struct_arch_esf_xepc_OFFSET(sp) addi t0, t0, 4 - sr t0, __struct_arch_esf_mepc_OFFSET(sp) + sr t0, __struct_arch_esf_xepc_OFFSET(sp) #ifdef CONFIG_PMP_STACK_GUARD /* Re-activate PMP for m-mode */ @@ -505,9 +506,9 @@ is_user_syscall: * Same as for is_kernel_syscall: increment saved MEPC by 4 to * prevent triggering the same ecall again upon exiting the ISR. */ - lr t1, __struct_arch_esf_mepc_OFFSET(sp) + lr t1, __struct_arch_esf_xepc_OFFSET(sp) addi t1, t1, 4 - sr t1, __struct_arch_esf_mepc_OFFSET(sp) + sr t1, __struct_arch_esf_xepc_OFFSET(sp) /* Restore argument registers from user stack */ lr a0, __struct_arch_esf_a0_OFFSET(sp) @@ -565,7 +566,7 @@ is_interrupt: * If we came from userspace then we need to reconfigure the * PMP for kernel mode stack guard. */ - lr t0, __struct_arch_esf_mstatus_OFFSET(sp) + lr t0, __struct_arch_esf_xstatus_OFFSET(sp) li t1, MSTATUS_MPP and t0, t0, t1 bnez t0, 1f @@ -609,7 +610,7 @@ on_irq_stack: #endif /* Get IRQ causing interrupt */ - csrr a0, mcause + csrr a0, xcause li t0, CONFIG_RISCV_MCAUSE_EXCEPTION_MASK and a0, a0, t0 @@ -714,10 +715,10 @@ fp_trap_exit: #endif /* Restore MEPC and MSTATUS registers */ - lr t0, __struct_arch_esf_mepc_OFFSET(sp) - lr t2, __struct_arch_esf_mstatus_OFFSET(sp) - csrw mepc, t0 - csrw mstatus, t2 + lr t0, __struct_arch_esf_xepc_OFFSET(sp) + lr t2, __struct_arch_esf_xstatus_OFFSET(sp) + csrw xepc, t0 + csrw xstatus, t2 #ifdef CONFIG_USERSPACE /* @@ -775,4 +776,4 @@ fp_trap_exit: #endif /* CONFIG_RISCV_SOC_HAS_ISR_STACKING */ - mret + xret diff --git a/arch/riscv/core/offsets/offsets.c b/arch/riscv/core/offsets/offsets.c index 7b2d55953b29bb3..c4138c6ce216c94 100644 --- a/arch/riscv/core/offsets/offsets.c +++ b/arch/riscv/core/offsets/offsets.c @@ -13,9 +13,9 @@ * structures. */ -#include #include #include +#include #include #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE @@ -109,8 +109,8 @@ GEN_OFFSET_STRUCT(arch_esf, a6); GEN_OFFSET_STRUCT(arch_esf, a7); #endif /* !CONFIG_RISCV_ISA_RV32E */ -GEN_OFFSET_STRUCT(arch_esf, mepc); -GEN_OFFSET_STRUCT(arch_esf, mstatus); +GEN_OFFSET_STRUCT(arch_esf, xepc); +GEN_OFFSET_STRUCT(arch_esf, xstatus); GEN_OFFSET_STRUCT(arch_esf, s0); diff --git a/arch/riscv/core/reset.S b/arch/riscv/core/reset.S index 89c488faa94756a..08b6010f20d1c3f 100644 --- a/arch/riscv/core/reset.S +++ b/arch/riscv/core/reset.S @@ -38,7 +38,11 @@ SECTION_FUNC(reset, __reset) * the C domain */ SECTION_FUNC(TEXT, __initialize) - csrr a0, mhartid +#ifdef CONFIG_RISCV_HAS_HART_ID + csrr a0, xhartid +#else + li a0, CONFIG_RV_BOOT_HART +#endif li t0, CONFIG_RV_BOOT_HART beq a0, t0, boot_first_core j boot_secondary_core diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index 25a46205c147449..f92f5c273d52688 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -199,7 +199,7 @@ static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const stru if (esf != NULL) { /* Unwind the provided exception stack frame */ sp = z_riscv_get_sp_before_exc(esf); - ra = esf->mepc; + ra = esf->xepc; } else if ((csf == NULL) || (csf == &_current->callee_saved)) { /* Unwind current thread (default case when nothing is provided ) */ sp = current_stack_pointer; diff --git a/arch/riscv/core/thread.c b/arch/riscv/core/thread.c index aeb33b31f3b1f0f..8baa6d756bb919b 100644 --- a/arch/riscv/core/thread.c +++ b/arch/riscv/core/thread.c @@ -63,7 +63,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, * counter will be restored following the MEPC value set within the * thread stack. */ - stack_init->mstatus = MSTATUS_DEF_RESTORE; + stack_init->xstatus = XSTATUS_DEF_RESTORE; #if defined(CONFIG_FPU_SHARING) /* thread birth happens through the exception return path */ @@ -83,11 +83,11 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, if (IS_ENABLED(CONFIG_USERSPACE) && (thread->base.user_options & K_USER)) { /* User thread */ - stack_init->mepc = (unsigned long)k_thread_user_mode_enter; + stack_init->xepc = (unsigned long)k_thread_user_mode_enter; } else { /* Supervisor thread */ - stack_init->mepc = (unsigned long)z_thread_entry; + stack_init->xepc = (unsigned long)z_thread_entry; #if defined(CONFIG_PMP_STACK_GUARD) /* Enable PMP in mstatus.MPRV mode for RISC-V machine mode diff --git a/boards/qemu/riscv32/board.yml b/boards/qemu/riscv32/board.yml index 0ba208612a9906b..7981fdfe2e5b661 100644 --- a/boards/qemu/riscv32/board.yml +++ b/boards/qemu/riscv32/board.yml @@ -5,3 +5,4 @@ board: - name: qemu_virt_riscv32 variants: - name: smp + - name: opensbi diff --git a/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.dts b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.dts new file mode 100644 index 000000000000000..312f8f528548a7c --- /dev/null +++ b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.dts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 sensry.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + console0: console { + compatible = "opensbi,console-uart"; + foo = "abc"; + status = "okay"; + }; + + chosen { + zephyr,console = &console0; + zephyr,shell-uart = &console0; + zephyr,sram = &ram0; + }; +}; + +&ram0 { + device_type = "memory"; + reg = < 0x80400000 0x100000 >; +}; + +&uart0 { + status = "disabled"; +}; + +&plic { + status = "disabled"; +}; + +&clint{ + status = "disabled"; +}; diff --git a/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.yaml b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.yaml new file mode 100644 index 000000000000000..9a7faa0b68d285d --- /dev/null +++ b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.yaml @@ -0,0 +1,15 @@ +identifier: qemu_riscv32/qemu_virt_riscv32/opensbi +name: QEMU Emulation for RISC-V 32-bit openSBI +type: qemu +simulation: qemu +arch: riscv +toolchain: + - zephyr + - xtools +supported: + - netif +testing: + default: true + ignore_tags: + - net + - bluetooth diff --git a/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi_defconfig b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi_defconfig new file mode 100644 index 000000000000000..355331a0f72ba36 --- /dev/null +++ b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi_defconfig @@ -0,0 +1,32 @@ +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_STACK_SENTINEL=y +CONFIG_XIP=n +CONFIG_RISCV_PMP=y +CONFIG_SMP=y +CONFIG_MP_MAX_NUM_CPUS=1 +CONFIG_IDLE_STACK_SIZE=1024 +CONFIG_QEMU_ICOUNT=n + +# enable the openSBI support, requires a compiled version of openSBI binary in machine mode +CONFIG_RISCV_OPENSBI=y + +# we run zephyr in supervisor mode +CONFIG_RISCV_KERNEL_IN_SUPERVISOR_MODE=y +CONFIG_RISCV_MACHINE_TIMER=n + +# options that have to be disabled by now +CONFIG_USERSPACE=n +CONFIG_RISCV_HAS_HART_ID=n +CONFIG_SMP=n +CONFIG_RISCV_PMP=n + +# build output for qemu +CONFIG_BUILD_OUTPUT_BIN=y + + +CONFIG_THREAD_MONITOR=n diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index bbb7da14a9936f7..ce82848794b41e1 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -78,6 +78,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_RZT2M uart_rzt2m.c) zephyr_library_sources_ifdef(CONFIG_UART_RA8_SCI_B uart_renesas_ra8_sci_b.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c) zephyr_library_sources_ifdef(CONFIG_UART_SCI_RA uart_renesas_ra_sci.c) +zephyr_library_sources_ifdef(CONFIG_UART_OPENSBI_CONSOLE uart_opensbi_console.c) if(CONFIG_UART_NATIVE_POSIX) zephyr_library_compile_definitions(NO_POSIX_CHEATS) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ef557d090fc7734..c07373f3a206ee4 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -280,4 +280,6 @@ rsource "Kconfig.rzt2m" rsource "Kconfig.renesas_ra8" +rsource "Kconfig.opensbi_console" + endif # SERIAL diff --git a/drivers/serial/Kconfig.opensbi_console b/drivers/serial/Kconfig.opensbi_console new file mode 100644 index 000000000000000..259f4eac1523355 --- /dev/null +++ b/drivers/serial/Kconfig.opensbi_console @@ -0,0 +1,17 @@ +# openSBI Console UART driver configuration options + +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + + +if RISCV_OPENSBI + +config UART_OPENSBI_CONSOLE + bool "openSBI console serial driver" + default y + select SERIAL_HAS_DRIVER + help + This option enables the console driver for openSBI based RISCV family of + processors. + +endif # RISCV_OPENSBI diff --git a/drivers/serial/uart_opensbi_console.c b/drivers/serial/uart_opensbi_console.c new file mode 100644 index 000000000000000..a4281e091fe3037 --- /dev/null +++ b/drivers/serial/uart_opensbi_console.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 sensry.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT opensbi_console_uart + +#include +#include +#include +#include + +struct opensbi_console_config { + uint32_t instance; +}; + +struct opensbi_console_data { + uint32_t dummy; +}; + +static int opensbi_console_init(const struct device *dev) +{ + return 0; +} + +/* + * it should be avoided to read single characters only + */ +static int opensbi_console_poll_in(const struct device *dev, unsigned char *c) +{ + return -1; +} + + +/* + * it should be avoided to write single characters only + */ +static void opensbi_console_poll_out(const struct device *dev, unsigned char c) +{ + /* workaround: openSBI does handle '\r' a little strange */ + if (c == '\r') { + return; + } + sbi_console_put_char(c); +} + +static int opensbi_console_err_check(const struct device *dev) +{ + return 0; +} + +static const struct uart_driver_api opensbi_console_driver_api = { + + .poll_in = opensbi_console_poll_in, + .poll_out = opensbi_console_poll_out, + .err_check = opensbi_console_err_check, + +}; + + +#define OPENSBI_CONSOLE_INIT(n) \ + \ + static const struct opensbi_console_config opensbi_console_##n##_cfg = { \ + }; \ + \ + static struct opensbi_console_data opensbi_console_##n##_data = { \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &opensbi_console_init, \ + NULL, \ + &opensbi_console_##n##_data, \ + &opensbi_console_##n##_cfg, \ + PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, \ + &opensbi_console_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(OPENSBI_CONSOLE_INIT) diff --git a/drivers/timer/CMakeLists.txt b/drivers/timer/CMakeLists.txt index ac5bac6c244ad95..c8e8a705b50ce27 100644 --- a/drivers/timer/CMakeLists.txt +++ b/drivers/timer/CMakeLists.txt @@ -37,3 +37,4 @@ zephyr_library_sources_ifdef(CONFIG_XLNX_PSTTC_TIMER xlnx_psttc_timer.c) zephyr_library_sources_ifdef(CONFIG_XTENSA_TIMER xtensa_sys_timer.c) zephyr_library_sources_ifdef(CONFIG_SMARTBOND_TIMER smartbond_timer.c) zephyr_library_sources_ifdef(CONFIG_MTK_ADSP_TIMER mtk_adsp_timer.c) +zephyr_library_sources_ifdef(CONFIG_RISCV_OPENSBI_TIMER riscv_opensbi_timer.c) diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 3343f78d79ce06a..b8283ff6f1315de 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -96,6 +96,7 @@ source "drivers/timer/Kconfig.ti_dm_timer" source "drivers/timer/Kconfig.xlnx_psttc" source "drivers/timer/Kconfig.xtensa" source "drivers/timer/Kconfig.mtk_adsp" +source "drivers/timer/Kconfig.riscv_opensbi" endmenu diff --git a/drivers/timer/Kconfig.riscv_opensbi b/drivers/timer/Kconfig.riscv_opensbi new file mode 100644 index 000000000000000..d8e5e91d7315fab --- /dev/null +++ b/drivers/timer/Kconfig.riscv_opensbi @@ -0,0 +1,15 @@ +# openSBI timer driver configuration options + +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + + +if RISCV_OPENSBI + +config RISCV_OPENSBI_TIMER + bool "RISCV openSBI Timer" + default y + help + This enabled the use of openSBI timer to trigger the zephyr scheduler + +endif diff --git a/drivers/timer/riscv_opensbi_timer.c b/drivers/timer/riscv_opensbi_timer.c new file mode 100644 index 000000000000000..ea6749a665dc2ec --- /dev/null +++ b/drivers/timer/riscv_opensbi_timer.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024 sensry.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include + +static struct k_spinlock lock; +static uint64_t last_count; +static uint64_t last_ticks; +static uint32_t last_elapsed; + +#define TIMER_IRQN 0x5 +#define CYC_PER_TICK (100000) + +static uint64_t xtime(void) +{ + unsigned int current_time; + + __asm__ volatile("rdtime %0" : "=r"(current_time)); + + return current_time; +} + +static uintptr_t get_hart_xtimecmp(void) +{ + return xtime(); +} + +static void set_xtimecmp(uint64_t next_time) +{ + uint32_t time_low = (uint32_t) next_time; + uint32_t time_high = (uint32_t) (next_time >> 32); + + sbi_console_set_timer(time_low, time_high); +} + +static void timer_isr(const void *arg) +{ + ARG_UNUSED(arg); + + k_spinlock_key_t key = k_spin_lock(&lock); + + uint64_t now = xtime(); + + set_xtimecmp(now + CYC_PER_TICK); + + k_spin_unlock(&lock, key); + sys_clock_announce(1); +} + +uint32_t sys_clock_cycle_get_32(void) +{ + return xtime(); +} + +uint32_t sys_clock_elapsed(void) +{ + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + return 0; + } + + k_spinlock_key_t key = k_spin_lock(&lock); + uint64_t now = xtime(); + uint64_t dcycles = now - last_count; + uint32_t dticks = (uint32_t) dcycles / CYC_PER_TICK; + + last_elapsed = dticks; + k_spin_unlock(&lock, key); + return dticks; +} + + +static int sys_clock_driver_init(void) +{ + + IRQ_CONNECT(TIMER_IRQN, 0, timer_isr, NULL, 0); + + last_ticks = xtime(); + set_xtimecmp(last_ticks + CYC_PER_TICK); + irq_enable(TIMER_IRQN); + + arch_irq_unlock(XSTATUS_IEN); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/dts/bindings/serial/opensbi,console-uart.yaml b/dts/bindings/serial/opensbi,console-uart.yaml new file mode 100644 index 000000000000000..1d5f0a5805653b1 --- /dev/null +++ b/dts/bindings/serial/opensbi,console-uart.yaml @@ -0,0 +1,10 @@ +description: OpenSBI Console UART + +compatible: "opensbi,console-uart" + +include: [base.yaml] + +properties: + foo: + type: string + required: true diff --git a/dts/riscv/qemu/virt-riscv.dtsi b/dts/riscv/qemu/virt-riscv.dtsi index 8329a1ec62b8c87..b810f9fe7dcba29 100644 --- a/dts/riscv/qemu/virt-riscv.dtsi +++ b/dts/riscv/qemu/virt-riscv.dtsi @@ -181,7 +181,7 @@ #interrupt-cells = < 0x02 >; }; - clint@2000000 { + clint: clint@2000000 { compatible = "sifive,clint0"; reg = <0x2000000 0x10000>; interrupts-extended = <&hlic0 0x03 &hlic0 0x07 diff --git a/include/zephyr/arch/riscv/arch.h b/include/zephyr/arch/riscv/arch.h index 2bd19c5f267b47e..7fcce367fc8ddf5 100644 --- a/include/zephyr/arch/riscv/arch.h +++ b/include/zephyr/arch/riscv/arch.h @@ -171,6 +171,12 @@ #define MSTATUS_FS_CLEAN (2UL << 13) #define MSTATUS_FS_DIRTY (3UL << 13) +#define SSTATUS_IEN (1UL << 1) +#define SSTATUS_UPIE_IEN (1UL << 5) + +#define USTATUS_IEN (1UL << 0) +#define USTATUS_UPIE_IEN (1UL << 4) + /* This comes from openisa_rv32m1, but doesn't seem to hurt on other * platforms: * - Preserve machine privileges in MPP. If you see any documentation @@ -180,6 +186,8 @@ * by setting MPIE now, so it will be copied into IE on mret. */ #define MSTATUS_DEF_RESTORE (MSTATUS_MPP_M | MSTATUS_MPIE_EN) +#define SSTATUS_DEF_RESTORE (SSTATUS_SPP | SSTATUS_UPIE_IEN | SSTATUS_IEN) +#define USTATUS_DEF_RESTORE (USTATUS_UPIE_IEN | USTATUS_IEN) #ifndef _ASMLANGUAGE #include @@ -243,9 +251,9 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void) #else unsigned int key; - __asm__ volatile ("csrrc %0, mstatus, %1" + __asm__ volatile ("csrrc %0, %1, %2" : "=r" (key) - : "rK" (MSTATUS_IEN) + : "i" (XSTATUS), "rK" (XSTATUS_IEN) : "memory"); return key; @@ -259,11 +267,12 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void) static ALWAYS_INLINE void arch_irq_unlock(unsigned int key) { #ifdef CONFIG_RISCV_SOC_HAS_CUSTOM_IRQ_LOCK_OPS + extern void z_soc_irq_unlock(unsigned int key); z_soc_irq_unlock(key); #else - __asm__ volatile ("csrs mstatus, %0" + __asm__ volatile ("csrs %0, %1" : - : "r" (key & MSTATUS_IEN) + : "i" (XSTATUS), "r" (key & XSTATUS_IEN) : "memory"); #endif } @@ -271,9 +280,10 @@ static ALWAYS_INLINE void arch_irq_unlock(unsigned int key) static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) { #ifdef CONFIG_RISCV_SOC_HAS_CUSTOM_IRQ_LOCK_OPS + extern bool z_soc_irq_unlocked(unsigned int key); return z_soc_irq_unlocked(key); #else - return (key & MSTATUS_IEN) != 0; + return (key & XSTATUS_IEN) != 0; #endif } diff --git a/include/zephyr/arch/riscv/csr.h b/include/zephyr/arch/riscv/csr.h index 70e6e817b630ae7..a51b87b8cb47e19 100644 --- a/include/zephyr/arch/riscv/csr.h +++ b/include/zephyr/arch/riscv/csr.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2020 Michael Schaffner * Copyright (c) 2020 BayLibre, SAS + * Copyright (c) 2024 sensry.io * * SPDX-License-Identifier: SHL-0.51 * SPDX-License-Identifier: Apache-2.0 @@ -233,4 +234,74 @@ : "memory"); \ }) +/* uhartid -- user hardware thread id, seems to be not yet defined in toolchain */ +#ifdef CONFIG_RISCV_KERNEL_IN_USER_MODE + /* zephyr runs in user mode */ + + /* inline assembly defines */ + #define XSTATUS_IEN USTATUS_IEN + #define XSTATUS_DEF_RESTORE USTATUS_DEF_RESTORE + #define XSTATUS 0x000 + + /* register definition for assembly */ +#ifdef CONFIG_RISCV_HAS_HART_ID + #define uhartid 0x014 + #define xhartid uhartid +#endif + + #define xscratch uscratch + #define xstatus ustatus + #define xepc uepc + #define xcause ucause + #define xret uret + #define xtvec utvec + #define xie uie + #define xip uip + #define xtval utval +#elif CONFIG_RISCV_KERNEL_IN_SUPERVISOR_MODE + /* zephyr runs in supervisor mode */ + + /* inline assembly defines */ + #define XSTATUS_IEN SSTATUS_IEN + #define XSTATUS_DEF_RESTORE SSTATUS_DEF_RESTORE + #define XSTATUS 0x100 + + /* register definition for assembly */ +#ifdef CONFIG_RISCV_HAS_HART_ID + #define shartid 0x7D2 + #define xhartid shartid +#endif + + #define xscratch sscratch + #define xstatus sstatus + #define xepc sepc + #define xcause scause + #define xret sret + #define xtvec stvec + #define xie sie + #define xip sip + #define xtval stval +#elif CONFIG_RISCV_KERNEL_IN_MACHINE_MODE + /* default: zephyr runs in machine mode */ + + /* inline assembly defines */ + #define XSTATUS_IEN MSTATUS_IEN + #define XSTATUS_DEF_RESTORE MSTATUS_DEF_RESTORE + #define XSTATUS 0x300 + + /* register definition for assembly */ + #define xhartid mhartid + #define xscratch mscratch + #define xstatus mstatus + #define xepc mepc + #define xcause mcause + #define xret mret + #define xtvec mtvec + #define xie mie + #define xip mip + #define xtval mtval +#else + #error "missing mode" +#endif + #endif /* CSR_H_ */ diff --git a/include/zephyr/arch/riscv/exception.h b/include/zephyr/arch/riscv/exception.h index 097776227bb4729..b56159fa7cc6aeb 100644 --- a/include/zephyr/arch/riscv/exception.h +++ b/include/zephyr/arch/riscv/exception.h @@ -72,8 +72,8 @@ struct arch_esf { unsigned long a7; /* function argument */ #endif /* !CONFIG_RISCV_ISA_RV32E */ - unsigned long mepc; /* machine exception program counter */ - unsigned long mstatus; /* machine status register */ + unsigned long xepc; /* machine exception program counter */ + unsigned long xstatus; /* machine status register */ unsigned long s0; /* callee-saved s0 */ diff --git a/soc/common/CMakeLists.txt b/soc/common/CMakeLists.txt index 8deca3ca0e0862b..56ffaba3ac70330 100644 --- a/soc/common/CMakeLists.txt +++ b/soc/common/CMakeLists.txt @@ -1,4 +1,6 @@ # Copyright (c) 2024 Nordic Semiconductor ASA +# Copyright (c) 2024 sensry.io # SPDX-License-Identifier: Apache-2.0 +add_subdirectory_ifdef(CONFIG_RISCV_OPENSBI riscv-opensbi) add_subdirectory_ifdef(CONFIG_RISCV_PRIVILEGED riscv-privileged) diff --git a/soc/common/Kconfig b/soc/common/Kconfig index 3f8105b36899062..9802a2603979c56 100644 --- a/soc/common/Kconfig +++ b/soc/common/Kconfig @@ -1,6 +1,8 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +rsource "riscv-opensbi/Kconfig" + if RISCV_PRIVILEGED rsource "riscv-privileged/Kconfig" diff --git a/soc/common/riscv-opensbi/CMakeLists.txt b/soc/common/riscv-opensbi/CMakeLists.txt new file mode 100644 index 000000000000000..61ebf5747b3de82 --- /dev/null +++ b/soc/common/riscv-opensbi/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(.) + +zephyr_sources( + opensbi.c +) diff --git a/soc/common/riscv-opensbi/Kconfig b/soc/common/riscv-opensbi/Kconfig new file mode 100644 index 000000000000000..5c9bec46863dc7d --- /dev/null +++ b/soc/common/riscv-opensbi/Kconfig @@ -0,0 +1,11 @@ +# Configuration options for riscv SOCs supporting the riscv openSBI +# interface + +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + +config RISCV_OPENSBI + bool "openSBI support for RISCV SOCs" + help + This is the "master" switch to enable the support + for openSBI drivers. diff --git a/soc/common/riscv-opensbi/opensbi.c b/soc/common/riscv-opensbi/opensbi.c new file mode 100644 index 000000000000000..036abc5cd12d49c --- /dev/null +++ b/soc/common/riscv-opensbi/opensbi.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 sensry.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include + +#include "opensbi.h" + +#include "zephyr/arch/riscv/arch.h" + + +sbi_ret_t user_mode_sbi_ecall(int ext, int fid, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5) +{ + uint32_t irq = arch_irq_lock(); + + volatile sbi_ret_t ret; + + register unsigned long a0 __asm__ ("a0") = (unsigned long) (arg0); + register unsigned long a1 __asm__ ("a1") = (unsigned long) (arg1); + register unsigned long a2 __asm__ ("a2") = (unsigned long) (arg2); + register unsigned long a3 __asm__ ("a3") = (unsigned long) (arg3); + register unsigned long a4 __asm__ ("a4") = (unsigned long) (arg4); + register unsigned long a5 __asm__ ("a5") = (unsigned long) (arg5); + register unsigned long a6 __asm__ ("a6") = (unsigned long) (fid); + register unsigned long a7 __asm__ ("a7") = (unsigned long) (ext); + __asm__ volatile ("ecall" + : "+r" (a0), "+r" (a1) + : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) + : "memory"); + ret.error = (int32_t) a0; + ret.value = a1; + + + if (irq) { + arch_irq_unlock(irq); + } + + + return ret; +} diff --git a/soc/common/riscv-opensbi/opensbi.h b/soc/common/riscv-opensbi/opensbi.h new file mode 100644 index 000000000000000..5e814222d0b8357 --- /dev/null +++ b/soc/common/riscv-opensbi/opensbi.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 sensry.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#ifndef OPENSBI_H +#define OPENSBI_H + +#include "sbi_ecall_interface.h" + +typedef struct sbi_ret { + int32_t error; + uint32_t value; +} sbi_ret_t; + +extern sbi_ret_t user_mode_sbi_ecall(int ext, int fid, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5); + +/* --- VERSION --- */ +static inline sbi_ret_t sbi_version_get(void) +{ + return user_mode_sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION, 0, 0, 0, 0, 0, 0); +} + +/* --- CONSOLE --- */ +static inline sbi_ret_t sbi_console_put_char(char c) +{ + return user_mode_sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE_BYTE, c, 0, 0, 0, 0, 0); +} + +static inline sbi_ret_t sbi_console_puts(char *str, uint32_t len) +{ + return user_mode_sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE, len, (unsigned long) str, + 0, 0, 0, 0); +} + +static inline sbi_ret_t sbi_console_get_string(char *str, int32_t size) +{ + return user_mode_sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ, size, (uint32_t) str, + 0, 0, 0, 0); +} + +/* --- TIMER --- */ +static inline sbi_ret_t sbi_console_set_timer(uint32_t timeL, uint32_t timeH) +{ + return user_mode_sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, timeL, timeH, 0, 0, 0, 0); +} + +#endif //OPENSBI_H diff --git a/soc/common/riscv-opensbi/sbi_ecall_interface.h b/soc/common/riscv-opensbi/sbi_ecall_interface.h new file mode 100644 index 000000000000000..e9a8167760a9d1e --- /dev/null +++ b/soc/common/riscv-opensbi/sbi_ecall_interface.h @@ -0,0 +1,436 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + */ + +#ifndef __SBI_ECALL_INTERFACE_H__ +#define __SBI_ECALL_INTERFACE_H__ + +/* clang-format off */ + +/* SBI Extension IDs */ +#define SBI_EXT_0_1_SET_TIMER 0x0 +#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1 +#define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2 +#define SBI_EXT_0_1_CLEAR_IPI 0x3 +#define SBI_EXT_0_1_SEND_IPI 0x4 +#define SBI_EXT_0_1_REMOTE_FENCE_I 0x5 +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA 0x6 +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID 0x7 +#define SBI_EXT_0_1_SHUTDOWN 0x8 +#define SBI_EXT_BASE 0x10 +#define SBI_EXT_TIME 0x54494D45 +#define SBI_EXT_IPI 0x735049 +#define SBI_EXT_RFENCE 0x52464E43 +#define SBI_EXT_HSM 0x48534D +#define SBI_EXT_SRST 0x53525354 +#define SBI_EXT_PMU 0x504D55 +#define SBI_EXT_DBCN 0x4442434E +#define SBI_EXT_SUSP 0x53555350 +#define SBI_EXT_CPPC 0x43505043 +#define SBI_EXT_DBTR 0x44425452 +#define SBI_EXT_SSE 0x535345 +#define SBI_EXT_FWFT 0x46574654 + +/* SBI function IDs for BASE extension*/ +#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0 +#define SBI_EXT_BASE_GET_IMP_ID 0x1 +#define SBI_EXT_BASE_GET_IMP_VERSION 0x2 +#define SBI_EXT_BASE_PROBE_EXT 0x3 +#define SBI_EXT_BASE_GET_MVENDORID 0x4 +#define SBI_EXT_BASE_GET_MARCHID 0x5 +#define SBI_EXT_BASE_GET_MIMPID 0x6 + +/* SBI function IDs for TIME extension*/ +#define SBI_EXT_TIME_SET_TIMER 0x0 + +/* SBI function IDs for IPI extension*/ +#define SBI_EXT_IPI_SEND_IPI 0x0 + +/* SBI function IDs for RFENCE extension*/ +#define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0 +#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA 0x1 +#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID 0x2 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID 0x3 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA 0x4 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID 0x5 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA 0x6 + +/* SBI function IDs for HSM extension */ +#define SBI_EXT_HSM_HART_START 0x0 +#define SBI_EXT_HSM_HART_STOP 0x1 +#define SBI_EXT_HSM_HART_GET_STATUS 0x2 +#define SBI_EXT_HSM_HART_SUSPEND 0x3 + +#define SBI_HSM_STATE_STARTED 0x0 +#define SBI_HSM_STATE_STOPPED 0x1 +#define SBI_HSM_STATE_START_PENDING 0x2 +#define SBI_HSM_STATE_STOP_PENDING 0x3 +#define SBI_HSM_STATE_SUSPENDED 0x4 +#define SBI_HSM_STATE_SUSPEND_PENDING 0x5 +#define SBI_HSM_STATE_RESUME_PENDING 0x6 + +#define SBI_HSM_SUSP_BASE_MASK 0x7fffffff +#define SBI_HSM_SUSP_NON_RET_BIT 0x80000000 +#define SBI_HSM_SUSP_PLAT_BASE 0x10000000 + +#define SBI_HSM_SUSPEND_RET_DEFAULT 0x00000000 +#define SBI_HSM_SUSPEND_RET_PLATFORM SBI_HSM_SUSP_PLAT_BASE +#define SBI_HSM_SUSPEND_RET_LAST SBI_HSM_SUSP_BASE_MASK +#define SBI_HSM_SUSPEND_NON_RET_DEFAULT SBI_HSM_SUSP_NON_RET_BIT +#define SBI_HSM_SUSPEND_NON_RET_PLATFORM (SBI_HSM_SUSP_NON_RET_BIT | \ + SBI_HSM_SUSP_PLAT_BASE) +#define SBI_HSM_SUSPEND_NON_RET_LAST (SBI_HSM_SUSP_NON_RET_BIT | \ + SBI_HSM_SUSP_BASE_MASK) + +/* SBI function IDs for SRST extension */ +#define SBI_EXT_SRST_RESET 0x0 + +#define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0 +#define SBI_SRST_RESET_TYPE_COLD_REBOOT 0x1 +#define SBI_SRST_RESET_TYPE_WARM_REBOOT 0x2 +#define SBI_SRST_RESET_TYPE_LAST SBI_SRST_RESET_TYPE_WARM_REBOOT + +#define SBI_SRST_RESET_REASON_NONE 0x0 +#define SBI_SRST_RESET_REASON_SYSFAIL 0x1 + +/* SBI function IDs for PMU extension */ +#define SBI_EXT_PMU_NUM_COUNTERS 0x0 +#define SBI_EXT_PMU_COUNTER_GET_INFO 0x1 +#define SBI_EXT_PMU_COUNTER_CFG_MATCH 0x2 +#define SBI_EXT_PMU_COUNTER_START 0x3 +#define SBI_EXT_PMU_COUNTER_STOP 0x4 +#define SBI_EXT_PMU_COUNTER_FW_READ 0x5 +#define SBI_EXT_PMU_COUNTER_FW_READ_HI 0x6 +#define SBI_EXT_PMU_SNAPSHOT_SET_SHMEM 0x7 + +/* SBI function IDs for DBTR extension */ +#define SBI_EXT_DBTR_NUM_TRIGGERS 0x0 +#define SBI_EXT_DBTR_SETUP_SHMEM 0x1 +#define SBI_EXT_DBTR_TRIGGER_READ 0x2 +#define SBI_EXT_DBTR_TRIGGER_INSTALL 0x3 +#define SBI_EXT_DBTR_TRIGGER_UPDATE 0x4 +#define SBI_EXT_DBTR_TRIGGER_UNINSTALL 0x5 +#define SBI_EXT_DBTR_TRIGGER_ENABLE 0x6 +#define SBI_EXT_DBTR_TRIGGER_DISABLE 0x7 + +/* SBI function IDs for FW feature extension */ +#define SBI_EXT_FWFT_SET 0x0 +#define SBI_EXT_FWFT_GET 0x1 + +enum sbi_fwft_feature_t { + SBI_FWFT_MISALIGNED_EXC_DELEG = 0x0, + SBI_FWFT_LANDING_PAD = 0x1, + SBI_FWFT_SHADOW_STACK = 0x2, + SBI_FWFT_DOUBLE_TRAP = 0x3, + SBI_FWFT_PTE_AD_HW_UPDATING = 0x4, + SBI_FWFT_LOCAL_RESERVED_START = 0x5, + SBI_FWFT_LOCAL_RESERVED_END = 0x3fffffff, + SBI_FWFT_LOCAL_PLATFORM_START = 0x40000000, + SBI_FWFT_LOCAL_PLATFORM_END = 0x7fffffff, + + SBI_FWFT_GLOBAL_RESERVED_START = 0x80000000, + SBI_FWFT_GLOBAL_RESERVED_END = 0xbfffffff, + SBI_FWFT_GLOBAL_PLATFORM_START = 0xc0000000, + SBI_FWFT_GLOBAL_PLATFORM_END = 0xffffffff, +}; + +#define SBI_FWFT_GLOBAL_FEATURE_BIT (1 << 31) +#define SBI_FWFT_PLATFORM_FEATURE_BIT (1 << 30) + +#define SBI_FWFT_SET_FLAG_LOCK (1 << 0) + +/** General pmu event codes specified in SBI PMU extension */ +enum sbi_pmu_hw_generic_events_t { + SBI_PMU_HW_NO_EVENT = 0, + SBI_PMU_HW_CPU_CYCLES = 1, + SBI_PMU_HW_INSTRUCTIONS = 2, + SBI_PMU_HW_CACHE_REFERENCES = 3, + SBI_PMU_HW_CACHE_MISSES = 4, + SBI_PMU_HW_BRANCH_INSTRUCTIONS = 5, + SBI_PMU_HW_BRANCH_MISSES = 6, + SBI_PMU_HW_BUS_CYCLES = 7, + SBI_PMU_HW_STALLED_CYCLES_FRONTEND = 8, + SBI_PMU_HW_STALLED_CYCLES_BACKEND = 9, + SBI_PMU_HW_REF_CPU_CYCLES = 10, + + SBI_PMU_HW_GENERAL_MAX, +}; + +/** + * Generalized hardware cache events: + * + * { L1-D, L1-I, LLC, ITLB, DTLB, BPU, NODE } x + * { read, write, prefetch } x + * { accesses, misses } + */ +enum sbi_pmu_hw_cache_id { + SBI_PMU_HW_CACHE_L1D = 0, + SBI_PMU_HW_CACHE_L1I = 1, + SBI_PMU_HW_CACHE_LL = 2, + SBI_PMU_HW_CACHE_DTLB = 3, + SBI_PMU_HW_CACHE_ITLB = 4, + SBI_PMU_HW_CACHE_BPU = 5, + SBI_PMU_HW_CACHE_NODE = 6, + + SBI_PMU_HW_CACHE_MAX, +}; + +enum sbi_pmu_hw_cache_op_id { + SBI_PMU_HW_CACHE_OP_READ = 0, + SBI_PMU_HW_CACHE_OP_WRITE = 1, + SBI_PMU_HW_CACHE_OP_PREFETCH = 2, + + SBI_PMU_HW_CACHE_OP_MAX, +}; + +enum sbi_pmu_hw_cache_op_result_id { + SBI_PMU_HW_CACHE_RESULT_ACCESS = 0, + SBI_PMU_HW_CACHE_RESULT_MISS = 1, + + SBI_PMU_HW_CACHE_RESULT_MAX, +}; + +/** + * Special "firmware" events provided by the OpenSBI, even if the hardware + * does not support performance events. These events are encoded as a raw + * event type in Linux kernel perf framework. + */ +enum sbi_pmu_fw_event_code_id { + SBI_PMU_FW_MISALIGNED_LOAD = 0, + SBI_PMU_FW_MISALIGNED_STORE = 1, + SBI_PMU_FW_ACCESS_LOAD = 2, + SBI_PMU_FW_ACCESS_STORE = 3, + SBI_PMU_FW_ILLEGAL_INSN = 4, + SBI_PMU_FW_SET_TIMER = 5, + SBI_PMU_FW_IPI_SENT = 6, + SBI_PMU_FW_IPI_RECVD = 7, + SBI_PMU_FW_FENCE_I_SENT = 8, + SBI_PMU_FW_FENCE_I_RECVD = 9, + SBI_PMU_FW_SFENCE_VMA_SENT = 10, + SBI_PMU_FW_SFENCE_VMA_RCVD = 11, + SBI_PMU_FW_SFENCE_VMA_ASID_SENT = 12, + SBI_PMU_FW_SFENCE_VMA_ASID_RCVD = 13, + + SBI_PMU_FW_HFENCE_GVMA_SENT = 14, + SBI_PMU_FW_HFENCE_GVMA_RCVD = 15, + SBI_PMU_FW_HFENCE_GVMA_VMID_SENT = 16, + SBI_PMU_FW_HFENCE_GVMA_VMID_RCVD = 17, + + SBI_PMU_FW_HFENCE_VVMA_SENT = 18, + SBI_PMU_FW_HFENCE_VVMA_RCVD = 19, + SBI_PMU_FW_HFENCE_VVMA_ASID_SENT = 20, + SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD = 21, + SBI_PMU_FW_MAX, + /* + * Event codes 22 to 255 are reserved for future use. + * Event codes 256 to 65534 are reserved for SBI implementation + * specific custom firmware events. + */ + SBI_PMU_FW_RESERVED_MAX = 0xFFFE, + /* + * Event code 0xFFFF is used for platform specific firmware + * events where the event data contains any event specific information. + */ + SBI_PMU_FW_PLATFORM = 0xFFFF, +}; + +/** SBI PMU event idx type */ +enum sbi_pmu_event_type_id { + SBI_PMU_EVENT_TYPE_HW = 0x0, + SBI_PMU_EVENT_TYPE_HW_CACHE = 0x1, + SBI_PMU_EVENT_TYPE_HW_RAW = 0x2, + SBI_PMU_EVENT_TYPE_FW = 0xf, + SBI_PMU_EVENT_TYPE_MAX, +}; + +/** SBI PMU counter type */ +enum sbi_pmu_ctr_type { + SBI_PMU_CTR_TYPE_HW = 0, + SBI_PMU_CTR_TYPE_FW, +}; + +/* Helper macros to decode event idx */ +#define SBI_PMU_EVENT_IDX_MASK 0xFFFFF +#define SBI_PMU_EVENT_IDX_TYPE_OFFSET 16 +#define SBI_PMU_EVENT_IDX_TYPE_MASK (0xF << SBI_PMU_EVENT_IDX_TYPE_OFFSET) +#define SBI_PMU_EVENT_IDX_CODE_MASK 0xFFFF +#define SBI_PMU_EVENT_RAW_IDX 0x20000 + +#define SBI_PMU_EVENT_IDX_INVALID 0xFFFFFFFF + +#define SBI_PMU_EVENT_HW_CACHE_OPS_RESULT 0x1 +#define SBI_PMU_EVENT_HW_CACHE_OPS_ID_MASK 0x6 +#define SBI_PMU_EVENT_HW_CACHE_OPS_ID_OFFSET 1 +#define SBI_PMU_EVENT_HW_CACHE_ID_MASK 0xfff8 +#define SBI_PMU_EVENT_HW_CACHE_ID_OFFSET 3 + +/* Flags defined for config matching function */ +#define SBI_PMU_CFG_FLAG_SKIP_MATCH (1 << 0) +#define SBI_PMU_CFG_FLAG_CLEAR_VALUE (1 << 1) +#define SBI_PMU_CFG_FLAG_AUTO_START (1 << 2) +#define SBI_PMU_CFG_FLAG_SET_VUINH (1 << 3) +#define SBI_PMU_CFG_FLAG_SET_VSINH (1 << 4) +#define SBI_PMU_CFG_FLAG_SET_UINH (1 << 5) +#define SBI_PMU_CFG_FLAG_SET_SINH (1 << 6) +#define SBI_PMU_CFG_FLAG_SET_MINH (1 << 7) + +/* Flags defined for counter start function */ +#define SBI_PMU_START_FLAG_SET_INIT_VALUE (1 << 0) +#define SBI_PMU_START_FLAG_INIT_FROM_SNAPSHOT (1 << 1) + +/* Flags defined for counter stop function */ +#define SBI_PMU_STOP_FLAG_RESET (1 << 0) +#define SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT (1 << 1) + +/* SBI function IDs for DBCN extension */ +#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0 +#define SBI_EXT_DBCN_CONSOLE_READ 0x1 +#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2 + +/* SBI function IDs for SUSP extension */ +#define SBI_EXT_SUSP_SUSPEND 0x0 + +#define SBI_SUSP_SLEEP_TYPE_SUSPEND 0x0 +#define SBI_SUSP_SLEEP_TYPE_LAST SBI_SUSP_SLEEP_TYPE_SUSPEND +#define SBI_SUSP_PLATFORM_SLEEP_START 0x80000000 + +/* SBI function IDs for CPPC extension */ +#define SBI_EXT_CPPC_PROBE 0x0 +#define SBI_EXT_CPPC_READ 0x1 +#define SBI_EXT_CPPC_READ_HI 0x2 +#define SBI_EXT_CPPC_WRITE 0x3 + +enum sbi_cppc_reg_id { + SBI_CPPC_HIGHEST_PERF = 0x00000000, + SBI_CPPC_NOMINAL_PERF = 0x00000001, + SBI_CPPC_LOW_NON_LINEAR_PERF = 0x00000002, + SBI_CPPC_LOWEST_PERF = 0x00000003, + SBI_CPPC_GUARANTEED_PERF = 0x00000004, + SBI_CPPC_DESIRED_PERF = 0x00000005, + SBI_CPPC_MIN_PERF = 0x00000006, + SBI_CPPC_MAX_PERF = 0x00000007, + SBI_CPPC_PERF_REDUC_TOLERANCE = 0x00000008, + SBI_CPPC_TIME_WINDOW = 0x00000009, + SBI_CPPC_CTR_WRAP_TIME = 0x0000000A, + SBI_CPPC_REFERENCE_CTR = 0x0000000B, + SBI_CPPC_DELIVERED_CTR = 0x0000000C, + SBI_CPPC_PERF_LIMITED = 0x0000000D, + SBI_CPPC_ENABLE = 0x0000000E, + SBI_CPPC_AUTO_SEL_ENABLE = 0x0000000F, + SBI_CPPC_AUTO_ACT_WINDOW = 0x00000010, + SBI_CPPC_ENERGY_PERF_PREFERENCE = 0x00000011, + SBI_CPPC_REFERENCE_PERF = 0x00000012, + SBI_CPPC_LOWEST_FREQ = 0x00000013, + SBI_CPPC_NOMINAL_FREQ = 0x00000014, + SBI_CPPC_ACPI_LAST = SBI_CPPC_NOMINAL_FREQ, + SBI_CPPC_TRANSITION_LATENCY = 0x80000000, + SBI_CPPC_NON_ACPI_LAST = SBI_CPPC_TRANSITION_LATENCY, +}; + +/* SBI Function IDs for SSE extension */ +#define SBI_EXT_SSE_READ_ATTR 0x00000000 +#define SBI_EXT_SSE_WRITE_ATTR 0x00000001 +#define SBI_EXT_SSE_REGISTER 0x00000002 +#define SBI_EXT_SSE_UNREGISTER 0x00000003 +#define SBI_EXT_SSE_ENABLE 0x00000004 +#define SBI_EXT_SSE_DISABLE 0x00000005 +#define SBI_EXT_SSE_COMPLETE 0x00000006 +#define SBI_EXT_SSE_INJECT 0x00000007 + +/* SBI SSE Event Attributes. */ +enum sbi_sse_attr_id { + SBI_SSE_ATTR_STATUS = 0x00000000, + SBI_SSE_ATTR_PRIO = 0x00000001, + SBI_SSE_ATTR_CONFIG = 0x00000002, + SBI_SSE_ATTR_PREFERRED_HART = 0x00000003, + SBI_SSE_ATTR_ENTRY_PC = 0x00000004, + SBI_SSE_ATTR_ENTRY_ARG = 0x00000005, + SBI_SSE_ATTR_INTERRUPTED_SEPC = 0x00000006, + SBI_SSE_ATTR_INTERRUPTED_FLAGS = 0x00000007, + SBI_SSE_ATTR_INTERRUPTED_A6 = 0x00000008, + SBI_SSE_ATTR_INTERRUPTED_A7 = 0x00000009, + + SBI_SSE_ATTR_MAX = 0x0000000A +}; + +#define SBI_SSE_ATTR_STATUS_STATE_OFFSET 0 +#define SBI_SSE_ATTR_STATUS_STATE_MASK 0x3 +#define SBI_SSE_ATTR_STATUS_PENDING_OFFSET 2 +#define SBI_SSE_ATTR_STATUS_INJECT_OFFSET 3 + +#define SBI_SSE_ATTR_CONFIG_ONESHOT (1 << 0) + +#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_STATUS_SPP BIT(0) +#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_STATUS_SPIE BIT(1) +#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPV BIT(2) +#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPVP BIT(3) + +enum sbi_sse_state { + SBI_SSE_STATE_UNUSED = 0, + SBI_SSE_STATE_REGISTERED = 1, + SBI_SSE_STATE_ENABLED = 2, + SBI_SSE_STATE_RUNNING = 3, +}; + +/* SBI SSE Event IDs. */ +#define SBI_SSE_EVENT_LOCAL_RAS 0x00000000 +#define SBI_SSE_EVENT_LOCAL_PLAT_0_START 0x00004000 +#define SBI_SSE_EVENT_LOCAL_PLAT_0_END 0x00007fff +#define SBI_SSE_EVENT_GLOBAL_RAS 0x00008000 +#define SBI_SSE_EVENT_GLOBAL_PLAT_0_START 0x00004000 +#define SBI_SSE_EVENT_GLOBAL_PLAT_0_END 0x00007fff + +#define SBI_SSE_EVENT_LOCAL_PMU 0x00010000 +#define SBI_SSE_EVENT_LOCAL_PLAT_1_START 0x00014000 +#define SBI_SSE_EVENT_LOCAL_PLAT_1_END 0x00017fff +#define SBI_SSE_EVENT_GLOBAL_PLAT_1_START 0x0001c000 +#define SBI_SSE_EVENT_GLOBAL_PLAT_1_END 0x0001ffff + +#define SBI_SSE_EVENT_LOCAL_PLAT_2_START 0x00024000 +#define SBI_SSE_EVENT_LOCAL_PLAT_2_END 0x00027fff +#define SBI_SSE_EVENT_GLOBAL_PLAT_2_START 0x0002c000 +#define SBI_SSE_EVENT_GLOBAL_PLAT_2_END 0x0002ffff + +#define SBI_SSE_EVENT_LOCAL_SOFTWARE 0xffff0000 +#define SBI_SSE_EVENT_LOCAL_PLAT_3_START 0xffff4000 +#define SBI_SSE_EVENT_LOCAL_PLAT_3_END 0xffff7fff +#define SBI_SSE_EVENT_GLOBAL_SOFTWARE 0xffff8000 +#define SBI_SSE_EVENT_GLOBAL_PLAT_3_START 0xffffc000 +#define SBI_SSE_EVENT_GLOBAL_PLAT_3_END 0xffffffff + +#define SBI_SSE_EVENT_GLOBAL_BIT (1 << 15) +#define SBI_SSE_EVENT_PLATFORM_BIT (1 << 14) + +/* SBI base specification related macros */ +#define SBI_SPEC_VERSION_MAJOR_OFFSET 24 +#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f +#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff +#define SBI_EXT_VENDOR_START 0x09000000 +#define SBI_EXT_VENDOR_END 0x09FFFFFF +#define SBI_EXT_FIRMWARE_START 0x0A000000 +#define SBI_EXT_FIRMWARE_END 0x0AFFFFFF + +/* SBI return error codes */ +#define SBI_SUCCESS 0 +#define SBI_ERR_FAILED -1 +#define SBI_ERR_NOT_SUPPORTED -2 +#define SBI_ERR_INVALID_PARAM -3 +#define SBI_ERR_DENIED -4 +#define SBI_ERR_INVALID_ADDRESS -5 +#define SBI_ERR_ALREADY_AVAILABLE -6 +#define SBI_ERR_ALREADY_STARTED -7 +#define SBI_ERR_ALREADY_STOPPED -8 +#define SBI_ERR_NO_SHMEM -9 +#define SBI_ERR_INVALID_STATE -10 +#define SBI_ERR_BAD_RANGE -11 + +#define SBI_LAST_ERR SBI_ERR_BAD_RANGE + +/* clang-format on */ + +#endif diff --git a/soc/common/riscv-privileged/Kconfig b/soc/common/riscv-privileged/Kconfig index 10c2e37712bbcee..6db6ad62ed9b8c8 100644 --- a/soc/common/riscv-privileged/Kconfig +++ b/soc/common/riscv-privileged/Kconfig @@ -2,6 +2,7 @@ # architecture specification # Copyright (c) 2017 Jean-Paul Etienne +# Copyright (c) 2024 sensry.io # SPDX-License-Identifier: Apache-2.0 config RISCV_VECTORED_MODE @@ -9,3 +10,11 @@ config RISCV_VECTORED_MODE depends on RISCV_PRIVILEGED help Should the SOC use vectored mode. + +config RISCV_HAS_HART_ID + bool "Use of hartID (mhartid/shartid/uarthid)" + default y + help + Depending on selected kernel run mode, the appropriate hartID + will be used. Should be enabled when booting in machine mode; if disabled + then booting on first core will be assumed. diff --git a/soc/common/riscv-privileged/soc_common_irq.c b/soc/common/riscv-privileged/soc_common_irq.c index 24aee37bdafacec..a71e3a6f9687388 100644 --- a/soc/common/riscv-privileged/soc_common_irq.c +++ b/soc/common/riscv-privileged/soc_common_irq.c @@ -56,7 +56,7 @@ void arch_irq_enable(unsigned int irq) * CSR mie register is updated using atomic instruction csrrs * (atomic read and set bits in CSR register) */ - mie = csr_read_set(mie, 1 << irq); + mie = csr_read_set(xie, 1 << irq); } void arch_irq_disable(unsigned int irq) @@ -76,7 +76,7 @@ void arch_irq_disable(unsigned int irq) * Use atomic instruction csrrc to disable device interrupt in mie CSR. * (atomic read and clear bits in CSR register) */ - mie = csr_read_clear(mie, 1 << irq); + mie = csr_read_clear(xie, 1 << irq); } int arch_irq_is_enabled(unsigned int irq) @@ -91,7 +91,7 @@ int arch_irq_is_enabled(unsigned int irq) } #endif - mie = csr_read(mie); + mie = csr_read(xie); return !!(mie & (1 << irq)); } @@ -114,7 +114,7 @@ __weak void soc_interrupt_init(void) /* ensure that all interrupts are disabled */ (void)arch_irq_lock(); - csr_write(mie, 0); - csr_write(mip, 0); + csr_write(xie, 0); + csr_write(xip, 0); } #endif diff --git a/soc/common/riscv-privileged/soc_irq.S b/soc/common/riscv-privileged/soc_irq.S index 21d6bd56f99df56..bd735087f62e043 100644 --- a/soc/common/riscv-privileged/soc_irq.S +++ b/soc/common/riscv-privileged/soc_irq.S @@ -13,6 +13,7 @@ #include #include #include +#include /* * __soc_handle_irq is defined as .weak to allow re-implementation by @@ -28,7 +29,7 @@ SECTION_FUNC(exception.other, __soc_handle_irq) /* Clear exception number from CSR mip register */ li t1, 1 sll t0, t1, a0 - csrrc t1, mip, t0 + csrrc t1, xip, t0 /* Return */ ret diff --git a/soc/common/riscv-privileged/vector.S b/soc/common/riscv-privileged/vector.S index 7230561a340d105..65b7b7cf0f62e2d 100644 --- a/soc/common/riscv-privileged/vector.S +++ b/soc/common/riscv-privileged/vector.S @@ -6,6 +6,7 @@ */ #include +#include /* exports */ GTEXT(__start) @@ -43,7 +44,7 @@ SECTION_FUNC(vectors, __start) add t0, zero, zero #endif addi t0, t0, 0x03 /* Enable CLIC vectored mode by setting LSB */ - csrw mtvec, t0 + csrw xtvec, t0 /* * CLIC vectored mode has a similar concept to CLINT vectored mode, @@ -76,7 +77,7 @@ SECTION_FUNC(vectors, __start) */ la t0, _irq_vector_table /* Load address of interrupt vector table */ addi t0, t0, 0x01 /* Enable vectored mode by setting LSB */ - csrw mtvec, t0 + csrw xtvec, t0 #endif /* CONFIG_RISCV_HAS_CLIC */ @@ -86,7 +87,7 @@ SECTION_FUNC(vectors, __start) la t0, _isr_wrapper addi t0, t0, 0x03 /* Set mode bits to 3, signifying CLIC. Everything else is reserved. */ - csrw mtvec, t0 + csrw xtvec, t0 #else /* !CONFIG_RISCV_HAS_CLIC || CONFIG_LEGACY_CLIC */ @@ -97,7 +98,7 @@ SECTION_FUNC(vectors, __start) * to _isr_wrapper. */ la t0, _isr_wrapper - csrw mtvec, t0 + csrw xtvec, t0 #endif /* CONFIG_RISCV_HAS_CLIC&& !CONFIG_LEGACY_CLIC */ diff --git a/soc/nordic/common/vpr/soc_isr_stacking.h b/soc/nordic/common/vpr/soc_isr_stacking.h index 8d2f64ad7291fa4..9b7d6ced7273ef7 100644 --- a/soc/nordic/common/vpr/soc_isr_stacking.h +++ b/soc/nordic/common/vpr/soc_isr_stacking.h @@ -91,16 +91,16 @@ #define STORE_SP_ALIGN_BIT_FROM_MEPC \ addi t1, sp, __struct_arch_esf_soc_context_OFFSET; \ - lr t0, __struct_arch_esf_mepc_OFFSET(sp); \ + lr t0, __struct_arch_esf_xepc_OFFSET(sp); \ andi t0, t0, MEPC_SP_ALIGN_BIT_MASK; \ sr t0, __soc_esf_t_sp_align_OFFSET(t1) #define RESTORE_SP_ALIGN_BIT_TO_MEPC \ addi t1, sp, __struct_arch_esf_soc_context_OFFSET; \ lr t0, __soc_esf_t_sp_align_OFFSET(t1); \ - lr t1, __struct_arch_esf_mepc_OFFSET(sp); \ + lr t1, __struct_arch_esf_xepc_OFFSET(sp); \ or t2, t1, t0; \ - sr t2, __struct_arch_esf_mepc_OFFSET(sp) + sr t2, __struct_arch_esf_xepc_OFFSET(sp) #define SOC_ISR_SW_STACKING \ csrw mscratch, t0; \ diff --git a/soc/qemu/virt_riscv/Kconfig b/soc/qemu/virt_riscv/Kconfig index 1c3382371bb46c6..ab4807df901e42b 100644 --- a/soc/qemu/virt_riscv/Kconfig +++ b/soc/qemu/virt_riscv/Kconfig @@ -9,7 +9,7 @@ config SOC_FAMILY_QEMU_VIRT_RISCV select RISCV_ISA_EXT_C select RISCV select RISCV_PRIVILEGED - select RISCV_HAS_PLIC + select RISCV_HAS_PLIC if RISCV_KERNEL_IN_MACHINE_MODE if SOC_FAMILY_QEMU_VIRT_RISCV