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:
parent
d344a6bc85
commit
c1a462e1a5
2 changed files with 30 additions and 2 deletions
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue