Skip to content

Commit 9f0f596

Browse files
dcpleungcfriedt
authored andcommitted
xtensa: save EXCCAUSE/EXCVADDR in BSA during exception
This saves the EXCCAUSE and EXCVADDR into BSA during exception. These will then be used during exception handling. The reason for doing this instead of reading from both registers during exception handing is that another exception will override the value in these register (e.g. DTLB miss). When returning to the previous exception handler, these register no longer contains the original exception cause and address. We need to save it so that we are actually handling the orignal exception. Coredump also now uses the EXCCAUSE and EXCVADDR from BSA instead of reading the registers. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
1 parent c76b338 commit 9f0f596

File tree

6 files changed

+31
-27
lines changed

6 files changed

+31
-27
lines changed

arch/xtensa/core/coredump.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,6 @@ void arch_coredump_info_dump(const struct arch_esf *esf)
135135
xtensa_coredump_fault_sp = (uint32_t)esf;
136136
#endif
137137

138-
__asm__ volatile("rsr.exccause %0" : "=r"(arch_blk.r.exccause));
139-
140138
_xtensa_irq_stack_frame_raw_t *frame = (void *)esf;
141139
_xtensa_irq_bsa_t *bsa = frame->ptr_to_bsa;
142140
uintptr_t num_high_regs;
@@ -150,7 +148,7 @@ void arch_coredump_info_dump(const struct arch_esf *esf)
150148
regs_blk_remaining = (int)num_high_regs / 4;
151149

152150
arch_blk.r.pc = bsa->pc;
153-
__asm__ volatile("rsr.excvaddr %0" : "=r"(arch_blk.r.excvaddr));
151+
arch_blk.r.excvaddr = bsa->excvaddr;
154152
arch_blk.r.ps = bsa->ps;
155153
#if XCHAL_HAVE_S32C1I
156154
arch_blk.r.scompare1 = bsa->scompare1;
@@ -160,6 +158,7 @@ void arch_coredump_info_dump(const struct arch_esf *esf)
160158
arch_blk.r.a1 = (uint32_t)((char *)bsa) + sizeof(*bsa);
161159
arch_blk.r.a2 = bsa->a2;
162160
arch_blk.r.a3 = bsa->a3;
161+
arch_blk.r.exccause = bsa->exccause;
163162
if (regs_blk_remaining > 0) {
164163
regs_blk_remaining--;
165164

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", "DEPC_SAVE", "EXCCAUSE_SAVE"]
34+
NEEDED += ["DBLEXC", "DEPC_SAVE"]
3535
if args.flush_reg:
3636
NEEDED += ["FLUSH"]
3737

arch/xtensa/core/offsets/offsets.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ GEN_OFFSET_SYM(_xtensa_irq_bsa_t, a2);
2222
GEN_OFFSET_SYM(_xtensa_irq_bsa_t, a3);
2323

2424
GEN_OFFSET_SYM(_xtensa_irq_bsa_t, exccause);
25+
GEN_OFFSET_SYM(_xtensa_irq_bsa_t, excvaddr);
2526
GEN_OFFSET_SYM(_xtensa_irq_bsa_t, pc);
2627
GEN_OFFSET_SYM(_xtensa_irq_bsa_t, ps);
2728
GEN_OFFSET_SYM(_xtensa_irq_bsa_t, sar);

arch/xtensa/core/vector_handlers.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -220,38 +220,35 @@ static inline unsigned int get_bits(int offset, int num_bits, unsigned int val)
220220
return val & mask;
221221
}
222222

223-
static void print_fatal_exception(void *print_stack, int cause,
224-
bool is_dblexc, uint32_t depc)
223+
static void print_fatal_exception(void *print_stack, bool is_dblexc, uint32_t depc)
225224
{
226225
void *pc;
227-
uint32_t ps, vaddr;
226+
uint32_t ps;
228227
_xtensa_irq_bsa_t *bsa = (void *)*(int **)print_stack;
229228

230-
__asm__ volatile("rsr.excvaddr %0" : "=r"(vaddr));
231-
232229
if (is_dblexc) {
233230
EXCEPTION_DUMP(" ** FATAL EXCEPTION (DOUBLE)");
234231
} else {
235232
EXCEPTION_DUMP(" ** FATAL EXCEPTION");
236233
}
237234

238-
EXCEPTION_DUMP(" ** CPU %d EXCCAUSE %d (%s)",
239-
arch_curr_cpu()->id, cause,
240-
xtensa_exccause(cause));
235+
EXCEPTION_DUMP(" ** CPU %d EXCCAUSE %u (%s)",
236+
arch_curr_cpu()->id, (uint32_t)bsa->exccause,
237+
xtensa_exccause(bsa->exccause));
241238

242239
/* Don't print information if the BSA area is invalid as any elements
243240
* obtained via de-referencing the pointer are probably also invalid.
244241
* Or worse, cause another access violation.
245242
*/
246243
if (xtensa_is_outside_stack_bounds((uintptr_t)bsa, sizeof(*bsa), UINT32_MAX)) {
247-
EXCEPTION_DUMP(" ** VADDR %p Invalid SP %p", (void *)vaddr, print_stack);
244+
EXCEPTION_DUMP(" ** VADDR %p Invalid SP %p", (void *)bsa->excvaddr, print_stack);
248245
return;
249246
}
250247

251248
ps = bsa->ps;
252249
pc = (void *)bsa->pc;
253250

254-
EXCEPTION_DUMP(" ** PC %p VADDR %p", pc, (void *)vaddr);
251+
EXCEPTION_DUMP(" ** PC %p VADDR %p", pc, (void *)bsa->excvaddr);
255252

256253
if (is_dblexc) {
257254
EXCEPTION_DUMP(" ** DEPC %p", (void *)depc);
@@ -547,13 +544,12 @@ void *xtensa_excint1_c(void *esf)
547544

548545
#ifdef CONFIG_XTENSA_MMU
549546
depc = XTENSA_RSR(ZSR_DEPC_SAVE_STR);
550-
cause = XTENSA_RSR(ZSR_EXCCAUSE_SAVE_STR);
551547

552548
is_dblexc = (depc != 0U);
553-
#else /* CONFIG_XTENSA_MMU */
554-
__asm__ volatile("rsr.exccause %0" : "=r"(cause));
555549
#endif /* CONFIG_XTENSA_MMU */
556550

551+
cause = bsa->exccause;
552+
557553
switch (cause) {
558554
case EXCCAUSE_LEVEL1_INTERRUPT:
559555
#ifdef CONFIG_XTENSA_MMU
@@ -664,7 +660,6 @@ void *xtensa_excint1_c(void *esf)
664660
if (cause == EXCCAUSE_ILLEGAL) {
665661
if (pc == (void *)&xtensa_arch_except_epc) {
666662
cause = 63;
667-
__asm__ volatile("wsr.exccause %0" : : "r"(cause));
668663
reason = bsa->a2;
669664
} else if (pc == (void *)&xtensa_arch_kernel_oops_epc) {
670665
cause = 64; /* kernel oops */
@@ -677,11 +672,13 @@ void *xtensa_excint1_c(void *esf)
677672
*/
678673
print_stack = (void *)bsa->a3;
679674
}
675+
676+
bsa->exccause = cause;
680677
}
681678

682679
skip_checks:
683680
if (reason != K_ERR_KERNEL_OOPS) {
684-
print_fatal_exception(print_stack, cause, is_dblexc, depc);
681+
print_fatal_exception(print_stack, is_dblexc, depc);
685682
}
686683
#ifdef CONFIG_XTENSA_EXCEPTION_ENTER_GDB
687684
extern void z_gdb_isr(struct arch_esf *esf);

arch/xtensa/include/xtensa_asm2_context.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
#endif
117117

118118
/* Must have fields regardless of features. */
119-
#define _BSA_PADDING_COMMON (sizeof(uintptr_t) * 12U)
119+
#define _BSA_PADDING_COMMON (sizeof(uintptr_t) * 13U)
120120

121121
/* Raw size by adding up all the above. */
122122
#define _BSA_PADDING_BASE_SIZE \
@@ -194,6 +194,7 @@ struct xtensa_irq_base_save_area {
194194
#endif
195195

196196
uintptr_t exccause;
197+
uintptr_t excvaddr;
197198

198199
#if XCHAL_HAVE_LOOPS
199200
uintptr_t lcount;

arch/xtensa/include/xtensa_asm2_s.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ _Level\LVL\()Vector:
663663
* For double exception, DEPC in saved in earlier vector
664664
* code.
665665
*/
666-
wsr a0, ZSR_EXCCAUSE_SAVE
666+
wsr a0, ZSR_A0SAVE
667667

668668
esync
669669

@@ -690,15 +690,11 @@ _Level\LVL\()Vector:
690690
* jump to an infinite loop, or quit the simulator, or invoke
691691
* debugger.
692692
*/
693-
rsr a0, ZSR_EXCCAUSE_SAVE
693+
rsr a0, ZSR_A0SAVE
694694
j _TripleFault
695695

696696
_not_triple_fault:
697-
rsr.exccause a0
698-
699-
xsr a0, ZSR_EXCCAUSE_SAVE
700-
701-
esync
697+
rsr a0, ZSR_A0SAVE
702698
.endif
703699
#endif
704700

@@ -707,6 +703,16 @@ _Level\LVL\()Vector:
707703
s32i a2, a1, ___xtensa_irq_bsa_t_a2_OFFSET
708704
s32i a3, a1, ___xtensa_irq_bsa_t_a3_OFFSET
709705

706+
/* Save registers needed for handling the exception as
707+
* these registers can be overwritten during nested
708+
* exceptions.
709+
*/
710+
rsr.exccause a0
711+
s32i a0, a1, ___xtensa_irq_bsa_t_exccause_OFFSET
712+
713+
rsr.excvaddr a0
714+
s32i a0, a1, ___xtensa_irq_bsa_t_excvaddr_OFFSET
715+
710716
/* Level "1" is the exception handler, which uses a different
711717
* calling convention. No special register holds the
712718
* interrupted PS, instead we just assume that the CPU has

0 commit comments

Comments
 (0)