]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
powerpc: Disable relocation on exceptions when kexecing
authorIan Munsie <imunsie@au1.ibm.com>
Thu, 8 Nov 2012 05:40:28 +0000 (16:40 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Thu, 15 Nov 2012 04:08:08 +0000 (15:08 +1100)
Since we don't know if they new kernel we are kexecing into has been
built to support relocation on exceptions, we disable them before we
kexec.

We do NOT disable them if we are execing a kdump kernel, because we
want to change as little state as possible and it is likely that we are
execing ourselves and will be able to handle them anyway.

Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/platforms/pseries/setup.c

index 5d97553e5c226b92bcceb2de31020116c7f713be..ca55882465d6b0d027ef785f941c64a342985f99 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/root_dev.h>
 #include <linux/cpuidle.h>
 #include <linux/of.h>
+#include <linux/kexec.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -397,6 +398,35 @@ static int __init pSeries_enable_reloc_on_exc(void)
        }
 }
 
+#ifdef CONFIG_KEXEC
+static long pSeries_disable_reloc_on_exc(void)
+{
+       long rc;
+
+       while (1) {
+               rc = disable_reloc_on_exceptions();
+               if (!H_IS_LONG_BUSY(rc))
+                       return rc;
+               mdelay(get_longbusy_msecs(rc));
+       }
+}
+
+static void pSeries_machine_kexec(struct kimage *image)
+{
+       long rc;
+
+       if (firmware_has_feature(FW_FEATURE_SET_MODE) &&
+           (image->type != KEXEC_TYPE_CRASH)) {
+               rc = pSeries_disable_reloc_on_exc();
+               if (rc != H_SUCCESS)
+                       pr_warning("Warning: Failed to disable relocation on "
+                                  "exceptions: %ld\n", rc);
+       }
+
+       default_machine_kexec(image);
+}
+#endif
+
 static void __init pSeries_setup_arch(void)
 {
        panic_timeout = 10;
@@ -697,4 +727,7 @@ define_machine(pseries) {
        .progress               = rtas_progress,
        .system_reset_exception = pSeries_system_reset_exception,
        .machine_check_exception = pSeries_machine_check_exception,
+#ifdef CONFIG_KEXEC
+       .machine_kexec          = pSeries_machine_kexec,
+#endif
 };