]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - arch/arm64/mm/fault.c
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
[mirror_ubuntu-bionic-kernel.git] / arch / arm64 / mm / fault.c
index b64958b23a7fa193c23dd1a9039f69f4e9f0b863..22168cd0dde73e06698bc40b166867df17a00134 100644 (file)
@@ -105,13 +105,11 @@ static void data_abort_decode(unsigned int esr)
                 (esr & ESR_ELx_WNR) >> ESR_ELx_WNR_SHIFT);
 }
 
-/*
- * Decode mem abort information
- */
 static void mem_abort_decode(unsigned int esr)
 {
        pr_alert("Mem abort info:\n");
 
+       pr_alert("  ESR = 0x%08x\n", esr);
        pr_alert("  Exception class = %s, IL = %u bits\n",
                 esr_get_class_string(esr),
                 (esr & ESR_ELx_IL) ? 32 : 16);
@@ -249,9 +247,6 @@ static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs,
        return false;
 }
 
-/*
- * The kernel tried to access some page that wasn't present.
- */
 static void __do_kernel_fault(unsigned long addr, unsigned int esr,
                              struct pt_regs *regs)
 {
@@ -264,9 +259,6 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
        if (!is_el1_instruction_abort(esr) && fixup_exception(regs))
                return;
 
-       /*
-        * No handler, we'll have to terminate things with extreme prejudice.
-        */
        bust_spinlocks(1);
 
        if (is_permission_fault(esr, regs, addr)) {
@@ -291,10 +283,6 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
        do_exit(SIGKILL);
 }
 
-/*
- * Something tried to access memory that isn't in our memory map. User mode
- * accesses just cause a SIGSEGV
- */
 static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
                            unsigned int esr, unsigned int sig, int code,
                            struct pt_regs *regs, int fault)
@@ -559,23 +547,6 @@ no_context:
        return 0;
 }
 
-/*
- * First Level Translation Fault Handler
- *
- * We enter here because the first level page table doesn't contain a valid
- * entry for the address.
- *
- * If the address is in kernel space (>= TASK_SIZE), then we are probably
- * faulting in the vmalloc() area.
- *
- * If the init_task's first level page tables contains the relevant entry, we
- * copy the it to this task.  If not, we send the process a signal, fixup the
- * exception, or oops the kernel.
- *
- * NOTE! We MUST NOT take any locks for this case. We may be in an interrupt
- * or a critical region, and should only copy the information from the master
- * page table, nothing more.
- */
 static int __kprobes do_translation_fault(unsigned long addr,
                                          unsigned int esr,
                                          struct pt_regs *regs)
@@ -594,18 +565,11 @@ static int do_alignment_fault(unsigned long addr, unsigned int esr,
        return 0;
 }
 
-/*
- * This abort handler always returns "fault".
- */
 static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 {
-       return 1;
+       return 1; /* "fault" */
 }
 
-/*
- * This abort handler deals with Synchronous External Abort.
- * It calls notifiers, and then returns "fault".
- */
 static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 {
        struct siginfo info;
@@ -668,14 +632,14 @@ static const struct fault_info fault_info[] = {
        { do_sea,               SIGBUS,  0,             "level 1 (translation table walk)"      },
        { do_sea,               SIGBUS,  0,             "level 2 (translation table walk)"      },
        { do_sea,               SIGBUS,  0,             "level 3 (translation table walk)"      },
-       { do_sea,               SIGBUS,  0,             "synchronous parity or ECC error" },
+       { do_sea,               SIGBUS,  0,             "synchronous parity or ECC error" },    // Reserved when RAS is implemented
        { do_bad,               SIGBUS,  0,             "unknown 25"                    },
        { do_bad,               SIGBUS,  0,             "unknown 26"                    },
        { do_bad,               SIGBUS,  0,             "unknown 27"                    },
-       { do_sea,               SIGBUS,  0,             "level 0 synchronous parity error (translation table walk)"     },
-       { do_sea,               SIGBUS,  0,             "level 1 synchronous parity error (translation table walk)"     },
-       { do_sea,               SIGBUS,  0,             "level 2 synchronous parity error (translation table walk)"     },
-       { do_sea,               SIGBUS,  0,             "level 3 synchronous parity error (translation table walk)"     },
+       { do_sea,               SIGBUS,  0,             "level 0 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
+       { do_sea,               SIGBUS,  0,             "level 1 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
+       { do_sea,               SIGBUS,  0,             "level 2 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
+       { do_sea,               SIGBUS,  0,             "level 3 synchronous parity error (translation table walk)"     },      // Reserved when RAS is implemented
        { do_bad,               SIGBUS,  0,             "unknown 32"                    },
        { do_alignment_fault,   SIGBUS,  BUS_ADRALN,    "alignment fault"               },
        { do_bad,               SIGBUS,  0,             "unknown 34"                    },
@@ -693,7 +657,7 @@ static const struct fault_info fault_info[] = {
        { do_bad,               SIGBUS,  0,             "unknown 46"                    },
        { do_bad,               SIGBUS,  0,             "unknown 47"                    },
        { do_bad,               SIGBUS,  0,             "TLB conflict abort"            },
-       { do_bad,               SIGBUS,  0,             "unknown 49"                    },
+       { do_bad,               SIGBUS,  0,             "Unsupported atomic hardware update fault"      },
        { do_bad,               SIGBUS,  0,             "unknown 50"                    },
        { do_bad,               SIGBUS,  0,             "unknown 51"                    },
        { do_bad,               SIGBUS,  0,             "implementation fault (lockdown abort)" },
@@ -710,13 +674,6 @@ static const struct fault_info fault_info[] = {
        { do_bad,               SIGBUS,  0,             "unknown 63"                    },
 };
 
-/*
- * Handle Synchronous External Aborts that occur in a guest kernel.
- *
- * The return value will be zero if the SEA was successfully handled
- * and non-zero if there was an error processing the error or there was
- * no error to process.
- */
 int handle_guest_sea(phys_addr_t addr, unsigned int esr)
 {
        int ret = -ENOENT;
@@ -727,9 +684,6 @@ int handle_guest_sea(phys_addr_t addr, unsigned int esr)
        return ret;
 }
 
-/*
- * Dispatch a data abort to the relevant handler.
- */
 asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
                                         struct pt_regs *regs)
 {
@@ -739,11 +693,14 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
        if (!inf->fn(addr, esr, regs))
                return;
 
-       pr_alert("Unhandled fault: %s (0x%08x) at 0x%016lx\n",
-                inf->name, esr, addr);
+       pr_alert("Unhandled fault: %s at 0x%016lx\n",
+                inf->name, addr);
 
        mem_abort_decode(esr);
 
+       if (!user_mode(regs))
+               show_pte(addr);
+
        info.si_signo = inf->sig;
        info.si_errno = 0;
        info.si_code  = inf->code;
@@ -751,9 +708,6 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
        arm64_notify_die("", regs, &info, esr);
 }
 
-/*
- * Handle stack alignment exceptions.
- */
 asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
                                           unsigned int esr,
                                           struct pt_regs *regs)