aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorIan Munsie <imunsie@au1.ibm.com>2012-11-08 00:40:28 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-11-14 23:08:08 -0500
commitcedddd812a79a4fda3885a15711aee3de78c4a24 (patch)
tree7a9a3dbf97109a6259b655eed87794410c007d86 /arch/powerpc
parentfc8effa4e46fb7bd8a3c5e293efc56b74a54b7a5 (diff)
powerpc: Disable relocation on exceptions when kexecing
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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/pseries/setup.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 5d97553e5c22..ca55882465d6 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -41,6 +41,7 @@
41#include <linux/root_dev.h> 41#include <linux/root_dev.h>
42#include <linux/cpuidle.h> 42#include <linux/cpuidle.h>
43#include <linux/of.h> 43#include <linux/of.h>
44#include <linux/kexec.h>
44 45
45#include <asm/mmu.h> 46#include <asm/mmu.h>
46#include <asm/processor.h> 47#include <asm/processor.h>
@@ -397,6 +398,35 @@ static int __init pSeries_enable_reloc_on_exc(void)
397 } 398 }
398} 399}
399 400
401#ifdef CONFIG_KEXEC
402static long pSeries_disable_reloc_on_exc(void)
403{
404 long rc;
405
406 while (1) {
407 rc = disable_reloc_on_exceptions();
408 if (!H_IS_LONG_BUSY(rc))
409 return rc;
410 mdelay(get_longbusy_msecs(rc));
411 }
412}
413
414static void pSeries_machine_kexec(struct kimage *image)
415{
416 long rc;
417
418 if (firmware_has_feature(FW_FEATURE_SET_MODE) &&
419 (image->type != KEXEC_TYPE_CRASH)) {
420 rc = pSeries_disable_reloc_on_exc();
421 if (rc != H_SUCCESS)
422 pr_warning("Warning: Failed to disable relocation on "
423 "exceptions: %ld\n", rc);
424 }
425
426 default_machine_kexec(image);
427}
428#endif
429
400static void __init pSeries_setup_arch(void) 430static void __init pSeries_setup_arch(void)
401{ 431{
402 panic_timeout = 10; 432 panic_timeout = 10;
@@ -697,4 +727,7 @@ define_machine(pseries) {
697 .progress = rtas_progress, 727 .progress = rtas_progress,
698 .system_reset_exception = pSeries_system_reset_exception, 728 .system_reset_exception = pSeries_system_reset_exception,
699 .machine_check_exception = pSeries_machine_check_exception, 729 .machine_check_exception = pSeries_machine_check_exception,
730#ifdef CONFIG_KEXEC
731 .machine_kexec = pSeries_machine_kexec,
732#endif
700}; 733};