]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.19.7/xtensa-enable-coprocessors-that-are-being-flushed.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.19.7 / xtensa-enable-coprocessors-that-are-being-flushed.patch
CommitLineData
f570a3f8
GKH
1From 2958b66694e018c552be0b60521fec27e8d12988 Mon Sep 17 00:00:00 2001
2From: Max Filippov <jcmvbkbc@gmail.com>
3Date: Mon, 26 Nov 2018 13:29:41 -0800
4Subject: xtensa: enable coprocessors that are being flushed
5
6From: Max Filippov <jcmvbkbc@gmail.com>
7
8commit 2958b66694e018c552be0b60521fec27e8d12988 upstream.
9
10coprocessor_flush_all may be called from a context of a thread that is
11different from the thread being flushed. In that case contents of the
12cpenable special register may not match ti->cpenable of the target
13thread, resulting in unhandled coprocessor exception in the kernel
14context.
15Set cpenable special register to the ti->cpenable of the target register
16for the duration of the flush and restore it afterwards.
17This fixes the following crash caused by coprocessor register inspection
18in native gdb:
19
20 (gdb) p/x $w0
21 Illegal instruction in kernel: sig: 9 [#1] PREEMPT
22 Call Trace:
23 ___might_sleep+0x184/0x1a4
24 __might_sleep+0x41/0xac
25 exit_signals+0x14/0x218
26 do_exit+0xc9/0x8b8
27 die+0x99/0xa0
28 do_illegal_instruction+0x18/0x6c
29 common_exception+0x77/0x77
30 coprocessor_flush+0x16/0x3c
31 arch_ptrace+0x46c/0x674
32 sys_ptrace+0x2ce/0x3b4
33 system_call+0x54/0x80
34 common_exception+0x77/0x77
35 note: gdb[100] exited with preempt_count 1
36 Killed
37
38Cc: stable@vger.kernel.org
39Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
40Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
41
42---
43 arch/xtensa/kernel/process.c | 5 ++++-
44 1 file changed, 4 insertions(+), 1 deletion(-)
45
46--- a/arch/xtensa/kernel/process.c
47+++ b/arch/xtensa/kernel/process.c
48@@ -94,18 +94,21 @@ void coprocessor_release_all(struct thre
49
50 void coprocessor_flush_all(struct thread_info *ti)
51 {
52- unsigned long cpenable;
53+ unsigned long cpenable, old_cpenable;
54 int i;
55
56 preempt_disable();
57
58+ RSR_CPENABLE(old_cpenable);
59 cpenable = ti->cpenable;
60+ WSR_CPENABLE(cpenable);
61
62 for (i = 0; i < XCHAL_CP_MAX; i++) {
63 if ((cpenable & 1) != 0 && coprocessor_owner[i] == ti)
64 coprocessor_flush(ti, i);
65 cpenable >>= 1;
66 }
67+ WSR_CPENABLE(old_cpenable);
68
69 preempt_enable();
70 }