arm64: traps: Allow force_signal_inject to pass esr error code
authorAmit Daniel Kachhap <amit.kachhap@arm.com>
Mon, 14 Sep 2020 08:36:52 +0000 (14:06 +0530)
committerWill Deacon <will@kernel.org>
Mon, 14 Sep 2020 11:07:02 +0000 (12:07 +0100)
Some error signal need to pass proper ARM esr error code to userspace to
better identify the cause of the signal. So the function
force_signal_inject is extended to pass this as a parameter. The
existing code is not affected by this change.

Signed-off-by: Amit Daniel Kachhap <amit.kachhap@arm.com>
Reviewed-by: Dave Martin <Dave.Martin@arm.com>
Link: https://lore.kernel.org/r/20200914083656.21428-3-amit.kachhap@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/include/asm/traps.h
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/traps.c

index cee5928..d96dc2c 100644 (file)
@@ -24,7 +24,7 @@ struct undef_hook {
 
 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 force_signal_inject(int signal, int code, unsigned long address, unsigned int err);
 void arm64_notify_segfault(unsigned long addr);
 void arm64_force_sig_fault(int signo, int code, void __user *addr, const char *str);
 void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, const char *str);
index 55c8f3e..7748435 100644 (file)
@@ -312,7 +312,7 @@ static void fpsimd_save(void)
                                 * re-enter user with corrupt state.
                                 * There's no way to recover, so kill it:
                                 */
-                               force_signal_inject(SIGKILL, SI_KERNEL, 0);
+                               force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
                                return;
                        }
 
@@ -936,7 +936,7 @@ void do_sve_acc(unsigned int esr, struct pt_regs *regs)
 {
        /* Even if we chose not to use SVE, the hardware could still trap: */
        if (unlikely(!system_supports_sve()) || WARN_ON(is_compat_task())) {
-               force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc);
+               force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
                return;
        }
 
index 13ebd5c..29fd00f 100644 (file)
@@ -412,7 +412,7 @@ exit:
        return fn ? fn(regs, instr) : 1;
 }
 
-void force_signal_inject(int signal, int code, unsigned long address)
+void force_signal_inject(int signal, int code, unsigned long address, unsigned int err)
 {
        const char *desc;
        struct pt_regs *regs = current_pt_regs();
@@ -438,7 +438,7 @@ void force_signal_inject(int signal, int code, unsigned long address)
                signal = SIGKILL;
        }
 
-       arm64_notify_die(desc, regs, signal, code, (void __user *)address, 0);
+       arm64_notify_die(desc, regs, signal, code, (void __user *)address, err);
 }
 
 /*
@@ -455,7 +455,7 @@ void arm64_notify_segfault(unsigned long addr)
                code = SEGV_ACCERR;
        mmap_read_unlock(current->mm);
 
-       force_signal_inject(SIGSEGV, code, addr);
+       force_signal_inject(SIGSEGV, code, addr, 0);
 }
 
 void do_undefinstr(struct pt_regs *regs)
@@ -468,14 +468,14 @@ void do_undefinstr(struct pt_regs *regs)
                return;
 
        BUG_ON(!user_mode(regs));
-       force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc);
+       force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
 }
 NOKPROBE_SYMBOL(do_undefinstr);
 
 void do_bti(struct pt_regs *regs)
 {
        BUG_ON(!user_mode(regs));
-       force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc);
+       force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
 }
 NOKPROBE_SYMBOL(do_bti);
 
@@ -528,7 +528,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
                __user_cache_maint("ic ivau", address, ret);
                break;
        default:
-               force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc);
+               force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
                return;
        }
 
@@ -581,7 +581,7 @@ static void mrs_handler(unsigned int esr, struct pt_regs *regs)
        sysreg = esr_sys64_to_sysreg(esr);
 
        if (do_emulate_mrs(regs, sysreg, rt) != 0)
-               force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc);
+               force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
 }
 
 static void wfi_handler(unsigned int esr, struct pt_regs *regs)