diff options
Diffstat (limited to 'arch/ppc64/mm/fault.c')
-rw-r--r-- | arch/ppc64/mm/fault.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c index 772f0714a5b7..be3f25cf3e9f 100644 --- a/arch/ppc64/mm/fault.c +++ b/arch/ppc64/mm/fault.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/system.h> | 38 | #include <asm/system.h> |
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
40 | #include <asm/kdebug.h> | 40 | #include <asm/kdebug.h> |
41 | #include <asm/siginfo.h> | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Check whether the instruction at regs->nip is a store using | 44 | * Check whether the instruction at regs->nip is a store using |
@@ -77,6 +78,28 @@ static int store_updates_sp(struct pt_regs *regs) | |||
77 | return 0; | 78 | return 0; |
78 | } | 79 | } |
79 | 80 | ||
81 | static void do_dabr(struct pt_regs *regs, unsigned long error_code) | ||
82 | { | ||
83 | siginfo_t info; | ||
84 | |||
85 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | ||
86 | 11, SIGSEGV) == NOTIFY_STOP) | ||
87 | return; | ||
88 | |||
89 | if (debugger_dabr_match(regs)) | ||
90 | return; | ||
91 | |||
92 | /* Clear the DABR */ | ||
93 | set_dabr(0); | ||
94 | |||
95 | /* Deliver the signal to userspace */ | ||
96 | info.si_signo = SIGTRAP; | ||
97 | info.si_errno = 0; | ||
98 | info.si_code = TRAP_HWBKPT; | ||
99 | info.si_addr = (void __user *)regs->nip; | ||
100 | force_sig_info(SIGTRAP, &info, current); | ||
101 | } | ||
102 | |||
80 | /* | 103 | /* |
81 | * The error_code parameter is | 104 | * The error_code parameter is |
82 | * - DSISR for a non-SLB data access fault, | 105 | * - DSISR for a non-SLB data access fault, |
@@ -111,12 +134,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
111 | if (!user_mode(regs) && (address >= TASK_SIZE)) | 134 | if (!user_mode(regs) && (address >= TASK_SIZE)) |
112 | return SIGSEGV; | 135 | return SIGSEGV; |
113 | 136 | ||
114 | if (error_code & DSISR_DABRMATCH) { | 137 | if (error_code & DSISR_DABRMATCH) { |
115 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | 138 | do_dabr(regs, error_code); |
116 | 11, SIGSEGV) == NOTIFY_STOP) | 139 | return 0; |
117 | return 0; | ||
118 | if (debugger_dabr_match(regs)) | ||
119 | return 0; | ||
120 | } | 140 | } |
121 | 141 | ||
122 | if (in_atomic() || mm == NULL) { | 142 | if (in_atomic() || mm == NULL) { |