diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2005-12-04 02:39:37 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 22:52:21 -0500 |
commit | 0cc4746cadda16826a1b3214c042a2f75445b71c (patch) | |
tree | ec8decc81a3f9fd09454ff208fd3b82cf5bdb730 /arch/powerpc/kernel | |
parent | 8c4f1f2958ff9d4a6760f3bdd0cfb7d2b9e12093 (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/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/crash_dump.c | 53 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 5 |
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 | |||
34 | obj-$(CONFIG_IBMEBUS) += ibmebus.o | 34 | obj-$(CONFIG_IBMEBUS) += ibmebus.o |
35 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o | 35 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o |
36 | obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o | 36 | obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o |
37 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | ||
37 | 38 | ||
38 | ifeq ($(CONFIG_PPC_MERGE),y) | 39 | ifeq ($(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 | |||
25 | static 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 | |||
39 | void __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 | /* |