[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