diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 4ef91c6be8df69f..efaf962724b9a92 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -199,6 +199,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 c2f0d669f9f5991..481289a5ba81e0d 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 8ba7b615b422607..b639b81b301d3bd 100644 --- a/arch/riscv/core/irq_manage.c +++ b/arch/riscv/core/irq_manage.c @@ -25,15 +25,15 @@ FUNC_NORETURN void z_irq_spurious(const void *unused) CODE_UNREACHABLE; #else - 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 361e152f00ca3b8..0046b7aabe779f0 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -180,7 +180,7 @@ static void walk_stackframe(riscv_stacktrace_cb cb, void *cookie, const struct k 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 59adbc42e4688b2..2baddd74ab9ac44 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..00b14a76d419467 --- /dev/null +++ b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_opensbi.dts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 sensry.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/delete-node/ &ram0; + +/ { + console0: console { + compatible = "opensbi,console-uart"; + status = "okay"; + }; + + ram0: memory@80400000 { + device_type = "memory"; + reg = < 0x80400000 0x100000 >; + }; + + chosen { + zephyr,console = &console0; + zephyr,shell-uart = &console0; + zephyr,sram = &ram0; + }; +}; + + + +&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 946f00cfddfcd1e..f4219cd2c41d933 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -79,6 +79,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_RA8_SCI_B uart_renesas_ra8_sci_b.c) zephyr_library_sources_ifdef(CONFIG_UART_SI32_USART uart_si32_usart.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 cb4207d1200779a..d296d35e1ba2ceb 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -280,6 +280,8 @@ rsource "Kconfig.rzt2m" rsource "Kconfig.renesas_ra8" +rsource "Kconfig.opensbi_console" + source "drivers/serial/Kconfig.si32" 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..ad9f4cd2354a592 --- /dev/null +++ b/drivers/serial/uart_opensbi_console.c @@ -0,0 +1,70 @@ +/* + * 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..668306ecfe5b09c --- /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..6f5f3efc88d6896 --- /dev/null +++ b/drivers/timer/riscv_opensbi_timer.c @@ -0,0 +1,95 @@ +/* + * 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..20bbf456cfe7d0d --- /dev/null +++ b/dts/bindings/serial/opensbi,console-uart.yaml @@ -0,0 +1,5 @@ +description: OpenSBI Console UART + +compatible: "opensbi,console-uart" + +include: [base.yaml] 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 4cdedb700d3261b..28c4da9d6e8f37f 100644 --- a/include/zephyr/arch/riscv/arch.h +++ b/include/zephyr/arch/riscv/arch.h @@ -166,6 +166,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 @@ -175,6 +181,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 @@ -238,10 +246,10 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void) #else unsigned int key; - __asm__ volatile ("csrrc %0, mstatus, %1" - : "=r" (key) - : "rK" (MSTATUS_IEN) - : "memory"); + __asm__ volatile("csrrc %0, %1, %2" + : "=r"(key) + : "i"(XSTATUS), "rK"(XSTATUS_IEN) + : "memory"); return key; #endif @@ -254,21 +262,20 @@ 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" - : - : "r" (key & MSTATUS_IEN) - : "memory"); + __asm__ volatile("csrs %0, %1" : : "i"(XSTATUS), "r"(key & XSTATUS_IEN) : "memory"); #endif } 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 } @@ -303,5 +310,4 @@ static inline uint64_t arch_k_cycle_get_64(void) #include #endif - #endif diff --git a/include/zephyr/arch/riscv/csr.h b/include/zephyr/arch/riscv/csr.h index 70e6e817b630ae7..7d1530cda8ac62b 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,73 @@ : "memory"); \ }) +#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..aee408589f37e77 --- /dev/null +++ b/soc/common/riscv-opensbi/opensbi.c @@ -0,0 +1,41 @@ +/* + * 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..a1837dd8f3c215d --- /dev/null +++ b/soc/common/riscv-opensbi/opensbi.h @@ -0,0 +1,51 @@ +/* + * 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..e4211a3b088768e 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 directly from CSR (mhartid/shartid/uarthid)" + default y + help + When booting the CSR is used to determine the current hartID. + Should be enabled when booting in machine mode; if disabled + then booting on core defined by RV_BOOT_HART will be assumed. diff --git a/soc/common/riscv-privileged/soc_common_irq.c b/soc/common/riscv-privileged/soc_common_irq.c index 48de19030afe024..03d866206500762 100644 --- a/soc/common/riscv-privileged/soc_common_irq.c +++ b/soc/common/riscv-privileged/soc_common_irq.c @@ -65,7 +65,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) @@ -85,7 +85,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) @@ -100,7 +100,7 @@ int arch_irq_is_enabled(unsigned int irq) } #endif - mie = csr_read(mie); + mie = csr_read(xie); return !!(mie & (1 << irq)); } @@ -123,7 +123,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 0145f14b8546489..0ea85630497f108 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 imply XIP if SOC_FAMILY_QEMU_VIRT_RISCV