aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/Makefile5
-rw-r--r--arch/powerpc/kernel/machine_kexec.c67
-rw-r--r--arch/powerpc/kernel/machine_kexec_32.c65
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c25
-rw-r--r--arch/powerpc/kernel/misc_32.S113
-rw-r--r--arch/powerpc/kernel/setup-common.c4
-rw-r--r--arch/powerpc/platforms/cell/setup.c5
-rw-r--r--arch/powerpc/platforms/maple/setup.c5
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c1
-rw-r--r--arch/powerpc/platforms/powermac/setup.c5
-rw-r--r--arch/powerpc/platforms/pseries/setup.c3
11 files changed, 272 insertions, 26 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 9ed551b6c172..e7776a438a84 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -65,8 +65,9 @@ pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \
65 pci_direct_iommu.o iomap.o 65 pci_direct_iommu.o iomap.o
66obj-$(CONFIG_PCI) += $(pci64-y) 66obj-$(CONFIG_PCI) += $(pci64-y)
67 67
68kexec64-$(CONFIG_PPC64) += machine_kexec_64.o 68kexec-$(CONFIG_PPC64) := machine_kexec_64.o
69obj-$(CONFIG_KEXEC) += $(kexec64-y) 69kexec-$(CONFIG_PPC32) := machine_kexec_32.o
70obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y)
70 71
71ifeq ($(CONFIG_PPC_ISERIES),y) 72ifeq ($(CONFIG_PPC_ISERIES),y)
72$(obj)/head_64.o: $(obj)/lparmap.s 73$(obj)/head_64.o: $(obj)/lparmap.s
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
new file mode 100644
index 000000000000..d8225c797199
--- /dev/null
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -0,0 +1,67 @@
1/*
2 * Code to handle transition of Linux booting another kernel.
3 *
4 * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
5 * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
6 * Copyright (C) 2005 IBM Corporation.
7 *
8 * This source code is licensed under the GNU General Public License,
9 * Version 2. See the file COPYING for more details.
10 */
11
12#include <linux/kexec.h>
13#include <linux/reboot.h>
14#include <linux/threads.h>
15#include <asm/machdep.h>
16
17/*
18 * Provide a dummy crash_notes definition until crash dump is implemented.
19 * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
20 */
21note_buf_t crash_notes[NR_CPUS];
22
23void machine_crash_shutdown(struct pt_regs *regs)
24{
25 if (ppc_md.machine_crash_shutdown)
26 ppc_md.machine_crash_shutdown();
27}
28
29/*
30 * Do what every setup is needed on image and the
31 * reboot code buffer to allow us to avoid allocations
32 * later.
33 */
34int machine_kexec_prepare(struct kimage *image)
35{
36 if (ppc_md.machine_kexec_prepare)
37 return ppc_md.machine_kexec_prepare(image);
38 /*
39 * Fail if platform doesn't provide its own machine_kexec_prepare
40 * implementation.
41 */
42 return -ENOSYS;
43}
44
45void machine_kexec_cleanup(struct kimage *image)
46{
47 if (ppc_md.machine_kexec_cleanup)
48 ppc_md.machine_kexec_cleanup(image);
49}
50
51/*
52 * Do not allocate memory (or fail in any way) in machine_kexec().
53 * We are past the point of no return, committed to rebooting now.
54 */
55NORET_TYPE void machine_kexec(struct kimage *image)
56{
57 if (ppc_md.machine_kexec)
58 ppc_md.machine_kexec(image);
59 else {
60 /*
61 * Fall back to normal restart if platform doesn't provide
62 * its own kexec function, and user insist to kexec...
63 */
64 machine_restart(NULL);
65 }
66 for(;;);
67}
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c
new file mode 100644
index 000000000000..443606134dff
--- /dev/null
+++ b/arch/powerpc/kernel/machine_kexec_32.c
@@ -0,0 +1,65 @@
1/*
2 * PPC32 code to handle Linux booting another kernel.
3 *
4 * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
5 * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
6 * Copyright (C) 2005 IBM Corporation.
7 *
8 * This source code is licensed under the GNU General Public License,
9 * Version 2. See the file COPYING for more details.
10 */
11
12#include <linux/kexec.h>
13#include <linux/mm.h>
14#include <linux/string.h>
15#include <asm/cacheflush.h>
16#include <asm/hw_irq.h>
17#include <asm/io.h>
18
19typedef NORET_TYPE void (*relocate_new_kernel_t)(
20 unsigned long indirection_page,
21 unsigned long reboot_code_buffer,
22 unsigned long start_address) ATTRIB_NORET;
23
24/*
25 * This is a generic machine_kexec function suitable at least for
26 * non-OpenFirmware embedded platforms.
27 * It merely copies the image relocation code to the control page and
28 * jumps to it.
29 * A platform specific function may just call this one.
30 */
31void default_machine_kexec(struct kimage *image)
32{
33 const extern unsigned char relocate_new_kernel[];
34 const extern unsigned int relocate_new_kernel_size;
35 unsigned long page_list;
36 unsigned long reboot_code_buffer, reboot_code_buffer_phys;
37 relocate_new_kernel_t rnk;
38
39 /* Interrupts aren't acceptable while we reboot */
40 local_irq_disable();
41
42 page_list = image->head;
43
44 /* we need both effective and real address here */
45 reboot_code_buffer =
46 (unsigned long)page_address(image->control_code_page);
47 reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
48
49 /* copy our kernel relocation code to the control code page */
50 memcpy((void *)reboot_code_buffer, relocate_new_kernel,
51 relocate_new_kernel_size);
52
53 flush_icache_range(reboot_code_buffer,
54 reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
55 printk(KERN_INFO "Bye!\n");
56
57 /* now call it */
58 rnk = (relocate_new_kernel_t) reboot_code_buffer;
59 (*rnk)(page_list, reboot_code_buffer_phys, image->start);
60}
61
62int default_machine_kexec_prepare(struct kimage *image)
63{
64 return 0;
65}
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index 97c51e452be7..ec0f06bfc24a 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * machine_kexec.c - handle transition of Linux booting another kernel 2 * PPC64 code to handle Linux booting another kernel.
3 * 3 *
4 * Copyright (C) 2004-2005, IBM Corp. 4 * Copyright (C) 2004-2005, IBM Corp.
5 * 5 *
@@ -28,21 +28,7 @@
28 28
29#define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */ 29#define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */
30 30
31/* Have this around till we move it into crash specific file */ 31int default_machine_kexec_prepare(struct kimage *image)
32note_buf_t crash_notes[NR_CPUS];
33
34/* Dummy for now. Not sure if we need to have a crash shutdown in here
35 * and if what it will achieve. Letting it be now to compile the code
36 * in generic kexec environment
37 */
38void machine_crash_shutdown(struct pt_regs *regs)
39{
40 /* do nothing right now */
41 /* smp_relase_cpus() if we want smp on panic kernel */
42 /* cpu_irq_down to isolate us until we are ready */
43}
44
45int machine_kexec_prepare(struct kimage *image)
46{ 32{
47 int i; 33 int i;
48 unsigned long begin, end; /* limits of segment */ 34 unsigned long begin, end; /* limits of segment */
@@ -111,11 +97,6 @@ int machine_kexec_prepare(struct kimage *image)
111 return 0; 97 return 0;
112} 98}
113 99
114void machine_kexec_cleanup(struct kimage *image)
115{
116 /* we do nothing in prepare that needs to be undone */
117}
118
119#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE) 100#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE)
120 101
121static void copy_segments(unsigned long ind) 102static void copy_segments(unsigned long ind)
@@ -283,7 +264,7 @@ extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start,
283 void (*clear_all)(void)) ATTRIB_NORET; 264 void (*clear_all)(void)) ATTRIB_NORET;
284 265
285/* too late to fail here */ 266/* too late to fail here */
286void machine_kexec(struct kimage *image) 267void default_machine_kexec(struct kimage *image)
287{ 268{
288 269
289 /* prepare control code if any */ 270 /* prepare control code if any */
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 @@
5 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) 5 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
6 * and Paul Mackerras. 6 * and Paul Mackerras.
7 * 7 *
8 * kexec bits:
9 * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
10 * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
11 *
8 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 14 * as published by the Free Software Foundation; either version
@@ -24,6 +28,8 @@
24#include <asm/ppc_asm.h> 28#include <asm/ppc_asm.h>
25#include <asm/thread_info.h> 29#include <asm/thread_info.h>
26#include <asm/asm-offsets.h> 30#include <asm/asm-offsets.h>
31#include <asm/processor.h>
32#include <asm/kexec.h>
27 33
28 .text 34 .text
29 35
@@ -1006,3 +1012,110 @@ _GLOBAL(execve)
1006 */ 1012 */
1007_GLOBAL(__main) 1013_GLOBAL(__main)
1008 blr 1014 blr
1015
1016#ifdef CONFIG_KEXEC
1017 /*
1018 * Must be relocatable PIC code callable as a C function.
1019 */
1020 .globl relocate_new_kernel
1021relocate_new_kernel:
1022 /* r3 = page_list */
1023 /* r4 = reboot_code_buffer */
1024 /* r5 = start_address */
1025
1026 li r0, 0
1027
1028 /*
1029 * Set Machine Status Register to a known status,
1030 * switch the MMU off and jump to 1: in a single step.
1031 */
1032
1033 mr r8, r0
1034 ori r8, r8, MSR_RI|MSR_ME
1035 mtspr SPRN_SRR1, r8
1036 addi r8, r4, 1f - relocate_new_kernel
1037 mtspr SPRN_SRR0, r8
1038 sync
1039 rfi
1040
10411:
1042 /* from this point address translation is turned off */
1043 /* and interrupts are disabled */
1044
1045 /* set a new stack at the bottom of our page... */
1046 /* (not really needed now) */
1047 addi r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
1048 stw r0, 0(r1)
1049
1050 /* Do the copies */
1051 li r6, 0 /* checksum */
1052 mr r0, r3
1053 b 1f
1054
10550: /* top, read another word for the indirection page */
1056 lwzu r0, 4(r3)
1057
10581:
1059 /* is it a destination page? (r8) */
1060 rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
1061 beq 2f
1062
1063 rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
1064 b 0b
1065
10662: /* is it an indirection page? (r3) */
1067 rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
1068 beq 2f
1069
1070 rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
1071 subi r3, r3, 4
1072 b 0b
1073
10742: /* are we done? */
1075 rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
1076 beq 2f
1077 b 3f
1078
10792: /* is it a source page? (r9) */
1080 rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
1081 beq 0b
1082
1083 rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
1084
1085 li r7, PAGE_SIZE / 4
1086 mtctr r7
1087 subi r9, r9, 4
1088 subi r8, r8, 4
10899:
1090 lwzu r0, 4(r9) /* do the copy */
1091 xor r6, r6, r0
1092 stwu r0, 4(r8)
1093 dcbst 0, r8
1094 sync
1095 icbi 0, r8
1096 bdnz 9b
1097
1098 addi r9, r9, 4
1099 addi r8, r8, 4
1100 b 0b
1101
11023:
1103
1104 /* To be certain of avoiding problems with self-modifying code
1105 * execute a serializing instruction here.
1106 */
1107 isync
1108 sync
1109
1110 /* jump to the entry point, usually the setup routine */
1111 mtlr r5
1112 blrl
1113
11141: b 1b
1115
1116relocate_new_kernel_end:
1117
1118 .globl relocate_new_kernel_size
1119relocate_new_kernel_size:
1120 .long relocate_new_kernel_end - relocate_new_kernel
1121#endif
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index bd3eb4292b53..6088a39edc26 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -93,8 +93,8 @@ EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
93/* also used by kexec */ 93/* also used by kexec */
94void machine_shutdown(void) 94void machine_shutdown(void)
95{ 95{
96 if (ppc_md.nvram_sync) 96 if (ppc_md.machine_shutdown)
97 ppc_md.nvram_sync(); 97 ppc_md.machine_shutdown();
98} 98}
99 99
100void machine_restart(char *cmd) 100void machine_restart(char *cmd)
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 9a495634d0c2..d45dc18855a5 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -33,6 +33,7 @@
33#include <asm/mmu.h> 33#include <asm/mmu.h>
34#include <asm/processor.h> 34#include <asm/processor.h>
35#include <asm/io.h> 35#include <asm/io.h>
36#include <asm/kexec.h>
36#include <asm/pgtable.h> 37#include <asm/pgtable.h>
37#include <asm/prom.h> 38#include <asm/prom.h>
38#include <asm/rtas.h> 39#include <asm/rtas.h>
@@ -138,4 +139,8 @@ struct machdep_calls __initdata cell_md = {
138 .set_rtc_time = rtas_set_rtc_time, 139 .set_rtc_time = rtas_set_rtc_time,
139 .calibrate_decr = generic_calibrate_decr, 140 .calibrate_decr = generic_calibrate_decr,
140 .progress = cell_progress, 141 .progress = cell_progress,
142#ifdef CONFIG_KEXEC
143 .machine_kexec = default_machine_kexec,
144 .machine_kexec_prepare = default_machine_kexec_prepare,
145#endif
141}; 146};
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 7ece8983a105..95b2352655fe 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -51,6 +51,7 @@
51#include <asm/pgtable.h> 51#include <asm/pgtable.h>
52#include <asm/bitops.h> 52#include <asm/bitops.h>
53#include <asm/io.h> 53#include <asm/io.h>
54#include <asm/kexec.h>
54#include <asm/pci-bridge.h> 55#include <asm/pci-bridge.h>
55#include <asm/iommu.h> 56#include <asm/iommu.h>
56#include <asm/machdep.h> 57#include <asm/machdep.h>
@@ -292,4 +293,8 @@ struct machdep_calls __initdata maple_md = {
292 .calibrate_decr = generic_calibrate_decr, 293 .calibrate_decr = generic_calibrate_decr,
293 .progress = maple_progress, 294 .progress = maple_progress,
294 .idle_loop = native_idle, 295 .idle_loop = native_idle,
296#ifdef CONFIG_KEXEC
297 .machine_kexec = default_machine_kexec,
298 .machine_kexec_prepare = default_machine_kexec_prepare,
299#endif
295}; 300};
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 4042e2f06ee0..59e0e51cf663 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -549,6 +549,7 @@ static int __init core99_nvram_setup(struct device_node *dp)
549 ppc_md.nvram_write = core99_nvram_write; 549 ppc_md.nvram_write = core99_nvram_write;
550 ppc_md.nvram_size = core99_nvram_size; 550 ppc_md.nvram_size = core99_nvram_size;
551 ppc_md.nvram_sync = core99_nvram_sync; 551 ppc_md.nvram_sync = core99_nvram_sync;
552 ppc_md.machine_shutdown = core99_nvram_sync;
552 /* 553 /*
553 * Maybe we could be smarter here though making an exclusive list 554 * Maybe we could be smarter here though making an exclusive list
554 * of known flash chips is a bit nasty as older OF didn't provide us 555 * of known flash chips is a bit nasty as older OF didn't provide us
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 7acb0546671f..3b7a492d9b68 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -60,6 +60,7 @@
60#include <asm/system.h> 60#include <asm/system.h>
61#include <asm/pgtable.h> 61#include <asm/pgtable.h>
62#include <asm/io.h> 62#include <asm/io.h>
63#include <asm/kexec.h>
63#include <asm/pci-bridge.h> 64#include <asm/pci-bridge.h>
64#include <asm/ohare.h> 65#include <asm/ohare.h>
65#include <asm/mediabay.h> 66#include <asm/mediabay.h>
@@ -773,7 +774,11 @@ struct machdep_calls __initdata pmac_md = {
773 .pci_probe_mode = pmac_probe_mode, 774 .pci_probe_mode = pmac_probe_mode,
774 .idle_loop = native_idle, 775 .idle_loop = native_idle,
775 .enable_pmcs = power4_enable_pmcs, 776 .enable_pmcs = power4_enable_pmcs,
777#ifdef CONFIG_KEXEC
778 .machine_kexec = default_machine_kexec,
779 .machine_kexec_prepare = default_machine_kexec_prepare,
776#endif 780#endif
781#endif /* CONFIG_PPC64 */
777#ifdef CONFIG_PPC32 782#ifdef CONFIG_PPC32
778 .pcibios_enable_device_hook = pmac_pci_enable_device_hook, 783 .pcibios_enable_device_hook = pmac_pci_enable_device_hook,
779 .pcibios_after_init = pmac_pcibios_after_init, 784 .pcibios_after_init = pmac_pcibios_after_init,
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 4a465f067ede..8a4238a3757f 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -56,6 +56,7 @@
56#include <asm/dma.h> 56#include <asm/dma.h>
57#include <asm/machdep.h> 57#include <asm/machdep.h>
58#include <asm/irq.h> 58#include <asm/irq.h>
59#include <asm/kexec.h>
59#include <asm/time.h> 60#include <asm/time.h>
60#include <asm/nvram.h> 61#include <asm/nvram.h>
61#include "xics.h" 62#include "xics.h"
@@ -638,5 +639,7 @@ struct machdep_calls __initdata pSeries_md = {
638 .machine_check_exception = pSeries_machine_check_exception, 639 .machine_check_exception = pSeries_machine_check_exception,
639#ifdef CONFIG_KEXEC 640#ifdef CONFIG_KEXEC
640 .kexec_cpu_down = pseries_kexec_cpu_down, 641 .kexec_cpu_down = pseries_kexec_cpu_down,
642 .machine_kexec = default_machine_kexec,
643 .machine_kexec_prepare = default_machine_kexec_prepare,
641#endif 644#endif
642}; 645};