]>
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 | ||
cc532915 ME |
14 | #include <linux/crash_dump.h> |
15 | #include <linux/bootmem.h> | |
0cc4746c ME |
16 | #include <asm/kdump.h> |
17 | #include <asm/lmb.h> | |
18 | #include <asm/firmware.h> | |
19 | ||
20 | #ifdef DEBUG | |
21 | #include <asm/udbg.h> | |
22 | #define DBG(fmt...) udbg_printf(fmt) | |
23 | #else | |
24 | #define DBG(fmt...) | |
25 | #endif | |
26 | ||
27 | static void __init create_trampoline(unsigned long addr) | |
28 | { | |
29 | /* The maximum range of a single instruction branch, is the current | |
30 | * instruction's address + (32 MB - 4) bytes. For the trampoline we | |
31 | * need to branch to current address + 32 MB. So we insert a nop at | |
32 | * the trampoline address, then the next instruction (+ 4 bytes) | |
33 | * does a branch to (32 MB - 4). The net effect is that when we | |
34 | * branch to "addr" we jump to ("addr" + 32 MB). Although it requires | |
35 | * two instructions it doesn't require any registers. | |
36 | */ | |
37 | create_instruction(addr, 0x60000000); /* nop */ | |
38 | create_branch(addr + 4, addr + PHYSICAL_START, 0); | |
39 | } | |
40 | ||
41 | void __init kdump_setup(void) | |
42 | { | |
43 | unsigned long i; | |
44 | ||
45 | DBG(" -> kdump_setup()\n"); | |
46 | ||
47 | for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) { | |
48 | create_trampoline(i); | |
49 | } | |
50 | ||
51 | create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START); | |
52 | create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START); | |
53 | ||
54 | DBG(" <- kdump_setup()\n"); | |
55 | } | |
cc532915 ME |
56 | |
57 | static int __init parse_elfcorehdr(char *p) | |
58 | { | |
59 | if (p) | |
60 | elfcorehdr_addr = memparse(p, &p); | |
61 | ||
62 | return 0; | |
63 | } | |
64 | __setup("elfcorehdr=", parse_elfcorehdr); | |
65 | ||
66 | static int __init parse_savemaxmem(char *p) | |
67 | { | |
68 | if (p) | |
69 | saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; | |
70 | ||
71 | return 0; | |
72 | } | |
73 | __setup("savemaxmem=", parse_savemaxmem); |