Commit graph zephyr/arch/riscv
Author SHA1 Message Date
Anas Nashif
aca0af4a92 arch: riscv: use k_thread_is_user_thread()
Replace the open-coded tests of K_USER in a thread's user_options with
k_thread_is_user_thread(). No functional change.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-10-29 17:34:11 -04:00
Daniel DeGrasse
e05549cf53 arch: riscv: use csr APIs for IRQ lock operations
Use csr APIs instead of direct inline asm for IRQ lock/unlock
operations.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@analog.com>
2026-10-28 22:40:41 -04:00
Cheng Yueh
ac7be8f97e arch: riscv: pmp: preserve lock bit on start address for TOR
When Top-Of-Range (TOR) mode is used with two PMP entries, the first
entry defines the lower bound address and the second entry defines the
upper bound address with the desired permissions.

If the region being configured has the lock bit (PMP_L) set, the upper
bound entry correctly receives perm | PMP_TOR, which includes PMP_L.
However, the lower bound entry previously had its configuration set to
0. As a result, the lower bound address entry was not locked, leaving
it writable. This could allow M-mode software or subsequent updates to
alter the start address of what was intended to be an immutable, locked
TOR region.

Set the lower bound entry configuration to perm & PMP_L so that the
lock bit is preserved whenever the region is locked, while keeping
address matching disabled (A=OFF) and permissions cleared (R=W=X=0)
for the lower bound slot.

Signed-off-by: Cheng Yueh <fenzhangs@gmail.com>
2026-10-28 22:29:12 -04:00
Arjun Salunkhe
ac6af918a3 arch: riscv: add mcause 18 for SCE
Add exception values for Double Trap and Software Check
Exception (Required by Zicfilp and Zicfiss).

Signed-off-by: Arjun Salunkhe <arjun.salunkhe@proton.me>
2026-10-28 22:27:10 -04:00
Arjun Salunkhe
0aa4aaf58b arch: riscv: Add Zicfilp SMP enablement
Add mseccfg regsiter configuration for secondary cpus to
enable landing pad enforcement for them.

Signed-off-by: Arjun Salunkhe <arjun.salunkhe@proton.me>
2026-10-28 22:27:10 -04:00
Arjun Salunkhe
4cc75aee39 arch: riscv: Add initial Zicfilp support
Adds M-mode, S-mode (internal SBI) and U-mode enablement for the RISC-V
Zicfilp (Landing Pad) extension for forward-edge Control Flow Integrity:
- Kconfig: Added RISCV_ISA_EXT_ZICFILP and RISCV_LANDING_PADS options.
- Toolchain: Passed -fcf-protection=branch when Zicfilp is active.
- CSR: Added definitions for MSECCFG_MLPE, MENVCFG_LPE, and SENVCFG_LPE.
- M-Mode: Configured mseccfg.MLPE in arch_kernel_init().
- S-Mode: Configured menvcfg.LPE in reset.S for internal SBI.
- U-Mode: Configured senvcfg.LPE in arch_kernel_init().

Tested against qemu_riscv32 with Zicfilp enabled. Verified that indirect
jumps to assembly routines lacking lpad correctly trigger a CPU trap.

Signed-off-by: Arjun Salunkhe <arjun.salunkhe@proton.me>
2026-10-28 22:27:10 -04:00
Jimmy Zheng
94bf4f365e arch: riscv: make vectored mode optional with IRQ vector table
Default RISCV_VECTORED_MODE to enabled when GEN_IRQ_VECTOR_TABLE is
enabled, rather than selecting it.

This allows platforms with a custom vectored interrupt implementation to
disable the standard RISC-V mtvec optional vectored mode while keeping
the existing behavior by default.
For example, AE350 supports the RISC-V privileged architecture but not
the optional mtvec vectored mode, and may use the Andes Vectored PLIC
extension instead.

Signed-off-by: Jimmy Zheng <jimmyzhe@andestech.com>
2026-10-19 10:27:11 +02:00
Sylvio Alves
5a7b28425a arch: riscv: skip pmp guard when painting privileged stack
With CONFIG_INIT_STACKS, arch_user_mode_enter() fills the
privileged stack with 0xaa starting at priv_stack_start. Without
CONFIG_GEN_PRIV_STACKS the privileged stack lives in the thread
stack object and priv_stack_start is the base of the PMP stack
guard, which is still armed for the thread at that point, so the
memset takes a store access fault.

Paint only the area above the guard, and make
arch_thread_priv_stack_space_get() scan the same range so the
reported privileged stack size and usage exclude the guard. It
also returns -EINVAL for a user thread that has not entered user
mode yet, as its privileged stack is not set up.

Assisted-by: Claude:opus-5
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
2026-10-15 16:35:49 +02:00
Krzysztof Chruściński
c7d1299842 arch: riscv: no_multithreading: CPU idle after return from main
So far, forever busy loop with interrupts disabled was executed when
CONFIG_MULTITHREADING=n and main() returned. Change it to forever
k_cpu_idle() which is better from power consumption perspective.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
2026-10-08 15:05:21 +02:00
Benjamin Cabé
38b0970ef3 arch: riscv: pmp: round the null pointer guard up to the PMP granularity
NULL_POINTER_EXCEPTION_REGION_SIZE defaults to 16 bytes, less than the
128-byte PMP granularity of the ESP32-C5, so the null pointer guard
always fails the alignment assertion in set_pmp_entry(), which GCC
turns into an -Warray-bounds error in z_riscv_pmp_kernelmode_disable().
Round the size up to the PMP granularity.

Assisted-by: Claude:opus-5.5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-10-06 07:24:12 +02:00
Omar Naffaa
e07b471772 arch: riscv: add NMI support for secondary cores
Configure MNSTATUS.NMIE for secondary cores to enable NMI handling.
The current configuration to enable it in reset.S only applies to
the primary core.

Signed-off-by: Omar Naffaa <onaffaa@qti.qualcomm.com>
2026-09-29 07:47:46 +02:00
Joel Holdsworth
e3802d3e1f arch: riscv: support building without generated SW ISR table
Make GEN_SW_ISR_TABLE depend on GEN_ISR_TABLES, and guard the import of
_sw_isr_table in isr.S so that applications can build without generated
ISR tables when interrupts are unused.

Assisted-by: Gemini:gemini-3.8-flash
Signed-off-by: Joel Holdsworth <jholdsworth@nvidia.com>
2026-09-26 08:40:33 +02:00
Sefa Celik
e560c91b1f arch: riscv: andes: handle NMI arriving at the reset vector
On AndeStar V5 cores such as the N25/N25F, the NMI vector base address
register (mnvec, CSR 0x7C3) is read-only and reads back the reset_vector
input signal. An NMI therefore enters the system at __reset, and the
boot path re-initialises the core, destroying the machine state the NMI
was raised to let software examine.

Add CONFIG_RISCV_CUSTOM_CSR_ANDES_NMI, gated on a CPU_HAS_ANDES_NMI
capability that the SoC selects, so the option is only offered on cores
implementing the Andes NMI extension rather than the RISC-V RNMI
extension. It tells the two cases apart at the top of __reset and
branches to _andes_nmi_entry instead of booting. Coming out of reset
mcause and mepc both read 0, whereas an NMI sets mcause to 1 and leaves
the interrupted PC in mepc. The option defaults to n, so behaviour is
unchanged unless a SoC enables it.

Note that Andes reports the NMI with the mcause interrupt bit clear,
rather than set as the privileged specification recommends, so the check
compares mcause against 1 exactly. That value is also the instruction
access fault code. Such exceptions are taken through mtvec, which is set
up early in boot, so in practice they do not reach the reset vector;
mtvec.BASE does reset to 0 however, so a fault raised before that setup
cannot be told apart from an NMI.

_andes_nmi_entry is weak and only parks the core, so that the option
links on its own. A SoC enabling NMIs is expected to provide a real
handler overriding it, and to set up whatever that handler needs, such
as an NMI stack in mscratch, before enabling any NMI source.

Signed-off-by: Sefa Celik <sefa.celik@analog.com>
2026-09-26 01:14:25 +02:00
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
Fin Maaß
d4120a7b0d arch: riscv: add Zkr ISA extension support
Add RISCV_ISA_EXT_ZKR for the Zkr entropy source extension. As for the
other ISA extensions, it is enabled from the riscv,isa-extensions
devicetree property. It is also enabled by Zk, which includes Zkr.

Add the addresses of the seed and mseccfg CSRs and the mseccfg.SSEED
bit, which grants S-mode access to the seed CSR.

Zkr is not added to -march: it adds no instructions and the CSRs are
addressed by number, while the LLVM toolchain of the Zephyr SDK selects
its multilib from the exact -march string and has none matching 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
Ayush Singh
c847bfbc8f arch: riscv: Add initial smp support with external sbi
This patch only allows enabling SMP in 1 core setups.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2026-09-24 03:49:59 +02:00
Ayush Singh
27619328e7 arch: riscv: core: Add ipi_sbi support
RISC-V Supervisor Binary Interface Specification supports
inter-processor interrupts using the IPI extension.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2026-09-24 03:49:59 +02:00
Adrian Śliwa
78087d0662 arch: riscv: enable U-mode access to the Zicntr counters
Reads of cycle, time and instret below M-mode are gated by mcounteren
and scounteren, both zero out of reset. Zephyr sets neither in a build
with user threads, so user mode cannot read these counters.

Set them during per-CPU init, since the registers are per-hart. An
M-mode kernel writes mcounteren, and scounteren when misa reports
S-mode, as it does not exist otherwise. An S-mode kernel writes
scounteren alone, because mcounteren is out of reach and is expected
to be set by the SBI, as reset.S does for the built-in one.

Signed-off-by: Adrian Śliwa <asliwa@internships.antmicro.com>
2026-09-16 05:58:39 +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
Dhruv Menon
908a2e5f0d arch: riscv: switch to main stack before unmasking interrupts
If an interrupt was already pending when z_cstart() completed (such as an
early timer compare event or peripheral interrupt), the ISR fired
immediately while sp still pointed to the interrupt stack. Because
_current_cpu->nested is 0, _isr_wrapper assumed the interruption came
from thread mode and reset sp to the top of _kernel.cpus[0].irq_stack,
causing subsequent ISR C call frames to write directly over the hardware-
saved ESF. This corrupted the saved mepc, leading to an Illegal Instruction
exception (mcause: 2) upon mret.

this commit fixes this by moving interrupt enablement
(csrs RV_STATUS_CSR, %2)  inside the inline assembly block after the stack
pointer has been  switched to main_stack (mv sp, %0)

Signed-off-by: Dhruv Menon <dhruvmenon1104@gmail.com>
2026-09-16 05:55:37 +02:00
Sylvio Alves
886d9899db arch: riscv: add soc hook to close the syscall ecall
Some RISC-V SoCs cannot deliver a fault raised by the syscall
body itself while the ECALL exception of a user-mode syscall is
still being handled. The stack guard below the privileged stack
catches a syscall whose call chain runs too deep, but on such a
SoC that access fault is reported asynchronously inside the open
ECALL and locks the core up, resetting the chip with nothing
delivered to software. A user-mode application can therefore
reset the board through the depth of a granted service call.

Masking interrupts does not help here. The existing
RISCV_SOC_HAS_SYSCALL_INTMASK holds off the interrupt
controller, while this fault comes from the body itself.

Add the hidden RISCV_SOC_SYSCALL_CLOSE_ECALL option. When a SoC
selects it, the IRQ wrapper leaves the exception before running
the syscall body: it returns to the following instruction with
the previous privilege set to machine mode, so the body runs on
the same privileged stack with the same privileges but outside
the exception. A fault taken there is an ordinary top-level trap
the SoC delivers normally, and a syscall that overflows the
privileged stack is reported as a stack overflow that kills only
the offending thread.

The exception exit path reloads the exception program counter
and status register from the saved frame, so borrowing both here
does not disturb the return to user mode.

Assisted-by: Claude:opus-5
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
2026-09-14 15:41:06 -04:00
Sylvio Alves
32381dcbfb arch: riscv: add soc hook to mask syscall interrupts
Some RISC-V SoCs cannot take an interrupt in the syscall body: an
interrupt, or another asynchronously reported event such as an
imprecise access fault, taken while the ECALL exception is still
being handled locks the CPU up, with no fault delivered to
software. Precise synchronous traps, such as the ECALL used to
switch out of the body, nest normally. The syscall path sets
mstatus.MIE before running the body, so such a SoC must hold
interrupts off another way.

This is not the Smdbltrp double trap. On the affected cores
reading mstatush traps, so there is no mstatus.MDT to clear, and
the vendor status CSR exposes the in-exception state as a
read-only bit that stays set until mret. Software cannot end the
exception window early, so the only option is to keep interrupts
from being taken while it is open.

Add the hidden RISCV_SOC_HAS_SYSCALL_INTMASK option following
the existing RISCV_SOC_HAS_* hook pattern. When a SoC selects it,
the IRQ wrapper invokes a SoC-provided SOC_SYSCALL_INTMASK macro
on syscall entry, typically raising a hardware interrupt level
threshold, while the generic code carries no SoC register
knowledge. This is a SoC hook rather than part of the generic
CLIC interrupt level support because the SoCs that need it drive
their interrupt controller from SoC code and do not select
RISCV_HAS_CLIC.

The mask is per exception frame. The SoC context hooks save the
state on entry and restore it on the exception exit path, and
with RISCV_ALWAYS_SWITCH_THROUGH_ECALL every context switch goes
through that path: a thread that blocks in the body hands the
CPU to a thread that restores its own saved state, and a new
thread starts from SOC_ESF_INIT. The option therefore depends on
both. While the mask is raised the body is not preemptible and
pending interrupts, the tick included, wait for the syscall to
return or block; the help text says so.

Assisted-by: Claude:opus-5
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
2026-09-14 15:41:06 -04:00
Sylvio Alves
37d3022714 arch: riscv: pre-validate user strings on imprecise-fault socs
arch_user_string_nlen() dereferences a user pointer and recovers
from a bad address through a fault fixup that matches the
faulting mepc against the load instruction's range. On some
RISC-V SoCs the load access fault is imprecise: the reported mepc
lands past the faulting load, so the fixup misses it and the
fault escalates to a fatal reset.

Rename the asm routine to z_riscv_user_string_nlen() and alias
arch_user_string_nlen() to it by default. Under the new
RISCV_USER_STRING_NLEN_VALIDATE option a C implementation takes
over instead: it checks the whole range with
arch_buffer_validate() first and, when that fails, walks the
string in PMP-granularity chunks, validating each chunk before
reading it, so no load that could fault is ever issued. The
faulting load may sit at any offset (a string that starts in an
accessible region and runs unterminated into an inaccessible
one), which is why one check of the first byte is not enough.
The generic syscall handler is untouched.

Add a syscalls test scenario that enables the option on RISC-V.

Assisted-by: Claude:opus-5
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
2026-09-14 15:41:06 -04:00
Liu Qian
18b49e8379 arch: riscv: pmp: add NAPOT multi-slot mode for non-aligned regions
When TOR is unsupported (PMP_NO_TOR), the Kconfig forced
PMP_POWER_OF_TWO_ALIGNMENT=y, wasting memory: 33 KB of code+rodata
aligns to 64 KB, 257 KB aligns to 512 KB.

Add PMP_NAPOT_USE_MULTI_SLOTS: splits a non-naturally-aligned region
into multiple NAPOT entries, each covering the largest naturally-
aligned block at the current address. [0x1800, 0x3800) becomes
0x800 + 0x1000 + 0x800 (3 slots instead of padding to 8192).

Depends on !USERSPACE: arch_mem_domain_max_partitions_get() assumes
1-2 slots per partition and resync_pmp_domain() can only log on
failure, so a partition needing more slots would run unmapped (silent
loss of protection). Help text documents that disabling
PMP_POWER_OF_TWO_ALIGNMENT also splits stack guards and u-mode stacks,
and that PMP_GRANULARITY=64 cuts both ways for that case.

try_multi_entries_set() uses clz/ctz builtins, clears already-written
config bytes on failure before restoring *index_p (otherwise the
trailing write_pmp_entries(0, PMP_SLOTS) in z_riscv_pmp_init() would
program locked partial entries), and folds start/size into the inner
failure logs.

Signed-off-by: Liu Qian <liuqian.andy@picoheart.com>
2026-09-11 17:34:41 +02:00
Liu Qian
96c7e335e4 arch/riscv: add release barrier before publishing switch_handle
Under RVWMO the context stores (callee-saved registers, stack
pointer) may be reordered before the switch_handle store, so a hart
spinning in z_sched_switch_spin() could observe the handle before
the saved context is visible and restore stale registers.

Add fence rw, w before publishing switch_handle, pairing with the
acquire barrier in z_sched_switch_spin(), same as ARM64.

Signed-off-by: Liu Qian <liuqian.andy@picoheart.com>
2026-09-11 17:32:12 +02:00
Hongquan Li
999f33ee60 arch: riscv: smp: panic on secondary hartid lookup failure
If the loop searching for a matching hartid in
arch_secondary_cpu_init() exited without a match, cpu_num would
stay 0 and the secondary hart would initialize itself using
CPU 0's per-CPU state, TLS, PMP and startup callback.

This state is currently unreachable: reset.S gates each secondary
hart until riscv_cpu_wake_flag equals its own mhartid, and the
flag is only ever written from _kernel.cpus[].arch.hartid in
arch_cpu_start(), so a hart whose hartid is absent from the CPU
table never reaches this function. Add the check as defensive
hardening: break on the first match and call k_panic() if the
loop completes without one.

The check sits after the mscratch write because arch_curr_cpu()
reads mscratch, so the fatal path needs per-CPU state set first.

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-08-31 06:58:37 -04:00
Hongquan Li
181907202d arch: riscv: pass NULL thread to custom stack guard without multithreading
In !CONFIG_MULTITHREADING mode the inline assembly in
z_riscv_switch_to_main_no_multithreading() calls
z_riscv_custom_stack_guard_enable() without setting a0 to the
k_thread * the callee's contract requires. The Andes implementation
only survives because it ignores the argument; any implementation
that dereferences thread faults.

Change the contract to accept a NULL thread in no-multithreading mode
(no thread object exists there) and pass NULL from the caller; the
Andes HSP implementation now checks for NULL and guards the main
stack. Also pin main_entry to callee-saved s1 so the jalr target
survives the call.

Fixes #113190

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-08-28 15:28:18 -04:00
Lior David
58a459a991 arch/riscv: align TLS storage to ARCH_STACK_PTR_ALIGN
The TLS storage is stored in a reserved stack area, so it
needs to be aligned with ARCH_STACK_PTR_ALIGN (16 bytes),
otherwise the stack pointer gets out of alignment which
violates the RISCV psABI specification.
In addition, the Zcmp instructions such as cm.push and cm.pop
will have undefined behavior if called with unaligned stack
pointer. This can cause unexpected runtime failures.

Signed-off-by: Lior David <liord@qti.qualcomm.com>
2026-08-27 22:11:25 -04:00
Benjamin Cabé
2782b62e07 arch: riscv: skip the reschedule call on the IRQ exit fast path
On every non-nested interrupt exit, the ISR wrapper called
z_get_next_switch_handle() to ask the scheduler whether a context
switch is needed, including the stack juggling needed around the call
and a second stack sentinel check inside the callee (isr.S already
performs one on this path). For the vast majority of interrupts no
reschedule is needed and all of that work amounts to nothing.

On uniprocessor builds the scheduler's decision is fully captured by
_kernel.ready_q.cache: when it still designates the current thread,
z_get_next_switch_handle() reduces to no-op bookkeeping. Add a short
inline comparison (four instructions) to the interrupt exit path and
skip the call entirely in that case, the same way the Arm Cortex-M
exception exit decides whether to pend PendSV. The fast path is
disabled on SMP (where the decision requires the scheduler lock) and
when thread usage accounting needs to run on every switch decision.

Measured on ESP32-C6 @ 160 MHz (m5stack_nanoc6/esp32c6/hpcore):

* latency_measure: return from ISR to interrupted thread
  464 -> 401 ns (-14%); return from ISR to a different thread
  1099 -> 1124 ns (+2.3%, the added instructions, taken only when
  an actual reschedule follows); all other metrics unchanged. The
  regression is a constant cost paid only when a context switch
  follows anyway, and is amortized: the change nets out positive
  whenever more than ~28% of interrupt exits (~10% on QEMU) return
  to the interrupted thread, which tick and device interrupts
  overwhelmingly do.
* thread_metric: interrupt processing +3.3% (10303330 -> 10645986);
  interrupt preemption -0.5% (5027551 -> 5001353), every interrupt
  there reschedules so it only pays the added check; preemptive and
  cooperative scheduling unchanged (<0.01%).

Measured on qemu_riscv32 (QEMU icount, deterministic):

* latency_measure: return from ISR to interrupted thread
  50 -> 31 cycles (-38%); return from ISR to a different thread
  63 -> 65 cycles (+3.2%).
* thread_metric: interrupt processing +9.6% (1420879 -> 1557774);
  interrupt preemption -0.45% (713682 -> 710438).

Code size: +12 B text (+0.03% at -Os, +0.02% at -O2) on
qemu_riscv32; +16 B (+0.02%, -Os) on ESP32-C6.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-08-27 12:12:48 +01:00
Kaveesha Yalegama
b06c28cf3d riscv: fpu: improve FPU instruction filtering in trap handler
Updates the fast-path assembly in isr.S to explicitly filter out
vector instructions that share opcodes with FP loads/stores,
preventing them from corrupting the FPU context state.

Additionally, introduces CONFIG_RISCV_FPU_INSN_VALIDATE (default
'y' with CONFIG_ASSERT) to provide a C-level runtime validator in
z_riscv_fpu_trap(). This intercepts misrouted non-FPU instructions,
prints the faulting opcode, and throws a kernel oops.

Fixes #96551

Signed-off-by: Kaveesha Yalegama <kaveesha.yalegama@gmail.com>
2026-08-27 12:04:26 +01:00
Benjamin Cabé
5389672ba0 arch: riscv: remove deprecated EXTRA_EXCEPTION_INFO Kconfig option
The RISC-V specific shadow definition of EXTRA_EXCEPTION_INFO was
deprecated in Zephyr 4.3 and is now removed as part of the 4.5
deprecation removal cycle.

The RISC-V exception handling code (isr.S, fatal.c, coredump.c and the
offsets definitions) has been keyed off CONFIG_EXCEPTION_DEBUG since the
deprecation, so removing the symbol requires no code conversion. RISC-V
applications that still set CONFIG_EXTRA_EXCEPTION_INFO must use
CONFIG_EXCEPTION_DEBUG instead.

Note this only drops the deprecated RISC-V local definition. The generic
EXTRA_EXCEPTION_INFO option in arch/Kconfig, guarded by
ARCH_HAS_EXTRA_EXCEPTION_INFO and used by Arm and SPARC, is unaffected.

Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
2026-08-25 07:59:26 -07:00
Jinming Zhao
5b69ef3e99 arch: riscv: stacktrace: fix exception frame unwinding
The ra register is caller-saved. For a non-leaf function interrupted
after a call, esf->ra points back into that function instead of to its
caller. Emitting it unconditionally adds a bogus frame.

A leaf frame may have no saved return address, so its direct caller must
come from esf->ra. Detect the compact leaf layout using a validated,
monotonically increasing caller frame pointer, then continue through the
normal walk loop. This preserves callback and maximum-depth semantics.

Request leaf frame pointers when CONFIG_FRAME_POINTER is enabled so
supporting compilers cannot omit the frame entirely. Older compact leaf
frames remain supported.

Add exact RV32E, RV32, and RV64 traces for leaf and non-leaf exception
frames. Trigger the fault with an illegal instruction so M-mode and
S-mode exercise the same exception path without relying on ebreak
behavior.

Signed-off-by: Jinming Zhao <jinmzhao@qti.qualcomm.com>
2026-08-25 07:56:42 -07: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
Hongquan Li
c8f461d8a3 arch: riscv: pmp: panic when memory-attr regions exceed PMP slots
set_pmp_mem_attr() ignored the result of set_pmp_entry(), so when the
zephyr,memory-attr regions needed more PMP slots than available, the
trailing regions were silently dropped and their permissions never
enforced (default-allowed per the RISC-V privileged spec).

Log the region that could not be installed and call k_panic() so a
configuration that cannot be honored fails the boot loudly instead of
silently degrading security.

Fixes #113777

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-08-21 16:16:52 +02:00
Fin Maaß
67ad3e2902 include: sys: add common header for reversing bits
Add common function for reversing bits.

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-08-19 18:39:40 -04:00
Fin Maaß
a8649affcc riscv: select RISCV_ISA_EXT_ZBKB
select RISCV_ISA_EXT_ZBKB on extensions that
include it.

Signed-off-by: Fin Maaß <info@finmaass.de>
2026-08-17 16:27:42 -04:00
Hongquan Li
1740527e67 arch: riscv: fix arch_user_string_nlen() reading past maxsize
The loop loaded s[counter] before checking counter == maxsize, so it
read s[maxsize] when the first maxsize bytes were all non-NUL and
dereferenced s[0] when maxsize == 0, violating the strnlen()
semantics required by arch_user_string_nlen(). The over-read byte
cannot change the returned length, but if it is not accessible the
exception fixup reports a spurious error and callers reject valid
input with EFAULT.

Check the limit before the load instead.

Fixes zephyrproject-rtos/zephyr#113722

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-08-07 06:47:54 -04:00
Hongquan Li
fad5e2d7a7 arch: riscv: clear fpu_recently_used in arch_float_disable()
Clear the fpu_recently_used flag when disabling FPU access for a
thread. This flag is used by the context switch path to decide whether
to re-enable FPU access; leaving it set caused k_float_disable() to be
silently reverted on the next context switch back to the thread.

Fixes #113645

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-08-03 08:45:03 -04:00
Hongquan Li
3d2284ca98 arch: riscv: track K_FP_REGS coherently across FPU ownership changes
Set K_FP_REGS in z_riscv_fpu_load() when a thread becomes the FPU
owner, and clear it in arch_float_disable(). This keeps user_options
consistent across lazy-FPU architectures rather than only clearing
the flag.

Fixes #113645

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-08-03 08:45:03 -04:00
Hongquan Li
4e3cebb97e arch: riscv: refactor arch_float_disable() and add flush helper
Introduce z_riscv_fpu_flush_thread() to perform the
architecture-specific FPU context flush without touching thread
options or fpu_recently_used, and make arch_float_disable() use it.

Reject NULL thread pointers with -EINVAL in arch_float_disable().
Unlike Cortex-M, RISC-V does not restrict the call to the current
thread or exclude ISR context.

Switch arch_spin_relax() to the new helper: it only needs to flush
the current CPU FPU context in response to a pending IPI, so it must
not go through arch_float_disable(), which now rejects NULL pointers
while _current_cpu->arch.fpu_owner may legitimately be NULL.

Fixes #113645

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-08-03 08:45:03 -04:00
Hongquan Li
2374c3a0d3 arch: riscv: fix SBI SRST unsupported return
Store SBI_ERR_NOT_SUPPORTED in the saved a0 slot for unsupported
SRST functions. The previous store used the saved t2 offset.

S-mode callers kept the old a0 value, and t2 was restored as -1.

Fixes #113149.

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-07-22 19:07:46 +01:00
Hongquan Li
12edc1d062 arch: riscv: coredump: skip priv stack dump for unstarted user threads
The RISC-V coredump hook arch_coredump_priv_stack_dump() derives the
privilege stack region from thread->arch.priv_stack_start. That field
is only initialized when a thread enters user mode via
arch_user_mode_enter(). For a K_USER thread that has been created but
has never run, priv_stack_start is still 0, causing the hook to dump a
low-address region near 0 and potentially trigger a nested memory
fault.

Add an early return when priv_stack_start is 0 so that unstarted user
threads are skipped.

Fixes #113875

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-07-22 19:06:50 +01:00
Sylvio Alves
9dae2a0c21 arch: riscv: deny gracefully when a thread runs out of pmp slots
arch_mem_domain_max_partitions_get() returns an optimistic slot
estimate and its comment says resync_pmp_domain() should deny
availability when the estimate is too high, but that path asserted
instead. On a SoC whose global regions leave few slots, a domain can
hold more partitions than fit a thread's remaining PMP entries, so the
assert fired during a context switch and reset the whole system. Stop
programming and log instead: the thread runs with the partitions that
fit and faults, only itself, on an access to an unmapped one, which is
recoverable.

Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
2026-07-20 16:44:28 -05:00
Sylvio Alves
659faff954 arch: riscv: accept flash rodata in buffer validation
On SoCs whose flash-mapped read-only data sits in an address window
separate from the executable text, the __rom_region symbol only spans
the text. A user-mode thread passing a const string or other rodata
pointer to a syscall then failed the buffer validation, because the
rodata fell outside the only read-only range that was checked.

Accept the rodata region as well so reads of flash-mapped constants
from user mode validate correctly. SoCs with contiguous text and
rodata are unaffected since __rom_region already covers both.

Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
2026-07-20 16:44:28 -05:00
Sylvio Alves
28a743a54a arch: riscv: let llext modules call syscalls under userspace
On RISC-V with CONFIG_USERSPACE, arch_is_user_context() read the
thread-local is_user_mode symbol directly inline. Every syscall stub
inlines this check, so any extension (llext) that called a syscall
pulled in a thread-local relocation the loader cannot resolve, failing
to link with an undefined is_user_mode symbol.

Move the thread-local read into an exported, non-inline accessor
z_riscv_thread_is_user_mode(), declared in arch/riscv/thread.h and
called from arch_is_user_context(), mirroring the Arm
z_arm_thread_is_in_user_mode() approach. Extensions now resolve the
exported symbol instead of a thread-local one, so a loaded module can
call syscalls. The tp-not-initialized fast path stays inline.

Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
2026-07-20 16:44:28 -05:00
Omar Naffaa
3f020fe3c4 arch: riscv: Use new CPU macro to iterate through CPUs
Replace DT_FOREACH_CHILD_STATUS_OKAY_SEP usage with new
DT_FOREACH_CPU_STATUS_OKAY_SEP macro.

Signed-off-by: Omar Naffaa <onaffaa@qti.qualcomm.com>
2026-07-20 08:30:45 -05:00
Adrian Śliwa
5bf87816ff arch: riscv: bump idle stack size
Test

```
west twister -p mpfs_icicle/polarfire/u54/smp -s
kernel.threads.thread_stack
```

fails with `idle thread stack size 512 too low`.

Signed-off-by: Adrian Śliwa <asliwa@internships.antmicro.com>
2026-07-17 11:56:19 -04:00
Anas Nashif
25d08114e9 arch: gate idle notification hooks on SYS_IDLE_HOOKS
The architecture idle paths call sys_trace_idle() and
sys_trace_idle_exit() to notify subscribers when the CPU enters and
leaves the idle state. These calls were guarded by CONFIG_TRACING,
which tied idle-time accounting to the tracing subsystem even though
no tracing backend is required to service the hooks.

Introduce a hidden Kconfig symbol, SYS_IDLE_HOOKS, that any subsystem
needing these notifications can select, and have TRACING select it.
Switch the idle-path guards in every architecture and SoC that emits
the hooks from CONFIG_TRACING to CONFIG_SYS_IDLE_HOOKS. Because
TRACING selects the new symbol, existing tracing behaviour is
unchanged; the change only lets non-tracing consumers receive the
hooks.

This is a prerequisite for building the CPU load module without the
tracing subsystem.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-17 11:55:28 -04:00
Adrian Śliwa
cda79d7ac6 arch: riscv: Bump privileged stack size
Since 5528dee556 (`device: Add asserts to DEVICE_API_GET`), the
following tests fail with a privileged-stack overflow during the
`log_panic()` syscall:

```
west twister -p hifive_unmatched/fu740/u74 -s logging.log_user
west twister -p hifive_unleashed/fu540/u54 -s logging.log_user
```

`qemu_riscv64` passes only because its defconfig sets
`CONFIG_PRIVILEGED_STACK_SIZE=2048`, lowering it to `1024` reproduces
the failure in a similar way.

The bad commit makes stack frames bigger along the `log_panic()` flush
chain. Peak privileged-stack usage goes from just-under to just-over
1024 bytes.

Signed-off-by: Adrian Śliwa <asliwa@internships.antmicro.com>
2026-07-07 17:25:03 +01:00
Omar Naffaa
b284cdb15c drivers: interrupt_controller: APLIC IRQ affinity support
Implement and enable IRQ affinity in APLIC direct mode driver

Signed-off-by: Omar Naffaa <onaffaa@qti.qualcomm.com>
2026-07-07 17:24:52 +01:00