Commit Graph

442 Commits

Author SHA1 Message Date
Daniel Leung
917bc51d2d xtensa: gdbstub: add arch_gdb_post_memory_write()
This adds arch_gdb_post_memory_write() to deal with caching
after GDB writing to memory.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-06-17 16:27:27 -05:00
Daniel Leung
733305293a xtensa: gdbstub: fix backtracing and stack unwinding
This fixes GDB backtracing by forcibly spilling all registers,
and faking values for WINDOWSTART and WINDOWBASE. This is
effectively telling GDB that only A0-A3 and AR0-AR3 contain
active data and other physical registers do not. GDB then must
rely on spilled values on stack. Otherwise, GDB will try to
look at all AR* registers for previous frame(s). Since we
do not save all AR* register values, there is nothing for GDB
to look at, and thus failing to unwind stack.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-06-17 16:27:27 -05:00
Daniel Leung
c7841ce472 xtensa: gdbstub: fix compiler warning about discarding const
Inside copy_to_ctx(), we are typecasting the stack pointer into
a 32-bit array pointer, and there was unbalanced const between
two sides. Since we should not be modifying anything inside
that array, add const to the 32-bit array pointer too. So now
the compiler will not complain about discarding the const
qualifier.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-06-17 16:27:27 -05:00
Daniel Leung
d00095c4a6 xtensa: fix num_high_regs calculation when dumping stack
The calculation of number of high registers is not entirely
correct. We need to get past the pointer to BSA in the stack
frame before reaching the high registers. The location address
difference between the BSA and start of high registers then
can be used to calculate how many high registers in the stack
frame. So correct the start location of high registers in
the calculation as it was incorrect before. Though the result
would be the same as further divisions would mask this error.
However, it is better to correct this for readability.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-06-17 16:27:27 -05:00
Guennadi Liakhovetski
53a179ac4e llext: make unresolved symbol errors fatal
With experience it becomes clear, that failing to resolve symbols
during the linking process is likely fatal for the module loading and
a simple warning isn't enough. Fail loading instead.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2025-06-17 16:09:50 +02:00
Daniel Leung
d31ee53b60 xtensa: allow flushing auto-refill DTLBs on page table swap
This adds a new kconfig and corresponding code to allow flushing
auto-refill data TLBs when page tables are swapped (e.g. during
context switching). This is mainly used to avoid multi-hit TLB
exception raised by certain memory access pattern. If memory is
only marked for user mode access but not inside a memory domain,
accessing that page in kernel mode would result in a TLB being
filled with kernel ASID. When going back into user mode, access
to the memory would result in another TLB being filled with
the user mode ASID. Now there are two entries on the same memory
page, and the multi-hit TLB exception will be raised if that
memory page is accessed. This type of access is better served
using memory partition and memory domain to share data. However,
this type of access is not prohibited but highly discouraged.
Wrapping the code in kconfig is simply because of the execution
penalty as there will be unnecessary TLB refilling being done.
So only enable this if necessary.

Fixes #88772

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-05-28 20:01:58 +02:00
Anas Nashif
2aacbcaab5 style: add missing curly braces in if/while/for statements.
Add missing curly braces in if/while/for statements.

This is a style guideline we have that was not enforced in CI. All
issues fixed here were detected by sonarqube SCA.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2025-05-17 14:10:33 +02:00
Guennadi Liakhovetski
0a919055e6 xtensa: gdbstub: fix stack calculation
Fix a logic error when calculating stack frame sizes.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2025-05-13 18:38:12 +01:00
Guennadi Liakhovetski
5769c4d565 xtensa: gdbstub: fix compilation
Building gdbstub for xtensa is failing currently with multiple
failures like

arch/xtensa/core/gdbstub.c:432:24: error: invalid operands to \
binary - (have 'int *' and 'const struct arch_esf *')
  432 |         if ((int *)bsa - stack > 4) {

Fix them by using appropriate pointer types.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2025-05-13 18:38:12 +01:00
Daniel Leung
b6be487394 xtensa: update HAL path for custom compilations
Xtensa arch layer has some custom compilation commands to
generate the interrupt dispatchers and the core-isa* files.
However, the include path to find core-isa.h does not work
for Espressif ESP32. So update the mechanism to use correct
path pointing to Espressif HAL when targeting ESP32 family
SoCs.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-05-09 08:23:09 +02:00
Daniel Leung
9cadc8cbec xtensa: userspace: use ADDX4 to calculate syscall table index
When looking for jump address in the syscall table, we need to
multiply the syscall ID by 4 before adding the address offset
of the beginning of the table. This is due to the jump address
being 32-bit (4 bytes). Instead of using two instructions to
shift the ID by 4 first and then the addition, we can use one
ADDX4 instruction to achieve the same result.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
277fa9e8ac xtensa: userspace: swap page tables via assembly code
Since the necessary register values are now pre-computed and
stored in the memory domain struct, we can use them directly
in various assembly locations, thus replacing the function
call to xtensa_swap_update_page_tables().

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
2abf7ce2f1 xtensa: userspace: prevent potential privilege escalation
When context switching and dealing with non-nested interrupts,
the context to be restored are saved in the thread stack.
When userspace is enabled, this means saving context into
the user stacks for user threads. This allows PS values to be
manipulated externally by setting PS.RING in the saved PS
value to 0, resulting in granting kernel access privilege when
the thread is restored. To prevent this, we store the PS value
into the thread struct instead, where user threads cannot
manipulate that. Note that nested interrupts and syscalls are
not using the user stack but the interrupt stack and thread
privileged stack respectively, where they are not accessible
under user mode.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
d5c2e4b03c xtensa: userspace: workaround return PC calc with loops
When syscall assembly is executed, the EPC points to the syscall
instruction, and we have to manually advance it so we will
return to the instruction after syscall to continue execution.
However, with zero-overhead loops and the syscall instruction is
the last instruction, this simple addition does not work as it
would point past the loop and would have skipped the loop.
Because of this, syscall entrance would need to look at the loop
registers and set the PC back to the beginning of loop if we are
still looping. Assuming most of the syscalls are not inside
loops, the extra handling code consumes quite a few cycles.
To workaround this, simply adds a nop after syscall so we no
longer have to deal with loops at syscall entrance, and that
a nop is faster than all the code to manipulate loop registers.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
bdb5723f28 xtensa: userspace: remove ununsed syscall helpers
Syscall helpers with 0, 1, 2, and 3 number of args are not
used so remove them.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
0dce0bdc0b xtensa: userspace: pre-compute MMU registers at domain init
Instead of computing all the needed register values when
swapping page tables, we can pre-compute those values when
the memory domain is first initialized. Should save some
time during context switching.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
36064939d3 xtensa: no need for flush register if threads are pin only
There is no need for ZSR_FLUSH when threads are pin only
(CONFIG_SCHED_CPU_MASK_PIN_ONLY=y), so there is no need to
reserve it.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
50abe89970 xtensa: userspace: use ZSR_RFI_LEVEL for userspace enter
In xtensa_userspace_enter, we were hard-coding to use level 2
interrupt return mechanism to pivot to user mode and start
running the user thread. However, EPC2 and EPS2 may be used
for other purposes, and they could be used for interrupt
return if there are only two level interrupts. So change
the userspace enter to use ZSR_RFI_LEVEL, ZSR_EPC and ZSR_EPS
instead to be more explicit.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
af5dfff3ae xtensa: userspace: use ZSR_RFI_LEVEL for syscall return
When returning from syscall, we cannot use RFE by using EPC1.
As there is no EPS1, we would need to write to PS before
returning. However, this creates a situation where interrupts
are being enabled (since PS is set), and any interrupts will
overwrite EPC1 before we return (which ensures chaos as we
would be returning to the wrong address). So utilize the same
mechanism as interrupt returning by use ZSR_EPS, ZSR_EPC and
ZSR_RFI_LEVEL.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
514cd38431 xtensa: userspace: remove jump to _syscall_returned
There is no need to do a jump to _syscall_returned as it is
the next to be run anyway. Keep the label there so we can
set breakpoint if needed.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
7f028e2f6e xtensa: userspace: align stack before calling syscall handler
We stuff the 7th argument into stack by moving the stack pointer
before calling syscall handler. The Xtensa ABI says stack must
be 16-byte aligned. So instead of moving stack pointer 4 bytes,
we move 16 bytes (assuming stack has been aligned so far).

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
e0752c2938 xtensa: userspace: swap page table earlier in xtensa_switch
When switching page table and MPU enties, we need to call
corresponding functions via call4 which would move the register
window. So we need to do that earlier before we start saving
context into stack by manipulating stack pointer manually which
definitely would interfere with window spilling.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
dcf75319e2 xtensa: set pointer to privileged stack only if user mode
When initializing the stack at thread creation, we should not
set the pointer to privileged stack pointer yet as the thread
can be a kernel thread. Only when a thread is transitioning to
user mode, then we need to set the pointer to point to
the privileged stack. This is a purely semantic change and
should not affect any functionality.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
d725f37d5e xtensa: userspace: calculate PC earlier at syscall entry
This moves the calculation of the return PC earlier in syscall
entry. There is no need to stash it into BSA, load it, do
the calculation and save it back. We can do the calculation
first and save it in BSA at the same time.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
1203ed05d9 xtensa: syscall: fix setting up PS for window spilling
We should not perform a straight OR operation on INTLEVEL as
we have no idea what existing PS.INTLEVEL is. Also, to avoid
any interferences, we disable interrupts very early during
syscall entrance. So we can remove the OR operation as
PS.INTLEVEL will still have all interrupts masked. Note that
we do not really need to OR PS_WOE into PS as we currently
only support windowed ABI which must have PS_WOE set in PS
anyway.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
7f693679b8 xtensa: move FPU_REG_SAVE out of ODD_REG_SAVE
Syscall entrance makes use of ODD_REG_SAVE but it does not
really need to save FPU registers as it is technically
the same thread and same context. So extract call to
FPU_REG_SAVE to interrupt handling code.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
c13c499557 xtensa: add ODD_REG_RESTORE
This adds ODD_REG_RESTORE as a counterpart to ODD_REG_SAVE.
Both the code in interrupt handling and syscall exit have
been refactored to use this new macro.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
fc85aface1 xtensa: parameterized ODD_REG_SAVE
This adds two parameters for ODD_REG_SAVE for scratch register
and BSA pointer, thus allowing a bit more flexibility on how
it can be called.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
10f8882eec xtensa: userspace: remove saving HiFi registers for syscalls
This removes the call to _xtensa_hifi_save() to save the HiFi
registers during syscalls. During syscall, we are not doing
context switching, and technically it is still the same thread.
There is no need to save HiFi registers.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
d9f6882071 xtensa: rsync before reading ZSR_FLUSH
The Xtensa ISA reference manual says to do rsync after wsr to
make sure register is updated before rsr. So do that.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
a4367eb514 xtensa: remove CONFIG_XTENSA_INVALIDATE_MEM_DOMAIN_TLB_ON_SWAP
Remove CONFIG_XTENSA_INVALIDATE_MEM_DOMAIN_TLB_ON_SWAP as it is
remnant from early MMU enabling work which is not needed as
the page table code is different from early version where
the PTEVADDR would be the same for all memory domains.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-17 00:57:19 +02:00
Daniel Leung
833bb667b2 xtensa: fix thread_page_tables_get being unused
thread_page_tables_get() is only used when userspace is
enabled. So move it with userspace #ifdef, or else
compiler would complain about it being unused.

Fixes #88421

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-04-15 19:09:52 +02:00
Luca Burelli
1b48f74346 llext: avoid redundant 'ldr_parm' checks
Since commit 0aa6b1c9de, the 'ldr_parm' pointer is guaranteed to be
valid inside all the functions of the llext_load() call tree.

This commit fixes the only exception of llext_copy_strings(), which was
not passed the 'ldr_parm' pointer, and remove the redundant checks.

No functional change is intended by this commit.

Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
2025-03-17 19:58:15 +01:00
Daniel Leung
c925b0ecd5 xtensa: mmu: fix incorrect caching attrs on double mapping
Inside map_memory() with double mapping enabled, we should not
be mapping the memory with the incoming attributes as-is since
the incoming address may be on un-cached region but with
caching attribute. So we need to sanitize the attributes
according to the incoming address.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2025-03-14 01:01:32 +01:00
Guennadi Liakhovetski
c29e0d3480 llext: xtensa: disable relative relocations for pre-located
When building pre-located LLEXTs of ET_DYN type (shared ELF object)
on Xtensa, all the R_XTENSA_RELATIVE relocations are already correct,
the current code actually breaks them by mobing the value from the
target address-space to a storage range address. Simply removing the
recalculation solves the issue.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2025-02-20 21:05:37 +01:00
Nicolas Pitre
46aa6717ff Revert "arch: deprecate _current"
Mostly a revert of commit b1def7145f ("arch: deprecate `_current`").

This commit was part of PR #80716 whose initial purpose was about providing
an architecture specific optimization for _current. The actual deprecation
was sneaked in later on without proper discussion.

The Zephyr core always used _current before and that was fine. It is quite
prevalent as well and the alternative is proving rather verbose.
Furthermore, as a concept, the "current thread" is not something that is
necessarily architecture specific. Therefore the primary abstraction
should not carry the arch_ prefix.

Hence this revert.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2025-01-10 07:49:08 +01:00
Andy Ross
8b39d4a613 arch/xtensa: Add build-time validation of cache line kconfig
Xtensa cache line sizes aren't an obtuse area of pedantry like they
are in x86.  Different cores already in Zephyr are already using
variant cache line sizes (64 and 128 bytes are both common).

And I tripped over this by using the wrong value because the kconfig
was being inherited (incorrectly) from a default somewhere.

Xtensa exposes the correct value in core-isa.h (well, unless the
toolchain/hal gets messed up).  Add a check to make sure that our
platform kconfig gets it right.

Note that qemu/dc233c was already getting this wrong, leaving the
value at the kconfig default of zero.  That was benign (qemu doesn't
provide any cache emulation for incoherent DMA), but needs to be
fixed.

Signed-off-by: Andy Ross <andyross@google.com>
2025-01-06 20:33:04 +01:00
Guennadi Liakhovetski
00b6ae5bbc llext: xtensa: fix RELATIVE relocations
With dynamically linked / shared ELF objects the displacement
between file offsets and memory addresses can differ between
sections. Therefore we cannot use .text for all such relocations and
have to locate the respective section instead.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2024-12-17 20:55:15 +01:00
Guennadi Liakhovetski
92287c4e8e llext: xtensa: (cosmetic) simplify a calculation
To obtain a section header reference we don't need to calculate its
location in the ELF image, we already have a pointer to all section
headers, just use them.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2024-12-17 20:55:15 +01:00
Guennadi Liakhovetski
024f43b1f0 llext: move a calculation to a more logical location
Currently llext_link_plt() calculates offsets to relocation addresses
relative to the .text section and passes them to
arch_elf_relocate_global() and arch_elf_relocate_local(), where then
.text memory address is added to them. Instead it's more logical to
concentrate the entire calculation in the caller, which then also
removes the assumption, that all sections have the same VMA - LMA
offset from those functions.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2024-12-17 20:55:15 +01:00
Guennadi Liakhovetski
acbd183b72 llext: fix .bss on heap
With writable LLEXT but without pre-assigned section addresses
.bss section offset in its ELF header will not match .bss eventual
location as it's allocated on the heap. Use llext_loaded_sect_ptr()
to get a correct address in both cases.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2024-12-17 20:55:15 +01:00
Daniel Leung
42b209f816 xtensa: optimize syscall helper functions
The original idea of the syscall helpers is to workaround
an issue where the compiler could not correctly model register
usage with inline functions. It was supposed to be only used
when there are more then 3 arguments to syscalls. However,
during the original MMU code development, the helper got
expanded to cover "less then 2 arguments syscalls" as a way
for debugging syscall handling code and was never removed.
So fix that now by limiting the helper for syscalls with
more than 3 arguments.

Moreover, instead of using one helper with 6 arguments, now
we have separate implementations for both 4 and 5 arguments
syscall helpers. Now the compiler does not have to generate
code to always handle 6 arguments which saves a few code bytes
as there is no need to pass extra zeroes as arguments.

This has been verified to work with xt-clang RI-2022.10.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2024-12-04 14:16:15 -05:00
Yong Cong Sin
b1def7145f arch: deprecate _current
`_current` is now functionally equals to `arch_curr_thread()`, remove
its usage in-tree and deprecate it instead of removing it outright,
as it has been with us since forever.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
2024-11-23 20:12:24 -05:00
Guennadi Liakhovetski
4f0cb90c59 LLEXT: fix advanced uses of detached sections
When detached sections are used, STB_GLOBAL relocations also have to
be processed depending on the relocation type. This commit unified
STB_GLOBAL and STB_LOCAL flows by making them use the same relocation
type parser, adds support for R_XTENSA_GLOB_DAT and R_XTENSA_JMP_SLOT
type relocations on Xtensa and fixes STT_SECTION address calculation
for such sections.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2024-11-16 15:28:00 -05:00
Guennadi Liakhovetski
ce32eea24a LLEXT: Xtensa: fix logging level
Use the same logging level as in the rest of LLEXT.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2024-11-16 15:28:00 -05:00
Daniel Leung
cdb9166b81 cmake: toolchain/xcc,xt-clang: env vars for multiple cores
To use Xtensa toolchain, various environment variables must be
set so the executables can find necessary files and what core
to compile for. This becomes an annoyance when you have to
test multiple boards with different cores. You have to use
one set of environment variables per core. Twister cannot test
them all in one setting, and it is especially annoying doing
west builds. So enhance the environment variables handling so
that TOOLCHAIN_VER and XTENSA_CORE can be replaced by
TOOLCHAIN_VAR_<board> and XTENSA_CORE_<board> where <board>
is the normalized board target (think <board>.yaml). CMake
will then figure out the core ID for the toolchain to use.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2024-10-31 09:26:00 -05:00
Tahsin Mutlugun
94f307ab75 arch: xtensa: rename processor state save and restore calls
_xtos_pso_savearea and _xtos_core_restore_nw have been renamed to
xthal_pso_savearea and xthal_core_restore_nw in recent Xtensa
toolchains. Rename them in reset_vector.S to prevent linker errors
when building Zephyr with Xtensa toolchain.

Signed-off-by: Tahsin Mutlugun <Tahsin.Mutlugun@analog.com>
2024-10-29 07:07:42 -05:00
Guennadi Liakhovetski
18419b618f llext: xtensa: fix relocations with multiple SLOT0_OP
Support for R_XTENSA_SLOT0_OP was implemented with a relocation table
test case, containing only one entry at offset 0. For multiple
entries .r_addend has to be taken into account.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2024-10-17 10:49:50 -04:00
Guennadi Liakhovetski
d676d469bd LLEXT: Xtensa: add support for L32R relocation
When building LLEXT for Xtensa with custom sections the compiler
can leave unresolved references in them. Then this has to be done by
the LLEXT core during linking. This commit adds linking support for
the L32R Xtensa instruction.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2024-09-29 21:21:24 +02:00
Daniel Flodin
746c59c82a arch: kernel: lib: toolchain: Standardize TLS keyword
Up until now, the `__thread` keyword has been used for declaring
variables as Thread local storage. However, `__thread` is a GNU
specific keyword which thus limits compatibility with other
toolchains (for instance IAR).

This PR intoduces a new macro `Z_THREAD_LOCAL` which expands to the
corresponding C11, C23 or C++11 standard keyword based on the standard
that is specified during compilation, else it uses the old `__thread`
keyword.

Signed-off-by: Daniel Flodin <daniel.flodin@iar.com>
2024-09-23 10:01:48 +02:00