]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/kernel/traps.c
Merge tag 'v3.10' into next
[karo-tx-linux.git] / arch / powerpc / kernel / traps.c
index c0e5caf8ccc72c0f7624b1e7dc9c3f7ecfe4b242..bf33c22e38a40848221762497ca1a7b704a27f9f 100644 (file)
@@ -866,6 +866,10 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
                u8 val;
                u32 shift = 8 * (3 - (pos & 0x3));
 
+               /* if process is 32-bit, clear upper 32 bits of EA */
+               if ((regs->msr & MSR_64BIT) == 0)
+                       EA &= 0xFFFFFFFF;
+
                switch ((instword & PPC_INST_STRING_MASK)) {
                        case PPC_INST_LSWX:
                        case PPC_INST_LSWI:
@@ -1125,7 +1129,17 @@ void __kprobes program_check_exception(struct pt_regs *regs)
         * ESR_DST (!?) or 0.  In the process of chasing this with the
         * hardware people - not sure if it can happen on any illegal
         * instruction or only on FP instructions, whether there is a
-        * pattern to occurrences etc. -dgibson 31/Mar/2003 */
+        * pattern to occurrences etc. -dgibson 31/Mar/2003
+        */
+
+       /*
+        * If we support a HW FPU, we need to ensure the FP state
+        * if flushed into the thread_struct before attempting
+        * emulation
+        */
+#ifdef CONFIG_PPC_FPU
+       flush_fp_to_thread(current);
+#endif
        switch (do_mathemu(regs)) {
        case 0:
                emulate_single_step(regs);
@@ -1282,25 +1296,50 @@ void vsx_unavailable_exception(struct pt_regs *regs)
        die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT);
 }
 
-void tm_unavailable_exception(struct pt_regs *regs)
+void facility_unavailable_exception(struct pt_regs *regs)
 {
+       static char *facility_strings[] = {
+               "FPU",
+               "VMX/VSX",
+               "DSCR",
+               "PMU SPRs",
+               "BHRB",
+               "TM",
+               "AT",
+               "EBB",
+               "TAR",
+       };
+       char *facility, *prefix;
+       u64 value;
+
+       if (regs->trap == 0xf60) {
+               value = mfspr(SPRN_FSCR);
+               prefix = "";
+       } else {
+               value = mfspr(SPRN_HFSCR);
+               prefix = "Hypervisor ";
+       }
+
+       value = value >> 56;
+
        /* We restore the interrupt state now */
        if (!arch_irq_disabled_regs(regs))
                local_irq_enable();
 
-       /* Currently we never expect a TMU exception.  Catch
-        * this and kill the process!
-        */
-       printk(KERN_EMERG "Unexpected TM unavailable exception at %lx "
-              "(msr %lx)\n",
-              regs->nip, regs->msr);
+       if (value < ARRAY_SIZE(facility_strings))
+               facility = facility_strings[value];
+       else
+               facility = "unknown";
+
+       pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
+               prefix, facility, regs->nip, regs->msr);
 
        if (user_mode(regs)) {
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
                return;
        }
 
-       die("Unexpected TM unavailable exception", regs, SIGABRT);
+       die("Unexpected facility unavailable exception", regs, SIGABRT);
 }
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
@@ -1396,8 +1435,7 @@ void performance_monitor_exception(struct pt_regs *regs)
 void SoftwareEmulation(struct pt_regs *regs)
 {
        extern int do_mathemu(struct pt_regs *);
-       extern int Soft_emulate_8xx(struct pt_regs *);
-#if defined(CONFIG_MATH_EMULATION) || defined(CONFIG_8XX_MINIMAL_FPEMU)
+#if defined(CONFIG_MATH_EMULATION)
        int errcode;
 #endif
 
@@ -1430,23 +1468,6 @@ void SoftwareEmulation(struct pt_regs *regs)
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
                return;
        }
-
-#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
-       errcode = Soft_emulate_8xx(regs);
-       if (errcode >= 0)
-               PPC_WARN_EMULATED(8xx, regs);
-
-       switch (errcode) {
-       case 0:
-               emulate_single_step(regs);
-               return;
-       case 1:
-               _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
-               return;
-       case -EFAULT:
-               _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
-               return;
-       }
 #else
        _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 #endif
@@ -1796,8 +1817,6 @@ struct ppc_emulated ppc_emulated = {
        WARN_EMULATED_SETUP(unaligned),
 #ifdef CONFIG_MATH_EMULATION
        WARN_EMULATED_SETUP(math),
-#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
-       WARN_EMULATED_SETUP(8xx),
 #endif
 #ifdef CONFIG_VSX
        WARN_EMULATED_SETUP(vsx),