xtensa: enable coprocessors that are being flushed
Subsystems (2)
Max Filippov
maintainerPATCH 1/1 xtensa: enable coprocessors that are being flushed
coprocessor_flush_all may be called from a context of a thread that is different from the thread being flushed. In that case contents of the cpenable special register may not match ti->cpenable of the target thread, resulting in unhandled coprocessor exception in the kernel context.
Set cpenable special register to the ti->cpenable of the target register for the duration of the flush and restore it afterwards. This fixes the following crash caused by coprocessor register inspection in native gdb:
(gdb) p/x $w0
Illegal instruction in kernel: sig: 9 [#1] PREEMPT
Call Trace:
___might_sleep+0x184/0x1a4
__might_sleep+0x41/0xac
exit_signals+0x14/0x218
do_exit+0xc9/0x8b8
die+0x99/0xa0
do_illegal_instruction+0x18/0x6c
common_exception+0x77/0x77
coprocessor_flush+0x16/0x3c
arch_ptrace+0x46c/0x674
sys_ptrace+0x2ce/0x3b4
system_call+0x54/0x80
common_exception+0x77/0x77
note: gdb[100] exited with preempt_count 1
KilledSigned-off-by Max Filippov <[email protected]>
--- arch/xtensa/kernel/process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/xtensa/kernel/process.c +4 -1
@@ -94,18 +94,21 @@ void coprocessor_release_all(struct thread_info *ti)void coprocessor_flush_all (struct thread_info *ti) { -unsigned long cpenable; +unsigned long cpenable, old_cpenable;int i;preempt_disable (); +RSR_CPENABLE (old_cpenable); cpenable = ti->cpenable; +WSR_CPENABLE (cpenable);for (i =0 ; i <XCHAL_CP_MAX ; i++) {if ((cpenable &1 ) !=0 && coprocessor_owner[i] == ti)coprocessor_flush (ti, i); cpenable >>=1 ; } +WSR_CPENABLE (old_cpenable);preempt_enable (); }
Signature · 1 line
2.11.0