powerpc/64s/powernv: machine check dump SLB contents
authorNicholas Piggin <npiggin@gmail.com>
Fri, 2 Aug 2019 10:56:33 +0000 (20:56 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 30 Aug 2019 00:32:35 +0000 (10:32 +1000)
Re-use the code introduced in pseries to save and dump the contents
of the SLB in the case of an SLB involved machine check exception.

This patch also avoids allocating the SLB save array on pseries radix.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190802105709.27696-9-npiggin@gmail.com
arch/powerpc/kernel/mce.c
arch/powerpc/kernel/mce_power.c
arch/powerpc/platforms/powernv/setup.c
arch/powerpc/platforms/pseries/setup.c

index ec4b3e1..04280a5 100644 (file)
@@ -511,6 +511,12 @@ void machine_check_print_event_info(struct machine_check_event *evt,
        subtype = evt->error_class < ARRAY_SIZE(mc_error_class) ?
                mc_error_class[evt->error_class] : "Unknown";
        printk("%sMCE: CPU%d: %s\n", level, evt->cpu, subtype);
+
+#ifdef CONFIG_PPC_BOOK3S_64
+       /* Display faulty slb contents for SLB errors. */
+       if (evt->error_type == MCE_ERROR_TYPE_SLB)
+               slb_dump_contents(local_paca->mce_faulty_slbs);
+#endif
 }
 EXPORT_SYMBOL_GPL(machine_check_print_event_info);
 
index b6cbe34..356e7b9 100644 (file)
@@ -405,6 +405,8 @@ static int mce_handle_ierror(struct pt_regs *regs,
                /* attempt to correct the error */
                switch (table[i].error_type) {
                case MCE_ERROR_TYPE_SLB:
+                       if (local_paca->in_mce == 1)
+                               slb_save_contents(local_paca->mce_faulty_slbs);
                        handled = mce_flush(MCE_FLUSH_SLB);
                        break;
                case MCE_ERROR_TYPE_ERAT:
@@ -490,6 +492,8 @@ static int mce_handle_derror(struct pt_regs *regs,
                /* attempt to correct the error */
                switch (table[i].error_type) {
                case MCE_ERROR_TYPE_SLB:
+                       if (local_paca->in_mce == 1)
+                               slb_save_contents(local_paca->mce_faulty_slbs);
                        if (mce_flush(MCE_FLUSH_SLB))
                                handled = 1;
                        break;
index a5e52f9..8349860 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/bug.h>
 #include <linux/pci.h>
 #include <linux/cpufreq.h>
+#include <linux/memblock.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
@@ -166,6 +167,14 @@ static void __init pnv_init(void)
        else
 #endif
                add_preferred_console("hvc", 0, NULL);
+
+       if (!radix_enabled()) {
+               int i;
+
+               /* Allocate per cpu area to save old slb contents during MCE */
+               for_each_possible_cpu(i)
+                       paca_ptrs[i]->mce_faulty_slbs = memblock_alloc_node(mmu_slb_size, __alignof__(*paca_ptrs[i]->mce_faulty_slbs), cpu_to_node(i));
+       }
 }
 
 static void __init pnv_init_IRQ(void)
index d8930c3..b955d54 100644 (file)
@@ -142,17 +142,19 @@ static void __init fwnmi_init(void)
        }
 
 #ifdef CONFIG_PPC_BOOK3S_64
-       /* Allocate per cpu slb area to save old slb contents during MCE */
-       size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus;
-       slb_ptr = memblock_alloc_try_nid_raw(size, sizeof(struct slb_entry),
-                                       MEMBLOCK_LOW_LIMIT, ppc64_rma_size,
-                                       NUMA_NO_NODE);
-       if (!slb_ptr)
-               panic("Failed to allocate %zu bytes below %pa for slb area\n",
-                     size, &ppc64_rma_size);
-
-       for_each_possible_cpu(i)
-               paca_ptrs[i]->mce_faulty_slbs = slb_ptr + (mmu_slb_size * i);
+       if (!radix_enabled()) {
+               /* Allocate per cpu area to save old slb contents during MCE */
+               size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus;
+               slb_ptr = memblock_alloc_try_nid_raw(size,
+                               sizeof(struct slb_entry), MEMBLOCK_LOW_LIMIT,
+                               ppc64_rma_size, NUMA_NO_NODE);
+               if (!slb_ptr)
+                       panic("Failed to allocate %zu bytes below %pa for slb area\n",
+                             size, &ppc64_rma_size);
+
+               for_each_possible_cpu(i)
+                       paca_ptrs[i]->mce_faulty_slbs = slb_ptr + (mmu_slb_size * i);
+       }
 #endif
 }