aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/kernel/debug-monitors.c48
1 files changed, 22 insertions, 26 deletions
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 8aee3aeec3e6..c536c9e307b9 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -226,11 +226,28 @@ static int call_step_hook(struct pt_regs *regs, unsigned int esr)
226 return retval; 226 return retval;
227} 227}
228 228
229static void send_user_sigtrap(int si_code)
230{
231 struct pt_regs *regs = current_pt_regs();
232 siginfo_t info = {
233 .si_signo = SIGTRAP,
234 .si_errno = 0,
235 .si_code = si_code,
236 .si_addr = (void __user *)instruction_pointer(regs),
237 };
238
239 if (WARN_ON(!user_mode(regs)))
240 return;
241
242 if (interrupts_enabled(regs))
243 local_irq_enable();
244
245 force_sig_info(SIGTRAP, &info, current);
246}
247
229static int single_step_handler(unsigned long addr, unsigned int esr, 248static int single_step_handler(unsigned long addr, unsigned int esr,
230 struct pt_regs *regs) 249 struct pt_regs *regs)
231{ 250{
232 siginfo_t info;
233
234 /* 251 /*
235 * If we are stepping a pending breakpoint, call the hw_breakpoint 252 * If we are stepping a pending breakpoint, call the hw_breakpoint
236 * handler first. 253 * handler first.
@@ -239,11 +256,7 @@ static int single_step_handler(unsigned long addr, unsigned int esr,
239 return 0; 256 return 0;
240 257
241 if (user_mode(regs)) { 258 if (user_mode(regs)) {
242 info.si_signo = SIGTRAP; 259 send_user_sigtrap(TRAP_HWBKPT);
243 info.si_errno = 0;
244 info.si_code = TRAP_HWBKPT;
245 info.si_addr = (void __user *)instruction_pointer(regs);
246 force_sig_info(SIGTRAP, &info, current);
247 260
248 /* 261 /*
249 * ptrace will disable single step unless explicitly 262 * ptrace will disable single step unless explicitly
@@ -307,17 +320,8 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr)
307static int brk_handler(unsigned long addr, unsigned int esr, 320static int brk_handler(unsigned long addr, unsigned int esr,
308 struct pt_regs *regs) 321 struct pt_regs *regs)
309{ 322{
310 siginfo_t info;
311
312 if (user_mode(regs)) { 323 if (user_mode(regs)) {
313 info = (siginfo_t) { 324 send_user_sigtrap(TRAP_BRKPT);
314 .si_signo = SIGTRAP,
315 .si_errno = 0,
316 .si_code = TRAP_BRKPT,
317 .si_addr = (void __user *)instruction_pointer(regs),
318 };
319
320 force_sig_info(SIGTRAP, &info, current);
321 } else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) { 325 } else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) {
322 pr_warning("Unexpected kernel BRK exception at EL1\n"); 326 pr_warning("Unexpected kernel BRK exception at EL1\n");
323 return -EFAULT; 327 return -EFAULT;
@@ -328,7 +332,6 @@ static int brk_handler(unsigned long addr, unsigned int esr,
328 332
329int aarch32_break_handler(struct pt_regs *regs) 333int aarch32_break_handler(struct pt_regs *regs)
330{ 334{
331 siginfo_t info;
332 u32 arm_instr; 335 u32 arm_instr;
333 u16 thumb_instr; 336 u16 thumb_instr;
334 bool bp = false; 337 bool bp = false;
@@ -359,14 +362,7 @@ int aarch32_break_handler(struct pt_regs *regs)
359 if (!bp) 362 if (!bp)
360 return -EFAULT; 363 return -EFAULT;
361 364
362 info = (siginfo_t) { 365 send_user_sigtrap(TRAP_BRKPT);
363 .si_signo = SIGTRAP,
364 .si_errno = 0,
365 .si_code = TRAP_BRKPT,
366 .si_addr = pc,
367 };
368
369 force_sig_info(SIGTRAP, &info, current);
370 return 0; 366 return 0;
371} 367}
372 368