|
7 | 7 | #ifndef ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_S_H
|
8 | 8 | #define ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_S_H
|
9 | 9 |
|
| 10 | +#include <zsr.h> |
10 | 11 | #include "xtensa-asm2-context.h"
|
11 | 12 |
|
12 | 13 | #include <offsets.h>
|
|
242 | 243 | * should point to a stored pointer which points to one BSA below the
|
243 | 244 | * interrupted/old stack) in A1, a handler function in A2, and a "new"
|
244 | 245 | * stack pointer (i.e. a pointer to the word ABOVE the allocated stack
|
245 |
| - * area) in A3. On return A0/1 will be unchanged, A2 has the return |
246 |
| - * value of the called function, and A3 is clobbered. A4-A15 become |
247 |
| - * part of called frames and MUST NOT BE IN USE by the code that |
248 |
| - * expands this macro. The called function gets the context save |
249 |
| - * handle in A1 as it's first argument. |
| 246 | + * area) in A3. Exceptions should be enabled via PS.EXCM, but |
| 247 | + * PS.INTLEVEL must (!) be set such that no nested interrupts can |
| 248 | + * arrive (we restore the natural INTLEVEL from the value in ZSR_EPS |
| 249 | + * just before entering the call). On return A0/1 will be unchanged, |
| 250 | + * A2 has the return value of the called function, and A3 is |
| 251 | + * clobbered. A4-A15 become part of called frames and MUST NOT BE IN |
| 252 | + * USE by the code that expands this macro. The called function gets |
| 253 | + * the context save handle in A1 as it's first argument. |
250 | 254 | */
|
251 | 255 | .macro CROSS_STACK_CALL
|
252 | 256 | mov a6, a3 /* place "new sp" in the next frame's A2 */
|
|
266 | 270 | .align 4
|
267 | 271 | _xstack_call0_\@:
|
268 | 272 | /* We want an ENTRY to set a bit in windowstart and do the
|
269 |
| - * rotation, but we want our own SP |
| 273 | + * rotation, but we want our own SP. After that, we are |
| 274 | + * running in a valid frame, so re-enable interrupts. |
270 | 275 | */
|
271 | 276 | entry a1, 16
|
272 | 277 | mov a1, a2
|
| 278 | + rsr.ZSR_EPS a2 |
| 279 | + wsr.PS a2 |
273 | 280 | call4 _xstack_call1_\@
|
274 | 281 | mov a2, a6 /* copy return value */
|
275 | 282 | retw
|
@@ -330,13 +337,19 @@ _xstack_returned_\@:
|
330 | 337 | wsr.PS a0
|
331 | 338 | _not_l1:
|
332 | 339 |
|
333 |
| - /* Unmask EXCM bit so C code can spill/fill in window |
334 |
| - * exceptions. Note interrupts are already fully masked by |
335 |
| - * INTLEVEL, so this is safe. |
| 340 | + /* Setting up the cross stack call below has states where the |
| 341 | + * resulting frames are invalid/non-reentrant, so we can't |
| 342 | + * allow nested interrupts. But we do need EXCM unmasked, as |
| 343 | + * we use CALL/ENTRY instructions in the process and need to |
| 344 | + * handle exceptions to spill caller/interruptee frames. Use |
| 345 | + * PS.INTLEVEL at maximum to mask all interrupts and stash the |
| 346 | + * current value in our designated EPS register (which is |
| 347 | + * guaranteed unused across the call) |
336 | 348 | */
|
337 |
| - rsr.PS a0 |
| 349 | + rsil a0, 0xf |
338 | 350 | movi a3, ~(PS_EXCM_MASK)
|
339 | 351 | and a0, a0, a3
|
| 352 | + wsr.ZSR_EPS a0 |
340 | 353 | wsr.PS a0
|
341 | 354 | rsync
|
342 | 355 |
|
|
0 commit comments