aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2005-12-04 02:39:37 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 22:52:21 -0500
commit0cc4746cadda16826a1b3214c042a2f75445b71c (patch)
treeec8decc81a3f9fd09454ff208fd3b82cf5bdb730 /arch
parent8c4f1f2958ff9d4a6760f3bdd0cfb7d2b9e12093 (diff)
[PATCH] powerpc: Reroute interrupts from 0 + offset to PHYSICAL_START + offset
Regardless of where the kernel's linked we always get interrupts at low addresses. This patch creates a trampoline in the first 3 pages of memory, where interrupts land, and patches those addresses to jump into the real kernel code at PHYSICAL_START. We also need to reserve the trampoline code and a bit more in prom.c Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/Makefile1
-rw-r--r--arch/powerpc/kernel/crash_dump.c53
-rw-r--r--arch/powerpc/kernel/prom.c6
-rw-r--r--arch/powerpc/kernel/setup_64.c5
4 files changed, 64 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 89714929f444..5719248d344d 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_IBMVIO) += vio.o
34obj-$(CONFIG_IBMEBUS) += ibmebus.o 34obj-$(CONFIG_IBMEBUS) += ibmebus.o
35obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 35obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
36obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o 36obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
37obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
37 38
38ifeq ($(CONFIG_PPC_MERGE),y) 39ifeq ($(CONFIG_PPC_MERGE),y)
39 40
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
new file mode 100644
index 000000000000..63919bcfc9fe
--- /dev/null
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -0,0 +1,53 @@
1/*
2 * Routines for doing kexec-based kdump.
3 *
4 * Copyright (C) 2005, IBM Corp.
5 *
6 * Created by: Michael Ellerman
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#undef DEBUG
13
14#include <asm/kdump.h>
15#include <asm/lmb.h>
16#include <asm/firmware.h>
17
18#ifdef DEBUG
19#include <asm/udbg.h>
20#define DBG(fmt...) udbg_printf(fmt)
21#else
22#define DBG(fmt...)
23#endif
24
25static void __init create_trampoline(unsigned long addr)
26{
27 /* The maximum range of a single instruction branch, is the current
28 * instruction's address + (32 MB - 4) bytes. For the trampoline we
29 * need to branch to current address + 32 MB. So we insert a nop at
30 * the trampoline address, then the next instruction (+ 4 bytes)
31 * does a branch to (32 MB - 4). The net effect is that when we
32 * branch to "addr" we jump to ("addr" + 32 MB). Although it requires
33 * two instructions it doesn't require any registers.
34 */
35 create_instruction(addr, 0x60000000); /* nop */
36 create_branch(addr + 4, addr + PHYSICAL_START, 0);
37}
38
39void __init kdump_setup(void)
40{
41 unsigned long i;
42
43 DBG(" -> kdump_setup()\n");
44
45 for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
46 create_trampoline(i);
47 }
48
49 create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
50 create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
51
52 DBG(" <- kdump_setup()\n");
53}
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 3bf968e74095..9aac77ca3167 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -37,6 +37,7 @@
37#include <asm/processor.h> 37#include <asm/processor.h>
38#include <asm/irq.h> 38#include <asm/irq.h>
39#include <asm/io.h> 39#include <asm/io.h>
40#include <asm/kdump.h>
40#include <asm/smp.h> 41#include <asm/smp.h>
41#include <asm/system.h> 42#include <asm/system.h>
42#include <asm/mmu.h> 43#include <asm/mmu.h>
@@ -1335,11 +1336,14 @@ void __init early_init_devtree(void *params)
1335 of_scan_flat_dt(early_init_dt_scan_memory, NULL); 1336 of_scan_flat_dt(early_init_dt_scan_memory, NULL);
1336 lmb_enforce_memory_limit(memory_limit); 1337 lmb_enforce_memory_limit(memory_limit);
1337 lmb_analyze(); 1338 lmb_analyze();
1338 lmb_reserve(0, __pa(klimit));
1339 1339
1340 DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); 1340 DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
1341 1341
1342 /* Reserve LMB regions used by kernel, initrd, dt, etc... */ 1342 /* Reserve LMB regions used by kernel, initrd, dt, etc... */
1343 lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
1344#ifdef CONFIG_CRASH_DUMP
1345 lmb_reserve(0, KDUMP_RESERVE_LIMIT);
1346#endif
1343 early_reserve_mem(); 1347 early_reserve_mem();
1344 1348
1345 DBG("Scanning CPUs ...\n"); 1349 DBG("Scanning CPUs ...\n");
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6509dd7c2f8f..e67120e34652 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -34,6 +34,7 @@
34#include <linux/serial.h> 34#include <linux/serial.h>
35#include <linux/serial_8250.h> 35#include <linux/serial_8250.h>
36#include <asm/io.h> 36#include <asm/io.h>
37#include <asm/kdump.h>
37#include <asm/prom.h> 38#include <asm/prom.h>
38#include <asm/processor.h> 39#include <asm/processor.h>
39#include <asm/pgtable.h> 40#include <asm/pgtable.h>
@@ -268,6 +269,10 @@ void __init early_setup(unsigned long dt_ptr)
268 } 269 }
269 ppc_md = **mach; 270 ppc_md = **mach;
270 271
272#ifdef CONFIG_CRASH_DUMP
273 kdump_setup();
274#endif
275
271 DBG("Found, Initializing memory management...\n"); 276 DBG("Found, Initializing memory management...\n");
272 277
273 /* 278 /*