]>
Commit | Line | Data |
---|---|---|
0cc4746c ME |
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 | } |