mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-02 03:52:26 +00:00
This commit refactors kernel and arch headers to establish a boundary between private and public interface headers. The refactoring strategy used in this commit is detailed in the issue This commit introduces the following major changes: 1. Establish a clear boundary between private and public headers by removing "kernel/include" and "arch/*/include" from the global include paths. Ideally, only kernel/ and arch/*/ source files should reference the headers in these directories. If these headers must be used by a component, these include paths shall be manually added to the CMakeLists.txt file of the component. This is intended to discourage applications from including private kernel and arch headers either knowingly and unknowingly. - kernel/include/ (PRIVATE) This directory contains the private headers that provide private kernel definitions which should not be visible outside the kernel and arch source code. All public kernel definitions must be added to an appropriate header located under include/. - arch/*/include/ (PRIVATE) This directory contains the private headers that provide private architecture-specific definitions which should not be visible outside the arch and kernel source code. All public architecture- specific definitions must be added to an appropriate header located under include/arch/*/. - include/ AND include/sys/ (PUBLIC) This directory contains the public headers that provide public kernel definitions which can be referenced by both kernel and application code. - include/arch/*/ (PUBLIC) This directory contains the public headers that provide public architecture-specific definitions which can be referenced by both kernel and application code. 2. Split arch_interface.h into "kernel-to-arch interface" and "public arch interface" divisions. - kernel/include/kernel_arch_interface.h * provides private "kernel-to-arch interface" definition. * includes arch/*/include/kernel_arch_func.h to ensure that the interface function implementations are always available. * includes sys/arch_interface.h so that public arch interface definitions are automatically included when including this file. - arch/*/include/kernel_arch_func.h * provides architecture-specific "kernel-to-arch interface" implementation. * only the functions that will be used in kernel and arch source files are defined here. - include/sys/arch_interface.h * provides "public arch interface" definition. * includes include/arch/arch_inlines.h to ensure that the architecture-specific public inline interface function implementations are always available. - include/arch/arch_inlines.h * includes architecture-specific arch_inlines.h in include/arch/*/arch_inline.h. - include/arch/*/arch_inline.h * provides architecture-specific "public arch interface" inline function implementation. * supersedes include/sys/arch_inline.h. 3. Refactor kernel and the existing architecture implementations. - Remove circular dependency of kernel and arch headers. The following general rules should be observed: * Never include any private headers from public headers * Never include kernel_internal.h in kernel_arch_data.h * Always include kernel_arch_data.h from kernel_arch_func.h * Never include kernel.h from kernel_struct.h either directly or indirectly. Only add the kernel structures that must be referenced from public arch headers in this file. - Relocate syscall_handler.h to include/ so it can be used in the public code. This is necessary because many user-mode public codes reference the functions defined in this header. - Relocate kernel_arch_thread.h to include/arch/*/thread.h. This is necessary to provide architecture-specific thread definition for 'struct k_thread' in kernel.h. - Remove any private header dependencies from public headers using the following methods: * If dependency is not required, simply omit * If dependency is required, - Relocate a portion of the required dependencies from the private header to an appropriate public header OR - Relocate the required private header to make it public. This commit supersedes #20047, addresses #19666, and fixes #3056. Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
240 lines
9.8 KiB
ArmAsm
240 lines
9.8 KiB
ArmAsm
/*
|
|
* Copyright (c) 2016 Cadence Design Systems, Inc.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include <arch/xtensa/xtensa_rtos.h>
|
|
|
|
/* WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION
|
|
* HANDLER
|
|
*
|
|
* Here is the code for each window overflow/underflow exception vector and
|
|
* (interspersed) efficient code for handling the alloca exception cause.
|
|
* Window exceptions are handled entirely in the vector area and are very tight
|
|
* for performance. The alloca exception is also handled entirely in the window
|
|
* vector area so comes at essentially no cost in code size. Users should never
|
|
* need to modify them and Cadence Design Systems recommends they do not.
|
|
*
|
|
* Window handlers go at predetermined vector locations according to the Xtensa
|
|
* hardware configuration, which is ensured by their placement in a special
|
|
* section known to the Xtensa linker support package (LSP). Since their
|
|
* offsets in that section are always the same, the LSPs do not define a
|
|
* section per vector.
|
|
*
|
|
* These things are coded for XEA2 only (XEA1 is not supported).
|
|
*
|
|
* Note on Underflow Handlers:
|
|
*
|
|
* The underflow handler for returning from call[i+1] to call[i] must preserve
|
|
* all the registers from call[i+1]'s window. In particular, a0 and a1 must be
|
|
* preserved because the RETW instruction will be reexecuted (and may even
|
|
* underflow if an intervening exception has flushed call[i]'s registers).
|
|
* Registers a2 and up may contain return values.
|
|
*/
|
|
|
|
#if XCHAL_HAVE_WINDOWED
|
|
|
|
.section .WindowVectors.text, "ax"
|
|
|
|
/* Window Overflow Exception for Call4.
|
|
*
|
|
* Invoked if a call[i] referenced a register (a4-a15)
|
|
* that contains data from ancestor call[j];
|
|
* call[j] had done a call4 to call[j+1].
|
|
* On entry here:
|
|
* window rotated to call[j] start point;
|
|
* a0-a3 are registers to be saved;
|
|
* a4-a15 must be preserved;
|
|
* a5 is call[j+1]'s stack pointer.
|
|
*/
|
|
|
|
.org 0x0
|
|
.global _WindowOverflow4
|
|
_WindowOverflow4:
|
|
|
|
s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */
|
|
s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */
|
|
s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */
|
|
s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */
|
|
rfwo /* rotates back to call[i] position */
|
|
|
|
/* Window Underflow Exception for Call4
|
|
*
|
|
* Invoked by RETW returning from call[i+1] to call[i]
|
|
* where call[i]'s registers must be reloaded (not live in ARs);
|
|
* where call[i] had done a call4 to call[i+1].
|
|
* On entry here:
|
|
* window rotated to call[i] start point;
|
|
* a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
|
|
* a4-a15 must be preserved (they are call[i+1].reg[0..11]);
|
|
* a5 is call[i+1]'s stack pointer.
|
|
*/
|
|
|
|
.org 0x40
|
|
.global _WindowUnderflow4
|
|
_WindowUnderflow4:
|
|
|
|
l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */
|
|
l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */
|
|
l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */
|
|
l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */
|
|
rfwu
|
|
|
|
/* Handle alloca exception generated by interruptee executing 'movsp'.
|
|
* This uses space between the window vectors, so is essentially "free".
|
|
* All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
|
|
* and PS.EXCM has been set by the exception hardware (can't be interrupted).
|
|
* The fact the alloca exception was taken means the registers associated with
|
|
* the base-save area have been spilled and will be restored by the underflow
|
|
* handler, so those 4 registers are available for scratch.
|
|
* The code is optimized to avoid unaligned branches and minimize cache misses.
|
|
*/
|
|
|
|
.align 4
|
|
.global _xt_alloca_exc
|
|
_xt_alloca_exc:
|
|
|
|
rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */
|
|
rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */
|
|
rsr a2, PS
|
|
extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
|
|
xor a3, a3, a4 /* bits changed from old to current windowbase */
|
|
rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */
|
|
slli a3, a3, XCHAL_PS_OWB_SHIFT
|
|
xor a2, a2, a3 /* flip changed bits in old window base */
|
|
wsr a2, PS /* update PS.OWB to new window base */
|
|
rsync
|
|
|
|
_bbci.l a4, 31, _WindowUnderflow4
|
|
rotw -1 /* original a0 goes to a8 */
|
|
_bbci.l a8, 30, _WindowUnderflow8
|
|
rotw -1
|
|
j _WindowUnderflow12
|
|
|
|
/* Window Overflow Exception for Call8
|
|
*
|
|
* Invoked if a call[i] referenced a register (a4-a15)
|
|
* that contains data from ancestor call[j];
|
|
* call[j] had done a call8 to call[j+1].
|
|
* On entry here:
|
|
* window rotated to call[j] start point;
|
|
* a0-a7 are registers to be saved;
|
|
* a8-a15 must be preserved;
|
|
* a9 is call[j+1]'s stack pointer.
|
|
*/
|
|
|
|
.org 0x80
|
|
.global _WindowOverflow8
|
|
_WindowOverflow8:
|
|
|
|
s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */
|
|
l32e a0, a1, -12 /* a0 <- call[j-1]'s sp
|
|
(used to find end of call[j]'s frame) */
|
|
s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */
|
|
s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */
|
|
s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */
|
|
s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */
|
|
s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */
|
|
s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */
|
|
s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */
|
|
rfwo /* rotates back to call[i] position */
|
|
|
|
/*
|
|
* Window Underflow Exception for Call8
|
|
*
|
|
* Invoked by RETW returning from call[i+1] to call[i]
|
|
* where call[i]'s registers must be reloaded (not live in ARs);
|
|
* where call[i] had done a call8 to call[i+1].
|
|
* On entry here:
|
|
* window rotated to call[i] start point;
|
|
* a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
|
|
* a8-a15 must be preserved (they are call[i+1].reg[0..7]);
|
|
* a9 is call[i+1]'s stack pointer.
|
|
*/
|
|
|
|
.org 0xC0
|
|
.global _WindowUnderflow8
|
|
_WindowUnderflow8:
|
|
|
|
l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */
|
|
l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */
|
|
l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */
|
|
l32e a7, a1, -12 /* a7 <- call[i-1]'s sp
|
|
(used to find end of call[i]'s frame) */
|
|
l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */
|
|
l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */
|
|
l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */
|
|
l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */
|
|
l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */
|
|
rfwu
|
|
|
|
/*
|
|
* Window Overflow Exception for Call12
|
|
*
|
|
* Invoked if a call[i] referenced a register (a4-a15)
|
|
* that contains data from ancestor call[j];
|
|
* call[j] had done a call12 to call[j+1].
|
|
* On entry here:
|
|
* window rotated to call[j] start point;
|
|
* a0-a11 are registers to be saved;
|
|
* a12-a15 must be preserved;
|
|
* a13 is call[j+1]'s stack pointer.
|
|
*/
|
|
|
|
.org 0x100
|
|
.global _WindowOverflow12
|
|
_WindowOverflow12:
|
|
|
|
s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */
|
|
l32e a0, a1, -12 /* a0 <- call[j-1]'s sp
|
|
(used to find end of call[j]'s frame) */
|
|
s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */
|
|
s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */
|
|
s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */
|
|
s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */
|
|
s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */
|
|
s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */
|
|
s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */
|
|
s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */
|
|
s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */
|
|
s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */
|
|
s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */
|
|
rfwo /* rotates back to call[i] position */
|
|
|
|
/*
|
|
* Window Underflow Exception for Call12
|
|
*
|
|
* Invoked by RETW returning from call[i+1] to call[i]
|
|
* where call[i]'s registers must be reloaded (not live in ARs);
|
|
* where call[i] had done a call12 to call[i+1].
|
|
* On entry here:
|
|
* window rotated to call[i] start point;
|
|
* a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
|
|
* a12-a15 must be preserved (they are call[i+1].reg[0..3]);
|
|
* a13 is call[i+1]'s stack pointer.
|
|
*/
|
|
|
|
.org 0x140
|
|
.global _WindowUnderflow12
|
|
_WindowUnderflow12:
|
|
|
|
l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */
|
|
l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */
|
|
l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */
|
|
l32e a11, a1, -12 /* a11 <- call[i-1]'s sp
|
|
* (used to find end of call[i]'s frame) */
|
|
l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */
|
|
l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */
|
|
l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */
|
|
l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */
|
|
l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */
|
|
l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */
|
|
l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */
|
|
l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack
|
|
* frame */
|
|
l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack
|
|
* frame */
|
|
rfwu
|
|
|
|
#endif /* XCHAL_HAVE_WINDOWED */
|
|
|