MIPS: traps: Fix output of show_stacktrace
[linux-2.6-block.git] / arch / mips / kernel / traps.c
index 3de85be2486a44d5fbaedb64a556b3e9bf879210..25ce866b289589a21768ff767227f442f3d588ac 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/extable.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
@@ -48,6 +49,7 @@
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/idle.h>
+#include <asm/mips-cm.h>
 #include <asm/mips-r2-to-r6-emul.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
@@ -154,7 +156,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)
                print_ip_sym(pc);
                pc = unwind_stack(task, &sp, pc, &ra);
        } while (pc);
-       printk("\n");
+       pr_cont("\n");
 }
 
 /*
@@ -172,22 +174,24 @@ static void show_stacktrace(struct task_struct *task,
        printk("Stack :");
        i = 0;
        while ((unsigned long) sp & (PAGE_SIZE - 1)) {
-               if (i && ((i % (64 / field)) == 0))
-                       printk("\n       ");
+               if (i && ((i % (64 / field)) == 0)) {
+                       pr_cont("\n");
+                       printk("       ");
+               }
                if (i > 39) {
-                       printk(" ...");
+                       pr_cont(" ...");
                        break;
                }
 
                if (__get_user(stackdata, sp++)) {
-                       printk(" (Bad stack address)");
+                       pr_cont(" (Bad stack address)");
                        break;
                }
 
-               printk(" %0*lx", field, stackdata);
+               pr_cont(" %0*lx", field, stackdata);
                i++;
        }
-       printk("\n");
+       pr_cont("\n");
        show_backtrace(task, regs);
 }
 
@@ -444,6 +448,8 @@ asmlinkage void do_be(struct pt_regs *regs)
 
        if (board_be_handler)
                action = board_be_handler(regs, fixup != NULL);
+       else
+               mips_cm_error_report();
 
        switch (action) {
        case MIPS_BE_DISCARD:
@@ -2091,6 +2097,14 @@ static void configure_exception_vector(void)
 {
        if (cpu_has_veic || cpu_has_vint) {
                unsigned long sr = set_c0_status(ST0_BEV);
+               /* If available, use WG to set top bits of EBASE */
+               if (cpu_has_ebase_wg) {
+#ifdef CONFIG_64BIT
+                       write_c0_ebase_64(ebase | MIPS_EBASE_WG);
+#else
+                       write_c0_ebase(ebase | MIPS_EBASE_WG);
+#endif
+               }
                write_c0_ebase(ebase);
                write_c0_status(sr);
                /* Setting vector spacing enables EI/VI mode  */
@@ -2127,8 +2141,17 @@ void per_cpu_trap_init(bool is_boot_cpu)
                 * We shouldn't trust a secondary core has a sane EBASE register
                 * so use the one calculated by the boot CPU.
                 */
-               if (!is_boot_cpu)
+               if (!is_boot_cpu) {
+                       /* If available, use WG to set top bits of EBASE */
+                       if (cpu_has_ebase_wg) {
+#ifdef CONFIG_64BIT
+                               write_c0_ebase_64(ebase | MIPS_EBASE_WG);
+#else
+                               write_c0_ebase(ebase | MIPS_EBASE_WG);
+#endif
+                       }
                        write_c0_ebase(ebase);
+               }
 
                cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
                cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
@@ -2209,13 +2232,39 @@ void __init trap_init(void)
 
        if (cpu_has_veic || cpu_has_vint) {
                unsigned long size = 0x200 + VECTORSPACING*64;
+               phys_addr_t ebase_pa;
+
                ebase = (unsigned long)
                        __alloc_bootmem(size, 1 << fls(size), 0);
+
+               /*
+                * Try to ensure ebase resides in KSeg0 if possible.
+                *
+                * It shouldn't generally be in XKPhys on MIPS64 to avoid
+                * hitting a poorly defined exception base for Cache Errors.
+                * The allocation is likely to be in the low 512MB of physical,
+                * in which case we should be able to convert to KSeg0.
+                *
+                * EVA is special though as it allows segments to be rearranged
+                * and to become uncached during cache error handling.
+                */
+               ebase_pa = __pa(ebase);
+               if (!IS_ENABLED(CONFIG_EVA) && !WARN_ON(ebase_pa >= 0x20000000))
+                       ebase = CKSEG0ADDR(ebase_pa);
        } else {
                ebase = CAC_BASE;
 
-               if (cpu_has_mips_r2_r6)
-                       ebase += (read_c0_ebase() & 0x3ffff000);
+               if (cpu_has_mips_r2_r6) {
+                       if (cpu_has_ebase_wg) {
+#ifdef CONFIG_64BIT
+                               ebase = (read_c0_ebase_64() & ~0xfff);
+#else
+                               ebase = (read_c0_ebase() & ~0xfff);
+#endif
+                       } else {
+                               ebase += (read_c0_ebase() & 0x3ffff000);
+                       }
+               }
        }
 
        if (cpu_has_mmips) {