Commit graph zephyr/arch/arm
Author SHA1 Message Date
Benjamin Cabé
8b93109f26 arch: arm: cortex_m: pend PendSV with a plain store on thread abort
k_thread_abort() pends PendSV with SCB->ICSR |= PENDSVSET, the third
such site after arch_swap() and z_arm_exc_exit(). ICSR's writable bits
are write-one-to-set or write-one-to-clear and writing zero is a no-op,
so the read-modify-write is equivalent to a plain store while also
writing back a stale snapshot of the other write-one bits.

This path is not hot, so the motivation is consistency and dropping
that stale write-back rather than the saved access. The SHCSR update
immediately below stays a read-modify-write: its bits are ordinary
read/write ones that have to be preserved.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-09-26 00:44:46 +02:00
Benjamin Cabé
6f0188a56c arch: arm: cortex_m: pend PendSV with a plain ICSR store
arch_swap() and z_arm_exc_exit() pended PendSV with a read-modify-write
of SCB->ICSR. The register's writable bits are all write-one-to-set or
write-one-to-clear and writing zero to them has no effect, so the read
and the OR are pointless: a plain store of PENDSVSET is equivalent and
one memory access shorter on the two hottest exception paths. It also
avoids writing back a stale snapshot of the other write-one bits (for
instance re-pending a SysTick whose pend bit was cleared between the
read and the write, were the sequence ever preempted).

Measured standalone against main (latency_measure in cycles, lower is
better; thread_metric scores, higher is better):

* mps2/an385 (Cortex-M3, QEMU icount):
  - latency_measure: mean -1.8% over 47 ops, min/max/median
    -5.0/+0.0/-1.1%; k_yield context switch 182 -> 180 cycles.
  - thread_metric: cooperative and preemptive +1.1%.

* az3166_iotdevkit (STM32F412, Cortex-M4 @ 96 MHz):
  - thread_metric: preemptive +2.0%, cooperative +1.1%.
  - latency_measure: ops stay within ±2 cycles of code-placement
    noise, min/max/median -2.0/+2.2/+0.0%.

* Flash, az3166 latency_measure image: -8 B at both -Os and -O2.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-09-26 00:44:46 +02:00
Chidvilas Yerramsetti
014488bbc2 cmake: arm: clang: add -mtp=soft for thread-local storage
Clang's default ARM TLS codegen accesses the TLS block through
TPIDRURO (the per-CPU pointer) instead of TPIDRURW, which Zephyr
uses as the TLS base pointer on Cortex-A/R. This produced corrupted
z_tls_current and other thread-local accesses since the wrong base
was used.

Pass -mtp=soft to force calls through Zephyr's own __aeabi_read_tp,
matching the GCC toolchain's target_arm.cmake and Zephyr's TPIDRURW
based TLS mechanism.

Signed-off-by: Chidvilas Yerramsetti <cyerrams@qti.qualcomm.com>
2026-09-26 00:44:34 +02:00
Laurie Fay
d7b131763f arch: arm: Use CMSIS APIs for USE_SWITCH
Replace hand-written assembly with CMSIS APIs in the implementation
of USE_SWITCH, as in the review comments for #85248. This should
allow better maintainability and compiler compatibility, and ensure
correctness with respect to instruction barriers.

A small change to include order is needed to avoid errors when the
cmsis_core.h header includes zephyr/irq.h before the
arch/arm/irq.h implementation is included.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Laurie Fay <Laurie.Fay@arm.com>
2026-09-17 12:10:55 +01:00
Silesh C V
afaff5491e arch: arm: aarch32: enable SMP for ARMv8-A AArch32
The shared Cortex-A/R SMP support (GIC SGI-based scheduler IPIs,
secondary core bring-up via reset-time voting locks) is sufficient to
run SMP on ARMv8-A AArch32. Enabling it only requires selecting the
capability flags SCHED_IPI_SUPPORTED (under SMP) and
ARCH_HAS_DIRECTED_IPIS. Also drop the stale "UP only" note.

Signed-off-by: Silesh C V <silesh@alifsemi.com>
2026-09-16 09:22:52 +02:00
Silesh C V
046c597f13 arch: arm: cortex_a_r: smp: skip unmapped CPUs when sending IPIs
send_ipi() means to skip CPUs whose cpu_map[] entry is not yet
populated, but it compares the sender's MPIDR against INV_MPID
instead of the target's. GET_MPIDR() never returns INV_MPID, so the
guard never fires and an unmapped entry reaches gic_raise_sgi().
Fix this.

Signed-off-by: Silesh C V <silesh@alifsemi.com>
2026-09-16 09:22:52 +02:00
Silesh C V
79c794c6f8 arch: arm: remove unused offload_routine extern declarations
Remove unused extern declarations of offload_routine from cortex_m
and cortex_a_r exception.h as currently there are no users for these.

The global offload_routine (and the irq_offload code that set it to
the offloaded routine and cleared it back to NULL) was introduced by
commit 75caa2b084 ("arm: exception-assisted kernel panic/oops support")
so that _IsInIsr() could tell whether the active SVC was an irq_offload()
call.

On cortex-m, commit 4f11b6f8cf ("arch: arm: re-implement
z_arch_is_in_isr") switched arch_is_in_isr() to read the IPSR and
dropped the offload_routine != NULL check.

On cortex_a_r, the declaration was introduced by commit c30a71df95
("arch: arm: Add Cortex-R support") but it was never referenced.
arch_is_in_isr() derives interrupt context from arch_curr_cpu()->nested.

Signed-off-by: Silesh C V <silesh@alifsemi.com>
2026-09-16 09:22:52 +02:00
Silesh C V
1bca4d22dc arch: arm: cortex_a_r: add SMP/nested-capable irq_offload
The Cortex-A/R cores previously shared the Cortex-M irq_offload
implementation (arch/arm/core/irq_offload.c), which stores the offloaded
routine and parameter in global state and brackets the triggering svc
with k_sched_lock(). This is unsuitable for Cortex-A/R because:

On SMP, CPUs might need to run their offloaded functions at the same
time (for eg. the smp_abort test) so a single global routine/parameter
pair cannot be used. Also, k_sched_lock() is illegal in interrupt context,
so the shared backend cannot honour CONFIG_IRQ_OFFLOAD_NESTED
(irq_offload() called from an ISR, for eg. test_nested_irq_offload test).

Add a dedicated cortex_a_r/irq_offload.c that fixes the above by:

1. keeping the offloaded routine/parameter per-CPU, indexed by
   _current_cpu->id, so concurrent CPUs no longer interfere with each
   other.

2. using arch_irq_lock()/arch_irq_unlock() instead of k_sched_lock() to
   pin the caller to its CPU while the per-CPU slot is written and the
   svc is taken, while remaining legal from interrupt context. On
   Cortex-A/R the SVC is not masked by CPSR.I. So it still traps with
   interrupts locked.

The offloaded routine/parameter are kept in a per-CPU slot rather than
passed in registers (as arm64 does) to keep this change self-contained
in C and to avoid modifying the shared SVC exception entry used for
context switch, oops and syscalls.

Build the new file for Cortex-A/R, and select ARCH_HAS_IRQ_OFFLOAD_NESTED
for CPU_AARCH32_CORTEX_A and CPU_AARCH32_CORTEX_R.

Signed-off-by: Silesh C V <silesh@alifsemi.com>
2026-09-16 09:22:52 +02:00
Silesh C V
9d8ace20d0 arch: arm: cortex_a_r: smp: power on secondary cores via pm_cpu_ops
arch_cpu_start() relied solely on the reset.S voting lock to bring up
secondary cores. That is sufficient only on platforms that release all
cores at reset. On platforms that hold secondaries powered off until
requested (e.g. the Arm FVP Base model), they must be explicitly
powered on with their reset vector pointing at the Zephyr entry point.

Use the generic pm_cpu_on() API to start each secondary at __start.
This dispatches to whichever CPU power driver is enabled. The call is
guarded by CONFIG_PM_CPU_OPS, leaving platforms that release
all cores at reset unaffected.

Signed-off-by: Silesh C V <silesh@alifsemi.com>
2026-09-16 09:22:52 +02:00
Silesh C V
f7fb4047c9 arch: arm: cortex_a_r: smp: flush boot params before starting secondary
arm_cpu_boot_params is populated by the primary core and consumed by
the secondary being brought up. On platforms that start secondaries
cold, the secondary begins executing with its caches and MMU disabled
and reads the parameters directly from main memory.

The primary used sys_cache_data_invd_range() on the structure, which
invalidates the cache lines without writing them back. The freshly
written parameters can therefore be discarded before reaching memory,
leaving the secondary to read stale values (e.g. a wrong MPID).

Use sys_cache_data_flush_range() to write the lines back instead,
followed by a DSB to guarantee the flush has completed before the
secondary is brought up.

Signed-off-by: Silesh C V <silesh@alifsemi.com>
2026-09-16 09:22:52 +02:00
Silesh C V
5680176ea9 arch: arm: aarch32: mmu: only build shared page tables on primary core
z_arm_mmu_init() runs on every CPU and rebuilds the single, globally
shared L1/L2 page tables on each call. On SMP this is not only
unnecessary duplicate work on the secondary cores (the primary has
already built the tables), but also unsafe. While a secondary core
rebuilds the tables, descriptors that are live and in use by other
cores (the primary or any secondaries with their MMUs enabled) can
temporarily hold invalid values, which can lead to aborts on the
cores using the tables. In practice this manifested as a prefetch
abort on the primary core as soon as a secondary core was brought up
and began (re)building the shared tables.

Fix this by mirroring the arm64 z_arm64_mm_init(is_primary_core)
design: build the tables only on the primary core, in a new
arm_mmu_setup_ptables() helper, and have every core program its MMU
registers and enable translation using the shared tables. As the
page table region's memory attributes are needed while programming
TTBR0, introduce another helper arm_mmu_get_pt_attrs() that is run
by all the cores to look this up.

Also, remove the unused z_arm_mmu_init declaration from
cortex_m/kernel_arch_func.h as that header is included only under
CPU_CORTEX_M.

Single-core behaviour is unchanged.

Signed-off-by: Silesh C V <silesh@alifsemi.com>
2026-09-16 09:22:52 +02:00
Benjamin Cabé
a811b0f1cd arch: arm: cortex_m: drop redundant ISBs from IRQ lock and unlock
arch_irq_lock() and arch_irq_unlock() executed an ISB after every
BASEPRI write on ARMv7-M/ARMv8-M Mainline, and after CPSIE on ARMv6-M/
ARMv8-M Baseline unlock: two pipeline flushes for every kernel critical
section. Neither is architecturally required. Priority-raising MSR
writes are self-synchronizing (Arm DAI 0321A, section 4.8), and on
unlock a pended interrupt is taken within a couple of instructions
anyway; only arch_swap() relies on the pended PendSV being recognized
before the next instruction executes, so it gains an explicit ISB.

Cortex-M7 r0p0/r0p1 keeps the ISB on the raising side, where erratum
440977 (formerly 837070) can delay a priority-raising BASEPRI write. The
CONFIG_CORTEX_M_ERRATUM_440977_WORKAROUND option defaults to y on M7;
the same ISB in the PendSV handler prologue is handled identically.

The ISB occupies the instruction that can still be preempted before the
critical region begins. Retain this existing sequence to avoid masking
higher-priority interrupts through PRIMASK, as Arm's documented
CPSID i/MSR/CPSIE i workaround would do.

Measured standalone against main (latency_measure in cycles, lower is
better; thread_metric scores, higher is better):

* az3166_iotdevkit (STM32F412, Cortex-M4 @ 96 MHz):
  - latency_measure: mean -3.3% over 47 ops, min/max/median
    -8.1/+0.6/-2.9%; semaphore give no-waiter 74 -> 68 cycles.
  - thread_metric: synchronization +15.4%, cooperative +3.3%,
    preemptive +4.6%, interrupt +2.9%.

* mps2/an385 (Cortex-M3, QEMU icount):
  - latency_measure: mean -3.8%, min/max/median -6.8/+0.0/-3.8%.
  - thread_metric: synchronization +8.3%.

* Flash, az3166 latency_measure image: -400 B at -Os, -424 B at -O2.

Assisted-by: Codex:gpt-6-astra
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-09-14 08:42:05 -04:00
Andrei-Edward Popa
ef5b9dc5c1 arch: arm: mpu: fix region init for Cortex-R
ARM_MPU_REGION_INIT() currently includes the MPU region size in the region
attributes for both Cortex-M and Cortex-R.

On Cortex-M, the region attributes and size are both programmed through
RASR, so this is correct. Cortex-R uses separate registers for region
access attributes and region size. Including the size in the attributes
therefore corrupts the memory type attributes programmed into DRACR.

Store the encoded region size in the dedicated size field for Cortex-R
and exclude it from the region attributes. This fixes devicetree-defined
MPU regions on Cortex-R, where the region size could alter the TEX, S, C,
and B attribute bits.

Signed-off-by: Andrei-Edward Popa <andrei.popa105@yahoo.com>
2026-09-13 21:38:15 -04:00
Daniel Leung
2d088dd1c1 arm: mmu: memory mappings to return error value not panic
This changes the error handling of the call chain of both
arch_mem_map() and arch_mem_unmap() in ARM AArch32 to return
errors if possible when actions fail, instead of causing kernel
panic or silently ignoring them. This allows the error code to
be propagated to the caller so it can be handled properly.

arm_mmu_assign_l2_table() previously relied solely on assertions
to catch running out of L2 page tables. With assertions disabled,
it would underflow the free table counter and hand out a table
which is still in use, silently corrupting existing mappings.
It now returns NULL instead, and the failure is propagated up
through arm_mmu_l2_map_page() and its callers as -ENOMEM.

Unsupported cache modes are now rejected with -ENOTSUP instead
of being silently mapped as device memory, and unmapping a page
table entry of an unexpected type is reported as -EFAULT instead
of only being logged. Boot time mappings keep using assertions
as there is no way to recover from those failures.

Both wrappers now invalidate the TLB even if the operation has
failed, since page tables may have been modified before bailing
out.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2026-09-11 05:23:20 -04:00
Daniel Leung
c21850fdd6 arch: change arch_mem_unmap() to return an error code
Mirror the arch_mem_map() change and give arch_mem_unmap() the same
treatment: change the prototype to return int instead of void, so
architecture code has a consistent way to report unmapping failures.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2026-09-11 05:23:20 -04:00
Daniel Leung
aec25bce22 arch: change arch_mem_map() to return an error code
Previously arch_mem_map() was a void function, so architecture
code had no consistent way to report mapping failures to callers
other than panicking or asserting. Change arch_mem_map() to
return int.

Note that this mostly maintains the k_panic() calls unless
the error is easy to handle (like invalid arguments). Each
architecture will need to be amended in the future to properly
handle the error conditions. Also some of the users are
converted to do k_panic() after failure. This is to keep
the signature change commit easier to review.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2026-09-11 05:23:20 -04:00
Bjarki Arge Andreasen
fa61529665 arch: arm: cortex-m: exception: add system control regs to extra_info
During fault handling on the cortex-m, namely ARMV7_M_ARMV8_M_MAINLINE,
some system control registers are modified before reaching
z_fatal_error(). Applications may want to inspect the state of these
registers at time of fault from within k_sys_fatal_error_handler().

- Extend struct __extra_esf_info with the following relevant system
  control registers:

    - CFSR
    - HFSR
    - DFSR
    - MMFAR
    - BFAR

  and extend it with the following SAU registers if
  CONFIG_ARM_SECURE_FIRMWARE=y

    - SFSR
    - SFAR

  and the following field indicating whether the ESF is from the
  non-secure stack

    - bool non_secure

- Update z_arm_fault() to snapshot these registers into the esf copy
  extra_info before fault handling touches any of them.

- Extend esf_dump() to include these registers in case they are
  present. If CONFIG_ARM_SECURE_FIRMWARE=y, the value of the
  non_secure member is dumped, preceeding the system registers, to
  indicate whether the SCB registers are from the SCB or SCB_NS
  instance.

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
2026-09-09 10:36:08 -04:00
Yiren Guo
c720659e6b arch: arm: timing: fix hang in DWT frequency calibration
if the first call to arch_timing_freq_get() happens after
arch_timing_stop(), CYCCNT stays frozen, ddwt is always 0 and the
calibration loop never terminates.

Enable the cycle counter for the measurement and restore its previous
state afterwards.

Signed-off-by: Yiren Guo <guoyr_2013@hotmail.com>
2026-09-07 10:30:00 +02:00
Benjamin Cabé
833321182a dts: bindings: remove deprecated zephyr,memory-region-mpu
Remove the "zephyr,memory-region-mpu" property, deprecated in Zephyr 3.5
in favor of the "zephyr,memory-attr" bitmask.

The three BUILD_ASSERT tripwires in the ARM/ARM64 MPU drivers already
turned any remaining use of the property into a build failure, so they go
away with it, together with the now unused NODE_HAS_PROP_AND_OR helper.

The migration section in doc/services/mem_mgmt/index.rst documented a
property that no longer exists, so it is dropped and its value mapping
table moved to the 4.5 migration guide.

Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
2026-09-01 16:25:35 -04:00
Benjamin Cabé
6ff5f3b89e arch: arm: mpu: drop redundant RNR write in ARMv7-M region_init
Writing RBAR with the VALID bit and the region number set also updates
RNR (Arm v7-M ARM, B3.5.7), so explicitly selecting the region with a
separate RNR write first is only needed on Cortex-R, whose RBAR variant
has no VALID/REGION fields. Move the RNR write into the Cortex-R
branch, saving one MPU register write per programmed region on every
context switch when MPU_STACK_GUARD or USERSPACE is enabled.

Measured standalone against main (latency_measure in cycles, lower is
better; thread_metric scores, higher is better):

* mps2/an385 (Cortex-M3, QEMU icount, instruction-exact):
  - latency_measure, stack guard: mean -1.3%, min/max/median
    -3.4/+0.0/-0.4%.
  - latency_measure, userspace: mean -1.1%, min/max/median
    -2.9/+0.0/-0.6%.
  - thread_metric, stack guard: cooperative and preemptive +0.5%.

* az3166_iotdevkit (STM32F412, Cortex-M4 @ 96 MHz):
  - thread_metric: +0.2–0.3%.
  - latency_measure: within the platform's ±2–3% code-placement
    noise (stack guard min/max/median -3.2/+2.4/+0.0%).

* Flash, az3166 stack-guard image: -8 B at -Os, +8 B at -O2.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-09-01 16:25:29 -04:00
Anas Nashif
101330945c cpp: name the parameters in the __cxa_atexit declarations
MISRA C:2012 Rule 8.2 requires every parameter in a function type to be
named, including the parameters of function pointer parameters.
The C++ ABI __cxa_atexit() stub, its local prototype in the ARM
__aeabi_atexit() wrapper and that wrapper itself left the destructor's
parameter unnamed.

Name them after the arguments the documentation or the
definitions already use. No functional change.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-09-01 16:25:13 -04:00
Laurie Fay
790c09cdcc arch: arm: cortex_m: Auto-enable FP workaround where needed
Automatically select ARM_GCC_FP_WORKAROUND (renamed to
ARM_FP_CLOBBER_WORKAROUND as the workaround is needed for
clang as well as GCC) whenever CONFIG_FRAME_POINTER is set.
CONFIG_FRAME_POINTER passes -fno-omit-frame-pointer as a
compile flag, forcing frame pointers to be enabled on all
files. Thus the FP workaround is needed to manually
spill/restore r7 around the context switch.

Similarly the workaround is needed if the scheduler is using
a red-black tree, as this uses dynamic stack allocation.

Signed-off-by: Laurie Fay <Laurie.Fay@arm.com>
2026-09-01 15:19:11 +01:00
Pei Cheng Sung
0c080b9cc4 arch: arm: add ARM_A_PROFILE_AARCH32 capability flag
The AArch32 A-profile support was shared between ARMv7-A and ARMv8-A
AArch32 by threading "defined(CONFIG_ARMV7_A) ||
defined(CONFIG_AARCH32_ARMV8_A)" through every affected site. Each new
A-profile AArch32 variant would have to be added to all of those guards.

Introduce a hidden capability flag, ARM_A_PROFILE_AARCH32, selected by
both ARMV7_A and AARCH32_ARMV8_A, and migrate the shared guards to the
single CONFIG_ARM_A_PROFILE_AARCH32 symbol. Since the flag is selected
by exactly those two symbols, the guards are logically unchanged; a
future A-profile AArch32 variant now only needs to select the flag to
pick up the shared code paths.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Pei Cheng Sung <pc_sung@realtek.com>
2026-09-01 11:04:18 +01:00
Abderrahmane JARMOUNI
f04b68e2fd arch: Kconfig: remove I/DCACHE_LINE_SIZE depend on !LINE_SIZE_DETECT
Across the tree, I/DCACHE_LINE_SIZE is required at compile-time for
macros, compiler attributes, & linker scripts to function correctly
even if run-time cache line detection is available.
So remove the dependency of ICACHE_LINE_SIZE on
ICACHE_LINE_SIZE_DETECT=n, and of DCACHE_LINE_SIZE on
DCACHE_LINE_SIZE_DETECT=n.

DCACHE_LINE_SIZE_DETECT & ICACHE_LINE_SIZE_DETECT Kconfig options
enable querying some SoC register for finding the i/d-cache line size
at the expense of taking more memory and code and a slightly
increased boot time.

Add new hidden options D/ICACHE_LINE_SIZE_DETECT_SUPPORT only selected
by the software component (arch/SoC layer, driver) implementing the system
cache API.

Signed-off-by: Abderrahmane JARMOUNI <git@jarmouni.me>
2026-09-01 11:03:32 +01:00
Laurie Fay
7a5431a6d8 arch: arm: cortex_m: select USE_SWITCH_SUPPORTED if not nonsecure
USE_SWITCH isn't yet supported for a non-secure Zephyr image on
Cortex-M, as CONFIG_ARM_STORE_EXC_RETURN is not implemented.

Prevent such a non-functional build by only selecting
USE_SWITCH_SUPPORTED if Zephyr is not running as non-secure.
(USE_SWITCH is fine if Zephyr is running as secure or if there
is no security extension.)

Signed-off-by: Laurie Fay <Laurie.Fay@arm.com>
2026-08-27 12:11:19 +01:00
Anas Nashif
0916a30c74 arch: add per-CPU active-IRQ tracking on Cortex-A/R
Vendor HAL interrupt handlers are often entered without their vector
number and have to discover it themselves. On Cortex-M the IPSR
register answers that, but on Cortex-A/R with a GIC the INTID exists
only at acknowledge time inside the ISR wrapper. The Renesas RZ SoCs
work around this today by selecting ARM_CUSTOM_INTERRUPT_CONTROLLER
with pass-through z_soc_irq_* wrappers around the standard GIC driver,
purely to intercept the ack/eoi moments and log the INTID into a
fixed-depth side stack for the FSP HAL, duplicated across six SoCs.

Add k_irq_get_active(), backed by arch_irq_get_active(): the
interrupt line whose handler is executing on the current CPU, or
K_IRQ_ACTIVE_NONE outside interrupt context. The capability symbol
ARCH_HAS_IRQ_GET_ACTIVE only promises the query; whether an
architecture reads it from a register or records it in the dispatch
path is its own business.

On Cortex-A/R recording is the only option, so the implementation is
gated behind an arch-level opt-in, ARM_TRACK_ACTIVE_IRQ, keeping the
cost decision where the cost lives: the shared ISR wrapper publishes
the acknowledged INTID in a per-CPU field of _cpu_arch and keeps the
previous value on the exception stack across the dispatch, so nested
interrupts unwind to the preempted INTID and the outermost exit back
to "none". The stored value is biased by one so the zero-initialized
boot state reads as "none" on every CPU without explicit
initialization, including secondary SMP cores. The wrapper records
whatever get_active returned, so it works with both the GIC and a
custom interrupt controller. Cost is zero when the option is off and
a few instructions per interrupt entry and exit when on.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-08-25 14:36:35 -07:00
Anas Nashif
5524bbc3e4 arch: add portable IRQ pending-state operations
Drivers that need to touch an interrupt's latched pending state
currently reach into the interrupt controller themselves.
NVIC_ClearPendingIRQ() alone appears at 88 call sites across 50 files
under drivers/, NVIC_SetPendingIRQ() at 34 (26 of them in
drivers/counter/, which pends its own IRQ to fire an alarm whose
deadline has already passed) and NVIC_GetPendingIRQ() at 11. Each
site pulls cmsis_core.h and a CONFIG_CPU_CORTEX_M guard into
otherwise portable code, and several counter drivers had already
written private GIC-or-NVIC dispatch helpers for exactly these
operations.

Add k_irq_set_pending(), k_irq_clear_pending() and k_irq_is_pending()
as ALWAYS_INLINE wrappers over matching arch_irq_* functions, and
implement them for the ARM NVIC (AArch32 Cortex-M) and the GIC
(AArch32 Cortex-A/R and AArch64), where the GIC driver already
exported all three as arm_gic_irq_*.

The k_ prefix is deliberate: vendor HAL headers already declare
plain irq_set_pending()/irq_clear_pending() as their own functions
(the Realtek Ameba ROM ABI, pico-sdk's hardware/irq.h), and several
drivers carry private static helpers or API struct members with the
bare names. A namespaced API collides with none of them, needs no
macro tricks, and no renaming of existing code.

The operations are gated on a single capability symbol,
CONFIG_ARCH_HAS_IRQ_PENDING_OPS, so an unported target fails to
build instead of silently doing nothing. Both implemented backends
support all three operations; should an architecture with partial
support materialize (a RISC-V PLIC can report pending state but only
clears it by claiming, and cannot latch from software), the symbol
can be split then.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-08-25 14:36:35 -07:00
Benjamin Cabé
f28028e730 arch: arm: remove deprecated CONFIG_PLATFORM_SPECIFIC_INIT
Remove CONFIG_PLATFORM_SPECIFIC_INIT and its z_arm_platform_init() hook,
deprecated in favour of CONFIG_SOC_RESET_HOOK / soc_reset_hook() well
before Zephyr 4.2 and therefore due for removal in 4.5.

The option had no reader left: neither cortex_m/reset.S nor
cortex_a_r/reset.S tests it, both only branch to soc_reset_hook(). Its
single in-tree selector, soc/renode/cortex_r8_virtual, is migrated to
select SOC_RESET_HOOK and its hook renamed to soc_reset_hook(); the body
is unchanged. Note that this re-activates the SCTLR.V clear on that SoC,
which had silently been dead code since the reset paths stopped calling
z_arm_platform_init() - the SoC now again selects the low exception
vector base as originally intended. It runs slightly later in the reset
sequence, after the per-mode stack pointers are set up. This should be
smoke-tested under Renode.

The stale z_arm_platform_init mention in the IAR linker script helper
comment is updated to soc_reset_hook.

Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
2026-08-21 14:23:38 +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
Tony Han
6f882517f9 arch: arm: core: add Cortex-A5 support to Kconfig and gcc-m-cpu.cmake
Add 'config CPU_CORTEX_A5' to arch/arm/core/cortex_a_r/Kconfig file.
Set 'GCC_M_CPU' to 'cortex-a5' in cmake/gcc-m-cpu.cmake for the
compiler.

Signed-off-by: Tony Han <tony.han@microchip.com>
2026-08-18 17:20:08 -04:00
Hongquan Li
66e1978051 arch/arm: Fix CFSR MMARVALID/BFARVALID clear with write-1-to-clear
The CFSR register uses write-1-to-clear semantics for all fault
status bits per the ARMv7-M/ARMv8-M Architecture Reference Manual.
Two locations in the MemManage and BusFault handlers incorrectly
used `&= ~Msk` (write-0) instead of `= Msk` (write-1), which has
no effect on these sticky bits.

This caused stale VALID bits to persist, leading subsequent fault
handlers to read expired MMFAR/BFAR addresses and potentially
misdiagnose stack overflows.

Fixes zephyrproject-rtos/zephyr#113515

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-08-14 16:12:20 -04:00
Mathieu Choplain
6c5a23e937 arch: arm: core: mpu: simplify predicate for MPU variant selection
We already determine whether the target is PMSAv8 or (PMSAv6/PMSAv7)
using the selected architecture profile (ARMv6-M/ARMv7-M or ARMv8-M
Baseline/Mainline) and define a symbol accordingly. Make use of that
symbol everywhere instead of repeating CPU checks all over arch code.

While at it, drop the allowlist which generated a build error when the
MPU was enabled on an "unknown" CPU. The header is only included from
SoC-specific code which knows whether an MPU exists or not, or generic
code gated behind CONFIG_ARM_MPU, which guarantees that the MPU exists
as CONFIG_ARM_MPU depends on CONFIG_CPU_HAS_ARM_MPU.

Note: this tangentially fixes a bug that misclassified ARMv8-R targets
as using the PMSAv6/PMSAv7 MPU. This bug did not seem to have any
adverse effect though...

Signed-off-by: Mathieu Choplain <mathieu.choplain-ext@st.com>
2026-08-08 16:31:13 -04:00
Hongquan Li
d499b271a4 arch: arm: 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
Laurie Fay
95eca64dca Revert "arch/arm: Work around FVP stkalign glitch"
This reverts commit c18885e95f:
the issue that this commit worked around was fixed in the
previous commit by preserving the original stack alignment.

Signed-off-by: Laurie Fay <Laurie.Fay@arm.com>
2026-08-05 14:09:45 +01:00
Laurie Fay
6cfc248b9f arch: arm: Restore stack alignment with USE_SWITCH
Preserve the alignment indication and rebuild the hardware frame with its
padding word to ensure the stack is always 8-byte aligned when returning
from exception: this is required on Armv8-M.

When an exception is taken with a stack pointer that is not 8-byte
aligned, Armv8-M, and Armv7-M when configured, adds a 4-byte padding word
to align the exception frame. Bit 9 of xPSR records the presence of this
padding.

However, arm_m_switch_to_cpu() does not restore the padding word when
rebuilding the hardware frame. The existing workaround clears the xPSR
alignment bit, which is sufficient on Armv7-M but is invalid on Armv8-M.

Signed-off-by: Laurie Fay <Laurie.Fay@arm.com>
2026-08-05 14:09:45 +01:00
Laurie Fay
d62b57e511 arch: arm: cortex_m: Fix undefined behavior in FPU spill
Declare dummy as a read-write output operand, to reflect how it
is used in the assembly block.

The inline assembly overwrites dummy before reading it, but declares the
operand as input-only. The compiler may therefore assume that the backing
register is unchanged and reuse it for another live value, even though the
assembly clobbers it.

Signed-off-by: Laurie Fay <Laurie.Fay@arm.com>
2026-08-05 14:09:45 +01:00
Sudan Landge
90aeee3cd5 profiling: perf: add Cortex-M stack sampling backend
Add a Cortex-M perf backend that samples interrupted context from the
SysTick exception frame.

Install a SysTick wrapper when stack-sampling perf is enabled and
capture the interrupted stack pointer, EXC_RETURN, and r7 on exception
entry. Validate the complete hardware-stacked frame, including optional
alignment padding and extended FP state, against the Thread-mode or
Handler-mode stack before unwinding with arch_stack_walk().

The Arm stack walker uses EHABI unwind tables, so the backend does not
require CONFIG_FRAME_POINTER. Preserve r7 because EHABI unwind recipes
may use it to recover VSP even when frame pointers are not enabled
globally.

Return -EAGAIN when the interrupted context is invalid or unavailable
so the perf core discards that sample without reporting buffer
exhaustion.

Limit the backend to uniprocessor configurations because its captured
sample state is global and remote SMP sampling does not enter the
SysTick wrapper.

Disable the backend for Non-secure Trusted Execution images. A
Non-secure SysTick can be taken while the core executes Secure code,
but Non-secure firmware cannot access the Secure exception frame.
The stack pointer read by the wrapper instead refers to the suspended
Non-secure context, so it cannot be unwound as the interrupted frame.

Sampling across Security states is unsupported.

Signed-off-by: Sudan Landge <sudan.landge@arm.com>
2026-08-04 06:52:02 -04:00
Sudan Landge
d45fe926f7 arch: arm: stacktrace: unwind Cortex-M MSP frames
Cortex-M exception frames can be stacked on MSP when execution is
interrupted in handler mode. The Arm EHABI stack walker currently seeds
VSP from the saved PSP unconditionally, which only works for frames
stacked on PSP.

Select the exception frame stack pointer from EXC_RETURN.SPSEL so
MSP-backed frames seed the unwinder from extra_info.msp, while preserving
the existing PSP path. This also allows perf sampling backends to unwind
handler-mode call chains captured on MSP.

Signed-off-by: Sudan Landge <sudan.landge@arm.com>
2026-08-04 06:52:02 -04:00
Phil Hindman
296ca62c6f arch: arm: Don't use dump_fault when CONFIG_FAULT_DUMP < 2
Otherwise, "warning: implicit declaration of function 'dump_fault'" is
generated, which may be promoted to an error when also using
CONFIG_COMPILER_WARNINGS_AS_ERRORS=y.

Some variables may be unused when the dump_fault isn't called, so mark them
as unused to avoid warnings.

Signed-off-by: Phil Hindman <phindman@xes-inc.com>
2026-08-03 15:03:45 -04:00
Mathieu Choplain
7e0b4adea3 arch: arm: core: mpu: drop arm_core_mpu_mem_partition_config_update()
Commit 2222fa1426 removed all callers of
the function arm_core_mpu_mem_partition_config_update()... but not the
function itself, which became dead code lingering in tree since then...

Get rid of this function - it has served no purpose for long enough.

Signed-off-by: Mathieu Choplain <mathieu.choplain-ext@st.com>
2026-08-03 08:49:48 -04:00
Evan Chen
c5d5312a0a arch: arm: cortex_m: rename pm_s2ram assembly source
Rename pm_s2ram.S to pm_s2ram_asm.S and update the
Cortex-M source list to reference the new filename.

This avoids generating colliding object paths for the
C and assembly suspend-to-RAM sources when both are
built together.

Assisted-by: GitHub Copilot:GPT-5.4
Signed-off-by: Evan Chen <bugena123@gmail.com>
2026-07-31 20:07:40 -04:00
Mathieu Choplain
b9d56c4704 arch: arm: core: cortex_a_r: use correct prototype for z_arm_mpu_init
The function returns an int, not void.

Signed-off-by: Mathieu Choplain <mathieu.choplain-ext@st.com>
2026-07-31 14:58:28 -04:00
Mathieu Choplain
0aa98dd337 arch: arm: core: mpu: remove guard in MPU API header
Code using this header is only built when CONFIG_ARM_MPU=y so it isn't
necessary to gate the header's declarations behind that option.

Signed-off-by: Mathieu Choplain <mathieu.choplain-ext@st.com>
2026-07-31 14:58:28 -04:00
Mathieu Choplain
378e8840f2 arch: arm: core: mpu: move MPU driver declarations to API header
`arm_core_mpu_dev.h` is the header describing the API that must be
implemented by drivers compatible with the core. Some functions were
were however accessed using an extern declaration inside the ARM MPU
Core module instead of a declaration in the API header.

Move the offending functions to the API header, making the extern
declaration unnecessary. While at it, also make `z_arm_mpu_init()`
part of the header because it is required, even if not consumed by
the ARM MPU Core module itself.

Signed-off-by: Mathieu Choplain <mathieu.choplain-ext@st.com>
2026-07-31 14:58:28 -04:00
Lucien Zhao
0d894e389d arch: arm: mpu: add catch-all region for Cortex-M7 speculative access
XN on device-type regions only protects mapped regions; unmapped holes
in the MPU map remain reachable through the PRIVDEFENA background map,
both by Cortex-M7 speculative instruction fetches (Cortex-M7 TRM) and
by PLD linefills to faulting addresses (erratum 1013783, SDEN-1068427,
all M7 revisions).

Add opt-in CONFIG_ARM_MPU_CM7_UNMAPPED_REGION to program region 0 as a
4GB Strongly-ordered, no-access, Execute-Never catch-all, as
recommended by the erratum workaround; static regions start from
region 1 and take precedence. Opt-in because the catch-all defeats the
PRIVDEFENA background map: the static MPU region table must explicitly
cover all memory the firmware uses.

Signed-off-by: Lucien Zhao <lucien.zhao@nxp.com>
2026-07-30 07:46:26 -05:00
Etienne Carriere
396f412256 arch: use include/zephyr/sys/clock.h
Header file include/zephyr/sys_clock.h is deprecated and will be removed
someday. Update the whole file tree to include zephyr/sys/clock.h
straight instead of zephyr/sys_clock.h.

This change was made running the sed shell command below:
$ sed -i 's/zephyr\/sys_clock\.h/zephyr\/sys\/clock\.h/' \
      `grep -rsl "zephyr/sys_clock\.h" arch/`

Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
2026-07-30 07:45:05 -05:00
Mike J. Chen
15717b6f65 arch: arm: support stacktrace for threads
Add support for stacktrace of threads. The shell command
"kernel unwind <thread_ptr>" now works.

Signed-off-by: Mike J. Chen <mjchen@google.com>
Co-authored-by: Filip Kokosinski <fkokosinski@antmicro.com>
Signed-off-by: Filip Kokosinski <fkokosinski@antmicro.com>
2026-07-30 07:43:42 -05:00
CHEN Xing
9d3ce4ce52 arch: arm: mmu: add l1 section mapping support for soc's memory regions
Mapping large memory regions at the soc level will consume too
many l2 entries, adding l1 section mapping functionality to
reduce excessive use of l2 entries.

Signed-off-by: CHEN Xing <xing.chen@microchip.com>
2026-07-30 07:43:01 -05:00
Hongquan Li
81e3159b10 arch: arm: fix boot params stack pointers
arm_cpu_boot_params stack pointer fields used pointer arithmetic on
two-dimensional K_KERNEL_STACK_ARRAY_DECLARE arrays before casting to
char *, producing invalid initialized pointer values.

Use K_KERNEL_STACK_BUFFER() on the CPU 0 stack elements instead,
matching the runtime initialization in arch_cpu_start().

Fixes #113125

Signed-off-by: Hongquan Li <hongquan.li@processmission.com>
2026-07-29 10:44:40 +02:00
Josh DeWitt
d2fbd32a63 kernel: Only define z_main_thread if multithreading is enabled
z_main_thread is only needed if multithreading is enabled, so move its
definition inside a multithreading check.

Signed-off-by: Josh DeWitt <josh.dewitt@garmin.com>
2026-07-24 15:34:40 -04:00