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 29abc8adc0
("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 <andrew.j.ross@intel.com>
This commit is contained in:
parent
a71336cab3
commit
b76bc6c80d
2 changed files with 5 additions and 2 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue