aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/a.out-core.h10
-rw-r--r--arch/x86/include/asm/debugreg.h2
-rw-r--r--arch/x86/kernel/hw_breakpoint.c35
3 files changed, 39 insertions, 8 deletions
diff --git a/arch/x86/include/asm/a.out-core.h b/arch/x86/include/asm/a.out-core.h
index fc4685dd6e4d..7a15588e45d4 100644
--- a/arch/x86/include/asm/a.out-core.h
+++ b/arch/x86/include/asm/a.out-core.h
@@ -17,6 +17,7 @@
17 17
18#include <linux/user.h> 18#include <linux/user.h>
19#include <linux/elfcore.h> 19#include <linux/elfcore.h>
20#include <asm/debugreg.h>
20 21
21/* 22/*
22 * fill in the user structure for an a.out core dump 23 * fill in the user structure for an a.out core dump
@@ -32,14 +33,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
32 >> PAGE_SHIFT; 33 >> PAGE_SHIFT;
33 dump->u_dsize -= dump->u_tsize; 34 dump->u_dsize -= dump->u_tsize;
34 dump->u_ssize = 0; 35 dump->u_ssize = 0;
35 dump->u_debugreg[0] = current->thread.debugreg[0]; 36 aout_dump_debugregs(dump);
36 dump->u_debugreg[1] = current->thread.debugreg[1];
37 dump->u_debugreg[2] = current->thread.debugreg[2];
38 dump->u_debugreg[3] = current->thread.debugreg[3];
39 dump->u_debugreg[4] = 0;
40 dump->u_debugreg[5] = 0;
41 dump->u_debugreg[6] = current->thread.debugreg6;
42 dump->u_debugreg[7] = current->thread.debugreg7;
43 37
44 if (dump->start_stack < TASK_SIZE) 38 if (dump->start_stack < TASK_SIZE)
45 dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack)) 39 dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
diff --git a/arch/x86/include/asm/debugreg.h b/arch/x86/include/asm/debugreg.h
index 9a3333c91f9a..f1b673f08239 100644
--- a/arch/x86/include/asm/debugreg.h
+++ b/arch/x86/include/asm/debugreg.h
@@ -89,6 +89,8 @@ static inline void hw_breakpoint_disable(void)
89 set_debugreg(0UL, 3); 89 set_debugreg(0UL, 3);
90} 90}
91 91
92extern void aout_dump_debugregs(struct user *dump);
93
92#ifdef CONFIG_KVM 94#ifdef CONFIG_KVM
93extern void hw_breakpoint_restore(void); 95extern void hw_breakpoint_restore(void);
94#endif 96#endif
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c
index e622620790bd..57dcee5fa958 100644
--- a/arch/x86/kernel/hw_breakpoint.c
+++ b/arch/x86/kernel/hw_breakpoint.c
@@ -376,6 +376,41 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp,
376} 376}
377 377
378/* 378/*
379 * Dump the debug register contents to the user.
380 * We can't dump our per cpu values because it
381 * may contain cpu wide breakpoint, something that
382 * doesn't belong to the current task.
383 *
384 * TODO: include non-ptrace user breakpoints (perf)
385 */
386void aout_dump_debugregs(struct user *dump)
387{
388 int i;
389 int dr7 = 0;
390 struct perf_event *bp;
391 struct arch_hw_breakpoint *info;
392 struct thread_struct *thread = &current->thread;
393
394 for (i = 0; i < HBP_NUM; i++) {
395 bp = thread->ptrace_bps[i];
396
397 if (bp && !bp->attr.disabled) {
398 dump->u_debugreg[i] = bp->attr.bp_addr;
399 info = counter_arch_bp(bp);
400 dr7 |= encode_dr7(i, info->len, info->type);
401 } else {
402 dump->u_debugreg[i] = 0;
403 }
404 }
405
406 dump->u_debugreg[4] = 0;
407 dump->u_debugreg[5] = 0;
408 dump->u_debugreg[6] = current->thread.debugreg6;
409
410 dump->u_debugreg[7] = dr7;
411}
412
413/*
379 * Release the user breakpoints used by ptrace 414 * Release the user breakpoints used by ptrace
380 */ 415 */
381void flush_ptrace_hw_breakpoint(struct task_struct *tsk) 416void flush_ptrace_hw_breakpoint(struct task_struct *tsk)