arm64: Introduce arm64_force_sig_info and hook up in arm64_notify_die
authorWill Deacon <will.deacon@arm.com>
Tue, 20 Feb 2018 13:46:05 +0000 (13:46 +0000)
committerWill Deacon <will.deacon@arm.com>
Tue, 6 Mar 2018 18:52:23 +0000 (18:52 +0000)
In preparation for consolidating our handling of printing unhandled
signals, introduce a wrapper around force_sig_info which can act as
the canonical place for dealing with show_unhandled_signals.

Initially, we just hook this up to arm64_notify_die.

Signed-off-by: Will Deacon <will.deacon@arm.com>
arch/arm64/include/asm/traps.h
arch/arm64/kernel/traps.c

index 1ee63dc38579b2e9d2f9ef5cf6e4a37d21b3181c..c320f3bf6c57c6eef3e91c0a92706a6ebc09cf2b 100644 (file)
@@ -37,6 +37,8 @@ void register_undef_hook(struct undef_hook *hook);
 void unregister_undef_hook(struct undef_hook *hook);
 void force_signal_inject(int signal, int code, unsigned long address);
 void arm64_notify_segfault(unsigned long addr);
+void arm64_force_sig_info(struct siginfo *info, const char *str,
+                         struct task_struct *tsk);
 
 /*
  * Move regs->pc to next instruction and do necessary setup before it
index 3f52c07b4bf4322bbaa9fd98195d1b45afbee19a..00516f3956e4d31eba5a9ba661e022677819454d 100644 (file)
@@ -223,13 +223,39 @@ void die(const char *str, struct pt_regs *regs, int err)
                do_exit(SIGSEGV);
 }
 
+void arm64_force_sig_info(struct siginfo *info, const char *str,
+                         struct task_struct *tsk)
+{
+       unsigned int esr = tsk->thread.fault_code;
+       struct pt_regs *regs = task_pt_regs(tsk);
+
+       if (!unhandled_signal(tsk, info->si_signo))
+               goto send_sig;
+
+       if (!show_unhandled_signals_ratelimited())
+               goto send_sig;
+
+       pr_info("%s[%d]: unhandled exception: ", tsk->comm, task_pid_nr(tsk));
+       if (esr)
+               pr_cont("%s, ESR 0x%08x, ", esr_get_class_string(esr), esr);
+
+       pr_cont("%s", str);
+       print_vma_addr(KERN_CONT " in ", regs->pc);
+       pr_cont("\n");
+       __show_regs(regs);
+
+send_sig:
+       force_sig_info(info->si_signo, info, tsk);
+}
+
 void arm64_notify_die(const char *str, struct pt_regs *regs,
                      struct siginfo *info, int err)
 {
        if (user_mode(regs)) {
+               WARN_ON(regs != current_pt_regs());
                current->thread.fault_address = 0;
                current->thread.fault_code = err;
-               force_sig_info(info->si_signo, info, current);
+               arm64_force_sig_info(info, str, current);
        } else {
                die(str, regs, err);
        }