arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
|
2018-06-10 19:02:14 +02:00
|
|
|
* Contributors: 2018 Antmicro <www.antmicro.com>
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
*/
|
|
|
|
|
|
2022-05-09 13:56:13 +02:00
|
|
|
#include <zephyr/toolchain.h>
|
|
|
|
|
#include <zephyr/linker/sections.h>
|
|
|
|
|
#include <zephyr/arch/cpu.h>
|
2024-01-24 17:35:04 +08:00
|
|
|
#include <zephyr/offsets.h>
|
2025-07-28 19:51:48 +01:00
|
|
|
#include <zephyr/arch/riscv/csr.h>
|
arch: riscv: add Supervisor-mode (S-mode) support
Introduce CONFIG_RISCV_S_MODE to select Supervisor-mode execution.
Add depends on !RISCV_S_MODE to RISCV_PMP since PMP CSRs are
inaccessible from S-mode.
Add an M-mode SBI shim (reset.S + sbi.S) that configures exception
delegation, PMP, and counter access before dropping to S-mode via mret.
The shim handles SBI_SET_TIMER ecalls from S-mode and forwards MTIP to
STIP so the supervisor timer driver works without a full SBI firmware.
Introduce privilege-level abstractions in isr.S (RV_CAUSE, RV_EPC,
RV_STATUS, RV_TVAL, etc.) and update all runtime code that previously
accessed M-mode-only CSRs (mcause, mtval, mstatus, mie, mip) to use the
S-mode equivalents when CONFIG_RISCV_S_MODE is set.
ARCH_EXCEPT in kernel context uses ebreak (cause=3, Breakpoint) instead
of a direct z_riscv_fatal_error() call. In S-mode, ecall (cause=9) is
kept in M-mode for SBI and never reaches the S-mode exception handler;
a direct call with NULL esf caused the stack unwinder to crash into an
infinite fault loop. ebreak is delegated to S-mode by our medeleg
configuration; isr.S treats ebreak with t0=RV_ECALL_RUNTIME_EXCEPT the
same way M-mode treats ecall-based ARCH_EXCEPT.
Signed-off-by: Alexios Lyrakis <alexios.lyrakis@gmail.com>
2026-03-28 15:34:55 +00:00
|
|
|
#include <zephyr/arch/riscv/irq.h>
|
2022-02-22 14:09:55 -05:00
|
|
|
#include "asm_macros.inc"
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
|
arch: riscv: add Supervisor-mode (S-mode) support
Introduce CONFIG_RISCV_S_MODE to select Supervisor-mode execution.
Add depends on !RISCV_S_MODE to RISCV_PMP since PMP CSRs are
inaccessible from S-mode.
Add an M-mode SBI shim (reset.S + sbi.S) that configures exception
delegation, PMP, and counter access before dropping to S-mode via mret.
The shim handles SBI_SET_TIMER ecalls from S-mode and forwards MTIP to
STIP so the supervisor timer driver works without a full SBI firmware.
Introduce privilege-level abstractions in isr.S (RV_CAUSE, RV_EPC,
RV_STATUS, RV_TVAL, etc.) and update all runtime code that previously
accessed M-mode-only CSRs (mcause, mtval, mstatus, mie, mip) to use the
S-mode equivalents when CONFIG_RISCV_S_MODE is set.
ARCH_EXCEPT in kernel context uses ebreak (cause=3, Breakpoint) instead
of a direct z_riscv_fatal_error() call. In S-mode, ecall (cause=9) is
kept in M-mode for SBI and never reaches the S-mode exception handler;
a direct call with NULL esf caused the stack unwinder to crash into an
infinite fault loop. ebreak is delegated to S-mode by our medeleg
configuration; isr.S treats ebreak with t0=RV_ECALL_RUNTIME_EXCEPT the
same way M-mode treats ecall-based ARCH_EXCEPT.
Signed-off-by: Alexios Lyrakis <alexios.lyrakis@gmail.com>
2026-03-28 15:34:55 +00:00
|
|
|
#ifdef CONFIG_RISCV_S_MODE
|
|
|
|
|
/* mcounteren bits */
|
|
|
|
|
#define MCOUNTEREN_CY BIT(0) /* cycle counter */
|
|
|
|
|
#define MCOUNTEREN_TM BIT(1) /* time counter */
|
|
|
|
|
#define MCOUNTEREN_IR BIT(2) /* instret counter */
|
|
|
|
|
#endif
|
|
|
|
|
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
/* exports */
|
2018-06-10 19:02:14 +02:00
|
|
|
GTEXT(__initialize)
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
GTEXT(__reset)
|
|
|
|
|
|
|
|
|
|
/* imports */
|
2023-12-08 07:55:21 -05:00
|
|
|
GTEXT(z_prep_c)
|
2025-06-03 06:25:18 -07:00
|
|
|
GDATA(riscv_cpu_wake_flag)
|
|
|
|
|
GDATA(riscv_cpu_sp)
|
2023-12-13 15:27:41 -05:00
|
|
|
GTEXT(arch_secondary_cpu_init)
|
2026-07-15 21:32:14 +05:30
|
|
|
#ifdef CONFIG_RISCV_S_MODE_INTERNAL_SBI
|
arch: riscv: add Supervisor-mode (S-mode) support
Introduce CONFIG_RISCV_S_MODE to select Supervisor-mode execution.
Add depends on !RISCV_S_MODE to RISCV_PMP since PMP CSRs are
inaccessible from S-mode.
Add an M-mode SBI shim (reset.S + sbi.S) that configures exception
delegation, PMP, and counter access before dropping to S-mode via mret.
The shim handles SBI_SET_TIMER ecalls from S-mode and forwards MTIP to
STIP so the supervisor timer driver works without a full SBI firmware.
Introduce privilege-level abstractions in isr.S (RV_CAUSE, RV_EPC,
RV_STATUS, RV_TVAL, etc.) and update all runtime code that previously
accessed M-mode-only CSRs (mcause, mtval, mstatus, mie, mip) to use the
S-mode equivalents when CONFIG_RISCV_S_MODE is set.
ARCH_EXCEPT in kernel context uses ebreak (cause=3, Breakpoint) instead
of a direct z_riscv_fatal_error() call. In S-mode, ecall (cause=9) is
kept in M-mode for SBI and never reaches the S-mode exception handler;
a direct call with NULL esf caused the stack unwinder to crash into an
infinite fault loop. ebreak is delegated to S-mode by our medeleg
configuration; isr.S treats ebreak with t0=RV_ECALL_RUNTIME_EXCEPT the
same way M-mode treats ecall-based ARCH_EXCEPT.
Signed-off-by: Alexios Lyrakis <alexios.lyrakis@gmail.com>
2026-03-28 15:34:55 +00:00
|
|
|
GTEXT(__m_mode_sbi_handler)
|
|
|
|
|
#endif
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
|
|
|
|
|
#if CONFIG_INCLUDE_RESET_VECTOR
|
|
|
|
|
SECTION_FUNC(reset, __reset)
|
|
|
|
|
/*
|
2018-06-10 19:02:14 +02:00
|
|
|
* jump to __initialize
|
|
|
|
|
* use call opcode in case __initialize is far away.
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
* This will be dependent on linker.ld configuration.
|
|
|
|
|
*/
|
2018-06-10 19:02:14 +02:00
|
|
|
call __initialize
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
#endif /* CONFIG_INCLUDE_RESET_VECTOR */
|
|
|
|
|
|
|
|
|
|
/* use ABI name of registers for the sake of simplicity */
|
|
|
|
|
|
2026-03-16 17:53:53 -07:00
|
|
|
#ifdef CONFIG_THREAD_LOCAL_STORAGE
|
|
|
|
|
/*
|
|
|
|
|
* Allocate a TLS area on the current stack, initialize it via
|
2026-04-01 15:02:05 -07:00
|
|
|
* arch_riscv_early_tls_stack_update(), set tp to point to it.
|
2026-03-16 17:53:53 -07:00
|
|
|
*/
|
|
|
|
|
.macro riscv_tls_init_early
|
2026-04-01 15:02:05 -07:00
|
|
|
/* Save s0/s1, else they get clobbered */
|
|
|
|
|
addi sp, sp, -16
|
|
|
|
|
sr s0, 0(sp)
|
|
|
|
|
sr s1, 8(sp)
|
2026-03-16 17:53:53 -07:00
|
|
|
mv s0, sp
|
|
|
|
|
|
|
|
|
|
call z_tls_data_size_asm
|
|
|
|
|
beqz a0, tls_skip\@
|
|
|
|
|
mv s1, a0
|
|
|
|
|
sub sp, sp, a0
|
|
|
|
|
|
|
|
|
|
mv a0, s0 /* arg0: stack_top */
|
|
|
|
|
mv a1, s1 /* arg1: tls_size */
|
|
|
|
|
call arch_riscv_early_tls_stack_update
|
|
|
|
|
tls_skip\@:
|
2026-04-01 15:02:05 -07:00
|
|
|
/* Restore s0/s1. sp intentionally stays below the TLS area so the
|
|
|
|
|
* runtime stack grows away from it. The 16-byte save frame above
|
|
|
|
|
* sp is abandoned.
|
|
|
|
|
*/
|
|
|
|
|
lr s1, 8(s0)
|
|
|
|
|
lr s0, 0(s0)
|
2026-03-16 17:53:53 -07:00
|
|
|
.endm
|
|
|
|
|
#endif /* CONFIG_THREAD_LOCAL_STORAGE */
|
|
|
|
|
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
/*
|
|
|
|
|
* Remainder of asm-land initialization code before we can jump into
|
|
|
|
|
* the C domain
|
|
|
|
|
*/
|
2018-06-10 19:02:14 +02:00
|
|
|
SECTION_FUNC(TEXT, __initialize)
|
2026-07-15 21:32:14 +05:30
|
|
|
#ifndef CONFIG_RISCV_S_MODE_EXTERNAL_SBI
|
|
|
|
|
/*
|
|
|
|
|
* When entered directly in S-mode by an external bootloader/SBI, a0
|
|
|
|
|
* already holds the hart id per the RISC-V S-mode boot protocol
|
|
|
|
|
* (a0=hartid, a1=dtb), and mhartid would trap, so only read it here.
|
|
|
|
|
*/
|
2019-09-12 12:07:16 +00:00
|
|
|
csrr a0, mhartid
|
2026-07-15 21:32:14 +05:30
|
|
|
#endif /* CONFIG_RISCV_S_MODE_EXTERNAL_SBI */
|
2023-01-16 13:53:06 +00:00
|
|
|
li t0, CONFIG_RV_BOOT_HART
|
|
|
|
|
beq a0, t0, boot_first_core
|
|
|
|
|
j boot_secondary_core
|
2019-09-12 12:07:16 +00:00
|
|
|
|
2021-12-29 10:22:48 -08:00
|
|
|
boot_first_core:
|
2019-09-12 12:07:16 +00:00
|
|
|
|
2020-04-23 17:27:24 +09:00
|
|
|
#ifdef CONFIG_FPU
|
2020-03-11 18:15:29 -07:00
|
|
|
/*
|
|
|
|
|
* Enable floating-point.
|
|
|
|
|
*/
|
2022-02-21 21:36:55 -05:00
|
|
|
li t0, MSTATUS_FS_INIT
|
2026-07-15 21:32:14 +05:30
|
|
|
#ifdef CONFIG_RISCV_S_MODE_EXTERNAL_SBI
|
|
|
|
|
csrs sstatus, t0
|
|
|
|
|
#else
|
2022-02-21 21:36:55 -05:00
|
|
|
csrs mstatus, t0
|
2026-07-15 21:32:14 +05:30
|
|
|
#endif /* CONFIG_RISCV_S_MODE_EXTERNAL_SBI */
|
2020-03-11 18:15:29 -07:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Floating-point rounding mode set to IEEE-754 default, and clear
|
|
|
|
|
* all exception flags.
|
|
|
|
|
*/
|
2022-02-21 21:36:55 -05:00
|
|
|
fscsr zero
|
2020-03-11 18:15:29 -07:00
|
|
|
#endif
|
|
|
|
|
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
#ifdef CONFIG_INIT_STACKS
|
2020-03-12 15:37:29 -07:00
|
|
|
/* Pre-populate all bytes in z_interrupt_stacks with 0xAA */
|
|
|
|
|
la t0, z_interrupt_stacks
|
2024-09-10 19:04:32 +08:00
|
|
|
/* Total size of all cores' IRQ stack */
|
|
|
|
|
li t1, __z_interrupt_all_stacks_SIZEOF
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
add t1, t1, t0
|
|
|
|
|
|
2020-03-12 15:37:29 -07:00
|
|
|
/* Populate z_interrupt_stacks with 0xaaaaaaaa */
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
li t2, 0xaaaaaaaa
|
|
|
|
|
aa_loop:
|
|
|
|
|
sw t2, 0x00(t0)
|
|
|
|
|
addi t0, t0, 4
|
|
|
|
|
blt t0, t1, aa_loop
|
2024-09-10 19:04:32 +08:00
|
|
|
#endif /* CONFIG_INIT_STACKS */
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initially, setup stack pointer to
|
2022-09-26 22:58:21 -04:00
|
|
|
* z_interrupt_stacks + __z_interrupt_stack_SIZEOF
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
*/
|
2020-03-12 15:37:29 -07:00
|
|
|
la sp, z_interrupt_stacks
|
2022-09-26 22:58:21 -04:00
|
|
|
li t0, __z_interrupt_stack_SIZEOF
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
add sp, sp, t0
|
|
|
|
|
|
2026-03-16 17:53:53 -07:00
|
|
|
#ifdef CONFIG_THREAD_LOCAL_STORAGE
|
2026-04-01 15:02:05 -07:00
|
|
|
/*
|
2026-04-20 14:54:21 -07:00
|
|
|
* Initialize TLS before the first C function call. The compiler inserts
|
|
|
|
|
* stack canary checks into C functions, and the canary value is read from
|
|
|
|
|
* a TLS variable via tp. Without this early init, tp is not set up and
|
|
|
|
|
* any C function called during early boot (e.g. z_prep_c) would read the
|
|
|
|
|
* canary from an arbitrary memory location.
|
2026-04-01 15:02:05 -07:00
|
|
|
*/
|
2026-03-16 17:53:53 -07:00
|
|
|
riscv_tls_init_early
|
|
|
|
|
#endif
|
|
|
|
|
|
2026-07-15 21:32:14 +05:30
|
|
|
#if defined(CONFIG_RISCV_SMRNMI_ENABLE_NMI_DELIVERY) && !defined(CONFIG_RISCV_S_MODE_EXTERNAL_SBI)
|
2025-07-28 19:51:48 +01:00
|
|
|
csrs CSR_MNSTATUS, MNSTATUS_NMIE
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-11-13 14:37:41 -07:00
|
|
|
#ifdef CONFIG_WDOG_INIT
|
|
|
|
|
call _WdogInit
|
|
|
|
|
#endif
|
|
|
|
|
|
arch: riscv: add Supervisor-mode (S-mode) support
Introduce CONFIG_RISCV_S_MODE to select Supervisor-mode execution.
Add depends on !RISCV_S_MODE to RISCV_PMP since PMP CSRs are
inaccessible from S-mode.
Add an M-mode SBI shim (reset.S + sbi.S) that configures exception
delegation, PMP, and counter access before dropping to S-mode via mret.
The shim handles SBI_SET_TIMER ecalls from S-mode and forwards MTIP to
STIP so the supervisor timer driver works without a full SBI firmware.
Introduce privilege-level abstractions in isr.S (RV_CAUSE, RV_EPC,
RV_STATUS, RV_TVAL, etc.) and update all runtime code that previously
accessed M-mode-only CSRs (mcause, mtval, mstatus, mie, mip) to use the
S-mode equivalents when CONFIG_RISCV_S_MODE is set.
ARCH_EXCEPT in kernel context uses ebreak (cause=3, Breakpoint) instead
of a direct z_riscv_fatal_error() call. In S-mode, ecall (cause=9) is
kept in M-mode for SBI and never reaches the S-mode exception handler;
a direct call with NULL esf caused the stack unwinder to crash into an
infinite fault loop. ebreak is delegated to S-mode by our medeleg
configuration; isr.S treats ebreak with t0=RV_ECALL_RUNTIME_EXCEPT the
same way M-mode treats ecall-based ARCH_EXCEPT.
Signed-off-by: Alexios Lyrakis <alexios.lyrakis@gmail.com>
2026-03-28 15:34:55 +00:00
|
|
|
#ifdef CONFIG_RISCV_S_MODE
|
2026-07-15 21:32:14 +05:30
|
|
|
#ifdef CONFIG_RISCV_S_MODE_INTERNAL_SBI
|
arch: riscv: add Supervisor-mode (S-mode) support
Introduce CONFIG_RISCV_S_MODE to select Supervisor-mode execution.
Add depends on !RISCV_S_MODE to RISCV_PMP since PMP CSRs are
inaccessible from S-mode.
Add an M-mode SBI shim (reset.S + sbi.S) that configures exception
delegation, PMP, and counter access before dropping to S-mode via mret.
The shim handles SBI_SET_TIMER ecalls from S-mode and forwards MTIP to
STIP so the supervisor timer driver works without a full SBI firmware.
Introduce privilege-level abstractions in isr.S (RV_CAUSE, RV_EPC,
RV_STATUS, RV_TVAL, etc.) and update all runtime code that previously
accessed M-mode-only CSRs (mcause, mtval, mstatus, mie, mip) to use the
S-mode equivalents when CONFIG_RISCV_S_MODE is set.
ARCH_EXCEPT in kernel context uses ebreak (cause=3, Breakpoint) instead
of a direct z_riscv_fatal_error() call. In S-mode, ecall (cause=9) is
kept in M-mode for SBI and never reaches the S-mode exception handler;
a direct call with NULL esf caused the stack unwinder to crash into an
infinite fault loop. ebreak is delegated to S-mode by our medeleg
configuration; isr.S treats ebreak with t0=RV_ECALL_RUNTIME_EXCEPT the
same way M-mode treats ecall-based ARCH_EXCEPT.
Signed-off-by: Alexios Lyrakis <alexios.lyrakis@gmail.com>
2026-03-28 15:34:55 +00:00
|
|
|
/* Set M-mode trap vector to our SBI handler */
|
|
|
|
|
la t0, __m_mode_sbi_handler
|
|
|
|
|
csrw mtvec, t0
|
|
|
|
|
|
|
|
|
|
/* Delegate all exceptions to S-mode except S-mode ecall and
|
|
|
|
|
* M-mode ecall, which stay in M-mode to be handled by our SBI.
|
|
|
|
|
*/
|
|
|
|
|
li t0, ~((1 << RISCV_EXC_ECALLS) | (1 << RISCV_EXC_ECALLM))
|
|
|
|
|
csrw medeleg, t0
|
|
|
|
|
|
|
|
|
|
/* Delegate supervisor software, timer and external interrupts
|
|
|
|
|
* to S-mode.
|
|
|
|
|
*/
|
|
|
|
|
li t0, (MIP_SSIP | MIP_STIP | MIP_SEIP)
|
|
|
|
|
csrw mideleg, t0
|
|
|
|
|
|
|
|
|
|
/* PMP entry 0: NAPOT, RWX, covers all memory so S-mode can
|
|
|
|
|
* access everything
|
|
|
|
|
*/
|
|
|
|
|
li t0, -1
|
|
|
|
|
csrw pmpaddr0, t0
|
|
|
|
|
li t0, (PMP_NAPOT | PMP_R | PMP_W | PMP_X)
|
|
|
|
|
csrw pmpcfg0, t0
|
|
|
|
|
|
|
|
|
|
/* Initialize mscratch to M-mode stack top */
|
|
|
|
|
la t0, m_mode_stack_top
|
|
|
|
|
csrw mscratch, t0
|
|
|
|
|
|
|
|
|
|
/* Allow S-mode to read cycle, time and instret counters */
|
|
|
|
|
li t0, (MCOUNTEREN_CY | MCOUNTEREN_TM | MCOUNTEREN_IR)
|
|
|
|
|
csrw mcounteren, t0
|
|
|
|
|
|
|
|
|
|
/* Enable M-mode timer interrupt so MTIP fires and is forwarded to S-mode as STIP */
|
|
|
|
|
li t0, MIP_MTIP
|
|
|
|
|
csrs mie, t0
|
|
|
|
|
|
|
|
|
|
/* Set MPP=S-mode in mstatus then mret into S-mode */
|
|
|
|
|
li t0, MSTATUS_MPP
|
|
|
|
|
csrc mstatus, t0
|
|
|
|
|
li t0, MSTATUS_MPP_S
|
|
|
|
|
csrs mstatus, t0
|
|
|
|
|
la t0, s_mode_entry
|
|
|
|
|
csrw mepc, t0
|
|
|
|
|
mret
|
2026-07-15 21:32:14 +05:30
|
|
|
#endif /* CONFIG_RISCV_S_MODE_INTERNAL_SBI */
|
arch: riscv: add Supervisor-mode (S-mode) support
Introduce CONFIG_RISCV_S_MODE to select Supervisor-mode execution.
Add depends on !RISCV_S_MODE to RISCV_PMP since PMP CSRs are
inaccessible from S-mode.
Add an M-mode SBI shim (reset.S + sbi.S) that configures exception
delegation, PMP, and counter access before dropping to S-mode via mret.
The shim handles SBI_SET_TIMER ecalls from S-mode and forwards MTIP to
STIP so the supervisor timer driver works without a full SBI firmware.
Introduce privilege-level abstractions in isr.S (RV_CAUSE, RV_EPC,
RV_STATUS, RV_TVAL, etc.) and update all runtime code that previously
accessed M-mode-only CSRs (mcause, mtval, mstatus, mie, mip) to use the
S-mode equivalents when CONFIG_RISCV_S_MODE is set.
ARCH_EXCEPT in kernel context uses ebreak (cause=3, Breakpoint) instead
of a direct z_riscv_fatal_error() call. In S-mode, ecall (cause=9) is
kept in M-mode for SBI and never reaches the S-mode exception handler;
a direct call with NULL esf caused the stack unwinder to crash into an
infinite fault loop. ebreak is delegated to S-mode by our medeleg
configuration; isr.S treats ebreak with t0=RV_ECALL_RUNTIME_EXCEPT the
same way M-mode treats ecall-based ARCH_EXCEPT.
Signed-off-by: Alexios Lyrakis <alexios.lyrakis@gmail.com>
2026-03-28 15:34:55 +00:00
|
|
|
|
|
|
|
|
s_mode_entry:
|
|
|
|
|
#endif /* CONFIG_RISCV_S_MODE */
|
|
|
|
|
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
/*
|
2023-12-08 07:55:21 -05:00
|
|
|
* Jump into C domain. z_prep_c zeroes BSS, copies rw data into RAM,
|
2019-03-08 14:19:05 -07:00
|
|
|
* and then enters kernel z_cstart
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by the SOC level:
__soc_is_irq: to check if the exception is the result of an
interrupt or not.
__soc_handle_irq: handle pending IRQ at SOC level (ex: clear
pending IRQ in SOC-specific IRQ register)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
*/
|
2023-12-08 07:55:21 -05:00
|
|
|
call z_prep_c
|
2021-12-29 10:22:48 -08:00
|
|
|
|
|
|
|
|
boot_secondary_core:
|
2023-01-06 22:33:35 -05:00
|
|
|
#if CONFIG_MP_MAX_NUM_CPUS > 1
|
2023-11-09 13:50:31 +09:00
|
|
|
la t0, riscv_cpu_wake_flag
|
|
|
|
|
li t1, -1
|
|
|
|
|
sr t1, 0(t0)
|
|
|
|
|
la t0, riscv_cpu_boot_flag
|
|
|
|
|
sr zero, 0(t0)
|
|
|
|
|
|
|
|
|
|
wait_secondary_wake_flag:
|
2021-12-29 10:22:48 -08:00
|
|
|
la t0, riscv_cpu_wake_flag
|
2022-02-22 14:09:55 -05:00
|
|
|
lr t0, 0(t0)
|
2023-11-09 13:50:31 +09:00
|
|
|
bne a0, t0, wait_secondary_wake_flag
|
2021-12-29 10:22:48 -08:00
|
|
|
|
|
|
|
|
/* Set up stack */
|
|
|
|
|
la t0, riscv_cpu_sp
|
2022-02-22 14:09:55 -05:00
|
|
|
lr sp, 0(t0)
|
2021-12-29 10:22:48 -08:00
|
|
|
|
2026-03-16 17:53:53 -07:00
|
|
|
#ifdef CONFIG_THREAD_LOCAL_STORAGE
|
|
|
|
|
/* Initialize tp early so TLS-based stack canaries work on secondary CPUs */
|
|
|
|
|
mv s2, a0 /* save hartid across TLS init calls */
|
|
|
|
|
riscv_tls_init_early
|
|
|
|
|
mv a0, s2 /* restore hartid */
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-11-09 13:50:31 +09:00
|
|
|
la t0, riscv_cpu_boot_flag
|
|
|
|
|
li t1, 1
|
|
|
|
|
sr t1, 0(t0)
|
2023-12-13 15:27:41 -05:00
|
|
|
j arch_secondary_cpu_init
|
2023-01-06 22:33:35 -05:00
|
|
|
#else
|
|
|
|
|
j loop_unconfigured_cores
|
|
|
|
|
#endif
|
2023-01-16 13:53:06 +00:00
|
|
|
|
|
|
|
|
loop_unconfigured_cores:
|
|
|
|
|
wfi
|
|
|
|
|
j loop_unconfigured_cores
|