]>
Commit | Line | Data |
---|---|---|
87d2113e GKH |
1 | From a7e89326b415b5d81c4b1016fd4a40db861eb58d Mon Sep 17 00:00:00 2001 |
2 | From: James Hogan <james.hogan@imgtec.com> | |
3 | Date: Tue, 1 Mar 2016 22:19:36 +0000 | |
4 | Subject: MIPS: Fix watchpoint restoration | |
5 | ||
6 | From: James Hogan <james.hogan@imgtec.com> | |
7 | ||
8 | commit a7e89326b415b5d81c4b1016fd4a40db861eb58d upstream. | |
9 | ||
10 | Commit f51246efee2b ("MIPS: Get rid of finish_arch_switch().") moved the | |
11 | __restore_watch() call from finish_arch_switch() (i.e. after resume() | |
12 | returns) to before the resume() call in switch_to(). This results in | |
13 | watchpoints only being restored when a task is descheduled, preventing | |
14 | the watchpoints from being effective most of the time, except due to | |
15 | chance before the watchpoints are lazily removed. | |
16 | ||
17 | Fix the call sequence from switch_to() through to | |
18 | mips_install_watch_registers() to pass the task_struct pointer of the | |
19 | next task, instead of using current. This allows the watchpoints for the | |
20 | next (non-current) task to be restored without reintroducing | |
21 | finish_arch_switch(). | |
22 | ||
23 | Fixes: f51246efee2b ("MIPS: Get rid of finish_arch_switch().") | |
24 | Signed-off-by: James Hogan <james.hogan@imgtec.com> | |
25 | Cc: Paul Burton <paul.burton@imgtec.com> | |
26 | Cc: linux-mips@linux-mips.org | |
27 | Patchwork: https://patchwork.linux-mips.org/patch/12726/ | |
28 | Signed-off-by: Ralf Baechle <ralf@linux-mips.org> | |
29 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
30 | ||
31 | --- | |
32 | arch/mips/include/asm/switch_to.h | 2 +- | |
33 | arch/mips/include/asm/watch.h | 10 +++++----- | |
34 | arch/mips/kernel/pm.c | 2 +- | |
35 | arch/mips/kernel/watch.c | 5 ++--- | |
36 | 4 files changed, 9 insertions(+), 10 deletions(-) | |
37 | ||
38 | --- a/arch/mips/include/asm/switch_to.h | |
39 | +++ b/arch/mips/include/asm/switch_to.h | |
40 | @@ -105,7 +105,7 @@ do { \ | |
41 | __clear_software_ll_bit(); \ | |
42 | if (cpu_has_userlocal) \ | |
43 | write_c0_userlocal(task_thread_info(next)->tp_value); \ | |
44 | - __restore_watch(); \ | |
45 | + __restore_watch(next); \ | |
46 | (last) = resume(prev, next, task_thread_info(next)); \ | |
47 | } while (0) | |
48 | ||
49 | --- a/arch/mips/include/asm/watch.h | |
50 | +++ b/arch/mips/include/asm/watch.h | |
51 | @@ -12,21 +12,21 @@ | |
52 | ||
53 | #include <asm/mipsregs.h> | |
54 | ||
55 | -void mips_install_watch_registers(void); | |
56 | +void mips_install_watch_registers(struct task_struct *t); | |
57 | void mips_read_watch_registers(void); | |
58 | void mips_clear_watch_registers(void); | |
59 | void mips_probe_watch_registers(struct cpuinfo_mips *c); | |
60 | ||
61 | #ifdef CONFIG_HARDWARE_WATCHPOINTS | |
62 | -#define __restore_watch() do { \ | |
63 | +#define __restore_watch(task) do { \ | |
64 | if (unlikely(test_bit(TIF_LOAD_WATCH, \ | |
65 | - ¤t_thread_info()->flags))) { \ | |
66 | - mips_install_watch_registers(); \ | |
67 | + &task_thread_info(task)->flags))) { \ | |
68 | + mips_install_watch_registers(task); \ | |
69 | } \ | |
70 | } while (0) | |
71 | ||
72 | #else | |
73 | -#define __restore_watch() do {} while (0) | |
74 | +#define __restore_watch(task) do {} while (0) | |
75 | #endif | |
76 | ||
77 | #endif /* _ASM_WATCH_H */ | |
78 | --- a/arch/mips/kernel/pm.c | |
79 | +++ b/arch/mips/kernel/pm.c | |
80 | @@ -56,7 +56,7 @@ static void mips_cpu_restore(void) | |
81 | write_c0_userlocal(current_thread_info()->tp_value); | |
82 | ||
83 | /* Restore watch registers */ | |
84 | - __restore_watch(); | |
85 | + __restore_watch(current); | |
86 | } | |
87 | ||
88 | /** | |
89 | --- a/arch/mips/kernel/watch.c | |
90 | +++ b/arch/mips/kernel/watch.c | |
91 | @@ -15,10 +15,9 @@ | |
92 | * Install the watch registers for the current thread. A maximum of | |
93 | * four registers are installed although the machine may have more. | |
94 | */ | |
95 | -void mips_install_watch_registers(void) | |
96 | +void mips_install_watch_registers(struct task_struct *t) | |
97 | { | |
98 | - struct mips3264_watch_reg_state *watches = | |
99 | - ¤t->thread.watch.mips3264; | |
100 | + struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264; | |
101 | switch (current_cpu_data.watch_reg_use_cnt) { | |
102 | default: | |
103 | BUG(); |