mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 01:04:19 +08:00
cc53291521
Implementing the machine_crash_shutdown which will be called by crash_kexec (called in case of a panic, sysrq etc.). Disable the interrupts, shootdown cpus using debugger IPI and collect regs for all CPUs. elfcorehdr= specifies the location of elf core header stored by the crashed kernel. This command line option will be passed by the kexec-tools to capture kernel. savemaxmem= specifies the actual memory size that the first kernel has and this value will be used for dumping in the capture kernel. This command line option will be passed by the kexec-tools to capture kernel. Signed-off-by: Haren Myneni <haren@us.ibm.com> Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
74 lines
1.7 KiB
C
74 lines
1.7 KiB
C
/*
|
|
* Routines for doing kexec-based kdump.
|
|
*
|
|
* Copyright (C) 2005, IBM Corp.
|
|
*
|
|
* Created by: Michael Ellerman
|
|
*
|
|
* This source code is licensed under the GNU General Public License,
|
|
* Version 2. See the file COPYING for more details.
|
|
*/
|
|
|
|
#undef DEBUG
|
|
|
|
#include <linux/crash_dump.h>
|
|
#include <linux/bootmem.h>
|
|
#include <asm/kdump.h>
|
|
#include <asm/lmb.h>
|
|
#include <asm/firmware.h>
|
|
|
|
#ifdef DEBUG
|
|
#include <asm/udbg.h>
|
|
#define DBG(fmt...) udbg_printf(fmt)
|
|
#else
|
|
#define DBG(fmt...)
|
|
#endif
|
|
|
|
static void __init create_trampoline(unsigned long addr)
|
|
{
|
|
/* The maximum range of a single instruction branch, is the current
|
|
* instruction's address + (32 MB - 4) bytes. For the trampoline we
|
|
* need to branch to current address + 32 MB. So we insert a nop at
|
|
* the trampoline address, then the next instruction (+ 4 bytes)
|
|
* does a branch to (32 MB - 4). The net effect is that when we
|
|
* branch to "addr" we jump to ("addr" + 32 MB). Although it requires
|
|
* two instructions it doesn't require any registers.
|
|
*/
|
|
create_instruction(addr, 0x60000000); /* nop */
|
|
create_branch(addr + 4, addr + PHYSICAL_START, 0);
|
|
}
|
|
|
|
void __init kdump_setup(void)
|
|
{
|
|
unsigned long i;
|
|
|
|
DBG(" -> kdump_setup()\n");
|
|
|
|
for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
|
|
create_trampoline(i);
|
|
}
|
|
|
|
create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
|
|
create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
|
|
|
|
DBG(" <- kdump_setup()\n");
|
|
}
|
|
|
|
static int __init parse_elfcorehdr(char *p)
|
|
{
|
|
if (p)
|
|
elfcorehdr_addr = memparse(p, &p);
|
|
|
|
return 0;
|
|
}
|
|
__setup("elfcorehdr=", parse_elfcorehdr);
|
|
|
|
static int __init parse_savemaxmem(char *p)
|
|
{
|
|
if (p)
|
|
saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
|
|
|
|
return 0;
|
|
}
|
|
__setup("savemaxmem=", parse_savemaxmem);
|