From b76bc6c80dea2f04214fac8ef5a27393db9054b7 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Thu, 12 Aug 2021 12:45:23 -0700 Subject: [PATCH] arch/xtensa: Fix outgoing stack flush for dummy threads On CPU startup, When we reach the cache flush code in arch_switch(), the outgoing thread is a dummy. The behavior of the existing code was to leave the existing value in the SR unchanged (probably NULL at startup). Then the context switch would walk from that address up to the top of the outgoing stack, flushing everything in between. That's wrong, because the outgoing stack is a real pointer (generally the interrupt stack of the current CPU), and we're flushing everything in memory underneath it. This also reverts commit 29abc8adc025 ("xtensa: fix booting secondary cores on the dummy thread"), which appears to have been an early attempt to address this issue. It worked (modulo all the extra and potentially incorrect flushing) on cavs v1.5/1.8 because of the way the entry code worked there. But on 2.5 we now hit the first context switch in a case where those extra lines are in address space already marked unwritable by the CPU, so the flush explodes. Signed-off-by: Andy Ross --- arch/xtensa/core/xtensa-asm2-util.S | 5 ++++- arch/xtensa/include/kernel_arch_func.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/xtensa/core/xtensa-asm2-util.S b/arch/xtensa/core/xtensa-asm2-util.S index d46ea5ee3a7..0646c338672 100644 --- a/arch/xtensa/core/xtensa-asm2-util.S +++ b/arch/xtensa/core/xtensa-asm2-util.S @@ -248,14 +248,17 @@ xtensa_switch: #ifdef CONFIG_KERNEL_COHERENCE /* Flush the stack. The top of stack was stored for us in - * EXCSAVE3 (FIXME: shouldn't be hardcoded!) by arch_cohere_stacks(). + * EXCSAVE3 (FIXME: shouldn't be hardcoded!) by + * arch_cohere_stacks(). It can be NULL for a dummy thread. */ rsr.EXCSAVE3 a0 + beqz a0, noflush mov a3, a1 flushloop: dhwb a3, 0 addi a3, a3, XCHAL_DCACHE_LINESIZE blt a3, a0, flushloop +noflush: #endif /* Restore the A3 argument we spilled earlier (via the base diff --git a/arch/xtensa/include/kernel_arch_func.h b/arch/xtensa/include/kernel_arch_func.h index 061b6a480eb..b69f951adce 100644 --- a/arch/xtensa/include/kernel_arch_func.h +++ b/arch/xtensa/include/kernel_arch_func.h @@ -111,7 +111,7 @@ static ALWAYS_INLINE void arch_cohere_stacks(struct k_thread *old_thread, /* Dummy threads appear at system initialization, but don't * have stack_info data and will never be saved. Ignore. */ - if (!osz) { + if (old_thread->base.thread_state & _THREAD_DUMMY) { return; }