[PATCH 0/3] pseries kexec fixes
From: Anton Blanchard <hidden>
Date: 2011-07-25 11:46:31
Here are a few pseries kexec fixes after testing on a recent version version. Anton
4 messages, 1 author, 2011-07-25 · open the first message on its own page
From: Anton Blanchard <hidden>
Date: 2011-07-25 11:46:31
Here are a few pseries kexec fixes after testing on a recent version version. Anton
From: Anton Blanchard <hidden>
Date: 2011-07-25 11:46:32
Recent versions of firmware will fail to unmap the virtual processor area if we have a dispatch trace log registered. This causes kexec to fail. If a trace log is registered this patch unregisters it before the SLB shadow and virtual processor areas, fixing the problem. The address argument is ignored by firmware on unregister so we may as well remove it. Signed-off-by: Anton Blanchard <redacted> Cc: <stable@kernel.org> --- Index: linux-powerpc/arch/powerpc/platforms/pseries/kexec.c ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/kexec.c 2011-07-25 21:06:49.510413446 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/kexec.c 2011-07-25 21:06:52.340464687 +1000@@ -26,6 +26,17 @@ static void pseries_kexec_cpu_down(int c /* Don't risk a hypervisor call if we're crashing */ if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { unsigned long addr; + int ret; + + if (get_lppaca()->dtl_enable_mask) { + ret = unregister_dtl(hard_smp_processor_id()); + if (ret) { + pr_err("WARNING: DTL deregistration for cpu " + "%d (hw %d) failed with %d\n", + smp_processor_id(), + hard_smp_processor_id(), ret); + } + } addr = __pa(get_slb_shadow()); if (unregister_slb_shadow(hard_smp_processor_id(), addr))
Index: linux-powerpc/arch/powerpc/platforms/pseries/dtl.c ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/dtl.c 2011-07-25 21:06:49.520413628 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/dtl.c 2011-07-25 21:06:52.340464687 +1000@@ -181,7 +181,7 @@ static void dtl_stop(struct dtl *dtl) lppaca_of(dtl->cpu).dtl_enable_mask = 0x0; - unregister_dtl(hwcpu, __pa(dtl->buf)); + unregister_dtl(hwcpu); } static u64 dtl_current_index(struct dtl *dtl)
Index: linux-powerpc/arch/powerpc/platforms/pseries/plpar_wrappers.h ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/plpar_wrappers.h 2011-07-25 21:06:49.500413264 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/plpar_wrappers.h 2011-07-25 21:06:52.340464687 +1000@@ -73,9 +73,9 @@ static inline long register_slb_shadow(u return vpa_call(0x3, cpu, vpa); } -static inline long unregister_dtl(unsigned long cpu, unsigned long vpa) +static inline long unregister_dtl(unsigned long cpu) { - return vpa_call(0x6, cpu, vpa); + return vpa_call(0x6, cpu, 0); } static inline long register_dtl(unsigned long cpu, unsigned long vpa)
From: Anton Blanchard <hidden>
Date: 2011-07-25 11:46:33
Make the VPA, SLB shadow and DTL registration and deregistration functions print consistent messages on error. I needed the firmware error code while chasing a kexec bug but we weren't printing it. Signed-off-by: Anton Blanchard <redacted> --- Index: linux-powerpc/arch/powerpc/platforms/pseries/kexec.c ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/kexec.c 2011-07-25 21:06:52.340464687 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/kexec.c 2011-07-25 21:06:56.260535670 +1000@@ -39,17 +39,20 @@ static void pseries_kexec_cpu_down(int c } addr = __pa(get_slb_shadow()); - if (unregister_slb_shadow(hard_smp_processor_id(), addr)) - printk("SLB shadow buffer deregistration of " - "cpu %u (hw_cpu_id %d) failed\n", + ret = unregister_slb_shadow(hard_smp_processor_id(), addr); + if (ret) { + pr_err("WARNING: SLB shadow buffer deregistration " + "for cpu %d (hw %d) failed with %d\n", smp_processor_id(), - hard_smp_processor_id()); + hard_smp_processor_id(), ret); + } addr = __pa(get_lppaca()); - if (unregister_vpa(hard_smp_processor_id(), addr)) { - printk("VPA deregistration of cpu %u (hw_cpu_id %d) " - "failed\n", smp_processor_id(), - hard_smp_processor_id()); + ret = unregister_vpa(hard_smp_processor_id(), addr); + if (ret) { + pr_err("WARNING: VPA deregistration for cpu %d " + "(hw %d) failed with %d\n", smp_processor_id(), + hard_smp_processor_id(), ret); } } }
Index: linux-powerpc/arch/powerpc/platforms/pseries/lpar.c ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/lpar.c 2011-07-25 21:06:49.440412178 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/lpar.c 2011-07-25 21:06:56.260535670 +1000@@ -67,9 +67,8 @@ void vpa_init(int cpu) ret = register_vpa(hwcpu, addr); if (ret) { - printk(KERN_ERR "WARNING: vpa_init: VPA registration for " - "cpu %d (hw %d) of area %lx returns %ld\n", - cpu, hwcpu, addr, ret); + pr_err("WARNING: VPA registration for cpu %d (hw %d) of area " + "%lx failed with %ld\n", cpu, hwcpu, addr, ret); return; } /*
@@ -80,10 +79,9 @@ void vpa_init(int cpu) if (firmware_has_feature(FW_FEATURE_SPLPAR)) { ret = register_slb_shadow(hwcpu, addr); if (ret) - printk(KERN_ERR - "WARNING: vpa_init: SLB shadow buffer " - "registration for cpu %d (hw %d) of area %lx " - "returns %ld\n", cpu, hwcpu, addr, ret); + pr_err("WARNING: SLB shadow buffer registration for " + "cpu %d (hw %d) of area %lx failed with %ld\n", + cpu, hwcpu, addr, ret); } /*
@@ -100,8 +98,9 @@ void vpa_init(int cpu) dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES; ret = register_dtl(hwcpu, __pa(dtl)); if (ret) - pr_warn("DTL registration failed for cpu %d (%ld)\n", - cpu, ret); + pr_err("WARNING: DTL registration of cpu %d (hw %d) " + "failed with %ld\n", smp_processor_id(), + hwcpu, ret); lppaca_of(cpu).dtl_enable_mask = 2; } }
Index: linux-powerpc/arch/powerpc/platforms/pseries/setup.c ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/setup.c 2011-07-25 21:06:49.450412359 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/setup.c 2011-07-25 21:06:56.260535670 +1000@@ -324,8 +324,9 @@ static int alloc_dispatch_logs(void) dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES; ret = register_dtl(hard_smp_processor_id(), __pa(dtl)); if (ret) - pr_warn("DTL registration failed for boot cpu %d (%d)\n", - smp_processor_id(), ret); + pr_err("WARNING: DTL registration of cpu %d (hw %d) failed " + "with %d\n", smp_processor_id(), + hard_smp_processor_id(), ret); get_paca()->lppaca_ptr->dtl_enable_mask = 2; return 0;
From: Anton Blanchard <hidden>
Date: 2011-07-25 11:46:34
The VPA, SLB shadow and DTL degistration functions do not need an address, so simplify things and remove it. Also cleanup pseries_kexec_cpu_down a bit by storing the cpu IDs in local variables. Signed-off-by: Anton Blanchard <redacted> --- Index: linux-powerpc/arch/powerpc/platforms/pseries/hotplug-cpu.c ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/hotplug-cpu.c 2011-07-25 21:06:49.390411273 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/hotplug-cpu.c 2011-07-25 21:06:57.380555950 +1000@@ -135,7 +135,7 @@ static void pseries_mach_cpu_die(void) get_lppaca()->idle = 0; if (get_preferred_offline_state(cpu) == CPU_STATE_ONLINE) { - unregister_slb_shadow(hwcpu, __pa(get_slb_shadow())); + unregister_slb_shadow(hwcpu); /* * Call to start_secondary_resume() will not return.
@@ -150,7 +150,7 @@ static void pseries_mach_cpu_die(void) WARN_ON(get_preferred_offline_state(cpu) != CPU_STATE_OFFLINE); set_cpu_current_state(cpu, CPU_STATE_OFFLINE); - unregister_slb_shadow(hwcpu, __pa(get_slb_shadow())); + unregister_slb_shadow(hwcpu); rtas_stop_self(); /* Should never get here... */
Index: linux-powerpc/arch/powerpc/platforms/pseries/kexec.c ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/kexec.c 2011-07-25 21:06:56.260535670 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/kexec.c 2011-07-25 21:09:20.033141478 +1000@@ -25,34 +25,30 @@ static void pseries_kexec_cpu_down(int c { /* Don't risk a hypervisor call if we're crashing */ if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { - unsigned long addr; int ret; + int cpu = smp_processor_id(); + int hwcpu = hard_smp_processor_id(); if (get_lppaca()->dtl_enable_mask) { - ret = unregister_dtl(hard_smp_processor_id()); + ret = unregister_dtl(hwcpu); if (ret) { pr_err("WARNING: DTL deregistration for cpu " "%d (hw %d) failed with %d\n", - smp_processor_id(), - hard_smp_processor_id(), ret); + cpu, hwcpu, ret); } } - addr = __pa(get_slb_shadow()); - ret = unregister_slb_shadow(hard_smp_processor_id(), addr); + ret = unregister_slb_shadow(hwcpu); if (ret) { pr_err("WARNING: SLB shadow buffer deregistration " "for cpu %d (hw %d) failed with %d\n", - smp_processor_id(), - hard_smp_processor_id(), ret); + cpu, hwcpu, ret); } - addr = __pa(get_lppaca()); - ret = unregister_vpa(hard_smp_processor_id(), addr); + ret = unregister_vpa(hwcpu); if (ret) { pr_err("WARNING: VPA deregistration for cpu %d " - "(hw %d) failed with %d\n", smp_processor_id(), - hard_smp_processor_id(), ret); + "(hw %d) failed with %d\n", cpu, hwcpu, ret); } } }
Index: linux-powerpc/arch/powerpc/platforms/pseries/plpar_wrappers.h ===================================================================
--- linux-powerpc.orig/arch/powerpc/platforms/pseries/plpar_wrappers.h 2011-07-25 21:06:52.340464687 +1000
+++ linux-powerpc/arch/powerpc/platforms/pseries/plpar_wrappers.h 2011-07-25 21:06:57.380555950 +1000@@ -53,9 +53,9 @@ static inline long vpa_call(unsigned lon return plpar_hcall_norets(H_REGISTER_VPA, flags, cpu, vpa); } -static inline long unregister_vpa(unsigned long cpu, unsigned long vpa) +static inline long unregister_vpa(unsigned long cpu) { - return vpa_call(0x5, cpu, vpa); + return vpa_call(0x5, cpu, 0); } static inline long register_vpa(unsigned long cpu, unsigned long vpa)
@@ -63,9 +63,9 @@ static inline long register_vpa(unsigned return vpa_call(0x1, cpu, vpa); } -static inline long unregister_slb_shadow(unsigned long cpu, unsigned long vpa) +static inline long unregister_slb_shadow(unsigned long cpu) { - return vpa_call(0x7, cpu, vpa); + return vpa_call(0x7, cpu, 0); } static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)