aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/hw_breakpoint.h3
-rw-r--r--arch/powerpc/kernel/hw_breakpoint.c18
-rw-r--r--arch/powerpc/kernel/signal.c3
3 files changed, 24 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/hw_breakpoint.h b/arch/powerpc/include/asm/hw_breakpoint.h
index b111713b593e..6576bad1069c 100644
--- a/arch/powerpc/include/asm/hw_breakpoint.h
+++ b/arch/powerpc/include/asm/hw_breakpoint.h
@@ -65,9 +65,12 @@ static inline void hw_breakpoint_disable(void)
65{ 65{
66 set_dabr(0); 66 set_dabr(0);
67} 67}
68extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs);
68 69
69#else /* CONFIG_HAVE_HW_BREAKPOINT */ 70#else /* CONFIG_HAVE_HW_BREAKPOINT */
70static inline void hw_breakpoint_disable(void) { } 71static inline void hw_breakpoint_disable(void) { }
72static inline void thread_change_pc(struct task_struct *tsk,
73 struct pt_regs *regs) { }
71#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 74#endif /* CONFIG_HAVE_HW_BREAKPOINT */
72#endif /* __KERNEL__ */ 75#endif /* __KERNEL__ */
73#endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */ 76#endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 7a2ad5e84c16..7bd01a56d194 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -175,6 +175,24 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
175} 175}
176 176
177/* 177/*
178 * Restores the breakpoint on the debug registers.
179 * Invoke this function if it is known that the execution context is
180 * about to change to cause loss of MSR_SE settings.
181 */
182void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
183{
184 struct arch_hw_breakpoint *info;
185
186 if (likely(!tsk->thread.last_hit_ubp))
187 return;
188
189 info = counter_arch_bp(tsk->thread.last_hit_ubp);
190 regs->msr &= ~MSR_SE;
191 set_dabr(info->address | info->type | DABR_TRANSLATION);
192 tsk->thread.last_hit_ubp = NULL;
193}
194
195/*
178 * Handle debug exception notifications. 196 * Handle debug exception notifications.
179 */ 197 */
180int __kprobes hw_breakpoint_handler(struct die_args *args) 198int __kprobes hw_breakpoint_handler(struct die_args *args)
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index a0afb555a7c9..7109f5b1baa8 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -11,6 +11,7 @@
11 11
12#include <linux/tracehook.h> 12#include <linux/tracehook.h>
13#include <linux/signal.h> 13#include <linux/signal.h>
14#include <asm/hw_breakpoint.h>
14#include <asm/uaccess.h> 15#include <asm/uaccess.h>
15#include <asm/unistd.h> 16#include <asm/unistd.h>
16 17
@@ -149,6 +150,8 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
149 if (current->thread.dabr) 150 if (current->thread.dabr)
150 set_dabr(current->thread.dabr); 151 set_dabr(current->thread.dabr);
151#endif 152#endif
153 /* Re-enable the breakpoints for the signal stack */
154 thread_change_pc(current, regs);
152 155
153 if (is32) { 156 if (is32) {
154 if (ka.sa.sa_flags & SA_SIGINFO) 157 if (ka.sa.sa_flags & SA_SIGINFO)