1 /* 2 * Copyright (c) 2017, Intel Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 #ifndef ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ 7 #define ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ 8 9 #include <xtensa/corebits.h> 10 #include <xtensa/config/core-isa.h> 11 #include <xtensa/config/tie.h> 12 13 /* 14 * Stack frame layout for a saved processor context, in memory order, 15 * high to low address: 16 * 17 * SP-0 <-- Interrupted stack pointer points here 18 * 19 * SP-4 Caller A3 spill slot \ 20 * SP-8 Caller A2 spill slot | 21 * SP-12 Caller A1 spill slot + (Part of ABI standard) 22 * SP-16 Caller A0 spill slot / 23 * 24 * SP-20 Saved A3 25 * SP-24 Saved A2 26 * SP-28 Unused (not "Saved A1" because the SP is saved externally as a handle) 27 * SP-32 Saved A0 28 * 29 * SP-36 Saved PC (address to jump to following restore) 30 * SP-40 Saved/interrupted PS special register 31 * 32 * SP-44 Saved SAR special register 33 * 34 * SP-48 Saved LBEG special register (if loops enabled) 35 * SP-52 Saved LEND special register (if loops enabled) 36 * SP-56 Saved LCOUNT special register (if loops enabled) 37 * 38 * SP-60 Saved SCOMPARE special register (if S32C1I enabled) 39 * 40 * SP-64 Saved EXCCAUSE special register 41 * 42 * SP-68 Saved THREADPTR special register (if processor has thread pointer) 43 * 44 * (The above fixed-size region is known as the "base save area" in the 45 * code below) 46 * 47 * - 18 FPU registers (if FPU is present and CONFIG_FPU_SHARING enabled) 48 * 49 * - Saved A7 \ 50 * - Saved A6 | 51 * - Saved A5 +- If not in-use by another frame 52 * - Saved A4 / 53 * 54 * - Saved A11 \ 55 * - Saved A10 | 56 * - Saved A9 +- If not in-use by another frame 57 * - Saved A8 / 58 * 59 * - Saved A15 \ 60 * - Saved A14 | 61 * - Saved A13 +- If not in-use by another frame 62 * - Saved A12 / 63 * 64 * - Saved intermediate stack pointer (points to low word of base save 65 * area, i.e. the saved LCOUNT or SAR). The pointer to this value 66 * (i.e. the final stack pointer) is stored externally as the 67 * "restore handle" in the thread context. 68 * 69 * Essentially, you can recover a pointer to the BSA by loading *SP. 70 * Adding the fixed BSA size to that gets you back to the 71 * original/interrupted stack pointer. 72 */ 73 74 #ifndef __ASSEMBLER__ 75 76 #include <stdint.h> 77 #include <zephyr/toolchain.h> 78 79 /** 80 * Base Save Area (BSA) during interrupt. 81 * 82 * This saves the registers during interrupt entrance 83 * so they can be restored later. 84 * 85 * Note that only A0-A3 are saved here. High registers 86 * are saved after the BSA. 87 */ 88 struct xtensa_irq_base_save_area { 89 #if XCHAL_HAVE_FP && defined(CONFIG_CPU_HAS_FPU) && defined(CONFIG_FPU_SHARING) 90 uintptr_t fcr; 91 uintptr_t fsr; 92 uintptr_t fpu0; 93 uintptr_t fpu1; 94 uintptr_t fpu2; 95 uintptr_t fpu3; 96 uintptr_t fpu4; 97 uintptr_t fpu5; 98 uintptr_t fpu6; 99 uintptr_t fpu7; 100 uintptr_t fpu8; 101 uintptr_t fpu9; 102 uintptr_t fpu10; 103 uintptr_t fpu11; 104 uintptr_t fpu12; 105 uintptr_t fpu13; 106 uintptr_t fpu14; 107 uintptr_t fpu15; 108 #endif 109 110 #if defined(CONFIG_XTENSA_HIFI_SHARING) 111 112 /* 113 * Carve space for the registers used by the HiFi audio engine 114 * coprocessor (which is always CP1). Carve additional space to 115 * manage alignment at run-time as we can not yet guarantee the 116 * alignment of the BSA. 117 */ 118 119 uint8_t hifi[XCHAL_CP1_SA_SIZE + XCHAL_CP1_SA_ALIGN]; 120 #endif 121 122 #if XCHAL_HAVE_THREADPTR 123 uintptr_t threadptr; 124 #endif 125 126 #if XCHAL_HAVE_S32C1I 127 uintptr_t scompare1; 128 #endif 129 130 uintptr_t exccause; 131 132 #if XCHAL_HAVE_LOOPS 133 uintptr_t lcount; 134 uintptr_t lend; 135 uintptr_t lbeg; 136 #endif 137 138 uintptr_t sar; 139 uintptr_t ps; 140 uintptr_t pc; 141 uintptr_t a0; 142 uintptr_t scratch; 143 uintptr_t a2; 144 uintptr_t a3; 145 146 uintptr_t caller_a0; 147 uintptr_t caller_a1; 148 uintptr_t caller_a2; 149 uintptr_t caller_a3; 150 }; 151 152 typedef struct xtensa_irq_base_save_area _xtensa_irq_bsa_t; 153 154 /** 155 * Raw interrupt stack frame. 156 * 157 * This provides a raw interrupt stack frame to make it 158 * easier to construct general purpose code in loops. 159 * Avoid using this if possible. 160 */ 161 struct xtensa_irq_stack_frame_raw { 162 _xtensa_irq_bsa_t *ptr_to_bsa; 163 164 struct { 165 uintptr_t r0; 166 uintptr_t r1; 167 uintptr_t r2; 168 uintptr_t r3; 169 } blks[3]; 170 }; 171 172 typedef struct xtensa_irq_stack_frame_raw _xtensa_irq_stack_frame_raw_t; 173 174 /** 175 * Interrupt stack frame containing A0 - A15. 176 */ 177 struct xtensa_irq_stack_frame_a15 { 178 _xtensa_irq_bsa_t *ptr_to_bsa; 179 180 uintptr_t a12; 181 uintptr_t a13; 182 uintptr_t a14; 183 uintptr_t a15; 184 185 uintptr_t a8; 186 uintptr_t a9; 187 uintptr_t a10; 188 uintptr_t a11; 189 190 uintptr_t a4; 191 uintptr_t a5; 192 uintptr_t a6; 193 uintptr_t a7; 194 195 _xtensa_irq_bsa_t bsa; 196 }; 197 198 typedef struct xtensa_irq_stack_frame_a15 _xtensa_irq_stack_frame_a15_t; 199 200 /** 201 * Interrupt stack frame containing A0 - A11. 202 */ 203 struct xtensa_irq_stack_frame_a11 { 204 _xtensa_irq_bsa_t *ptr_to_bsa; 205 206 uintptr_t a8; 207 uintptr_t a9; 208 uintptr_t a10; 209 uintptr_t a11; 210 211 uintptr_t a4; 212 uintptr_t a5; 213 uintptr_t a6; 214 uintptr_t a7; 215 216 _xtensa_irq_bsa_t bsa; 217 }; 218 219 typedef struct xtensa_irq_stack_frame_a11 _xtensa_irq_stack_frame_a11_t; 220 221 /** 222 * Interrupt stack frame containing A0 - A7. 223 */ 224 struct xtensa_irq_stack_frame_a7 { 225 _xtensa_irq_bsa_t *ptr_to_bsa; 226 227 uintptr_t a4; 228 uintptr_t a5; 229 uintptr_t a6; 230 uintptr_t a7; 231 232 _xtensa_irq_bsa_t bsa; 233 }; 234 235 typedef struct xtensa_irq_stack_frame_a7 _xtensa_irq_stack_frame_a7_t; 236 237 /** 238 * Interrupt stack frame containing A0 - A3. 239 */ 240 struct xtensa_irq_stack_frame_a3 { 241 _xtensa_irq_bsa_t *ptr_to_bsa; 242 243 _xtensa_irq_bsa_t bsa; 244 }; 245 246 typedef struct xtensa_irq_stack_frame_a3 _xtensa_irq_stack_frame_a3_t; 247 248 #endif /* __ASSEMBLER__ */ 249 250 #endif /* ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ */ 251