Skip to content

Commit bc3e77b

Browse files
dcpleungnashif
authored andcommitted
xtensa: make it work with TLB misses during interrupt handling
If there are any TLB misses during interrupt handling, the user, kernel and double exception vector will be triggered for the miss and the DEPC and EXCCAUSE overwritten as the TLB missse are be handled in the assembly code and execution returned to the original vector code. Because of this, both DEPC and EXCCAUSE being read in the C handler are not the ones that triggered the original exception (for example, level-1 interrupt). So stash both DEPC and EXCCAUSE such that the original cause of exception is visible in the C handler. Signed-off-by: Daniel Leung <[email protected]>
1 parent 371ad01 commit bc3e77b

File tree

4 files changed

+41
-5
lines changed

4 files changed

+41
-5
lines changed

arch/xtensa/core/gen_zsr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def parse_args():
3131

3232
NEEDED = ["A0SAVE", "CPU"]
3333
if args.mmu:
34-
NEEDED += ["DBLEXC"]
34+
NEEDED += ["DBLEXC", "DEPC_SAVE", "EXCCAUSE_SAVE"]
3535
if args.coherence:
3636
NEEDED += ["FLUSH"]
3737

arch/xtensa/core/vector_handlers.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,13 @@ void *xtensa_excint1_c(void *esf)
229229
void *pc, *print_stack = (void *)interrupted_stack;
230230
uint32_t depc = 0;
231231

232-
__asm__ volatile("rsr.exccause %0" : "=r"(cause));
233-
234232
#ifdef CONFIG_XTENSA_MMU
235-
__asm__ volatile("rsr.depc %0" : "=r"(depc));
233+
depc = XTENSA_RSR(ZSR_DEPC_SAVE_STR);
234+
cause = XTENSA_RSR(ZSR_EXCCAUSE_SAVE_STR);
236235

237236
is_dblexc = (depc != 0U);
237+
#else /* CONFIG_XTENSA_MMU */
238+
__asm__ volatile("rsr.exccause %0" : "=r"(cause));
238239
#endif /* CONFIG_XTENSA_MMU */
239240

240241
switch (cause) {
@@ -375,7 +376,7 @@ void *xtensa_excint1_c(void *esf)
375376
#endif
376377
#if defined(CONFIG_XTENSA_MMU)
377378
if (is_dblexc) {
378-
__asm__ volatile("wsr.depc %0" : : "r"(0));
379+
XTENSA_WSR(ZSR_DEPC_SAVE_STR, 0);
379380
}
380381
#endif /* CONFIG_XTENSA_MMU */
381382

arch/xtensa/core/xtensa_asm2_util.S

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,15 @@ _DoubleExceptionVector:
489489
addi a0, a0, -EXCCAUSE_DTLB_MISS
490490
beqz a0, _handle_tlb_miss_dblexc
491491

492+
/* Need to stash the DEPC for used by the C handler.
493+
* If we encounter any DTLB misses when PS.EXCM is set,
494+
* this vector will be used and the DEPC register will
495+
* have the new address instead of the one resulted in
496+
* double exception.
497+
*/
498+
rsr.depc a0
499+
wsr a0, ZSR_DEPC_SAVE
500+
492501
rsr a0, ZSR_DBLEXC
493502

494503
j _Level1Vector

arch/xtensa/include/xtensa_asm2_s.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,32 @@ _Level\LVL\()VectorHelper :
604604
.global _Level\LVL\()Vector
605605
_Level\LVL\()Vector:
606606
#endif
607+
608+
#ifdef CONFIG_XTENSA_MMU
609+
.if \LVL == 1
610+
/* If there are any TLB misses during interrupt handling,
611+
* the user/kernel/double exception vector will be triggered
612+
* to handle these misses. This results in DEPC and EXCCAUSE
613+
* being overwritten, and then execution returned back to
614+
* this site of TLB misses. When it gets to the C handler,
615+
* it will not see the original cause. So stash
616+
* the EXCCAUSE here so C handler can see the original cause.
617+
*
618+
* For double exception, DEPC in saved in earlier vector
619+
* code.
620+
*/
621+
wsr a0, ZSR_EXCCAUSE_SAVE
622+
623+
esync
624+
625+
rsr.exccause a0
626+
627+
xsr a0, ZSR_EXCCAUSE_SAVE
628+
629+
esync
630+
.endif
631+
#endif
632+
607633
addi a1, a1, -___xtensa_irq_bsa_t_SIZEOF
608634
s32i a0, a1, ___xtensa_irq_bsa_t_a0_OFFSET
609635
s32i a2, a1, ___xtensa_irq_bsa_t_a2_OFFSET

0 commit comments

Comments
 (0)