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 ec4b3e1087bed69b1ca03e205d5b8b6dcf851167..04280a5871fc5cc4a09c8374a3e75d498af26f67 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 b6cbe34493581d4e56a00cb370b50a27a56a3fd4..356e7b99f66188dec49d104fd58f8c4d143b1740 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 a5e52f9eed3cc950f492d1678abb51bd858bfd52..83498604d322be152a04533af3a049752f76cc0b 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 d8930c3a8a11ed6a482754ecdcfdfee0eada9157..b955d54628ffde485b076e0fa16f7f5d6eec8467 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
 }