powerpc: Rename and flesh out the facility unavailable exception handler
authorMichael Ellerman <michaele@au1.ibm.com>
Tue, 25 Jun 2013 07:47:56 +0000 (17:47 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 1 Jul 2013 01:49:44 +0000 (11:49 +1000)
The exception at 0xf60 is not the TM (Transactional Memory) unavailable
exception, it is the "Facility Unavailable Exception", rename it as
such.

Flesh out the handler to acknowledge the fact that it can be called for
many reasons, one of which is TM being unavailable.

Use STD_EXCEPTION_COMMON() for the exception body, for some reason we
had it open-coded, I've checked the generated code is identical.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
CC: <stable@vger.kernel.org> [v3.10]
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/traps.c

index 89eba1f..6ee74f8 100644 (file)
@@ -341,10 +341,11 @@ vsx_unavailable_pSeries_1:
        EXCEPTION_PROLOG_0(PACA_EXGEN)
        b       vsx_unavailable_pSeries
 
+facility_unavailable_trampoline:
        . = 0xf60
        SET_SCRATCH0(r13)
        EXCEPTION_PROLOG_0(PACA_EXGEN)
-       b       tm_unavailable_pSeries
+       b       facility_unavailable_pSeries
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
@@ -522,7 +523,7 @@ denorm_done:
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf20)
        STD_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)
-       STD_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable)
+       STD_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf60)
 
 /*
@@ -829,11 +830,11 @@ vsx_unavailable_relon_pSeries_1:
        EXCEPTION_PROLOG_0(PACA_EXGEN)
        b       vsx_unavailable_relon_pSeries
 
-tm_unavailable_relon_pSeries_1:
+facility_unavailable_relon_trampoline:
        . = 0x4f60
        SET_SCRATCH0(r13)
        EXCEPTION_PROLOG_0(PACA_EXGEN)
-       b       tm_unavailable_relon_pSeries
+       b       facility_unavailable_relon_pSeries
 
        STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint)
 #ifdef CONFIG_PPC_DENORMALISATION
@@ -1159,15 +1160,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
        bl      .vsx_unavailable_exception
        b       .ret_from_except
 
-       .align  7
-       .globl tm_unavailable_common
-tm_unavailable_common:
-       EXCEPTION_PROLOG_COMMON(0xf60, PACA_EXGEN)
-       bl      .save_nvgprs
-       DISABLE_INTS
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       bl      .tm_unavailable_exception
-       b       .ret_from_except
+       STD_EXCEPTION_COMMON(0xf60, facility_unavailable, .facility_unavailable_exception)
 
        .align  7
        .globl  __end_handlers
@@ -1180,7 +1173,7 @@ __end_handlers:
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor)
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable)
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
-       STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable)
+       STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
 
 #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
index 300daf3..11f4488 100644 (file)
@@ -1286,25 +1286,42 @@ 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;
+       u64 value;
+
+       value = mfspr(SPRN_FSCR) >> 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("Facility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
+               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