summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/misc_32.S
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2005-11-14 13:35:00 +0100
committerPaul Mackerras <paulus@samba.org>2006-01-09 04:48:52 +0100
commit3d1229d6ae92ed1994f4411b8493327ef8f4b76f (patch)
treea50dbd6b52f1d653897147c48c57db28cefb69c7 /arch/powerpc/kernel/misc_32.S
parent[PATCH] PPC_PREP: remove unneeded exports (diff)
downloadlinux-3d1229d6ae92ed1994f4411b8493327ef8f4b76f.tar.xz
linux-3d1229d6ae92ed1994f4411b8493327ef8f4b76f.zip
[PATCH] powerpc: Merge kexec
This patch merges, to some extent, the PPC32 and PPC64 kexec implementations. We adopt the PPC32 approach of having ppc_md callbacks for the kexec functions. The current PPC64 implementation becomes the "default" implementation for PPC64 which platforms can select if they need no special treatment. I've added these default callbacks to pseries/maple/cell/powermac, this means iSeries no longer supports kexec - but it never worked anyway. I've renamed PPC32's machine_kexec_simple to default_machine_kexec, inline with PPC64. Judging by the comments it might be better named machine_kexec_non_of, or something, but at the moment it's the only implementation for PPC32 so it's the "default". Kexec requires machine_shutdown(), which is in machine_kexec.c on PPC32, but we already have in setup-common.c on powerpc. All this does is call ppc_md.nvram_sync, which only powermac implements, so instead make machine_shutdown a ppc_md member and have it call core99_nvram_sync directly on powermac. I've also stuck relocate_kernel.S into misc_32.S for powerpc. Built for ARCH=ppc, and 32 & 64 bit ARCH=powerpc, with KEXEC=y/n. Booted on P5 LPAR and successfully kexec'ed. Should apply on top of 493f25ef4087395891c99fcfe2c72e62e293e89f. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/misc_32.S')
-rw-r--r--arch/powerpc/kernel/misc_32.S113
1 files changed, 113 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 624a983a9676..01d0d97a16e1 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -5,6 +5,10 @@
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras.
*
+ * kexec bits:
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -24,6 +28,8 @@
#include <asm/ppc_asm.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
+#include <asm/processor.h>
+#include <asm/kexec.h>
.text
@@ -1006,3 +1012,110 @@ _GLOBAL(execve)
*/
_GLOBAL(__main)
blr
+
+#ifdef CONFIG_KEXEC
+ /*
+ * Must be relocatable PIC code callable as a C function.
+ */
+ .globl relocate_new_kernel
+relocate_new_kernel:
+ /* r3 = page_list */
+ /* r4 = reboot_code_buffer */
+ /* r5 = start_address */
+
+ li r0, 0
+
+ /*
+ * Set Machine Status Register to a known status,
+ * switch the MMU off and jump to 1: in a single step.
+ */
+
+ mr r8, r0
+ ori r8, r8, MSR_RI|MSR_ME
+ mtspr SPRN_SRR1, r8
+ addi r8, r4, 1f - relocate_new_kernel
+ mtspr SPRN_SRR0, r8
+ sync
+ rfi
+
+1:
+ /* from this point address translation is turned off */
+ /* and interrupts are disabled */
+
+ /* set a new stack at the bottom of our page... */
+ /* (not really needed now) */
+ addi r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
+ stw r0, 0(r1)
+
+ /* Do the copies */
+ li r6, 0 /* checksum */
+ mr r0, r3
+ b 1f
+
+0: /* top, read another word for the indirection page */
+ lwzu r0, 4(r3)
+
+1:
+ /* is it a destination page? (r8) */
+ rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
+ beq 2f
+
+ rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
+ b 0b
+
+2: /* is it an indirection page? (r3) */
+ rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
+ beq 2f
+
+ rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
+ subi r3, r3, 4
+ b 0b
+
+2: /* are we done? */
+ rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
+ beq 2f
+ b 3f
+
+2: /* is it a source page? (r9) */
+ rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
+ beq 0b
+
+ rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
+
+ li r7, PAGE_SIZE / 4
+ mtctr r7
+ subi r9, r9, 4
+ subi r8, r8, 4
+9:
+ lwzu r0, 4(r9) /* do the copy */
+ xor r6, r6, r0
+ stwu r0, 4(r8)
+ dcbst 0, r8
+ sync
+ icbi 0, r8
+ bdnz 9b
+
+ addi r9, r9, 4
+ addi r8, r8, 4
+ b 0b
+
+3:
+
+ /* To be certain of avoiding problems with self-modifying code
+ * execute a serializing instruction here.
+ */
+ isync
+ sync
+
+ /* jump to the entry point, usually the setup routine */
+ mtlr r5
+ blrl
+
+1: b 1b
+
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .long relocate_new_kernel_end - relocate_new_kernel
+#endif