Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 17549
b: refs/heads/master
c: ec9ce0d
h: refs/heads/master
i:
  17547: 2f86fe2
v: v3
  • Loading branch information
Vivek Goyal authored and Linus Torvalds committed Jan 10, 2006
1 parent 670030d commit caf3c2b
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cffe632a25b017dac4b6f060cad31940c6c167b4
refs/heads/master: ec9ce0dbaa734bc95ec73cf5c13f202f1adb219d
7 changes: 7 additions & 0 deletions trunk/arch/x86_64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,13 @@ config KEXEC
support. As of this writing the exact hardware interface is
strongly in flux, so no good recommendation can be made.

config CRASH_DUMP
bool "kernel crash dumps (EXPERIMENTAL)"
depends on EMBEDDED
depends on EXPERIMENTAL
help
Generate crash dump after being started by kexec.

config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
Expand Down
70 changes: 70 additions & 0 deletions trunk/arch/x86_64/kernel/crash.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/irq.h>
#include <linux/reboot.h>
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/elf.h>
#include <linux/elfcore.h>

#include <asm/processor.h>
#include <asm/hardirq.h>
Expand All @@ -24,6 +27,71 @@
/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu;

static u32 *append_elf_note(u32 *buf, char *name, unsigned type,
void *data, size_t data_len)
{
struct elf_note note;

note.n_namesz = strlen(name) + 1;
note.n_descsz = data_len;
note.n_type = type;
memcpy(buf, &note, sizeof(note));
buf += (sizeof(note) +3)/4;
memcpy(buf, name, note.n_namesz);
buf += (note.n_namesz + 3)/4;
memcpy(buf, data, note.n_descsz);
buf += (note.n_descsz + 3)/4;

return buf;
}

static void final_note(u32 *buf)
{
struct elf_note note;

note.n_namesz = 0;
note.n_descsz = 0;
note.n_type = 0;
memcpy(buf, &note, sizeof(note));
}

static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
{
struct elf_prstatus prstatus;
u32 *buf;

if ((cpu < 0) || (cpu >= NR_CPUS))
return;

/* Using ELF notes here is opportunistic.
* I need a well defined structure format
* for the data I pass, and I need tags
* on the data to indicate what information I have
* squirrelled away. ELF notes happen to provide
* all of that that no need to invent something new.
*/

buf = (u32*)per_cpu_ptr(crash_notes, cpu);

if (!buf)
return;

memset(&prstatus, 0, sizeof(prstatus));
prstatus.pr_pid = current->pid;
elf_core_copy_regs(&prstatus.pr_reg, regs);
buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
sizeof(prstatus));
final_note(buf);
}

static void crash_save_self(struct pt_regs *regs)
{
int cpu;

cpu = smp_processor_id();
crash_save_this_cpu(regs, cpu);
}

#ifdef CONFIG_SMP
static atomic_t waiting_for_crash_ipi;

Expand All @@ -38,6 +106,7 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu)
return 1;
local_irq_disable();

crash_save_this_cpu(regs, cpu);
disable_local_APIC();
atomic_dec(&waiting_for_crash_ipi);
/* Assume hlt works */
Expand Down Expand Up @@ -113,4 +182,5 @@ void machine_crash_shutdown(struct pt_regs *regs)
disable_IO_APIC();
#endif

crash_save_self(regs);
}
36 changes: 36 additions & 0 deletions trunk/include/asm-x86_64/kexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <asm/page.h>
#include <asm/proto.h>
#include <asm/ptrace.h>

/*
* KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
Expand All @@ -27,4 +28,39 @@

#define MAX_NOTE_BYTES 1024

/*
* Saving the registers of the cpu on which panic occured in
* crash_kexec to save a valid sp. The registers of other cpus
* will be saved in machine_crash_shutdown while shooting down them.
*/

static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs)
{
if (oldregs)
memcpy(newregs, oldregs, sizeof(*newregs));
else {
__asm__ __volatile__("movq %%rbx,%0" : "=m"(newregs->rbx));
__asm__ __volatile__("movq %%rcx,%0" : "=m"(newregs->rcx));
__asm__ __volatile__("movq %%rdx,%0" : "=m"(newregs->rdx));
__asm__ __volatile__("movq %%rsi,%0" : "=m"(newregs->rsi));
__asm__ __volatile__("movq %%rdi,%0" : "=m"(newregs->rdi));
__asm__ __volatile__("movq %%rbp,%0" : "=m"(newregs->rbp));
__asm__ __volatile__("movq %%rax,%0" : "=m"(newregs->rax));
__asm__ __volatile__("movq %%rsp,%0" : "=m"(newregs->rsp));
__asm__ __volatile__("movq %%r8,%0" : "=m"(newregs->r8));
__asm__ __volatile__("movq %%r9,%0" : "=m"(newregs->r9));
__asm__ __volatile__("movq %%r10,%0" : "=m"(newregs->r10));
__asm__ __volatile__("movq %%r11,%0" : "=m"(newregs->r11));
__asm__ __volatile__("movq %%r12,%0" : "=m"(newregs->r12));
__asm__ __volatile__("movq %%r13,%0" : "=m"(newregs->r13));
__asm__ __volatile__("movq %%r14,%0" : "=m"(newregs->r14));
__asm__ __volatile__("movq %%r15,%0" : "=m"(newregs->r15));
__asm__ __volatile__("movl %%ss, %%eax;" :"=a"(newregs->ss));
__asm__ __volatile__("movl %%cs, %%eax;" :"=a"(newregs->cs));
__asm__ __volatile__("pushfq; popq %0" :"=m"(newregs->eflags));

newregs->rip = (unsigned long)current_text_addr();
}
}
#endif /* _X86_64_KEXEC_H */

0 comments on commit caf3c2b

Please sign in to comment.