Commit graph zephyr/arch/riscv/core/reset.S
Author SHA1 Message Date
Fin Maaß
80c6a6f2ba arch: riscv: grant S-mode access to the Zkr seed CSR
The seed CSR of the Zkr extension is only accessible from M-mode after
reset. When the kernel runs in S-mode on top of the in-tree M-mode
runtime, set mseccfg.SSEED before dropping to S-mode, so that the
kernel can use the entropy source. U-mode access stays disabled.

With an external SBI implementation this is up to the firmware, OpenSBI
sets SSEED on harts that implement Zkr.

Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-09-24 17:12:58 +02:00
Adrian Śliwa
56164d22a4 arch: riscv: share the counter-enable bit definitions
The counter enable bits are identical in mcounteren, scounteren and
hcounteren, so move them out of reset.S into csr.h. This lets the arch
code that opens the counters to user mode reuse them instead of adding
a second copy.

Signed-off-by: Adrian Śliwa <asliwa@internships.antmicro.com>
2026-09-16 05:58:39 +02:00
Ayush Singh
5a95bb9cff arch: riscv: Add S-mode only support
- When launching Zephyr from a bootloader (eg: u-boot), the image binary
  launches in S-mode. Thus we cannot call M-mode only functions, or
  perform M to S mode transition.
- SMP is currently broken in this setup. MPU, FPU not tested yet either
  since PolarFire soc does not enable it by default.
- Tested on beaglev_fire with PolarFire soc.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2026-08-25 11:24:09 +02:00
Mayur Salve
f94efe2607 arch: riscv: address review nits on TLS canary patches
Add copyright year, reflow comments, remote duplicate __tls_end,
and remove commented-out code.

Signed-off-by: Mayur Salve <msalve@qti.qualcomm.com>
2026-05-14 21:52:56 +02:00
Mayur Salve
2d6bdab5dc arch/riscv: fix early TLS setup and save callee-saved registers
Fix the early TLS initialization sequence on RISC-V to correctly set up
the thread pointer (tp) before any C code runs, and save/restore
callee-saved registers as required by the ABI.

Signed-off-by: Mayur Salve <msalve@qti.qualcomm.com>
2026-05-14 21:52:56 +02:00
Mayur Salve
729110c12f arch: riscv: use TLS-based stack canary guard
This change enables per thread stack canary for RISC-V.

RISC-V GCC accesses the stack canary via a fixed offset from the
thread pointer (tp) when -mstack-protector-guard=tls is used. The
compiler emits code equivalent to:

  lw t0, 0(tp)   # load canary from tp+0

Additionally, tp is zeroed in arch_kernel_init() when TLS is enabled,
which means any C function called before thread setup completes (such
as z_early_rand_get or data_copy_xip_relocation) would fault trying
to access the canary.

Introduce STACK_CANARIES_TLS_PREPEND, which places the
.stack_chk.guard section at offset 0 of the TLS block, before .tdata
and .tbss. The compiler flags -mstack-protector-guard-reg=tp and
-mstack-protector-guard-offset=0 are passed so GCC generates the
correct canary access.

With STACK_CANARIES_TLS_PREPEND the per-thread TLS block layout is:

  tp --> +------------------+  offset 0
         | .stack_chk.guard |  (__stack_chk_guard)
         +------------------+
         | .tdata           |  (initialized TLS data)
         +------------------+
         | .tbss            |  (zero-initialized TLS data)
         +------------------+

The RISC-V reset path is extended to initialize tp before any C code
runs by allocating a TLS area on the boot stack and calling
arch_riscv_early_tls_stack_update(). Early boot functions that run
before tp is set up (z_early_rand_get, data_copy_xip_relocation) are
marked FUNC_NO_STACK_PROTECTOR to avoid canary access before tp is
valid.

Signed-off-by: Mayur Salve <msalve@qti.qualcomm.com>
2026-05-14 21:52:56 +02:00
Alexios Lyrakis
1cf1de81a1 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-05-04 14:54:52 +02:00
Afonso Oliveira
b9a15bf5c8 arch/riscv: Enable NMI delivery for SMRNMI hardware
Add option to enable NMI delivery on boot for SMRNMI hardware.

Changes:
- Add CONFIG_RISCV_SMRNMI_ENABLE_NMI_DELIVERY Kconfig option
- Define SMRNMI CSRs in arch/riscv/include/csr.h
- Set NMIE bit during boot to enable NMI delivery

SMRNMI hardware generates but doesn't deliver NMIs when NMIE=0 (default).
This causes twister test failures and prevents handling of critical
hardware events like watchdog NMIs and ECC errors.

Setting NMIE=1 enables NMI delivery, but note that this implementation
only sets the enable bit - it does not provide full SMRNMI support
(no mnret instruction handling, no RNMI handlers). Users must implement
proper RNMI handlers in SoC-specific code to avoid undefined behavior.

Signed-off-by: Afonso Oliveira <afonsoo@synopsys.com>
2025-11-17 09:23:11 -05:00
Tom Hughes
d66f081f06 arch: riscv: core: Fix type
riscv_cpu_wake_flag and riscv_cpu_sp are variables, not functions, so
they should use the GDATA macro instead of the GTEXT macro. Otherwise,
the linker will warn when LTO is enabled:

ld.bfd: warning: type of symbol `riscv_cpu_wake_flag' changed from 2 to
1 in /tmp/cc39w5oK.ltrans0.ltrans.o
ld.bfd: warning: type of symbol `riscv_cpu_sp' changed from 2 to 1 in
/tmp/cc39w5oK.ltrans0.ltrans.o

Signed-off-by: Tom Hughes <tomhughes@chromium.org>
2025-06-05 12:33:47 +02:00
Yong Cong Sin
035c822253 arch: riscv: fill all IRQ stacks with 0xAA
Fill the memory of all CPU's IRQ stack with 0xAA on init, so
that `z_stack_space_get` can calculate the remaining space
correctly.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
2024-09-13 09:17:34 +02:00
Yong Cong Sin
bbe5e1e6eb build: namespace the generated headers with zephyr/
Namespaced the generated headers with `zephyr` to prevent
potential conflict with other headers.

Introduce a temporary Kconfig `LEGACY_GENERATED_INCLUDE_PATH`
that is enabled by default. This allows the developers to
continue the use of the old include paths for the time being
until it is deprecated and eventually removed. The Kconfig will
generate a build-time warning message, similar to the
`CONFIG_TIMER_RANDOM_GENERATOR`.

Updated the includes path of in-tree sources accordingly.

Most of the changes here are scripted, check the PR for more
info.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
2024-05-28 22:03:55 +02:00
Anas Nashif
3f75373584 arch: introduce arch_secondary_cpu_init
Different architecture are doing this in custom ways and using different
naming conventions, unify this interface and make it part of the arch
implementation for SMP.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2024-01-09 10:00:17 +01:00
Anas Nashif
9f3ed1b2b3 arch: _PrepC -> z_prep_c
Rename to use common naming for z_prep_c applied to all architectures.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2023-12-11 18:23:52 -05:00
Katsuhiro Suzuki
4ce5f7ebe1 arch: riscv: fix hangup of multicore boot
This patch fixes hangup of RISC-V multicore boot.
Currently boot sequence uses a riscv_cpu_wake_flag to notify wakeup
request for secondary core(s).

But initial value of riscv_cpu_wake_flag is undefined, so current
mechanism is going to hangup if riscv_cpu_wake_flag and mhartid of
secondary core have the same value.

This is an example situation of this problem:

- hart1: check riscv_cpu_wake_flag (value is 1) and end the loop
- hart1: set riscv_cpu_wake_flag to 0
- hart0: set riscv_cpu_wake_flag to 1
         hart0 expects it will be changed to 0 by hart1 but it
         has never happened

Note:
  - hart0's mhartid is 0, hart1's mhartid is 1
  - hart0 is main, hart1 is secondary in this example

Signed-off-by: Katsuhiro Suzuki <katsuhiro@katsuster.net>
2023-11-10 10:40:01 +01:00
Conor Paxton
02391ed00d riscv: enable booting from non-zero indexed RISC-V hart
RISC-V multi-hart systems that employ a heterogeneous core complex are
not guaranteed to have the smp capable harts starting with a unique id
of zero, matching Zephyr's sequential zero indexed cpu numbering scheme.

Add option, RV_BOOT_HART to choose the hart to boot from.
On reset, check the current hart equals RV_BOOT_HART: if so, boot first
core. else, loop in the boot secondary core and wait to be brought up.

For multi-hart systems that are not running a Zephyr mp or smp
application, park the non zephyr related harts in a wfi loop.

Signed-off-by: Conor Paxton <conor.paxton@microchip.com>
2023-01-30 23:45:35 +00:00
Nicolas Pitre
96a65e2fc0 riscv: don't include the secondary CPU boot code when not needed
Linker garbage collection couldn't work due to the explicit reference
in reset.S.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2023-01-19 13:48:42 +01:00
Kumar Gala
3369997dd2 arch: riscv: Convert to CONFIG_MP_MAX_NUM_CPUS
Convert CONFIG_MP_NUM_CPUS to CONFIG_MP_MAX_NUM_CPUS as we work on
phasing out CONFIG_MP_NUM_CPUS.

Signed-off-by: Kumar Gala <kumar.gala@intel.com>
2022-10-25 10:52:25 +02:00
Nicolas Pitre
1f362a81f1 riscv: fix crash resulting from touching the initial stack's guard area
The interrupt stack is used as the system stack during kernel
initialization while IRQs are not yet enabled. The sp register is
set to z_interrupt_stacks + CONFIG_ISR_STACK_SIZE.

CONFIG_ISR_STACK_SIZE only represents the desired usable stack size.
This does not take into account the added guard area. Result is a stack
whose pointer is much closer to the trigger zone than expected when
CONFIG_PMP_STACK_GUARD=y, and the SMP configuration in particular pushes
it over the edge during many CI test cases.

Worse: during early init we're not quite ready to handle exceptions
yet and complete havoc ensues with no meaningful debugging output.

Make sure the early assembly code locates the actual top of the stack
by generating a constant with its true size.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2022-09-28 07:53:56 +00:00
Gerard Marull-Paretas
4b91c2d79f asm: update files with <zephyr/...> include prefix
Assembler files were not migrated with the new <zephyr/...> prefix.
Note that the conversion has been scripted, refer to #45388 for more
details.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2022-05-09 12:45:29 -04:00
Nicolas Pitre
a50c433012 riscv: exception code mega simplification and optimization
Complete revamp of the exception entry code, including syscall handling.
Proper syscall frame exception trigger. Many correctness fixes, hacks
removal, etc. etc.

I tried to make this into several commits, but this stuff is all
inter-related and a pain to split.

The diffstat summary:

 14 files changed, 250 insertions(+), 802 deletions(-)

Binary size (before):

   text	   data	    bss	    dec	    hex	filename
   1104	      0	      0	   1104	    450	isr.S.obj
     64	      0	      0	     64	     40	userspace.S.obj

Binary size (after):

   text	   data	    bss	    dec	    hex	filename
    600	      0	      0	    600	    258	isr.S.obj
     36	      0	      0	     36	     24	userspace.S.obj

Run of samples/userspace/syscall_perf (before):

*** Booting Zephyr OS build zephyr-v3.0.0-325-g3748accae018  ***
Main Thread started; qemu_riscv32
Supervisor thread started
User thread started
Supervisor thread(0x80010048):       384 cycles	     509 instructions
User thread(0x80010140):           77312 cycles	   77437 instructions

Run of samples/userspace/syscall_perf (after):

*** Booting Zephyr OS build zephyr-v3.0.0-326-g4c877a2753b3  ***
Main Thread started; qemu_riscv32
Supervisor thread started
User thread started
Supervisor thread(0x80010048):       384 cycles	     509 instructions
User thread(0x80010138):            7040 cycles     7165 instructions

Yes, that's more than a 10x speed-up!

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2022-03-21 07:28:05 -04:00
Nicolas Pitre
1fd79b3ef4 riscv: better abstraction for register-wide load/store opcodes
Those are prominent enough that having RV_OP_LOADREG and RV_OP_STOREREG
shouting at you all over the place is rather unpleasant and bad taste.

Let's create pseudo-instructions of our own with assembler macros
rather than preprocessor defines and only in assembly scope.
This makes the asm code way more uniform and readable.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2022-03-21 07:28:05 -04:00
Nicolas Pitre
9ed17943b9 riscv: use simplest asm expression when possible
Let's take advantage of assembler pseudoinstructions:

- convert `addi rd, rs, 0` to `mv rd, rs`
- convert `jal x0, somewhere` to `j somewhere`
- convert `csrrs x0, csrreg, rs` to `csrs csrreg, rs`
- convert `fscsr x0, rs` to `fscsr rs`

And simplify zero offsets to simply 0.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2022-03-21 07:28:05 -04:00
Ederson de Souza
d9ab35577b arch/riscv: Boot secondary CPUs for SMP support
Secondary CPUs are now initialised and made available to the system. If
the system has more CPUs than configured via CONFIG_MP_NUM_CPUS, those
are still left looping as before.

Some implementations of `soc_interrupt_init` also changed to use
`arch_irq_lock` instead of `irq_lock`.

Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
2022-02-25 19:13:50 -05:00
Alexandre Mergnat
542a7fa25d arch: riscv: add memory protection support
The IRQ handler has had a major changes to manage syscall, reschedule
and interrupt from user thread and stack guard.

Add userspace support:
- Use a global variable to know if the current execution is user or
  machine. The location of this variable is read only for all user
  thread and read/write for kernel thread.
- Memory shared is supported.
- Use dynamic allocation to optimize PMP slot usage. If the area size
  is a power of 2, only one PMP slot is used, else 2 are used.

Add stack guard support:
- Use MPRV bit to force PMP rules to machine mode execution.
- IRQ stack have a locked stack guard to avoid re-write PMP
  configuration registers for each interruption and then win some
  cycle.
- The IRQ stack is used as "temporary" stack at the beginning of IRQ
  handler to save current ESF. That avoid to trigger write fault on
  thread stack during store ESF which that call IRQ handler to
  infinity.
- A stack guard is also setup for privileged stack of a user thread.

Thread:
- A PMP setup is specific to each thread. PMP setup are saved in each
  thread structure to improve reschedule performance.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
Reviewed-by: Nicolas Royer <nroyer@baylibre.com>
2020-11-09 15:37:11 -05:00
Stephanos Ioannidis
0e6ede8929 kconfig: Rename CONFIG_FLOAT to CONFIG_FPU
This commit renames the Kconfig `FLOAT` symbol to `FPU`, since this
symbol only indicates that the hardware Floating Point Unit (FPU) is
used and does not imply and/or indicate the general availability of
toolchain-level floating point support (i.e. this symbol is not
selected when building for an FPU-less platform that supports floating
point operations through the toolchain-provided software floating point
library).

Moreover, given that the symbol that indicates the availability of FPU
is named `CPU_HAS_FPU`, it only makes sense to use "FPU" in the name of
the symbol that enables the FPU.

Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
2020-04-27 19:03:44 +02:00
Corey Wharton
58232d58e0 riscv: Add support for floating point
This change adds full shared floating point support for the RISCV
architecture with minimal impact on threads with floating point
support not enabled.

Signed-off-by: Corey Wharton <coreyw7@fb.com>
2020-04-22 16:39:48 -07:00
Andrew Boie
80a0d9d16b kernel: interrupt/idle stacks/threads as array
The set of interrupt stacks is now expressed as an array. We
also define the idle threads and their associated stacks this
way. This allows for iteration in cases where we have multiple
CPUs.

There is now a centralized declaration in kernel_internal.h.

On uniprocessor systems, z_interrupt_stacks has one element
and can be used in the same way as _interrupt_stack.

The IRQ stack for CPU 0 is now set in init.c instead of in
arch code.

The extern definition of the main thread stack is now removed,
this doesn't need to be in a header.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2020-03-16 23:17:36 +02:00
Stephanos Ioannidis
2d7460482d headers: Refactor kernel and arch headers.
This commit refactors kernel and arch headers to establish a boundary
between private and public interface headers.

The refactoring strategy used in this commit is detailed in the issue

This commit introduces the following major changes:

1. Establish a clear boundary between private and public headers by
  removing "kernel/include" and "arch/*/include" from the global
  include paths. Ideally, only kernel/ and arch/*/ source files should
  reference the headers in these directories. If these headers must be
  used by a component, these include paths shall be manually added to
  the CMakeLists.txt file of the component. This is intended to
  discourage applications from including private kernel and arch
  headers either knowingly and unknowingly.

  - kernel/include/ (PRIVATE)
    This directory contains the private headers that provide private
   kernel definitions which should not be visible outside the kernel
   and arch source code. All public kernel definitions must be added
   to an appropriate header located under include/.

  - arch/*/include/ (PRIVATE)
    This directory contains the private headers that provide private
   architecture-specific definitions which should not be visible
   outside the arch and kernel source code. All public architecture-
   specific definitions must be added to an appropriate header located
   under include/arch/*/.

  - include/ AND include/sys/ (PUBLIC)
    This directory contains the public headers that provide public
   kernel definitions which can be referenced by both kernel and
   application code.

  - include/arch/*/ (PUBLIC)
    This directory contains the public headers that provide public
   architecture-specific definitions which can be referenced by both
   kernel and application code.

2. Split arch_interface.h into "kernel-to-arch interface" and "public
  arch interface" divisions.

  - kernel/include/kernel_arch_interface.h
    * provides private "kernel-to-arch interface" definition.
    * includes arch/*/include/kernel_arch_func.h to ensure that the
     interface function implementations are always available.
    * includes sys/arch_interface.h so that public arch interface
     definitions are automatically included when including this file.

  - arch/*/include/kernel_arch_func.h
    * provides architecture-specific "kernel-to-arch interface"
     implementation.
    * only the functions that will be used in kernel and arch source
     files are defined here.

  - include/sys/arch_interface.h
    * provides "public arch interface" definition.
    * includes include/arch/arch_inlines.h to ensure that the
     architecture-specific public inline interface function
     implementations are always available.

  - include/arch/arch_inlines.h
    * includes architecture-specific arch_inlines.h in
     include/arch/*/arch_inline.h.

  - include/arch/*/arch_inline.h
    * provides architecture-specific "public arch interface" inline
     function implementation.
    * supersedes include/sys/arch_inline.h.

3. Refactor kernel and the existing architecture implementations.

  - Remove circular dependency of kernel and arch headers. The
   following general rules should be observed:

    * Never include any private headers from public headers
    * Never include kernel_internal.h in kernel_arch_data.h
    * Always include kernel_arch_data.h from kernel_arch_func.h
    * Never include kernel.h from kernel_struct.h either directly or
     indirectly. Only add the kernel structures that must be referenced
     from public arch headers in this file.

  - Relocate syscall_handler.h to include/ so it can be used in the
   public code. This is necessary because many user-mode public codes
   reference the functions defined in this header.

  - Relocate kernel_arch_thread.h to include/arch/*/thread.h. This is
   necessary to provide architecture-specific thread definition for
   'struct k_thread' in kernel.h.

  - Remove any private header dependencies from public headers using
   the following methods:

    * If dependency is not required, simply omit
    * If dependency is required,
      - Relocate a portion of the required dependencies from the
       private header to an appropriate public header OR
      - Relocate the required private header to make it public.

This commit supersedes #20047, addresses #19666, and fixes #3056.

Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
2019-11-06 16:07:32 -08:00
Huang Qi
2c277077fe arch: riscv: Use infinite loop instead of simple wfi to halt slave core
If it's a multicore system, infinite loop wfi to halt slave core

Signed-off-by: Huang Qi <757509347@qq.com>
2019-09-20 10:42:28 -04:00
Huang Qi
19da4ee379 arch: riscv: Add simple wrokaround to boot multicore system
Just boot master core, halt others

Signed-off-by: Huang Qi <757509347@qq.com>
2019-09-20 10:42:28 -04:00
Nicolas Pitre
1f4b5ddd0f riscv32: rename to riscv
With the upcoming riscv64 support, it is best to use "riscv" as the
subdirectory name and common symbols as riscv32 and riscv64 support
code is almost identical. Then later decide whether 32-bit or 64-bit
compilation is wanted.

Redirects for the web documentation are also included.

Then zephyrbot complained about this:

"
New files added that are not covered in CODEOWNERS:

dts/riscv/microsemi-miv.dtsi
dts/riscv/riscv32-fe310.dtsi

Please add one or more entries in the CODEOWNERS file to cover
those files
"

So I assigned them to those who created them. Feel free to readjust
as necessary.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2019-08-02 13:54:48 -07:00
Renamed from arch/riscv32/core/reset.S (Previous history)