powerpc: Hook in new transactional memory code
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / powerpc / kernel / traps.c
index 5c304697fe84d4e6731bd46f3131594f0c2f0628..f9b751b29558ec842af0f3cd5cdc2f55bb7e91a3 100644 (file)
@@ -1029,6 +1029,38 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
                return;
        }
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       if (reason & REASON_TM) {
+               /* This is a TM "Bad Thing Exception" program check.
+                * This occurs when:
+                * -  An rfid/hrfid/mtmsrd attempts to cause an illegal
+                *    transition in TM states.
+                * -  A trechkpt is attempted when transactional.
+                * -  A treclaim is attempted when non transactional.
+                * -  A tend is illegally attempted.
+                * -  writing a TM SPR when transactional.
+                */
+               if (!user_mode(regs) &&
+                   report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
+                       regs->nip += 4;
+                       return;
+               }
+               /* If usermode caused this, it's done something illegal and
+                * gets a SIGILL slap on the wrist.  We call it an illegal
+                * operand to distinguish from the instruction just being bad
+                * (e.g. executing a 'tend' on a CPU without TM!); it's an
+                * illegal /placement/ of a valid instruction.
+                */
+               if (user_mode(regs)) {
+                       _exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
+                       return;
+               } else {
+                       printk(KERN_EMERG "Unexpected TM Bad Thing exception "
+                              "at %lx (msr 0x%x)\n", regs->nip, reason);
+                       die("Unrecoverable exception", regs, SIGABRT);
+               }
+       }
+#endif
 
        /* We restore the interrupt state now */
        if (!arch_irq_disabled_regs(regs))