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/crash_dump.c | |
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/crash_dump.c')
-rw-r--r-- | arch/powerpc/kernel/crash_dump.c | 53 |
1 files changed, 53 insertions, 0 deletions
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 | } | ||