Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebieder...
[linux-2.6-microblaze.git] / arch / arm64 / mm / fault.c
index d0e638e..7d9571f 100644 (file)
@@ -303,9 +303,9 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
        die_kernel_fault(msg, addr, esr, regs);
 }
 
-static void __do_user_fault(struct siginfo *info, unsigned int esr)
+static void set_thread_esr(unsigned long address, unsigned int esr)
 {
-       current->thread.fault_address = (unsigned long)info->si_addr;
+       current->thread.fault_address = address;
 
        /*
         * If the faulting address is in the kernel, we must sanitize the ESR.
@@ -358,7 +358,6 @@ static void __do_user_fault(struct siginfo *info, unsigned int esr)
        }
 
        current->thread.fault_code = esr;
-       arm64_force_sig_info(info, esr_to_fault_info(esr)->name, current);
 }
 
 static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
@@ -369,14 +368,10 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
         */
        if (user_mode(regs)) {
                const struct fault_info *inf = esr_to_fault_info(esr);
-               struct siginfo si;
 
-               clear_siginfo(&si);
-               si.si_signo     = inf->sig;
-               si.si_code      = inf->code;
-               si.si_addr      = (void __user *)addr;
-
-               __do_user_fault(&si, esr);
+               set_thread_esr(addr, esr);
+               arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
+                                     inf->name);
        } else {
                __do_kernel_fault(addr, esr, regs);
        }
@@ -430,9 +425,9 @@ static bool is_el0_instruction_abort(unsigned int esr)
 static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
                                   struct pt_regs *regs)
 {
+       const struct fault_info *inf;
        struct task_struct *tsk;
        struct mm_struct *mm;
-       struct siginfo si;
        vm_fault_t fault, major = 0;
        unsigned long vm_flags = VM_READ | VM_WRITE;
        unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
@@ -568,37 +563,35 @@ retry:
                return 0;
        }
 
-       clear_siginfo(&si);
-       si.si_addr = (void __user *)addr;
-
+       inf = esr_to_fault_info(esr);
+       set_thread_esr(addr, esr);
        if (fault & VM_FAULT_SIGBUS) {
                /*
                 * We had some memory, but were unable to successfully fix up
                 * this page fault.
                 */
-               si.si_signo     = SIGBUS;
-               si.si_code      = BUS_ADRERR;
-       } else if (fault & VM_FAULT_HWPOISON_LARGE) {
-               unsigned int hindex = VM_FAULT_GET_HINDEX(fault);
-
-               si.si_signo     = SIGBUS;
-               si.si_code      = BUS_MCEERR_AR;
-               si.si_addr_lsb  = hstate_index_to_shift(hindex);
-       } else if (fault & VM_FAULT_HWPOISON) {
-               si.si_signo     = SIGBUS;
-               si.si_code      = BUS_MCEERR_AR;
-               si.si_addr_lsb  = PAGE_SHIFT;
+               arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
+                                     inf->name);
+       } else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
+               unsigned int lsb;
+
+               lsb = PAGE_SHIFT;
+               if (fault & VM_FAULT_HWPOISON_LARGE)
+                       lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
+
+               arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
+                                      inf->name);
        } else {
                /*
                 * Something tried to access memory that isn't in our memory
                 * map.
                 */
-               si.si_signo     = SIGSEGV;
-               si.si_code      = fault == VM_FAULT_BADACCESS ?
-                                 SEGV_ACCERR : SEGV_MAPERR;
+               arm64_force_sig_fault(SIGSEGV,
+                                     fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR,
+                                     (void __user *)addr,
+                                     inf->name);
        }
 
-       __do_user_fault(&si, esr);
        return 0;
 
 no_context:
@@ -631,8 +624,8 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 
 static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 {
-       struct siginfo info;
        const struct fault_info *inf;
+       void __user *siaddr;
 
        inf = esr_to_fault_info(esr);
 
@@ -651,15 +644,11 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
                        nmi_exit();
        }
 
-       clear_siginfo(&info);
-       info.si_signo = inf->sig;
-       info.si_errno = 0;
-       info.si_code  = inf->code;
        if (esr & ESR_ELx_FnV)
-               info.si_addr = NULL;
+               siaddr = NULL;
        else
-               info.si_addr  = (void __user *)addr;
-       arm64_notify_die(inf->name, regs, &info, esr);
+               siaddr  = (void __user *)addr;
+       arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
 
        return 0;
 }
@@ -740,7 +729,6 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
                                         struct pt_regs *regs)
 {
        const struct fault_info *inf = esr_to_fault_info(esr);
-       struct siginfo info;
 
        if (!inf->fn(addr, esr, regs))
                return;
@@ -751,12 +739,8 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
                show_pte(addr);
        }
 
-       clear_siginfo(&info);
-       info.si_signo = inf->sig;
-       info.si_errno = 0;
-       info.si_code  = inf->code;
-       info.si_addr  = (void __user *)addr;
-       arm64_notify_die(inf->name, regs, &info, esr);
+       arm64_notify_die(inf->name, regs,
+                        inf->sig, inf->code, (void __user *)addr, esr);
 }
 
 asmlinkage void __exception do_el0_irq_bp_hardening(void)
@@ -786,20 +770,14 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
                                           unsigned int esr,
                                           struct pt_regs *regs)
 {
-       struct siginfo info;
-
        if (user_mode(regs)) {
                if (instruction_pointer(regs) > TASK_SIZE)
                        arm64_apply_bp_hardening();
                local_daif_restore(DAIF_PROCCTX);
        }
 
-       clear_siginfo(&info);
-       info.si_signo = SIGBUS;
-       info.si_errno = 0;
-       info.si_code  = BUS_ADRALN;
-       info.si_addr  = (void __user *)addr;
-       arm64_notify_die("SP/PC alignment exception", regs, &info, esr);
+       arm64_notify_die("SP/PC alignment exception", regs,
+                        SIGBUS, BUS_ADRALN, (void __user *)addr, esr);
 }
 
 int __init early_brk64(unsigned long addr, unsigned int esr,
@@ -853,14 +831,8 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
        if (!inf->fn(addr, esr, regs)) {
                rv = 1;
        } else {
-               struct siginfo info;
-
-               clear_siginfo(&info);
-               info.si_signo = inf->sig;
-               info.si_errno = 0;
-               info.si_code  = inf->code;
-               info.si_addr  = (void __user *)addr;
-               arm64_notify_die(inf->name, regs, &info, esr);
+               arm64_notify_die(inf->name, regs,
+                                inf->sig, inf->code, (void __user *)addr, esr);
                rv = 0;
        }