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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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
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>
- 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>
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>
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.
Fixeszephyrproject-rtos/zephyr#113722
Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
z_riscv_fatal_error() may return: when a fatal error is handled (for
example an expected fault in ztest aborting the current thread), the
generic z_fatal_error() returns and the exception exit path in isr.S
takes care of rescheduling. isr.S explicitly sets the return address
to no_reschedule before tail-calling z_riscv_fault for this reason.
The CODE_UNREACHABLE hint made LLVM place a trapping instruction
(unimp) right after the call. When the handler returned, the CPU
executed the unimp and re-entered the fault path, so tests raising
expected faults hung in an endless fatal error loop when built with
clang. GCC builds only worked by chance, falling through into
whatever code the compiler laid out after the call.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Right now, the SBI hard-codes the usage of ld/sd instructions, which are
not available on 32-bit platforms. This commit changes this to sr/lr from
`asm_macros.inc`, which automatically resolves them to proper load/store
instructions on 32-bit and 64-bit configurations. It also ensures proper
timer handling through 32-bit registers.
Signed-off-by: Filip Kokosinski <fkokosinski@antmicro.com>
Co-authored-by: Jakub Klimczak <jklimczak@internships.antmicro.com>
Signed-off-by: Jakub Klimczak <jklimczak@internships.antmicro.com>
Use <> operator to include a Zephyr header file instead of "" that
is intended to local header files, not header files relative to
specifically defined search paths.
This change was made running the sed shell command below:
$ sed -i -E 's/#include "zephyr\/([^"]+)\.h"/#include <zephyr\/\1.h>/g' \
`grep -rsl "#include \"zephyr/" arch/`
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
Add RISCV_ISA_EXT_ZK (Scalar Cryptography) and RISCV_ISA_EXT_ZKS
(ShangMi Suite) Kconfig options, and append them to the GCC march
flag when enabled.
Signed-off-by: Liu Qian <liuqian.andy@picoheart.com>
As a part of the AIA specification two new extensions were introduced:
Smaia (Supervisor Machine AIA) and Ssaia (Supervisor Software AIA).
Support is added for these 2 extensions
Signed-off-by: Omar Naffaa <onaffaa@qti.qualcomm.com>
Add macros to read and write CSRs with immediates and use them for
setting userspace blocker in PMP instead of the existing helpers.
This makes the code simpler than with the large switch statement
and should be a bit more efficient.
Signed-off-by: Christoph Busold <cbusold@qti.qualcomm.com>
Move EXECUTE_XOR_WRITE back into userspace and update the comment
to reflect that it only applies to memory partitions.
PMP_DATA_EXECUTION_PREVENTION is now independent from it and no
longer a requirement.
For full protection both options should be enabled. Otherwise,
some data areas my be left executable and writable at the same
time.
Signed-off-by: Christoph Busold <cbusold@qti.qualcomm.com>
When set_userspace_blocker is called on context switches between
user and kernel, read only the required pmpcfg register instead
of all.
Signed-off-by: Christoph Busold <cbusold@qti.qualcomm.com>
CONFIG_EXECUTE_XOR_WRITE now depends on
PMP_DATA_EXECUTION_PREVENTION, which in turn selects
PMP_KERNEL_MODE_DYNAMIC if user space is enabled. Another new
config PMP_KERNEL_MODE_DYNAMIC_CATCHALL indicates whether dynamic
catch-all programming is required.
This simplifies the code structure.
Signed-off-by: Christoph Busold <cbusold@qti.qualcomm.com>
Remove userspace blocker in z_riscv_pmp_kernelmode_enable. This way
data execution will not only be blocked in kernel threads but also
during kernel execution in syscalls on behalf of user threads.
Signed-off-by: Christoph Busold <cbusold@qti.qualcomm.com>
CONFIG_EXECUTE_XOR_WRITE is a basic countermeasure to prevent code
injection attacks by making data non-executable. This can be done
on RISC-V with PMP by removing the executable permission.
Since PMP slots are statically prioritized, we can add a region
covering the whole address space into the last register giving
only read-write access. This will be overridden by any other
configured register with lower index so that the code region
remains executable.
In order to make this register apply to kernel threads in M mode,
it needs to be locked, but this means we cannot remove it anymore.
For CONFIG_USERSPACE we therefore need to reserve another register
so that we can add another address space-wide region with higher
priority without any permission to override the last one and limit
user threads to their assigned regions. This needs to be removed
when switching from user to kernel threads, which is done in the
new function z_riscv_pmp_usermode_disable.
This feature simplifies CONFIG_PMP_KERNEL_MODE_DYNAMIC because we
already have a catch-all register for kernel threads.
Does not work with CONFIG_CODE_DATA_RELOCATION for now and requires
PMP region locking.
Signed-off-by: Christoph Busold <cbusold@qti.qualcomm.com>