Commit bc3e77b3 authored by Daniel Leung's avatar Daniel Leung Committed by Anas Nashif
Browse files

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: default avatarDaniel Leung <daniel.leung@intel.com>
parent 371ad016
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ args = parse_args()

NEEDED = ["A0SAVE", "CPU"]
if args.mmu:
    NEEDED += ["DBLEXC"]
    NEEDED += ["DBLEXC", "DEPC_SAVE", "EXCCAUSE_SAVE"]
if args.coherence:
    NEEDED += ["FLUSH"]

+5 −4
Original line number Diff line number Diff line
@@ -229,12 +229,13 @@ void *xtensa_excint1_c(void *esf)
	void *pc, *print_stack = (void *)interrupted_stack;
	uint32_t depc = 0;

	__asm__ volatile("rsr.exccause %0" : "=r"(cause));

#ifdef CONFIG_XTENSA_MMU
	__asm__ volatile("rsr.depc %0" : "=r"(depc));
	depc = XTENSA_RSR(ZSR_DEPC_SAVE_STR);
	cause = XTENSA_RSR(ZSR_EXCCAUSE_SAVE_STR);

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

	switch (cause) {
@@ -375,7 +376,7 @@ fixup_out:
#endif
#if defined(CONFIG_XTENSA_MMU)
	if (is_dblexc) {
		__asm__ volatile("wsr.depc %0" : : "r"(0));
		XTENSA_WSR(ZSR_DEPC_SAVE_STR, 0);
	}
#endif /* CONFIG_XTENSA_MMU */

+9 −0
Original line number Diff line number Diff line
@@ -489,6 +489,15 @@ _DoubleExceptionVector:
	addi a0, a0, -EXCCAUSE_DTLB_MISS
	beqz a0, _handle_tlb_miss_dblexc

	/* Need to stash the DEPC for used by the C handler.
	 * If we encounter any DTLB misses when PS.EXCM is set,
	 * this vector will be used and the DEPC register will
	 * have the new address instead of the one resulted in
	 * double exception.
	 */
	rsr.depc a0
	wsr a0, ZSR_DEPC_SAVE

	rsr a0, ZSR_DBLEXC

	j _Level1Vector
+26 −0
Original line number Diff line number Diff line
@@ -604,6 +604,32 @@ _Level\LVL\()VectorHelper :
.global _Level\LVL\()Vector
_Level\LVL\()Vector:
#endif

#ifdef CONFIG_XTENSA_MMU
.if \LVL == 1
	/* If there are any TLB misses during interrupt handling,
	 * the user/kernel/double exception vector will be triggered
	 * to handle these misses. This results in DEPC and EXCCAUSE
	 * being overwritten, and then execution returned back to
	 * this site of TLB misses. When it gets to the C handler,
	 * it will not see the original cause. So stash
	 * the EXCCAUSE here so C handler can see the original cause.
	 *
	 * For double exception, DEPC in saved in earlier vector
	 * code.
	 */
	wsr a0, ZSR_EXCCAUSE_SAVE

	esync

	rsr.exccause a0

	xsr a0, ZSR_EXCCAUSE_SAVE

	esync
.endif
#endif

	addi a1, a1, -___xtensa_irq_bsa_t_SIZEOF
	s32i a0, a1, ___xtensa_irq_bsa_t_a0_OFFSET
	s32i a2, a1, ___xtensa_irq_bsa_t_a2_OFFSET