xtensa: mmu: bail on semantic triple faults

There actually is no triple faults on Xtensa. Once PS.EXCM is
set, it keeps going through double exception vector for any
new exceptions. However, our exception code needs to unmask
PS.EXCM to enable register window operations. So after that,
any new exceptions will go through the kernel or user vectors
depending on PS.UM. If there is continuous faults, it may
keep ping-ponging between double and kernel/user exception
vectors that may never get resolved. Since we stash DEPC
during double exception, and the stashed one is only cleared
once the double exception has been processed, we can use
the stashed DEPC value to detect if the next exception could
be considered a triple fault. If such a case exists, simply
jump to an infinite loop, or quit the simulator, or invoke
debugger.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2024-04-08 19:02:11 -07:00 committed by Anas Nashif
parent d344a6bc85
commit c1a462e1a5
2 changed files with 30 additions and 2 deletions

View file

@ -501,7 +501,9 @@ _DoubleExceptionVector:
rsr a0, ZSR_DBLEXC rsr a0, ZSR_DBLEXC
j _Level1Vector j _Level1Vector
#else
_TripleFault:
#endif /* CONFIG_XTENSA_MMU */
#if XCHAL_HAVE_DEBUG && defined(CONFIG_XTENSA_BREAK_ON_UNRECOVERABLE_EXCEPTIONS) #if XCHAL_HAVE_DEBUG && defined(CONFIG_XTENSA_BREAK_ON_UNRECOVERABLE_EXCEPTIONS)
/* Signals an unhandled double exception, and unrecoverable exceptions. /* Signals an unhandled double exception, and unrecoverable exceptions.
@ -521,7 +523,6 @@ _DoubleExceptionVector:
#endif #endif
1: 1:
j 1b j 1b
#endif /* CONFIG_XTENSA_MMU */
#ifdef CONFIG_XTENSA_MMU #ifdef CONFIG_XTENSA_MMU
_handle_tlb_miss_dblexc: _handle_tlb_miss_dblexc:

View file

@ -622,6 +622,33 @@ _Level\LVL\()Vector:
esync esync
rsr a0, ZSR_DEPC_SAVE
beqz a0, _not_triple_fault
/* If stashed DEPC is not zero, we have started servicing
* a double exception and yet we are here because there is
* another exception (through user/kernel if PS.EXCM is
* cleared, or through double if PS.EXCM is set). This can
* be considered triple fault. Although there is no triple
* faults on Xtensa. Once PS.EXCM is set, it keeps going
* through double exception vector for any new exceptions.
* However, our exception code needs to unmask PS.EXCM to
* enable register window operations. So after that, any
* new exceptions will go through the kernel or user vectors
* depending on PS.UM. If there is continuous faults, it may
* keep ping-ponging between double and kernel/user exception
* vectors that may never get resolved. Since we stash DEPC
* during double exception, and the stashed one is only cleared
* once the double exception has been processed, we can use
* the stashed DEPC value to detect if the next exception could
* be considered a triple fault. If such a case exists, simply
* jump to an infinite loop, or quit the simulator, or invoke
* debugger.
*/
rsr a0, ZSR_EXCCAUSE_SAVE
j _TripleFault
_not_triple_fault:
rsr.exccause a0 rsr.exccause a0
xsr a0, ZSR_EXCCAUSE_SAVE xsr a0, ZSR_EXCCAUSE_SAVE