[PATCH 03/10] powerpc: Add kexec support for PPC_85xx platforms
Dale Farnsworth
dale at farnsworth.org
Fri Nov 23 02:46:07 EST 2007
Book E processors need some extra setup in relocate_new_kernel,
because the MMU can't be turned off. Add the code to create
the required one-to-one memory map.
Signed-off-by: Dale Farnsworth <dale at farnsworth.org>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/misc_32.S | 69 +++++++++++++++++++++++++++++
arch/powerpc/platforms/85xx/mpc85xx_ads.c | 6 +++
arch/powerpc/platforms/85xx/mpc85xx_cds.c | 6 +++
arch/powerpc/platforms/85xx/mpc85xx_ds.c | 6 +++
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 6 +++
6 files changed, 94 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 191cc2c..9e9581a 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -236,7 +236,7 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
- depends on PPC_MULTIPLATFORM && EXPERIMENTAL
+ depends on (PPC_MULTIPLATFORM || PPC_85xx) && EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 8b642ab..db0e749 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -816,6 +816,75 @@ relocate_new_kernel:
/* r4 = reboot_code_buffer */
/* r5 = start_address */
+#ifdef CONFIG_E500
+ /*
+ * Since we can't turn off the MMU, we must create an identity
+ * map for kernel low memory. We start by invalidating the
+ * TLB entries we don't need.
+ *
+ * First, invalidate the TLB0 entries
+ */
+ li r6, 0x04
+ tlbivax 0, r6
+#ifdef CONFIG_SMP
+ tlbsync
+#endif
+ msync
+
+ /*
+ * Kernel low memory is mapped by TLB1 entries 0, 1, and 2.
+ * Preserve these, but invalidate all other TLB1 entries.
+ */
+ li r7, 3 /* first TLB1 entry */
+ mfspr r6, SPRN_TLB1CFG
+ andi. r6, r6, 0xfff
+ mr r8, r6
+ subf r6, r7, r6
+ mtctr r6
+1:
+ rlwinm r6, r7, 16, 12, 15
+ oris r6, r6, 0x1000
+ mtspr SPRN_MAS0, r6
+ tlbre
+ mfspr r6, SPRN_MAS1
+ rlwinm r6, r6, 0, 2, 31 /* Clear MAS1 Valid and IPROT */
+ mtspr SPRN_MAS1, r6
+ tlbwe
+ isync
+ addi r7, r7, 1
+ bdnz 1b
+
+ /*
+ * Using TLB1 entries 3, 4, and 5, identity-map kernel low
+ * memory by copying and modifying the contents of TLB1
+ * entries 0, 1 and 2, respectively.
+ */
+ li r7, 0 /* source TLB entry */
+ li r8, 3 /* destination TLB entry */
+ li r6, 3 /* number of TLBs to copy */
+ mtctr r6
+1:
+ rlwinm r6, r7, 16, 12, 15
+ oris r6, r6, 0x1000
+ mtspr SPRN_MAS0, r6
+ tlbre
+
+ mfspr r6, SPRN_MAS2
+ lis r0, PAGE_OFFSET at h
+ subf r6, r0, r6 /* identity map */
+ mtspr SPRN_MAS2, r6
+
+ rlwinm r6, r8, 16, 12, 15
+ oris r6, r6, 0x1000
+ mtspr SPRN_MAS0, r6
+ tlbwe
+ sync
+ isync
+ addi r7, r7, 1
+ addi r8, r8, 1
+ bdnz 1b
+#endif /* CONFIG_E500 */
+
li r0, 0
/*
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index bccdc25..1ade3dd 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/of_platform.h>
+#include <linux/kexec.h>
#include <asm/system.h>
#include <asm/time.h>
@@ -259,6 +260,11 @@ define_machine(mpc85xx_ads) {
.show_cpuinfo = mpc85xx_ads_show_cpuinfo,
.get_irq = mpic_get_irq,
.restart = fsl_rstcr_restart,
+#ifdef CONFIG_KEXEC
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+ .machine_kexec = default_machine_kexec,
+ .machine_crash_shutdown = default_machine_crash_shutdown,
+#endif
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 4d063ee..b8a5ed2 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/fsl_devices.h>
+#include <linux/kexec.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -352,6 +353,11 @@ define_machine(mpc85xx_cds) {
#else
.restart = fsl_rstcr_restart,
#endif
+#ifdef CONFIG_KEXEC
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+ .machine_kexec = default_machine_kexec,
+ .machine_crash_shutdown = default_machine_crash_shutdown,
+#endif
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 59c121a..4c106b6 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
+#include <linux/kexec.h>
#include <asm/system.h>
#include <asm/time.h>
@@ -224,6 +225,11 @@ define_machine(mpc8572_ds) {
#endif
.get_irq = mpic_get_irq,
.restart = fsl_rstcr_restart,
+#ifdef CONFIG_KEXEC
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+ .machine_kexec = default_machine_kexec,
+ .machine_crash_shutdown = default_machine_crash_shutdown,
+#endif
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 61b3eed..49f55c1 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -30,6 +30,7 @@
#include <linux/initrd.h>
#include <linux/module.h>
#include <linux/fsl_devices.h>
+#include <linux/kexec.h>
#include <asm/of_device.h>
#include <asm/of_platform.h>
@@ -202,6 +203,11 @@ define_machine(mpc85xx_mds) {
.init_IRQ = mpc85xx_mds_pic_init,
.get_irq = mpic_get_irq,
.restart = fsl_rstcr_restart,
+#ifdef CONFIG_KEXEC
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+ .machine_kexec = default_machine_kexec,
+ .machine_crash_shutdown = default_machine_crash_shutdown,
+#endif
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
#ifdef CONFIG_PCI
--
1.5.3.4
More information about the Linuxppc-dev
mailing list