[PATCH] lkcd kernel patch for linux kernel 2.4. for x86_64
"Sanjay Kumar" <[email protected]> Wed, 7 Jul 2004 15:26:46 +0530
| Newsgroups | gmane.linux.lkcd.general |
|---|---|
| Message-ID | <33BC33A9E76474479B76AD0DE8A16972FE73@exch-ntd.nec.noida.hcltech.com> |
Hello Everybody
please find attached lkcd kernel 2.4 patch for x86_64.
follow these steps to apply the patch:
1. extract lkcd kernel code from LKCD CVS dated 2004-05-22.=20
2. Download 2.4.21 kernel from kernel.org.
3. copy the lkcd cvs code to the linux 2.4.21 kernel.
4. Apply the lkcd-kernel-x86_64.patch on top of it.
5. build the kernel and boot.
Please provide feedback on patch.
I have tested this patch on AMD opterorn dual processor machine with 512 =
MB of RAM.
To Do:
=3D=3D=3D=3D=3D=3D=3D
Currently working on lkcdutils to analyse the dump generated by above =
patch.
thanks and regards
sanjay =20
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Contributing to the World by creating indispensable value !
System Software CoE @ HCLT-Noida
http://www.hcltechnologies.com
Ph. : +91-120-2510701/702=20
FAX : +91-120-2510713=20
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=20
diff -Naur linux-2.4.21_lkcd/arch/x86_64/boot/install.sh =
lkcd_linux_x86_64/arch/x86_64/boot/install.sh
--- linux-2.4.21_lkcd/arch/x86_64/boot/install.sh 2002-11-29 =
05:23:12.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/boot/install.sh 2004-07-01 =
20:36:03.000000000 +0530
@@ -16,7 +16,8 @@
# $1 - kernel version
# $2 - kernel image file
# $3 - kernel map file
-# $4 - default install path (blank if root directory)
+# $4 - kernel type file
+# $5 - default install path (blank if root directory)=20
#
=20
# User may have a custom install script
@@ -25,15 +26,21 @@
=20
# Default install - same as make zlilo
=20
-if [ -f $4/vmlinuz ]; then
- mv $4/vmlinuz $4/vmlinuz.old
+if [ -f $5/vmlinuz ]; then =09
+ mv $5/vmlinuz $4/vmlinuz.old=09
fi
=20
-if [ -f $4/System.map ]; then
- mv $4/System.map $4/System.old
+if [ -f $5/System.map ]; then =09
+ mv $5/System.map $4/System.old
fi
=20
-cat $2 > $4/vmlinuz
-cp $3 $4/System.map
+if [ -f $5/Kerntypes ]; then
+ mv $5/Kerntypes $5/Kerntypes.old
+fi
+
+cat $2 > $5/vmlinuz
+cp $3 $5/System.map
+cp $4 $5/Kerntypes
+
=20
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
diff -Naur linux-2.4.21_lkcd/arch/x86_64/boot/Makefile =
lkcd_linux_x86_64/arch/x86_64/boot/Makefile
--- linux-2.4.21_lkcd/arch/x86_64/boot/Makefile 2002-11-29 =
05:23:12.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/boot/Makefile 2004-07-01 =
20:37:47.000000000 +0530
@@ -35,12 +35,14 @@
zlilo: $(CONFIGURE) $(BOOTIMAGE)
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz =
$(INSTALL_PATH)/vmlinuz.old; fi
if [ -f $(INSTALL_PATH)/System.map ]; then mv =
$(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
+ if [ -f $(INSTALL_PATH)/Kerntypes ]; then mv $(INSTALL_PATH)/Kerntypes =
$(INSTALL_PATH)/Kerntypes.old; fi
cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
cp $(TOPDIR)/System.map $(INSTALL_PATH)/
+ cp $(TOPDIR)/Kerntypes $(INSTALL_PATH)/
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
=20
install: $(CONFIGURE) $(BOOTIMAGE)
- sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map =
"$(INSTALL_PATH)"
+ sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map =
$(TOPDIR)/Kerntypes "$(INSTALL_PATH)"
=20
tools/build: tools/build.c
$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
diff -Naur linux-2.4.21_lkcd/arch/x86_64/config.in =
lkcd_linux_x86_64/arch/x86_64/config.in
--- linux-2.4.21_lkcd/arch/x86_64/config.in 2003-06-13 =
20:21:32.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/config.in 2004-07-01 =
20:38:43.000000000 +0530
@@ -235,6 +235,12 @@
mainmenu_option next_comment
comment 'Kernel hacking'
=20
+tristate 'Linux Kernel Crash Dump (LKCD) Support' CONFIG_DUMP
+if [ "$CONFIG_DUMP" !=3D "n" ]; then
+ dep_tristate ' LKCD RLE compression' CONFIG_DUMP_COMPRESS_RLE =
$CONFIG_DUMP
+ dep_tristate ' LKCD GZIP compression' CONFIG_DUMP_COMPRESS_GZIP =
$CONFIG_DUMP
+fi
+
bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
if [ "$CONFIG_DEBUG_KERNEL" !=3D "n" ]; then
bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
diff -Naur linux-2.4.21_lkcd/arch/x86_64/kernel/irq.c =
lkcd_linux_x86_64/arch/x86_64/kernel/irq.c
--- linux-2.4.21_lkcd/arch/x86_64/kernel/irq.c 2002-11-29 =
05:23:12.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/kernel/irq.c 2004-07-01 =
21:11:56.000000000 +0530
@@ -1106,7 +1106,7 @@
=20
static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
=20
-static unsigned long irq_affinity [NR_IRQS] =3D { [0 ... NR_IRQS-1] =3D =
~0UL };
+unsigned long irq_affinity [NR_IRQS] =3D { [0 ... NR_IRQS-1] =3D ~0UL =
};
static int irq_affinity_read_proc (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
diff -Naur linux-2.4.21_lkcd/arch/x86_64/kernel/nmi.c =
lkcd_linux_x86_64/arch/x86_64/kernel/nmi.c
--- linux-2.4.21_lkcd/arch/x86_64/kernel/nmi.c 2003-06-13 =
20:21:32.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/kernel/nmi.c 2004-07-01 =
21:12:15.000000000 +0530
@@ -18,6 +18,9 @@
#include <linux/bootmem.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+#include <linux/dump.h>
+#endif
#include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h>
=20
@@ -354,6 +357,14 @@
=20
if (nmi_watchdog_disabled)
return;
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ /*
+ * Ignore watchdog when dumping is in progress.
+ * Todo: consider using the touch_nmi_watchdog() approach =
instead
+ */
+ if (dump_in_progress && cpu !=3D dumping_cpu) return;
+#endif
+
=20
sum =3D apic_timer_irqs[cpu];
=20
@@ -381,6 +392,10 @@
printk("NMI Watchdog detected LOCKUP on CPU%d, eip %16lx, =
registers:\n", cpu, regs->rip);
show_registers(regs);
printk("console shuts up ...\n");
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ dump("NMI Watchdog Detected", regs);
+#endif
+
console_silent();
spin_unlock(&nmi_print_lock);
bust_spinlocks(0);
diff -Naur linux-2.4.21_lkcd/arch/x86_64/kernel/smp.c =
lkcd_linux_x86_64/arch/x86_64/kernel/smp.c
--- linux-2.4.21_lkcd/arch/x86_64/kernel/smp.c 2003-06-13 =
20:21:32.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/kernel/smp.c 2004-07-01 =
21:14:10.000000000 +0530
@@ -16,6 +16,9 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+#include <linux/dump.h>
+#endif
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
=20
@@ -143,6 +146,16 @@
* No need to touch the target chip field
*/
cfg =3D __prepare_ICR(shortcut, vector);
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ if (vector =3D=3D DUMP_VECTOR) {
+ /*
+ * Setup DUMP IPI to be delivered as an NMI
+ */
+ cfg =3D (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+ }
+#endif /* CONFIG_DUMP */
+
+
=20
/*
* Send the IPI. The write to APIC_ICR fires this off.
@@ -308,6 +321,11 @@
static void flush_tlb_others (unsigned long cpumask, struct mm_struct =
*mm,
unsigned long va)
{
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ /* some cpu may not be running... LWS */
+ unsigned long ipi_mask;
+#endif
+
/*
* A couple of (to be removed) sanity checks:
*
@@ -317,8 +335,14 @@
*/
if (!cpumask)
BUG();
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ /* Some cpus may be stopped...like at crash dump time... LWS */
+ if ((ipi_mask =3D cpumask & cpu_online_map) =3D=3D 0)
+ return;
+#else
if ((cpumask & cpu_online_map) !=3D cpumask)
BUG();
+#endif
if (cpumask & (1 << smp_processor_id()))
BUG();
if (!mm)
@@ -334,12 +358,20 @@
=09
flush_mm =3D mm;
flush_va =3D va;
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ atomic_set_mask(ipi_mask, &flush_cpumask);
+#else
atomic_set_mask(cpumask, &flush_cpumask);
+#endif
/*
* We have to send the IPI only to
* CPUs affected.
*/
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ send_IPI_mask(ipi_mask, INVALIDATE_TLB_VECTOR);
+#else
send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+#endif
=20
while (flush_cpumask)
/* nothing. lockup detection does not belong here */;
@@ -409,6 +441,13 @@
=20
do_flush_tlb_all_local();
}
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+void dump_send_ipi(void)
+{
+ send_IPI_allbutself(DUMP_VECTOR);
+}
+#endif
+
=20
/*
* this function sends a 'reschedule' IPI to another CPU.
@@ -418,7 +457,15 @@
=20
void smp_send_reschedule(int cpu)
{
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ /* only do this for on-line CPUs */
+ unsigned long cpumask =3D (1 << cpu) & cpu_online_map;
+ if (cpumask) {
+ send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR);
+ }
+#else
send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR);
+#endif
}
=20
/*
@@ -477,8 +524,26 @@
send_IPI_allbutself(CALL_FUNCTION_VECTOR);
=20
/* Wait for response */
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ if (dump_in_progress) {
+ int i =3D 1 * 1000; /* milliseconds to delay waiting =
for other CPU to star
+t IPI processing (1 second) */
+ while (atomic_read(&data.started) !=3D cpus && i--) {
+ mdelay(1);
+ barrier();
+ }
+ if (i <=3D 0) {
+ spin_unlock_bh(&call_lock);
+ return -ETIMEDOUT;
+ }
+ } else {
+ while (atomic_read(&data.started) !=3D cpus)
+ barrier();
+ }
+#else
while (atomic_read(&data.started) !=3D cpus)
barrier();
+#endif
=20
if (wait)
while (atomic_read(&data.finished) !=3D cpus)
diff -Naur linux-2.4.21_lkcd/arch/x86_64/kernel/traps.c =
lkcd_linux_x86_64/arch/x86_64/kernel/traps.c
--- linux-2.4.21_lkcd/arch/x86_64/kernel/traps.c 2003-06-13 =
20:21:32.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/kernel/traps.c 2004-07-01 =
21:17:26.000000000 +0530
@@ -22,6 +22,10 @@
#include <linux/ptrace.h>
#include <linux/timer.h>
#include <linux/mm.h>
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+#include <linux/dump.h>
+#endif
+
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
@@ -83,6 +87,26 @@
=20
int kstack_depth_to_print =3D 40;
=20
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+#ifdef CONFIG_SMP
+void (*dump_trace_ptr)(struct pt_regs *) =3D NULL;
+/*
+ * This code mimics show_trace() etc in arch/i386/kernel/traps.c. We =
don't
+ * use them directly as they depend on 8K aligned kernel stacks that =
our
+ * saved stacks don't satisfy. However, there is move to relax the =
requirement
+ * on task_struct to be 8K-aligned. Once that happens, we could simpify =
this
+ * function.
+ */
+void show_this_cpu_state(int cpu, struct pt_regs * regs, struct =
task_struct *tsk)
+{
+//not implemented yet
+ return;
+}
+#endif /* CONFIG_SMP */
+#endif /* CONFIG_DUMP */
+
+
+
#ifdef CONFIG_KALLSYMS
#include <linux/kallsyms.h>=20
int printk_address(unsigned long address)
@@ -363,6 +387,10 @@
show_registers(regs);
bust_spinlocks(0);
spin_unlock_irq(&die_lock);
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ dump((char *)str, regs);
+#endif
+
do_exit(SIGSEGV);
}
=20
@@ -531,6 +559,22 @@
reason &=3D ~8;
outb(reason, 0x61);
}
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+#ifdef CONFIG_SMP
+int (*dump_ipi_function_ptr)(struct pt_regs *) =3D NULL;
+static int dump_ipi(struct pt_regs *regs)
+{
+ if (!(dump_ipi_function_ptr && dump_ipi_function_ptr(regs))) {
+ return 0;
+ }
+ ack_APIC_irq();
+ return 1;
+}
+#else
+#define dump_ipi(regs) 0
+#endif
+#endif
+
=20
static void unknown_nmi_error(unsigned char reason, struct pt_regs * =
regs)
{
@@ -544,6 +588,11 @@
unsigned char reason =3D inb(0x61);
=20
++nmi_count(safe_smp_processor_id());
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ if (dump_ipi(regs)) {
+ return;
+ }
+#endif
=09
if (!(reason & 0xc0)) {
#if CONFIG_X86_LOCAL_APIC
diff -Naur linux-2.4.21_lkcd/arch/x86_64/kernel/x8664_ksyms.c =
lkcd_linux_x86_64/arch/x86_64/kernel/x8664_ksyms.c
--- linux-2.4.21_lkcd/arch/x86_64/kernel/x8664_ksyms.c 2003-06-13 =
20:21:32.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/kernel/x8664_ksyms.c 2004-07-01 =
20:45:36.000000000 +0530
@@ -223,3 +223,30 @@
=20
extern void int_ret_from_sys_call(void);
EXPORT_SYMBOL(int_ret_from_sys_call);=20
+
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+extern void dump (char *, struct pt_regs *);
+EXPORT(dump);=20
+extern void get_current_regs( struct pt_regs *);
+EXPORT(get_current_regs);
+extern int (*dump_function_ptr)(char *, struct pt_regs *);
+EXPORT(dump_function_ptr);
+#ifdef CONFIG_SMP
+extern irq_desc_t irq_desc[];
+extern unsigned long irq_affinity[];
+EXPORT_SYMBOL(irq_affinity);
+EXPORT_SYMBOL(irq_desc);
+extern void dump_send_ipi(void);
+EXPORT_SYMBOL(dump_send_ipi);
+extern int (*dump_ipi_function_ptr)(struct pt_regs *);
+EXPORT_SYMBOL(dump_ipi_function_ptr);
+extern void (*dump_trace_ptr)(struct pt_regs *);
+EXPORT_SYMBOL(dump_trace_ptr);
+extern void show_this_cpu_state(int, struct pt_regs *, struct =
task_struct *);
+EXPORT_SYMBOL(show_this_cpu_state);
+#endif
+#ifdef CONFIG_HIGHMEM
+EXPORT_SYMBOL(kmap_prot);
+EXPORT_SYMBOL(kmap_pte);
+#endif
+#endif
diff -Naur linux-2.4.21_lkcd/arch/x86_64/mm/init.c =
lkcd_linux_x86_64/arch/x86_64/mm/init.c
--- linux-2.4.21_lkcd/arch/x86_64/mm/init.c 2003-06-13 =
20:21:32.000000000 +0530
+++ lkcd_linux_x86_64/arch/x86_64/mm/init.c 2004-07-01 =
20:46:11.000000000 +0530
@@ -338,7 +338,11 @@
free_area_init(zones_size);
}
=20
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+int page_is_ram (unsigned long pagenr)
+#else
static inline int page_is_ram (unsigned long pagenr)
+#endif
{
int i;
=20
diff -Naur linux-2.4.21_lkcd/drivers/dump/dump_x86_64.c =
lkcd_linux_x86_64/drivers/dump/dump_x86_64.c
--- linux-2.4.21_lkcd/drivers/dump/dump_x86_64.c 1970-01-01 =
05:30:00.000000000 +0530
+++ lkcd_linux_x86_64/drivers/dump/dump_x86_64.c 2004-07-02 =
20:59:48.000000000 +0530
@@ -0,0 +1,295 @@
+/*
+ * Architecture specific (x86_64) functions for Linux crash dumps.
+ *
+ * Created by: Matt Robinson ([email protected])
+ *
+ * modified for x86_64 by: Sanjay Kumar =
([email protected])
+ *
+ * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
+ *
+ * 2.3 kernel modifications by: Matt D. Robinson =
([email protected])
+ * Copyright 2000 TurboLinux, Inc. All rights reserved.
+ *=20
+ * This code is released under version 2 of the GNU GPL.
+ */
+
+/*
+ * The hooks for dumping the kernel virtual memory to disk are in this
+ * file. Any time a modification is made to the virtual memory =
mechanism,
+ * these routines must be changed to use the new mechanisms.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/dump.h>
+#include <linux/mm.h>
+#include <asm/processor.h>
+#include <asm/hardirq.h>
+#include <linux/irq.h>
+
+static int alloc_dha_stack(void)
+{
+ int i;
+ void *ptr;
+=09
+ if (dump_header_asm.dha_stack[0])
+ return 0;
+
+ ptr =3D vmalloc(THREAD_SIZE * smp_num_cpus);
+ if (!ptr) {
+ printk("vmalloc for dha_stacks failed\n");
+ return -ENOMEM;
+ }
+
+ for (i =3D 0; i < smp_num_cpus; i++) {
+ dump_header_asm.dha_stack[i] =3D (uint64_t)((unsigned long)ptr + (i * =
THREAD_SIZE));
+ }
+ return 0;
+}
+
+static int free_dha_stack(void)=20
+{
+ if (dump_header_asm.dha_stack[0])
+ vfree((void*)dump_header_asm.dha_stack[0]);=09
+ return 0;
+}
+
+static void
+save_this_cpu_state(int cpu, struct pt_regs *regs, struct task_struct =
*tsk)
+{
+ dump_header_asm.dha_smp_regs[cpu] =3D *regs;
+ dump_header_asm.dha_smp_current_task[cpu] =3D (uint64_t) tsk;
+
+ if (dump_header_asm.dha_stack[cpu]) {
+ memcpy((void*)dump_header_asm.dha_stack[cpu], tsk, THREAD_SIZE);
+ }
+ return;
+}
+
+#ifdef CONFIG_SMP
+static int dump_expect_ipi[NR_CPUS];
+static atomic_t waiting_for_dump_ipi;
+static int wait_for_dump_ipi =3D 1; /* always wait for ipi to to be =
handled */
+extern void (*dump_trace_ptr)(struct pt_regs *);
+static unsigned long saved_affinity[NR_IRQS];
+
+static int
+dump_ipi_handler(struct pt_regs *regs)=20
+{
+ int cpu =3D smp_processor_id();
+
+ if (!dump_expect_ipi[cpu]) {
+ return 0;
+ }
+=09
+ save_this_cpu_state(cpu, regs, current);
+
+ dump_expect_ipi[cpu] =3D 0;
+ atomic_dec(&waiting_for_dump_ipi);
+ return 1;
+}
+
+/* save registers on other processors */
+void=20
+save_other_cpu_states(void)
+{
+ int i;
+
+ if (smp_num_cpus > 1) {
+ atomic_set(&waiting_for_dump_ipi, smp_num_cpus-1);
+ for (i =3D 0; i < NR_CPUS; i++)
+ dump_expect_ipi[i] =3D 1;
+ =09
+ dump_ipi_function_ptr =3D dump_ipi_handler;
+ dump_send_ipi();
+ /* may be we dont need to wait for NMI to be processed.=20
+ just write out the header at the end of dumping, if
+ this IPI is not processed untill then, there probably
+ is a problem and we just fail to capture state of=20
+ other cpus. */
+ if (wait_for_dump_ipi) {
+ while(atomic_read(&waiting_for_dump_ipi))
+ barrier();
+ dump_ipi_function_ptr =3D NULL;
+ }
+ }
+ return;
+}
+
+/* located in arch/i386/kernel/traps.c */
+extern void show_this_cpu_state(int cpu, struct pt_regs * regs, struct =
task_struct *tsk);
+
+void=20
+show_cpu_state(struct pt_regs * regs)
+{
+ int i;
+ __dump_configure_header(regs);=09
+ for (i =3D 0; i < smp_num_cpus; i++) {
+ show_this_cpu_state(i, &dump_header_asm.dha_smp_regs[i],=20
+ (void*)dump_header_asm.dha_stack[i]);
+ }
+ return;
+}
+
+/*
+ * Non dumping cpus will spin here. If a cpu is handling an irq when =
ipi is
+ * received, we let go of it here while making sure that it hits =
schedule
+ * on the way up and make it spin there instead.
+ */
+static void
+__dump_spin(void *arg)
+{
+ if (in_irq()) {
+ current->need_resched =3D 1;
+ } else {
+ while (dump_in_progress) ;
+ }
+ return;
+}
+
+/*
+ * Routine to save the old irq affinities and change affinities of all =
irqs to
+ * the dumping cpu.
+ */
+static void
+__dump_set_irq_affinity(void)
+{
+ int i;
+ int cpu =3D smp_processor_id();
+
+ memcpy(saved_affinity, irq_affinity, NR_IRQS * sizeof(unsigned long));
+ for (i =3D 0; i < NR_IRQS; i++) {
+ if (irq_desc[i].handler =3D=3D NULL)
+ continue;
+ irq_affinity[i] =3D 1UL << cpu;
+ if (irq_desc[i].handler->set_affinity !=3D NULL)
+ irq_desc[i].handler->set_affinity(i, irq_affinity[i]);
+ }
+}
+
+/*
+ * Restore old irq affinities.
+ */
+static void
+__dump_reset_irq_affinity(void)
+{
+ int i;
+
+ memcpy(irq_affinity, saved_affinity, NR_IRQS * sizeof(unsigned long));
+ for (i =3D 0; i < NR_IRQS; i++) {
+ if (irq_desc[i].handler =3D=3D NULL)
+ continue;
+ if (irq_desc[i].handler->set_affinity !=3D NULL)
+ irq_desc[i].handler->set_affinity(i, saved_affinity[i]);
+ }
+}
+
+#else /* !CONFIG_SMP */
+#define save_other_cpu_states()
+#endif /* !CONFIG_SMP */
+
+/*
+ * Name: __dump_silence_system()
+ * Func: Do an architecture-specific silencing of the system.
+ * - Change irq affinities
+ * - Wait for other cpus to come out of irq handling
+ * - Send CALL_FUNCTION_VECTOR ipi to other cpus to put them to =
spin
+ */
+unsigned int
+__dump_silence_system(unsigned int stage)
+{
+#ifdef CONFIG_SMP
+ if (stage) { /* Do this after interrupts are enabled */
+ /* read the comments above ... */
+ __dump_set_irq_affinity();
+ synchronize_irq();
+ smp_call_function(__dump_spin, NULL, 0, 0);
+ }
+#endif
+
+ /* return */
+ return (0);
+}
+
+/*
+ * Name: __dump_resume_system()
+ * Func: Resume the system state in an architecture-specific way.
+ */
+unsigned int
+__dump_resume_system(unsigned int stage)
+{
+#ifdef CONFIG_SMP
+ /* put the irq affinity tables back */
+ __dump_reset_irq_affinity();
+#endif
+
+ /* return */
+ return (0);
+}
+
+/*
+ * Name: __dump_configure_header()
+ * Func: Configure the dump header with all proper values.
+ */
+int
+__dump_configure_header(struct pt_regs *regs)
+{
+ int cpu =3D smp_processor_id();
+
+ dump_header_asm.dha_smp_num_cpus =3D smp_num_cpus;
+ dump_header_asm.dha_dumping_cpu =3D cpu;
+
+ save_this_cpu_state(cpu, regs, current);
+
+ save_other_cpu_states();
+
+ return (1);
+}
+
+/*
+ * Name: __dump_init()
+ * Func: Initialize the dumping routine process. This is in case
+ * it's necessary in the future.
+ */
+void
+__dump_init(uint64_t local_memory_start)
+{
+ /* return */
+ return;
+}
+
+/*
+ * Name: __dump_open()
+ * Func: Open the dump device (architecture specific). This is in
+ * case it's necessary in the future.
+ */
+void
+__dump_open(void)
+{
+ alloc_dha_stack();
+#ifdef CONFIG_SMP=09
+ dump_trace_ptr =3D show_cpu_state;
+#endif
+ /* return */
+ return;
+}
+
+/*
+ * Name: __dump_cleanup()
+ * Func: Free any architecture specific data structures. This is called
+ * when the dump module is being removed.
+ */
+void
+__dump_cleanup(void)
+{
+ free_dha_stack();
+#ifdef CONFIG_SMP
+ dump_trace_ptr =3D NULL;
+#endif
+ /* return */
+ return;
+}
+
diff -Naur linux-2.4.21_lkcd/drivers/dump/Makefile =
lkcd_linux_x86_64/drivers/dump/Makefile
--- linux-2.4.21_lkcd/drivers/dump/Makefile 2004-06-04 =
10:54:44.000000000 +0530
+++ lkcd_linux_x86_64/drivers/dump/Makefile 2004-07-01 =
20:49:02.000000000 +0530
@@ -22,6 +22,10 @@
dump-objs +=3D dump_i386.o
endif
=20
+ifeq ($(ARCH),x86_64)
+ dump-objs +=3D dump_x86_64.o
+endif
+
ifeq ($(ARCH),alpha)
dump-objs +=3D dump_alpha.o
endif
diff -Naur linux-2.4.21_lkcd/include/asm-x86_64/dump.h =
lkcd_linux_x86_64/include/asm-x86_64/dump.h
--- linux-2.4.21_lkcd/include/asm-x86_64/dump.h 1970-01-01 =
05:30:00.000000000 +0530
+++ lkcd_linux_x86_64/include/asm-x86_64/dump.h 2004-07-02 =
21:01:28.000000000 +0530
@@ -0,0 +1,98 @@
+/*
+ * Kernel header file for Linux crash dumps.
+ *
+ * Created by: Matt Robinson ([email protected])
+ *=20
+ * modified for x86_64 by: Sanjay Kumar =
([email protected])
+ *
+ * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
+ *
+ * This code is released under version 2 of the GNU GPL.
+ */
+
+/* This header file holds the architecture specific crash dump header =
*/
+#ifndef _ASM_DUMP_H
+#define _ASM_DUMP_H
+
+/* necessary header files */
+#include <asm/ptrace.h> /* for pt_regs =
*/
+#include <linux/threads.h>
+
+/* definitions */
+#define DUMP_ASM_MAGIC_NUMBER 0xdeaddeadULL /* magic number =
*/
+#define DUMP_ASM_VERSION_NUMBER 0x3 /* version number =
*/
+
+/* max number of cpus */
+#define DUMP_MAX_NUM_CPUS 32
+
+/*
+ * Structure: dump_header_asm_t
+ * Function: This is the header for architecture-specific stuff. It
+ * follows right after the dump header.
+ */
+typedef struct _dump_header_asm_s {
+
+ /* the dump magic number -- unique to verify dump is valid */
+ uint64_t dha_magic_number;
+
+ /* the version number of this dump */
+ uint32_t dha_version;
+
+ /* the size of this header (in case we can't read it) */
+ uint32_t dha_header_size;
+
+ /* the esp for i386 systems */
+ uint32_t dha_esp;
+
+ /* the eip for i386 systems */
+ uint32_t dha_eip;
+
+ /* the dump registers */
+ struct pt_regs dha_regs;
+
+ /* smp specific */
+ uint32_t dha_smp_num_cpus;
+ uint32_t dha_dumping_cpu;=09
+ struct pt_regs dha_smp_regs[DUMP_MAX_NUM_CPUS];
+ uint64_t dha_smp_current_task[DUMP_MAX_NUM_CPUS];
+ uint64_t dha_stack[DUMP_MAX_NUM_CPUS];
+} __attribute__((packed)) dump_header_asm_t;
+
+#ifdef __KERNEL__
+static inline void get_current_regs(struct pt_regs *regs)
+{
+ asm("movq %%r15, %0": "=3Dr" (regs->r15));
+ asm("movq %%r14, %0": "=3Dr" (regs->r14));
+ asm("movq %%r13, %0": "=3Dr" (regs->r13));
+ asm("movq %%r12, %0": "=3Dr" (regs->r12));
+ asm("movq %%rbp, %0": "=3Dr" (regs->rbp));
+ asm("movq %%rbx, %0": "=3Dr" (regs->rbx));
+ asm("movq %%r11, %0": "=3Dr" (regs->r11));
+ asm("movq %%r10, %0": "=3Dr" (regs->r10));
+ asm("movq %%r9, %0": "=3Dr" (regs->r9));
+ asm("movq %%r8, %0": "=3Dr" (regs->r8));
+ asm("movq %%rax, %0": "=3Dr" (regs->rax));
+ asm("movq %%rcx, %0": "=3Dr" (regs->rcx));
+ asm("movq %%rdx, %0": "=3Dr" (regs->rdx));
+ asm("movq %%rsi, %0": "=3Dr" (regs->rsi));
+ asm("movq %%rdi, %0": "=3Dr" (regs->rdi));
+ asm("movl %%cs, %0": "=3Dm" (regs->cs));
+ asm("movq %%rsp, %0": "=3Dr" (regs->rsp));
+ asm("movl %%ss, %0": "=3Dm" (regs->ss));
+ asm("pushf; pop %0" :"=3Dm"(regs->eflags));
+ regs->rip =3D (unsigned long)current_text_addr();
+}
+
+extern volatile int dump_in_progress;
+extern unsigned long irq_affinity[];
+extern dump_header_asm_t dump_header_asm;
+
+#ifdef CONFIG_SMP
+extern int (*dump_ipi_function_ptr)(struct pt_regs *);
+extern void dump_send_ipi(void);
+#else
+#define dump_send_ipi()
+#endif
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_DUMP_H */
diff -Naur linux-2.4.21_lkcd/include/asm-x86_64/hw_irq.h =
lkcd_linux_x86_64/include/asm-x86_64/hw_irq.h
--- linux-2.4.21_lkcd/include/asm-x86_64/hw_irq.h 2003-06-13 =
20:21:38.000000000 +0530
+++ lkcd_linux_x86_64/include/asm-x86_64/hw_irq.h 2004-07-01 =
20:50:45.000000000 +0530
@@ -52,6 +52,9 @@
#define RESCHEDULE_VECTOR 0xfc
/* 0xfa free */
#define CALL_FUNCTION_VECTOR 0xfb
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+#define DUMP_VECTOR 0xfa
+#endif
=20
/*
* Local APIC timer IRQ vector is on a different priority level,
diff -Naur linux-2.4.21_lkcd/Makefile lkcd_linux_x86_64/Makefile
--- linux-2.4.21_lkcd/Makefile 2004-06-04 10:54:45.000000000 +0530
+++ lkcd_linux_x86_64/Makefile 2004-07-01 21:32:06.000000000 +0530
@@ -190,6 +190,7 @@
DRIVERS-$(CONFIG_BLUEZ) +=3D drivers/bluetooth/bluetooth.o
DRIVERS-$(CONFIG_HOTPLUG_PCI) +=3D drivers/hotplug/vmlinux-obj.o
DRIVERS-$(CONFIG_ISDN_BOOL) +=3D drivers/isdn/vmlinux-obj.o
+DRIVERS-$(CONFIG_DUMP) +=3D drivers/dump/dump.o
=20
DRIVERS :=3D $(DRIVERS-y)
=20
-------------------------------------------------------
This SF.Net email sponsored by Black Hat Briefings & Training.
Attend Black Hat Briefings & Training, Las Vegas July 24-29 -
digital self defense, top technical experts, no vendor pitches,
unmatched networking opportunities. Visit www.blackhat.com