blob: 882779c07874fd17b97144cfaa680f5038c701aa [file] [log] [blame]
Eric W. Biederman5033cba2005-06-25 14:57:56 -07001/*
2 * Architecture specific (i386) functions for kexec based crash dumps.
3 *
4 * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
5 *
6 * Copyright (C) IBM Corporation, 2004. All rights reserved.
7 *
8 */
9
10#include <linux/init.h>
11#include <linux/types.h>
12#include <linux/kernel.h>
13#include <linux/smp.h>
14#include <linux/irq.h>
15#include <linux/reboot.h>
16#include <linux/kexec.h>
17#include <linux/irq.h>
18#include <linux/delay.h>
19#include <linux/elf.h>
20#include <linux/elfcore.h>
21
22#include <asm/processor.h>
23#include <asm/hardirq.h>
24#include <asm/nmi.h>
25#include <asm/hw_irq.h>
Eric W. Biedermanc4ac4262005-06-25 14:57:58 -070026#include <mach_ipi.h>
Eric W. Biederman5033cba2005-06-25 14:57:56 -070027
28#define MAX_NOTE_BYTES 1024
29typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
30
31note_buf_t crash_notes[NR_CPUS];
32
Eric W. Biedermanc4ac4262005-06-25 14:57:58 -070033#ifdef CONFIG_SMP
34static atomic_t waiting_for_crash_ipi;
35
36static int crash_nmi_callback(struct pt_regs *regs, int cpu)
37{
38 local_irq_disable();
39 atomic_dec(&waiting_for_crash_ipi);
40 /* Assume hlt works */
41 __asm__("hlt");
42 for(;;);
43 return 1;
44}
45
46/*
47 * By using the NMI code instead of a vector we just sneak thru the
48 * word generator coming out with just what we want. AND it does
49 * not matter if clustered_apic_mode is set or not.
50 */
51static void smp_send_nmi_allbutself(void)
52{
53 send_IPI_allbutself(APIC_DM_NMI);
54}
55
56static void nmi_shootdown_cpus(void)
57{
58 unsigned long msecs;
59 atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
60
61 /* Would it be better to replace the trap vector here? */
62 set_nmi_callback(crash_nmi_callback);
63 /* Ensure the new callback function is set before sending
64 * out the NMI
65 */
66 wmb();
67
68 smp_send_nmi_allbutself();
69
70 msecs = 1000; /* Wait at most a second for the other cpus to stop */
71 while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
72 mdelay(1);
73 msecs--;
74 }
75
76 /* Leave the nmi callback set */
77}
78#else
79static void nmi_shootdown_cpus(void)
80{
81 /* There are no cpus to shootdown */
82}
83#endif
84
Eric W. Biederman5033cba2005-06-25 14:57:56 -070085void machine_crash_shutdown(void)
86{
87 /* This function is only called after the system
88 * has paniced or is otherwise in a critical state.
89 * The minimum amount of code to allow a kexec'd kernel
90 * to run successfully needs to happen here.
91 *
92 * In practice this means shooting down the other cpus in
93 * an SMP system.
94 */
Eric W. Biedermanc4ac4262005-06-25 14:57:58 -070095 /* The kernel is broken so disable interrupts */
96 local_irq_disable();
97 nmi_shootdown_cpus();
Eric W. Biederman5033cba2005-06-25 14:57:56 -070098}