diff -uNr linux.orig/Documentation/Configure.help linux/Documentation/Configure.help
--- linux.orig/Documentation/Configure.help	Mon Apr  5 15:02:37 2004
+++ linux/Documentation/Configure.help	Mon Apr  5 15:07:55 2004
@@ -20789,6 +20789,90 @@
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
+Kernel Debugging support
+CONFIG_KDB
+  This option provides a built-in kernel debugger.  The built-in
+  kernel debugger contains commands which allow memory to be examined,
+  instructions to be disassembled and breakpoints to be set.  For details,
+  see Documentation/kdb/kdb.mm and the manual pages kdb_bt, kdb_ss, etc.
+  Kdb can also be used via the serial port.  Set up the system to
+  have a serial console (see Documentation/serial-console.txt).
+  The Control-A key sequence on the serial port will cause the
+  kernel debugger to be entered with input from the serial port and
+  output to the serial console.  Selecting this option will
+  automatically set CONFIG_KALLSYMS. If unsure, say N.
+
+KDB modules
+CONFIG_KDB_MODULES
+  KDB can be extended by adding your own modules, in directory
+  kdb/modules.  This option selects the way that these modules should
+  be compiled, as free standing modules (select M) or built into the
+  kernel (select Y).  If unsure say M.
+
+KDB off by default
+CONFIG_KDB_OFF
+  Normally kdb is activated by default, as long as CONFIG_KDB is set.
+  If you want to ship a kernel with kdb support but only have kdb
+  turned on when the user requests it then select this option.  When
+  compiled with CONFIG_KDB_OFF, kdb ignores all events unless you boot
+  with kdb=on or you echo "1" > /proc/sys/kernel/kdb.  This option also
+  works in reverse, if kdb is normally activated, you can boot with
+  kdb=off or echo "0" > /proc/sys/kernel/kdb to deactivate kdb. If
+  unsure, say N.
+
+KDB continues after catastrophic errors
+CONFIG_KDB_CONTINUE_CATASTROPHIC
+  This integer controls the behaviour of kdb when the kernel gets a
+  catastrophic error, i.e. for a panic, oops, NMI or other watchdog
+  tripping.  CONFIG_KDB_CONTINUE_CATASTROPHIC interacts with
+  /proc/sys/kernel/kdb and CONFIG_DUMP (if your kernel has the LKCD
+  patch).
+
+  When KDB is active (/proc/sys/kernel/kdb == 1) and a catastrophic
+  error occurs, nothing extra happens until you type 'go'.
+
+    CONFIG_KDB_CONTINUE_CATASTROPHIC == 0 (default).  The first time
+    you type 'go', kdb warns you.  The second time you type 'go', KDB
+    tries to continue - no guarantees that the kernel is still usable.
+
+    CONFIG_KDB_CONTINUE_CATASTROPHIC == 1.  KDB tries to continue - no
+    guarantees that the kernel is still usable.
+
+    CONFIG_KDB_CONTINUE_CATASTROPHIC == 2.  If your kernel has the LKCD
+    patch and LKCD is configured to take a dump then KDB forces a dump.
+    Whether or not a dump is taken, KDB forces a reboot.
+
+  When KDB is not active (/proc/sys/kernel/kdb == 0) and a catastrophic
+  error occurs, the following steps are automatic, no human
+  intervention is required.
+
+    CONFIG_KDB_CONTINUE_CATASTROPHIC == 0 (default) or 1.  KDB attempts
+    to continue - no guarantees that the kernel is still usable.
+
+    CONFIG_KDB_CONTINUE_CATASTROPHIC == 2.  If your kernel has the LKCD
+    patch and LKCD is configured to take a dump then KDB automatically
+    forces a dump.  Whether or not a dump is taken, KDB forces a
+    reboot.
+
+  If you are not sure, say 0.  Read Documentation/kdb/dump.txt before
+  setting to 2.
+
+Support for USB Keyboard in KDB
+CONFIG_KDB_USB
+  If you want to use kdb from a USB keyboard then say Y here.  If you
+  say N then kdb can only be used from a PC (AT) keyboard or a serial
+  console.
+
+Load all symbols for debugging
+CONFIG_KALLSYMS
+  Normally only exported symbols are available to modules. For
+  debugging you may want all symbols, not just the exported ones. If
+  you say Y here then extra data is added to the kernel and modules,
+  this data lists all the non-stack symbols in the kernel or module
+  and can be used by any debugger.  You need modutils >= 2.3.11 to use
+  this option. See "man kallsyms" for the data format, it adds 10-20%
+  to the size of the kernel and the loaded modules. If unsure, say N.
+
 ISDN support
 CONFIG_ISDN
   ISDN ("Integrated Services Digital Networks", called RNIS in France)
diff -uNr linux.orig/Documentation/kdb/dump.txt linux/Documentation/kdb/dump.txt
--- linux.orig/Documentation/kdb/dump.txt	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/dump.txt	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,364 @@
+Interaction between KDB and LKCD.
+
+Executive summary: Do not select CONFIG_KDB_CONTINUE_CATASTROPHIC=2 or
+use KDB command 'sr c' without first patching LKCD to use KDB data.
+
+Both KDB and LKCD try to stop all the other cpus, so the system is not
+changing while it is being debugged or dumped.  KDB will cope with cpus
+that cannot be stopped, some versions of LKCD will just hang.  In
+particular, when LKCD is invoked from KDB, LKCD will attempt to stop
+the other cpus again and may hang.
+
+Some versions of LKCD detect that other cpus are not responding and
+ignore them.  This is almost as bad, the data is changing while it is
+being dumped.  Also the method used to avoid hung cpus has been known
+to cause oops when LKCD has finished dumping.
+
+LKCD does not know about several special cases on IA64, including INIT
+and MCA backtraces, interrupt handlers, out of line code etc.  LKCD
+cannot capture cpu state on any cpu that is not responding to OS
+interrupts, which means that any cpu that is spinning in a disabled
+loop cannot be debugged.  Any cpu that calls into SAL for MCA
+rendezvous cannot be debugged.  Even when LKCD captures IA64 state, the
+user space lcrash code cannot unwind through any assembler code, which
+rules out all the interesting cases.
+
+KDB knows far more than LKCD about architecture peculiarities, stack
+formats, interrupt handling etc.  The methods used by KDB to stop the
+other processors and capture their state are far more reliable than
+those used by LKCD.  KDB can capture INIT and MCA data on IA64, as well
+as save the state of cpus before they enter SAL.
+
+Rather than duplicating the complex KDB code in LKCD, LKCD can be
+patched to use the information that has already been captured by KDB.
+Obviously this only works when LKCD is invoked from KDB.  If you invoke
+LKCD directly from the console with SysRq-c or the dump() function is
+called from code outside KDB then you get the old and broken LKCD
+processing.  Because lcrash uses the old unwind algorithm which cannot
+unwind through IA64 assembler code, KDB kludges the saved state into
+something that the old unwind algorithm can cope with.  Calling LKCD
+from KDB gives you a clean dump, but you have to patch LKCD first.
+
+There are two ways to invoke LKCD from KDB.  One way is manual, using
+the KDB 'sr c' command.  This is identical to doing SysRq-C from the
+console except that it goes through KDB first, so LKCD can use the data
+that KDB has captured.  Obviously 'sr c' requires human intervention
+and KDB must be on, it is up to the person doing the debugging if they
+want to take a dump.
+
+The second way is to set CONFIG_KDB_CONTINUE_CATASTROPHIC=2.  With this
+setting, you automatically get a dump for catastrophic errors.  A
+catastrophic error is a panic, oops, NMI or other watchdog tripping,
+INIT and MCA events on IA64.  CONFIG_KDB_CONTINUE_CATASTROPHIC=2 has no
+effect on debugging events such as break points, single step etc. so it
+does not interfere with manual debugging.
+
+When CONFIG_KDB_CONTINUE_CATASTROPHIC=2 and KDB is on, a catastrophic
+error will drop into KDB to allow manual debugging, typing 'go' will
+take a dump and force a reboot.  With this setting and KDB is off, KDB
+detects a catastrophic error, does enough processing to capture the
+state, takes a dump and forces a reboot - all automatic with no human
+intervention.
+
+For unattended and clean LKCD dumps, patch LKCD to use KDB data.  Use
+  CONFIG_DUMP=y
+  CONFIG_KDB=y
+  CONFIG_KDB_OFF=y
+  CONFIG_KDB_CONTINUE_CATASTROPHIC=2
+
+If you want human intervention before taking a dump, use
+  CONFIG_DUMP=y
+  CONFIG_KDB=y
+  CONFIG_KDB_OFF=n
+  CONFIG_KDB_CONTINUE_CATASTROPHIC=2
+
+
+The following are indicative patches against lkcd 4.1, kernel 2.4.20.
+You may have to to modify the patches for other kernels or other
+versions of lkcd.
+
+diff -urp lkcd/drivers/dump/dump_base.c lkcd/drivers/dump/dump_base.c
+--- lkcd/drivers/dump/dump_base.c	Thu May  1 13:10:12 2003
++++ lkcd/drivers/dump/dump_base.c	Fri Jun 20 12:28:16 2003
+@@ -207,6 +207,9 @@
+ #include <asm/hardirq.h>
+ #include <linux/version.h>
+ #include <asm/system.h>
++#ifdef	CONFIG_KDB
++#include <linux/kdb.h>
++#endif
+ 
+ /*
+  * -----------------------------------------------------------------------
+@@ -852,6 +855,13 @@ dump_silence_system(void)
+ 	unsigned int stage = 0;
+ 	int cpu = smp_processor_id();
+ 
++#ifdef	CONFIG_KDB
++	if (KDB_IS_RUNNING()) {
++		/* kdb is in control, the system is already silenced */
++		printk(KERN_ALERT "LKCD entered from KDB\n");
++	}
++#endif	/* CONFIG_KDB */
++
+ 	if (in_interrupt()) {
+ 		printk(KERN_ALERT "Dumping from interrupt handler !\n");
+ 		printk(KERN_ALERT "Uncertain scenario - but will try my best\n");
+@@ -861,6 +871,9 @@ dump_silence_system(void)
+ 		 * another approach 
+ 		 */
+ 	}
+ 	/* see if there's something to do before we re-enable interrupts */
++#ifdef	CONFIG_KDB
++	if (!KDB_IS_RUNNING())
++#endif	/* CONFIG_KDB */
+ 	(void)__dump_silence_system(stage);
+ 
+@@ -905,6 +918,9 @@ dump_silence_system(void)
+ 
+ 	/* now increment the stage and do stuff after interrupts are enabled */
+ 	stage++;
++#ifdef	CONFIG_KDB
++	if (!KDB_IS_RUNNING())
++#endif	/* CONFIG_KDB */
+ 	(void)__dump_silence_system(stage);
+ 
+ 	/* time to leave */
+diff -urp lkcd/drivers/dump/dump_i386.c lkcd/drivers/dump/dump_i386.c
+--- lkcd/drivers/dump/dump_i386.c	Tue Jul  9 07:14:11 2002
++++ lkcd/drivers/dump/dump_i386.c	Fri Jun 20 12:29:12 2003
+@@ -27,6 +27,10 @@
+ #include <asm/processor.h>
+ #include <asm/hardirq.h>
+ #include <linux/irq.h>
++#ifdef	CONFIG_KDB
++#include <linux/kdb.h>
++#include <linux/kdbprivate.h>
++#endif	/* CONFIG_KDB */
+ 
+ static int alloc_dha_stack(void)
+ {
+@@ -119,6 +123,31 @@ save_other_cpu_states(void)
+ {
+ 	int i;
+ 
++#ifdef	CONFIG_KDB
++	if (KDB_IS_RUNNING()) {
++		/* invoked from kdb, which has already saved all the state */
++		int cpu;
++		struct kdb_running_process *krp;
++		for (cpu = 0, krp = kdb_running_process; cpu < smp_num_cpus; ++cpu, ++krp) {
++			if (krp->seqno < kdb_seqno - 1 ||
++			    !krp->regs ||
++			    !krp->p ||
++			    kdb_process_cpu(krp->p) != cpu) {
++				printk(KERN_WARNING "No KDB data for cpu %d, it will not be in the LKCD dump\n", cpu);
++				continue;
++			}
++			if (cpu == smp_processor_id())
++				continue;	/* dumped by save_this_cpu_state */
++			// kdb_printf("%s: cpu %d task %p regs %p\n", __FUNCTION__, cpu, krp->p, krp->regs);
++			save_this_cpu_state(cpu, krp->regs, krp->p);
++		}
++		return;
++	}
++	printk(KERN_WARNING "This kernel supports KDB but LKCD was invoked directly, not via KDB.\n");
++	printk(KERN_WARNING "Falling back to the old and broken LKCD method of getting data from all cpus,\n");
++	printk(KERN_WARNING "do not be surprised if LKCD hangs.\n");
++#endif	/* CONFIG_KDB */
++
+ 	if (smp_num_cpus > 1) {
+ 		atomic_set(&waiting_for_dump_ipi, smp_num_cpus-1);
+ 		for (i = 0; i < NR_CPUS; i++)
+diff -urp lkcd/drivers/dump/dump_ia64.c lkcd/drivers/dump/dump_ia64.c
+--- lkcd/drivers/dump/dump_ia64.c	Tue Jul  9 07:14:11 2002
++++ lkcd/drivers/dump/dump_ia64.c	Fri Jun 20 12:31:41 2003
+@@ -30,6 +30,10 @@
+ #include <asm/processor.h>
+ #include <asm/hardirq.h>
+ #include <linux/irq.h>
++#ifdef	CONFIG_KDB
++#include <linux/kdb.h>
++#include <linux/kdbprivate.h>
++#endif	/* CONFIG_KDB */
+ 
+ extern unsigned long irq_affinity[];
+ 
+@@ -75,6 +79,12 @@ save_this_cpu_state(int cpu, struct pt_r
+ 
+ 	if (tsk && dump_header_asm.dha_stack[cpu]) {
+ 		memcpy((void*)dump_header_asm.dha_stack[cpu], tsk, THREAD_SIZE);
++#ifdef	CONFIG_KDB
++		if (KDB_IS_RUNNING()) {
++			static void kludge_for_broken_lcrash(int);
++			kludge_for_broken_lcrash(cpu);
++		}
++#endif	/* CONFIG_KDB */
+ 	}
+ 	return;
+ }
+@@ -107,6 +117,32 @@ save_other_cpu_states(void)
+ {
+ 	int i;
+ 
++#ifdef	CONFIG_KDB
++	if (KDB_IS_RUNNING()) {
++		/* invoked from kdb, which has already saved all the state */
++		int cpu;
++		struct kdb_running_process *krp;
++		for (cpu = 0, krp = kdb_running_process; cpu < smp_num_cpus; ++cpu, ++krp) {
++			if (krp->seqno < kdb_seqno - 1 ||
++			    !krp->regs ||
++			    !krp->arch.sw ||
++			    !krp->p ||
++			    kdb_process_cpu(krp->p) != cpu) {
++				printk(KERN_WARNING "No KDB data for cpu %d, it will not be in the LKCD dump\n", cpu);
++				continue;
++			}
++			if (cpu == smp_processor_id())
++				continue;	/* dumped by save_this_cpu_state */
++			// kdb_printf("%s: cpu %d task %p regs %p\n", __FUNCTION__, cpu, krp->p, krp->regs);
++			save_this_cpu_state(cpu, krp->regs, krp->p);
++		}
++		return;
++	}
++	printk(KERN_WARNING "This kernel supports KDB but LKCD was invoked directly, not via KDB.\n");
++	printk(KERN_WARNING "Falling back to the old and broken LKCD method of getting data from all cpus,\n");
++	printk(KERN_WARNING "do not be surprised if LKCD hangs.\n");
++#endif	/* CONFIG_KDB */
++
+ 	if (smp_num_cpus > 1) {
+ 		atomic_set(&waiting_for_dump_ipi, smp_num_cpus-1);
+ 		for (i = 0; i < NR_CPUS; i++)
+@@ -380,3 +416,131 @@ void * __dump_memcpy(void * dest, const 
+ 	}
+ 	return(vp);
+ }
++
++#ifdef	CONFIG_KDB
++/*
++ * lcrash is broken.  It incorrectly assumes that all tasks are blocked, it
++ * assumes that all code is built by gcc (and therefore it cannot unwind through
++ * assembler code), it assumes that there is only one pt_regs at the base of the
++ * stack (where user space entered the kernel).  Dumping from kdb (or any
++ * interrupt context) breaks all those assumptions, resulting in a good dump
++ * that lcrash cannot get any useful backtraces from.
++ *
++ * The real fix is to correct lcrash, using libunwind.  That is not going to
++ * happen any time soon, so this kludge takes the kdb data and reformats it to
++ * suit the broken lcrash code.  The task state is unwound past the interrupt
++ * frame (pt_regs) before kdb, then a switch_stack is synthesized in place of
++ * the pt_regs, using the unwound data.  ksp is changed to point to this
++ * switch_stack, making it look like the task is blocked with no interrupt.
++ *
++ * This will not work when the interrupt occurred in a leaf function, with no
++ * save of b0.  But the old unwind code in lcrash cannot cope with that either,
++ * so no change.
++ */
++
++static inline void *
++kludge_copy_addr(int cpu, void *addr, struct task_struct *p)
++{
++	return (char *)addr - (char *)p + (char *)(dump_header_asm.dha_stack[cpu]);
++}
++
++static void
++kludge_for_broken_lcrash(int cpu)
++{
++	struct kdb_running_process *krp = kdb_running_process + cpu;
++	struct task_struct *p, *p_copy;
++	struct switch_stack *sw, *sw_copy, *sw_new;
++	struct pt_regs *regs;
++	struct unw_frame_info info;
++	kdb_symtab_t symtab;
++	kdb_machreg_t sp;
++	int count, i;
++	char nat;
++
++	if (krp->seqno < kdb_seqno - 1 ||
++	    !krp->regs ||
++	    user_mode(krp->regs) ||
++	    !krp->arch.sw ||
++	    !krp->p ||
++	    kdb_process_cpu(krp->p) != cpu)
++		return;
++	p = krp->p;
++	regs = krp->regs;
++	sw = krp->arch.sw;
++#if 0
++	{
++		char buf[80];
++		sprintf(buf, "btc %d\n", cpu);
++		kdb_parse(buf, regs);
++	}
++#endif
++
++	unw_init_frame_info(&info, p, sw);
++	count = 0;
++	do {
++		unw_get_sp(&info, &sp);
++		// kdb_printf("sp 0x%lx regs 0x%lx\n", sp, regs);
++	} while (sp < (kdb_machreg_t)regs && unw_unwind(&info) >= 0 && count++ < 200);
++	if (count >= 200) {
++		printk(KERN_WARNING "Unwind for process %d on cpu %d looped\n", p->pid, cpu);
++		return;
++	}
++
++	/* Must not touch the real stack data, kludge the data using the copies
++	 * in dump_header_asm.
++	 */
++	p_copy = kludge_copy_addr(cpu, p, p);
++	sw_new = (struct switch_stack *)((u64)(regs + 1) + 16) - 1;
++	sw_copy = kludge_copy_addr(cpu, sw_new, p);
++	// kdb_printf("p_copy 0x%p sw_new 0x%p sw_copy 0x%p\n", p_copy, sw_new, sw_copy);
++	memset(sw_copy, 0, sizeof(*sw_copy));
++
++	sw_copy->caller_unat = sw->caller_unat;
++	unw_access_ar(&info, UNW_AR_FPSR, &sw_copy->ar_fpsr, 0);
++	for (i = 2; i <= 5; ++i)
++		unw_access_fr(&info, i, &sw_copy->f2 + i - 2, 0);
++	for (i = 10; i <= 31; ++i)
++		unw_access_fr(&info, i, &sw_copy->f10 + i - 10, 0);
++	for (i = 4; i <= 7; ++i)
++		unw_access_gr(&info, i, &sw_copy->r4 + i - 4, &nat, 0);
++	for (i = 0; i <= 5; ++i)
++		unw_access_br(&info, i, &sw_copy->b0 + i, 0);
++	sw_copy->ar_pfs = *info.cfm_loc;
++	unw_access_ar(&info, UNW_AR_LC, &sw_copy->ar_lc, 0);
++	unw_access_ar(&info, UNW_AR_UNAT, &sw_copy->ar_unat, 0);
++	unw_access_ar(&info, UNW_AR_RNAT, &sw_copy->ar_rnat, 0);
++	/* FIXME: unwind.c returns the original bspstore, not the value that
++	 * matches the current unwind state.  Calculate our own value for the
++	 * modified bspstore.  This should work but does not
++	 *   unw_access_ar(&info, UNW_AR_BSPSTORE, &sw_copy->ar_bspstore, 0);
++	*/
++	sw_copy->ar_bspstore = (unsigned long)ia64_rse_skip_regs((unsigned long *)info.bsp, (*info.cfm_loc >> 7) & 0x7f);
++	unw_access_pr(&info, &sw_copy->pr, 0);
++
++	/* lcrash cannot unwind through the new spinlock contention code and it
++	 * is too important a case to ignore.  So the kludge extracts the
++	 * calling IP before saving the data.
++	 */
++	if (kdbnearsym(regs->cr_iip, &symtab) &&
++		strncmp(symtab.sym_name, "ia64_spinlock_contention", 24) == 0)
++		unw_get_rp(&info, &sw_copy->b0);
++
++	p_copy->thread.ksp = (__u64)sw_new - 16;
++	dump_header_asm.dha_smp_regs[cpu] = *((struct pt_regs *)((unsigned long)p + THREAD_SIZE) - 1);
++#if 0
++	{
++		/* debug.  Destructive overwrite of task, then bt the result in kdb to
++		 * validate the modified task.
++		 */
++		char buf[80];
++		memcpy(p, p_copy, THREAD_SIZE);
++		krp->regs = NULL;
++		krp->arch.sw = sw_new;
++		sprintf(buf, "btc %d\n", cpu);
++		kdb_parse(buf, NULL);
++		while(1){};
++	}
++#endif
++}
++
++#endif	/* CONFIG_KDB */
diff -uNr linux.orig/Documentation/kdb/kdb.mm linux/Documentation/kdb/kdb.mm
--- linux.orig/Documentation/kdb/kdb.mm	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb.mm	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,406 @@
+.TH KDB 8 "April 4, 2003"
+.hy 0
+.SH NAME
+Built-in Kernel Debugger for Linux - v4.1
+.SH "Overview"
+This document describes the built-in kernel debugger available
+for linux.   This debugger allows the programmer to interactively
+examine kernel memory, disassemble kernel functions, set breakpoints
+in the kernel code and display and modify register contents.
+.P
+A symbol table is included in the kernel image and in modules which
+enables all non-stack symbols (including static symbols) to be used as
+arguments to the kernel debugger commands.
+.SH "Getting Started"
+To include the kernel debugger in a linux kernel, use a
+configuration mechanism (e.g. xconfig, menuconfig, et. al.)
+to enable the \fBCONFIG_KDB\fP option.   Additionally, for accurate
+stack tracebacks, it is recommended that the \fBCONFIG_FRAME_POINTER\fP
+option be enabled (if present).   \fBCONFIG_FRAME_POINTER\fP changes the compiler
+flags so that the frame pointer register will be used as a frame
+pointer rather than a general purpose register.
+.P
+After linux has been configured to include the kernel debugger,
+make a new kernel with the new configuration file (a make clean
+is recommended before making the kernel), and install the kernel
+as normal.
+.P
+You can compile a kernel with kdb support but have kdb off by default,
+select \fBCONFIG_KDB_OFF\fR.  Then the user has to explicitly activate
+kdb by booting with the 'kdb=on' flag or, after /proc is mounted, by
+.nf
+  echo "1" > /proc/sys/kernel/kdb
+.fi
+You can also do the reverse, compile a kernel with kdb on and
+deactivate kdb with the boot flag 'kdb=off' or, after /proc is mounted,
+by
+.nf
+  echo "0" > /proc/sys/kernel/kdb
+.fi
+.P
+When booting the new kernel, the 'kdb=early' flag
+may be added after the image name on the boot line to
+force the kernel to stop in the kernel debugger early in the
+kernel initialization process.  'kdb=early' implies 'kdb=on'.
+If the 'kdb=early' flag isn't provided, then kdb will automatically be
+invoked upon system panic or when the \fBPAUSE\fP key is used from the
+keyboard, assuming that kdb is on.  Older versions of kdb used just a
+boot flag of 'kdb' to activate kdb early, this is still supported but
+is deprecated.
+.P
+Kdb can also be used via the serial port.  Set up the system to
+have a serial console (see \fIDocumentation/serial-console.txt\fP), you
+must also have a user space program such as agetty set up to read from
+the serial console..
+The \fBControl-A\fP key sequence on the serial port will cause the
+kernel debugger to be entered, assuming that kdb is on, that some
+program is reading from the serial console, at least one cpu is
+accepting interrupts and the serial consoel driver is still usable.
+.P
+\fBNote:\fR\ Your distributor may have chosen a different kdb
+activation sequence for the serial console.
+Consult your distribution documentation.
+.P
+If you have both a keyboard+video and a serial console, you can use
+either for kdb.
+Define both video and serial consoles with boot parameters
+.P
+.nf
+  console=tty0 console=ttyS0,38400
+.fi
+.P
+Any kdb data entered on the keyboard or the serial console will be echoed
+to both.
+.P
+While kdb is active, the keyboard (not serial console) indicators may strobe.
+The caps lock and scroll lock lights will turn on and off, num lock is not used
+because it can confuse laptop keyboards where the numeric keypad is mapped over
+the normal keys.
+On exit from kdb the keyboard indicators will probably be wrong, they will not match the kernel state.
+Pressing caps lock twice should get the indicators back in sync with
+the kernel.
+.SH "Basic Commands"
+There are several categories of commands available to the
+kernel debugger user including commands providing memory
+display and modification, register display and modification,
+instruction disassemble, breakpoints and stack tracebacks.
+Any command can be prefixed with '-' which will cause kdb to ignore any
+errors on that command, this is useful when packaging commands using
+defcmd.
+.P
+The following table shows the currently implemented standard commands,
+these are always available.  Other commands can be added by extra
+debugging modules, type '?' at the kdb prompt to get a list of all
+available commands.
+.DS
+.TS
+box, center;
+l | l
+l | l.
+Command	Description
+_
+bc	Clear Breakpoint
+bd	Disable Breakpoint
+be	Enable Breakpoint
+bl	Display breakpoints
+bp	Set or Display breakpoint
+bph	Set or Display hardware breakpoint
+bpa	Set or Display breakpoint globally
+bpha	Set or Display hardware breakpoint globally
+bt	Stack backtrace for current process
+btp	Stack backtrace for specific process
+bta	Stack backtrace for all processes
+btc	Cycle over all live cpus and backtrace each one
+cpu	Display or switch cpus
+dmesg	Display system messages
+defcmd	Define a command as a set of other commands
+ef	Print exception frame
+env	Show environment
+go	Restart execution
+help	Display help message
+id	Disassemble Instructions
+kill	Send a signal to a process
+ll	Follow Linked Lists
+lsmod	List loaded modules
+md	Display memory contents
+mdWcN	Display memory contents with width W and count N.
+mdr	Display raw memory contents
+mds	Display memory contents symbolically
+mm	Modify memory contents, words
+mmW	Modify memory contents, bytes
+ps	Display process status
+reboot	Reboot the machine
+rd	Display register contents
+rm	Modify register contents
+rmmod	Remove a module
+sections	List information on all known sections
+set	Add/change environment variable
+sr	Invoke SysReq commands
+ss	Single step a cpu
+ssb	Single step a cpu until a branch instruction
+.TE
+.DE
+.P
+Some commands can be abbreviated, such commands are indicated by a
+non-zero \fIminlen\fP parameter to \fBkdb_register\fP; the value of
+\fIminlen\fP being the minimum length to which the command can be
+abbreviated (for example, the \fBgo\fP command can be abbreviated
+legally to \fBg\fP).
+.P
+If an input string does not match a command in the command table,
+it is treated as an address expression and the corresponding address
+value and nearest symbol are shown.
+.P
+Some of the commands are described here.
+Information on the more complicated commands can be found in the
+appropriate manual pages.
+.TP 8
+cpu
+With no parameters, it lists the available cpus, '*' after a cpu number
+indicates a cpu that did not respond to the kdb stop signal.
+.I cpu
+followed by a number will switch to that cpu, you cannot switch to
+a cpu marked '*'.
+This command is only available if the kernel was configured for SMP.
+.TP 8
+dmesg [lines]
+Displays the last set of system messages from the kernel buffer.  If
+kdb logging is on, it is disabled by dmesg and is left as disabled.
+If lines is specified, only dump the last 'lines' from the buffer, 0
+dumps all lines.
+.TP 8
+defcmd
+Defines a new command as a set of other commands, all input until
+.I endefcmd
+is saved and executed as a package.
+.I defcmd
+takes three parameters, the command name to be defined and used to
+invoke the package, a quoted string containing the usage text and a
+quoted string containing the help text for the command.
+When using defcmd, it is a good idea to prefix commands that might fail
+with '-', this ignores errors so the following commands are still
+executed.
+For example,
+.P
+.nf
+        defcmd diag "" "Standard diagnostics"
+          set LINES 2000
+          set BTAPROMPT 0
+          -id %eip-0x40
+          -cpu
+          -ps
+          -dmesg 80
+          -bt
+          -bta
+        endefcmd          
+.fi
+.TP 8
+go
+Continue normal execution.
+Active breakpoints are reestablished and the processor(s) allowed to
+run normally.
+To continue at a specific address, use
+.I rm
+to change the instruction pointer then go.
+.TP 8
+id
+Disassemble instructions starting at an address.
+Environment variable IDCOUNT controls how many lines of disassembly
+output the command produces.
+.TP 8
+kill
+Internal command to send a signal (like kill(1)) to a process.
+kill -signal pid.
+.TP 8
+lsmod
+Internal command to list modules.
+This does not use any kernel nor user space services so can be used at any time.
+.TP 8
+ps
+Display status of all processes in the desired state.
+This command does not take any locks (all cpus should be frozen while
+kdb is running) so it can safely be used to debug lock problems with
+the process table.
+Without any parameters, \fBps\fP displays all processes.
+If a parameter is specified, it is a single string consisting of the
+letters D, R, S, T, Z and U, in any order.
+Each letter selects processes in a specific state, when multiple
+letters are specified, a process will be displayed if it is in any of
+the specified states.
+\fBps\ RD\fR displays only tasks that are running or are in an
+uninterruptible sleep.
+The states are\ :-
+.P
+.DS
+.TS
+box, center;
+l | l
+l | l.
+D	Uninterruptible sleep
+R	Running
+S	Interruptible sleep
+T	Traced or stopped
+Z	Zombie
+U	Unrunnable
+.TE
+.DE
+.P
+.TP 8
+reboot
+Reboot the system, with no attempt to do a clean close down.
+.TP 8
+rmmod
+Internal command to remove a module.
+This does not use any user space services, however it calls the module
+cleanup routine and that routine may try to use kernel services.
+Because kdb runs disabled there is no guarantee that the module cleanup
+routine will succeed, there is a real risk of the routine hanging and
+taking kdb with it.
+Use the
+.I rmmod
+command with extreme care.
+.TP 8
+sections
+List information for all known sections.  The output is one line per
+module plus the kernel, starting with the module name.  This is
+followed by one or more repeats of section name, section start,
+section end and section flags.  This data is not designed for human
+readability, it is intended to tell external debuggers where each
+section has been loaded.
+.SH INITIAL KDB COMMANDS
+kdb/kdb_cmds is a plain text file where you can define kdb commands
+which are to be issued during kdb_init().  One command per line, blank
+lines are ignored, lines starting with '#' are ignored.  kdb_cmds is
+intended for per user customization of kdb, you can use it to set
+environment variables to suit your hardware or to set standard
+breakpoints for the problem you are debugging.  This file is converted
+to a small C object, compiled and linked into the kernel.  You must
+rebuild and reinstall the kernel after changing kdb_cmds.  This file
+will never be shipped with any useful data so you can always override
+it with your local copy.  Sample kdb_cmds:
+.P
+.nf
+# Initial commands for kdb, alter to suit your needs.
+# These commands are executed in kdb_init() context, no SMP, no
+# processes.  Commands that require process data (including stack or
+# registers) are not reliable this early.  set and bp commands should
+# be safe.  Global breakpoint commands affect each cpu as it is booted.
+
+set LINES=50
+set MDCOUNT=25
+set RECURSE=1
+bp sys_init_module
+.fi
+.SH INTERRUPTS AND KDB
+When a kdb event occurs, one cpu (the initial cpu) enters kdb state.
+It uses a cross system interrupt to interrupt the
+other cpus and bring them all into kdb state.  All cpus run with
+interrupts disabled while they are inside kdb, this prevents most
+external events from disturbing the kernel while kdb is running.
+.B Note:
+Disabled interrupts means that any I/O that relies on interrupts cannot
+proceed while kdb is in control, devices can time out.  The clock tick
+is also disabled, machines will lose track of time while they are
+inside kdb.
+.P
+Even with interrupts disabled, some non-maskable interrupt events will
+still occur, these can disturb the kernel while you are debugging it.
+The initial cpu will still accept NMI events, assuming that kdb was not
+entered for an NMI event.  Any cpu where you use the SS or SSB commands
+will accept NMI events, even after the instruction has finished and the
+cpu is back in kdb.  This is an unavoidable side effect of the fact that
+doing SS[B] requires the cpu to drop all the way out of kdb, including
+exiting from the event that brought the cpu into kdb.  Under normal
+circumstances the only NMI event is for the NMI oopser and that is kdb
+aware so it does not disturb the kernel while kdb is running.
+.P
+Sometimes doing SS or SSB on ix86 will allow one interrupt to proceed,
+even though the cpu is disabled for interrupts.  I have not been able
+to track this one down but I suspect that the interrupt was pending
+when kdb was entered and it runs when kdb exits through IRET even
+though the popped flags are marked as cli().  If any ix86 hardware
+expert can shed some light on this problem, please notify the kdb
+maintainer.
+.SH RECOVERING FROM KDB ERRORS
+If a kdb command breaks and kdb has enough of a recovery environment
+then kdb will abort the command and drop back into mainline kdb code.
+This means that user written kdb commands can follow bad pointers
+without killing kdb.  Ideally all code should verify that data areas
+are valid (using kdb_getarea) before accessing it but lots of calls to
+kdb_getarea can be clumsy.
+.P
+The sparc64 port does not currently provide this error recovery.
+If someone would volunteer to write the necessary longjmp/setjmp
+code, their efforts would be greatly appreciated. In the
+meantime, it is possible for kdb to trigger a panic by accessing
+a bad address.
+.SH DEBUGGING THE DEBUGGER
+kdb has limited support for debugging problems within kdb.  If you
+suspect that kdb is failing, you can set environment variable KDBDEBUG
+to a bit pattern which will activate kdb_printf statements within kdb.
+See include/linux/kdb.h, KDB_DEBUG_FLAG_xxx defines.  For example
+.nf
+  set KDBDEBUG=0x60
+.fi
+activates the event callbacks into kdb plus state tracing in sections
+of kdb.
+.nf
+  set KDBDEBUG=0x18
+.fi
+gives lots of tracing as kdb tries to decode the process stack.
+.P
+You can also perform one level of recursion in kdb.  If environment
+variable RECURSE is not set or is 0 then kdb will either recover from
+an error (if the recovery environment is satisfactory) or kdb will
+allow the error to percolate, usually resulting in a dead system.  When
+RECURSE is 1 then kdb will recover from an error or, if there is no
+satisfactory recovery environment, it will drop into kdb state to let
+you diagnose the problem.  When RECURSE is 2 then all errors drop into
+kdb state, kdb does not attempt recovery first.  Errors while in
+recursive state all drop through, kdb does not even attempt to recover
+from recursive errors.
+.SH KEYBOARD EDITING
+kdb supports a command history, which can be accessed via keyboard
+sequences.
+It supports the special keys on PC keyboards, control characters and
+vt100 sequences on a serial console or a PC keyboard.
+.P
+.DS
+.TS
+box, center;
+l | l | l l | l
+l | l | l l | l.
+PC Special keys	Control	VT100 key	Codes	Action
+_
+Backspace	ctrl-H	Backspace	0x7f	Delete character to the left of the cursor
+Delete	ctrl-D	Delete	\\e[3~	Delete character to the right of the cursor
+Home	ctrl-A	Home	\\e[1~	Go to start of line
+End	ctrl-E	End	\\e[4~	Go to end of line
+Up arrow	ctrl-P	Up arrow	\\e[A	Up one command in history
+Down arrow	ctrl-N	Down arrow	\\e[B	Down one command in history
+Left arrow	ctrl-B	Left arrow	\\e[D	Left one character in current command
+Right arrow	ctrl-F	Right arrow	\\e[C	Right one character in current command
+.TE
+.DE
+.P
+There is no toggle for insert/replace mode, kdb editing is always in
+insert mode.
+Use delete and backspace to delete characters.
+.P
+kdb also supports tab completion for kernel symbols
+Type the start of a kernel symbol and press tab (ctrl-I) to complete
+the name
+If there is more than one possible match, kdb will append any common
+characters and wait for more input, pressing tab a second time will
+display the possible matches
+The number of matches is limited by environment variable DTABCOUNT,
+with a default of 30 if that variable is not set.
+.SH AUTHORS
+Scott Lurndal, Richard Bass, Scott Foehner, Srinivasa Thirumalachar,
+Masahiro Adegawa, Marc Esipovich, Ted Kline, Steve Lord, Andi Kleen,
+Sonic Zhang.
+.br
+Keith Owens <kaos@sgi.com> - kdb maintainer.
+.SH SEE ALSO
+.P
+linux/Documentation/kdb/kdb_{bp,bt,env,ll,md,rd,sr,ss}.man
diff -uNr linux.orig/Documentation/kdb/kdb_bp.man linux/Documentation/kdb/kdb_bp.man
--- linux.orig/Documentation/kdb/kdb_bp.man	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb_bp.man	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,194 @@
+.TH BD 1 "1 June 2003"
+.SH NAME
+bp, bpa, bph, bpha, bd, bc, be, bl \- breakpoint commands
+.SH SYNOPSIS
+bp \fIaddress-expression\fP
+.LP
+bpa \fIaddress-expression\fP
+.LP
+bph \fIaddress-expression\fP [\f(CWDATAR|DATAW|DATAA|IO\fP [\fIlength\fP]]
+.LP
+bpha \fIaddress-expression\fP [\f(CWDATAR|DATAW|DATAA|IO\fP [\fIlength\fP]]
+.LP
+bd \fIbreakpoint-number\fP
+.LP
+bc \fIbreakpoint-number\fP
+.LP
+be \fIbreakpoint-number\fP
+.LP
+bl
+.SH DESCRIPTION
+.hy 0
+The
+.B bp 
+family of commands are used to establish a breakpoint.   
+The \fIaddress-expression\fP may be a numeric value (decimal or
+hexidecimal), a symbol name, a register name preceeded by a 
+percent symbol '%', or a simple expression consisting of a 
+symbol name, an addition or subtraction character and a numeric
+value (decimal or hexidecimal).
+.P
+\fBbph\fP and \fBbpha\fP will force the use of a hardware register, provided 
+the processor architecture supports them. 
+.P
+The \fIaddress-expression\fP may also consist of a single
+asterisk '*' symbol which indicates that the command should
+operate on all existing breakpoints (valid only for \fBbc\fP, 
+\fBbd\fP and \fBbe\fP).
+.P
+Four different types of
+breakpoints may be set:
+
+.TP 8
+Instruction
+Causes the kernel debugger to be invoked from the debug exception
+path when an instruction is fetched from the specified address.  This
+is the default if no other type of breakpoint is requested or when
+the \fBbp\fP command is used.
+
+.TP 8
+DATAR
+Causes the kernel debugger to be entered when data of length
+\fIlength\fP is read from or written to the specified address.
+This type of breakpoint must use a processor debug register which
+places an architecture dependent limit on the number of data and I/O
+breakpoints that may be established. On arm mode XScale platform
+(thumb mode is not supported yet),
+debugger is triggered by reading from the specified address.
+The \fBbph\fP or \fBbpha\fP commands must be used.
+
+.TP 8
+DATAW
+Enters the kernel debugger when data of length \fIlength\fP
+is written to the specified address.  \fIlength\fP defaults 
+to four bytes if it is not explicitly specified.
+Note that the processor may have already overwritten the prior data at
+the breakpoint location before the kernel debugger is invoked.
+The prior data should be saved before establishing the breakpoint, if
+required. On arm mode XScale platform, the debugger is triggered 
+after having overwritten the specified address.
+The \fBbph\fP or \fBbpha\fP commands must be used.
+
+.TP 8
+IO
+Enters the kernel debugger when an \fBin\fP or \fBout\fP instruction
+targets the specified I/O address.  The \fBbph\fP or \fBbpha\fP
+commands must be used. This type of breakpoint is not valid in
+arm mode XScale platform. This option is not valid in arm 
+mode XScale platform.
+
+.TP 8
+DATAA
+Enters the kernel debugger after the data in specified address has
+been accessed (read or write), this option is only used in arm 
+mode XScale platform.
+
+.P
+The
+.B bpha
+command will establish a breakpoint on all processors in an
+SMP system.   This command is not available in an uniprocessor
+kernel.
+.P
+The
+.B bd
+command will disable a breakpoint without removing it from the kernel
+debugger's breakpoint table.
+This can be used to keep breakpoints in the table without exceeding the
+architecture limit on breakpoint registers.
+.P
+The
+.B be
+command will re-enable a disabled breakpoint.
+.P
+The
+.B bc
+command will clear a breakpoint from the breakpoint table.
+.P
+The 
+.B bl
+command will list the existing set of breakpoints.
+.SH LIMITATIONS
+There is a compile time limit of sixteen entries in the 
+breakpoint table at any one time.
+.P
+There are architecture dependent limits on the number of hardware
+breakpoints that can be set.
+.IP ix86 8
+Four.
+.PD 0
+.IP xscale 8
+Two for insruction breakpoints and another two for data breakpoint.
+.PD 0
+.IP ia64 8
+?
+.PD 0
+.IP sparc64 8
+None.
+.PD 1
+When issuing the "go" command after entering the debugger due to
+a breakpoint, kdb will silently perform a single step in order to
+reapply the breakpoint. The sparc64 port has some limitations on
+single stepping, which may limit where a breakpoint may be safely
+set. Please read the man page for \fBss\fP for more information.
+.SH ENVIRONMENT
+The breakpoint subsystem does not currently use any environment
+variables.
+.SH SMP CONSIDERATIONS
+Using
+.B bc
+is risky on SMP systems.
+If you clear a breakpoint when another cpu has hit that breakpoint but
+has not been processed then it may not be recognised as a kdb
+breakpoint, usually resulting in incorrect program counters and kernel
+panics.
+It is safer to disable the breakpoint with
+.BR bd ,
+then
+.B go
+to let any other processors that are waiting on the breakpoint to
+clear.
+After all processors are clear of the disabled breakpoint then it is
+safe to clear it using
+.BR bc .
+.P
+Breakpoints which use the processor breakpoint registers
+are only established on the processor which is
+currently active.  If you wish breakpoints to be universal
+use the
+.B bpa
+or
+.B bpha
+commands.
+.SH EXAMPLES
+.TP 8
+bp schedule
+Sets an instruction breakpoint at the begining of the 
+function \fBschedule\fP.
+
+.TP 8
+bp schedule+0x12e
+Sets an instruction breakpoint at the instruction located
+at \fBschedule\fP+\fI0x12e\fP.
+
+.TP 8
+bph ttybuffer+0x24 dataw
+Sets a data write breakpoint at the location referenced by
+\fBttybuffer\fP+\fI0x24\fP for a length of four bytes.
+
+.TP 8
+bph 0xc0254010 datar 1
+Establishes a data reference breakpoint at address \fB0xc0254010\fP
+for a length of one byte.
+
+.TP 8
+bp
+List current breakpoint table.
+
+.TP 8
+bd 0
+Disable breakpoint #0.
+
+.TP 8
+bc *
+Clear all breakpoints
diff -uNr linux.orig/Documentation/kdb/kdb_bt.man linux/Documentation/kdb/kdb_bt.man
--- linux.orig/Documentation/kdb/kdb_bt.man	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb_bt.man	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,219 @@
+.TH BT 1 "20 July 2003"
+.SH NAME
+bt \- Stack Traceback command
+.SH SYNOPSIS
+bt [ <stack-frame-address> ]
+.LP
+btp <pid>
+.LP
+btt <struct-task-address>
+.LP
+bta [ DRSTZU ]
+.LP
+btc [<cpu>]
+.SH DESCRIPTION
+.hy 0
+The
+.B bt 
+command is used to print a stack traceback.  It uses the 
+current registers (see \fBrd\fP command) to determine
+the starting context and attempts to provide a complete
+stack traceback for the active thread.   If \fIstack-frame-address\fP
+is supplied, it is assumed to point to the start of a valid
+stack frame and the stack will be traced back from that 
+point (e.g. on i386 architecture, \fIstack-frame-address\fP 
+should be the stack address of a saved \fB%eip\fP value from a \fBcall\fP
+instruction. on sparc64 architecture, it should be a pointer to a
+saved register window, as is found in the \fB%fp\fP register).
+.P
+If present, a kernel configuration option \fBCONFIG_FRAME_POINTER\fP
+should be enabled so that the compiler will utilize the frame pointer
+register properly to maintain a stack which can be correctly 
+analyzed. Some architectures (e.g. sparc64) always use
+\fBCONFIG_FRAME_POINTER\fP, and so the option is not present.
+.P
+The \fBbt\fP command will attempt to analyze the stack without
+frame pointers if the \fBCONFIG_FRAME_POINTER\fP option is not
+enabled, but the analysis is difficult and may not produce
+accurate nor complete results. 
+.P
+The \fBbtp\fP command will analyze the stack for the given
+process identification (see the \fBps\fP command).
+.P
+The \fBbtt\fP command will analyze the stack for the given task
+structure.
+It is exactly equivalent to \fBbtp\fR on the pid extracted from the
+task structure.
+.P
+The \fBbta\fP command lists the stack for all processes in the desired
+state.
+Without any parameters, \fBbta\fP gives a backtrace for all processes.
+If a parameter is specified, it is a single string consisting of the
+letters D, R, S, T, Z and U, in any order.
+Each letter selects processes in a specific state, when multiple
+letters are specified, a process will be traced if it is in any of the
+specified states.
+\fBbta\ RD\fR displays only tasks that are running or are in an
+uninterruptible sleep.
+The states are\ :-
+.IP D 3
+Uninterruptible sleep.
+.PD 0
+.IP R 3
+Running.
+The process may not be on a cpu at the moment, but it is ready to run.
+The header line above the backtrace contains '1' in the fourth field if
+the process is actually on a cpu.
+.IP S 3
+Interruptible sleep.
+.IP T 3
+Traced or stopped.
+.IP Z 3
+Zombie.
+.IP U 3
+Unrunnable.
+.PD 1
+.P
+The \fBbtc\fP command will analyze the stack for the current process on
+a specified cpu or, if no cpu number is supplied, for the current
+process on all cpus.
+It does not switch to the other cpus, instead it uses the task
+structures to identify and issue \fBbtt\fR against the current task on
+the desired cpus.
+.P
+For each function, the stack trace prints at least two lines.
+The first line contains four or five fields\ :-
+.IP * 3
+The pointer to the previous stack frame, blank if there is no valid
+frame pointer.
+.PD 0
+.IP * 3
+The current address within this frame.
+.IP * 3
+The address converted to a function name (actually the first non-local
+label which is <= the address).
+.IP * 3
+The offset of the address within the function.
+.IP * 3
+Any parameters to the function.
+.PD 1
+.PP
+On the next line there are five fields which are designed to make it
+easier to match the trace against the kernel code\ :-
+.IP * 3
+The module name that contains the address, "kernel" if it is in the
+base kernel.
+.PD 0
+.IP * 3
+The section name that contains the address.
+.IP * 3
+The start address of the section.
+.IP * 3
+The start address of the function.
+.IP * 3
+The end address of the function (the first non-local label which is >
+the address).
+.PD 1
+.PP
+If arguments are being converted to symbols, any argument which
+converts to a kernel or module address is printed as\ :-
+.IP * 3
+Argument address.
+.PD 0
+.IP * 3
+The module name that contains the address, "kernel" if it is in the
+base kernel.
+.IP * 3
+The symbol name the argument maps to.
+.IP * 3
+The offset of the argument from the symbol, suppressed if 0.
+.PD 1
+.SH MATCHING TRACE TO KERNEL CODE
+The command "objdump\ -S" will disassemble an object and, if the code
+was compiled with debugging (gcc flag -g), objdump will interleave the
+C source lines with the generated object.
+.PP
+A complete objdump of the kernel or a module is too big, normally you
+only want specific functions.
+By default objdump will only print the .text section but Linux uses
+other section names for executable code.
+When objdump prints relocatable objects (modules) it uses an offset of
+0 which is awkward to relate to the stack trace.
+The five fields which are printed for each function are designed to
+make it easier to match the stack trace against the kernel code using
+"objdump\ -S".
+.PP
+If the function is in the kernel then you need the section name, the
+start and end address of the function.  The command is
+.PP
+.nf
+  objdump -S -j <section_name> \\
+          --start-address=<start-address> \\
+          --stop-address=<end-address> \\
+          /usr/src/linux/vmlinux
+.fi
+.PP
+If the function is in a module then you need the section name, the
+start address of the section, the start and end address of the
+function, the module name.  The command is
+.PP
+.nf
+  objdump -S -j <section_name> \\
+          --adjust-vma=<section-start> \\
+          --start-address=<start-address> \\
+          --stop-address=<end-address> \\
+          /path/to/module/<module-name>.o
+.fi
+.PP
+All addresses to objdump must be preceded by '0x' if they are in hex,
+objdump does not assume hex.
+The stack trace values are printed with leading '0x' to make it easy to
+run objdump.
+.SH LIMITATIONS
+If the kernel is compiled without frame pointers, stack tracebacks
+may be incomplete.  The \fBmds %esp\fP (i386) or \fBmds %fp\fP (sparc64)
+command may be useful in attemping to determine the actual stack
+traceback manually.
+.P
+A stack trace can be misleading if any code in a function exit has been
+executed, the stack is partially unwound at that stage.
+.P
+The \fBbt\fP command may print more arguments for a function
+than that function accepts;  For sparc64, this will always happen
+as the debugger cannot determine the correct number. For i386, this happens
+when the C compiler doesn't immediately pop the arguments off the stack upon
+return from a called function.  When this is this case, these extra 
+stack words will be considered additional arguments by the \fBbt\fP
+command.
+.SH ENVIRONMENT
+The \fBBTARGS\fP environment variable governs the maximum number
+of arguments that are printed for any single function.
+.PP
+If the \fBBTSYMARG\fP environment variable is non-zero then any
+arguments that fall within the kernel are converted to symbols.
+.PP
+If the \fBNOSECT\fP environment variable is non-zero then the
+section information is suppressed.
+.PP
+The \fBBTAPROMPT\fP environment variable controls the prompt after each
+process is listed by the \fBbta\fP command.  If \fBBTAPROMPT\fP is not
+set or is non-zero then \fBbta\fP issues a prompt after each process is
+listed.  If \fBBTAPROMPT\fP is set to zero then no prompt is issued and
+all processes are listed without human intervention.
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.nf
+.na
+.ft CW
+Entering kdb (0xc3cb4000) due to Breakpoint @ 0xc011725d
+Instruction(i) breakpoint #0 at 0xc011725c
+qm_modules+0xd1:   movl   %ebp,%esp
+kdb> bt
+    EBP       EIP         Function(args)
+0xc3cb5f98 0xc011725d  qm_modules+0xd1 (0x80721c0, 0x100, 0xbfff5000)
+                       kernel .text 0xc0100000 0xc011718c 0xc0117264
+0xc3cb5fbc 0xc0117875  sys_query_module+0x1b1 (0x0, 0x1, 0x80721c0, 0x100, 0xbfff5000)
+                       kernel .text 0xc0100000 0xc01176c4 0xc01178e8
+           0xc01095f8  system_call+0x34
+                       kernel .text 0xc0100000 0xc01095c4 0xc01095fc
diff -uNr linux.orig/Documentation/kdb/kdb_env.man linux/Documentation/kdb/kdb_env.man
--- linux.orig/Documentation/kdb/kdb_env.man	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb_env.man	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,46 @@
+.TH ENV 1 "24 September 2000"
+.SH NAME
+env, set \- Environment manipulation commands
+.SH SYNOPSIS
+env
+.LP
+set \fIenvironment-variable\fP=\fIvalue\fP
+.SH DESCRIPTION
+The kernel debugger contains an environment which contains a series
+of name-value pairs.  Some environment variables are known to the
+various kernel debugger commands and have specific meaning to the
+command; such are enumerated on the respective reference material. 
+.P
+Arbitrary environment variables may be created and used with 
+many commands (those which require an \fIaddress-expression\fP).
+.P
+The
+.B env
+command is used to display the current environment.
+.P
+The
+.B set
+command is used to alter an existing environment variable or
+establish a new environment variable.   
+.SH LIMITATIONS
+There is a compile-time limit of 33 environment variables.
+.P
+There is a compile-time limit of 512 bytes (\fBKDB_ENVBUFSIZE\fP)
+of heap space available for new environment variables and for
+environment variables changed from their compile-time values.
+.SH ENVIRONMENT
+These commands explicitly manipulate the environment.
+.SH SMP CONSIDERATIONS
+None.
+.SH USER SETTINGS
+You can include "set" commands in kdb/kdb_cmds (see kdb.mm) to define
+your environment variables at kernel startup.
+.SH EXAMPLES
+.TP 8
+env
+Display current environment settings.
+
+.TP 8
+set IDCOUNT=100
+Set the number of lines to display for the \fBid\fP command
+to the value \fI100\fP.
diff -uNr linux.orig/Documentation/kdb/kdb_ll.man linux/Documentation/kdb/kdb_ll.man
--- linux.orig/Documentation/kdb/kdb_ll.man	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb_ll.man	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,134 @@
+.TH LL 1 "19 April 1999"
+.SH NAME
+ll \- Linked List examination
+.SH SYNOPSIS
+ll <addr> <link-offset> <cmd>
+.SH DESCRIPTION
+The
+.B ll
+command is used to execute a single command repetitively for
+each element of a linked list.
+.P
+The command specified by <cmd> will be executed with a single
+argument, the address of the current element.
+.SH LIMITATIONS
+Be careful if using this command recursively.
+.SH ENVIRONMENT
+None.
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.nf
+.na
+.ft CW
+# cd modules
+# insmod kdbm_vm.o
+# Entering kdb on processor 0 due to PAUSE
+kdb> ps
+Task Addr     Pid       Parent   cpu  lcpu    Tss     Command
+0xc03de000 0000000001 0000000000 0000 0000 0xc03de2d4 init
+0xc0090000 0000000002 0000000001 0000 0000 0xc00902d4 kflushd
+0xc000e000 0000000003 0000000001 0000 0000 0xc000e2d4 kpiod
+0xc000c000 0000000004 0000000001 0000 0000 0xc000c2d4 kswapd
+0xc7de2000 0000000056 0000000001 0000 0000 0xc7de22d4 kerneld
+0xc7d3a000 0000000179 0000000001 0000 0000 0xc7d3a2d4 syslogd
+0xc7a7e000 0000000188 0000000001 0000 0000 0xc7a7e2d4 klogd
+0xc7a04000 0000000199 0000000001 0000 0000 0xc7a042d4 atd
+0xc7b84000 0000000210 0000000001 0000 0000 0xc7b842d4 crond
+0xc79d6000 0000000221 0000000001 0000 0000 0xc79d62d4 portmap
+0xc798e000 0000000232 0000000001 0000 0000 0xc798e2d4 snmpd
+0xc7904000 0000000244 0000000001 0000 0000 0xc79042d4 inetd
+0xc78fc000 0000000255 0000000001 0000 0000 0xc78fc2d4 lpd
+0xc77ec000 0000000270 0000000001 0000 0000 0xc77ec2d4 sendmail
+0xc77b8000 0000000282 0000000001 0000 0000 0xc77b82d4 gpm
+0xc7716000 0000000300 0000000001 0000 0000 0xc77162d4 smbd
+0xc7ee2000 0000000322 0000000001 0000 0000 0xc7ee22d4 mingetty
+0xc7d6e000 0000000323 0000000001 0000 0000 0xc7d6e2d4 login
+0xc778c000 0000000324 0000000001 0000 0000 0xc778c2d4 mingetty
+0xc78b6000 0000000325 0000000001 0000 0000 0xc78b62d4 mingetty
+0xc77e8000 0000000326 0000000001 0000 0000 0xc77e82d4 mingetty
+0xc7708000 0000000327 0000000001 0000 0000 0xc77082d4 mingetty
+0xc770e000 0000000328 0000000001 0000 0000 0xc770e2d4 mingetty
+0xc76b0000 0000000330 0000000001 0000 0000 0xc76b02d4 update
+0xc7592000 0000000331 0000000323 0000 0000 0xc75922d4 ksh
+0xc7546000 0000000338 0000000331 0000 0000 0xc75462d4 su
+0xc74dc000 0000000339 0000000338 0000 0000 0xc74dc2d4 ksh
+kdb> md 0xc74dc2d4
+c74dc2d4: 00000000 c74de000 00000018 00000000  .....`MG........
+c74dc2e4: 00000000 00000000 00000000 074de000  .............`M.
+c74dc2f4: c01123ff 00000000 00000000 00000000  #.@............
+c74dc304: 00000000 00000000 c74dded0 00000000  ........P^MG....
+[omitted]
+c74dc474: 00000000 00000000 00000000 00000000  ................
+c74dc484: 00000000 c7c15d00 c77b0900 c026fbe0  .....]AG..{G`{&@
+c74dc494: 00000000 c76c2000 00000000 00000000  ..... lG........
+c74dc4a4: 00000000 00000000 00000000 c74dc4ac  ............,DMG
+kdb> md 0xc026fbe0
+c026fbe0: c0262b60 00000000 c7594940 c74de000  @HYG....@IYG.`MG
+[omitted]
+kdb> md 0xc0262b60
+c0262b60: c0266660 08048000 0804c000 c7bec360  `f&@.....@..`C>G
+kdb> ll c0262b60 12 md
+c0262b60: c0266660 08048000 0804c000 c7bec360  `f&@.....@..`C>G
+c7bec360: c0266660 0804c000 0804d000 c7becb20  `f&@.@...P.. K>G
+c7becb20: c0266660 0804d000 08050000 c7bec3a0  `f&@.P...... C>G
+c7bec3a0: c0266660 40000000 40009000 c7bec420  `f&@...@...@ D>G
+c7bec420: c0266660 40009000 4000b000 c7bec4a0  `f&@...@.0.@ D>G
+c7bec4a0: c0266660 4000b000 40010000 c7bec8e0  `f&@.0.@...@`H>G
+c7bec8e0: c0266660 40010000 400a1000 c7becbe0  `f&@...@...@`K>G
+c7becbe0: c0266660 400a1000 400a8000 c7becc60  `f&@...@...@`L>G
+c7becc60: c0266660 400a8000 400b4000 c7952300  `f&@...@.@.@.#.G
+c7952300: c0266660 400b5000 400bc000 c79521c0  `f&@.P.@.@.@@!.G
+c79521c0: c0266660 400bc000 400bd000 c7bec6e0  `f&@.@.@.P.@`F>G
+c7bec6e0: c0266660 bffff000 c0000000 00000000  `f&@.p?...@....
+kdb>
+kdb> ll c0262b60 12 vm
+struct vm_area_struct at 0xc0262b60 for 56 bytes
+vm_start = 0x8048000   vm_end = 0x804c000
+page_prot = 0x25   avl_height = 2244    vm_offset = 0x0
+flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE
+struct vm_area_struct at 0xc7bec360 for 56 bytes
+vm_start = 0x804c000   vm_end = 0x804d000
+page_prot = 0x25   avl_height = -31808    vm_offset = 0x3000
+flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE
+struct vm_area_struct at 0xc7becb20 for 56 bytes
+vm_start = 0x804d000   vm_end = 0x8050000
+page_prot = 0x25   avl_height = -28664    vm_offset = 0x0
+flags:  READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC
+struct vm_area_struct at 0xc7bec3a0 for 56 bytes
+vm_start = 0x40000000   vm_end = 0x40009000
+page_prot = 0x25   avl_height = 30126    vm_offset = 0x0
+flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC DENYWRITE
+struct vm_area_struct at 0xc7bec420 for 56 bytes
+vm_start = 0x40009000   vm_end = 0x4000b000
+page_prot = 0x25   avl_height = 30126    vm_offset = 0x8000
+flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC DENYWRITE
+struct vm_area_struct at 0xc7bec4a0 for 56 bytes
+vm_start = 0x4000b000   vm_end = 0x40010000
+page_prot = 0x25   avl_height = 26853    vm_offset = 0x0
+flags:  READ MAYREAD MAYWRITE MAYEXEC
+struct vm_area_struct at 0xc7bec8e0 for 56 bytes
+vm_start = 0x40010000   vm_end = 0x400a1000
+page_prot = 0x25   avl_height = 2244    vm_offset = 0x0
+flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC
+struct vm_area_struct at 0xc7becbe0 for 56 bytes
+vm_start = 0x400a1000   vm_end = 0x400a8000
+page_prot = 0x25   avl_height = 30126    vm_offset = 0x90000
+flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC
+struct vm_area_struct at 0xc7becc60 for 56 bytes
+vm_start = 0x400a8000   vm_end = 0x400b4000
+page_prot = 0x25   avl_height = 2244    vm_offset = 0x0
+flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC
+struct vm_area_struct at 0xc7952300 for 56 bytes
+vm_start = 0x400b5000   vm_end = 0x400bc000
+page_prot = 0x25   avl_height = 30126    vm_offset = 0x0
+flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC
+struct vm_area_struct at 0xc79521c0 for 56 bytes
+vm_start = 0x400bc000   vm_end = 0x400bd000
+page_prot = 0x25   avl_height = -16344    vm_offset = 0x6000
+flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC
+struct vm_area_struct at 0xc7bec6e0 for 56 bytes
+vm_start = 0xbffff000   vm_end = 0xc0000000
+page_prot = 0x25   avl_height = 2244    vm_offset = 0x0
+flags:  READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC GROWSDOWN
+kdb>
diff -uNr linux.orig/Documentation/kdb/kdb_md.man linux/Documentation/kdb/kdb_md.man
--- linux.orig/Documentation/kdb/kdb_md.man	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb_md.man	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,125 @@
+.TH MD 1 "25 September, 2001"
+.SH NAME
+md, mdWcN, mdr, mds, mm, mmW\- Memory manipulation commands
+.SH SYNOPSIS
+md [ \fIaddress-expression\fP [ \fIline-count\fP [\fIoutput-radix\fP ] ] ]
+.LP
+md\fIW\fRc\fIn\fR [ \fIaddress-expression\fP [ \fIline-count\fP [\fIoutput-radix\fP ] ] ]
+.LP
+mdr \fIaddress-expression\fP,\fIbytes\fP
+.LP
+mds [ \fIaddress-expression\fP [ \fIline-count\fP [\fIoutput-radix\fP ] ] ]
+.LP
+mm \fIaddress-expression\fP \fInew-contents\fP
+.LP
+mm\fIW\fR \fIaddress-expression\fP \fInew-contents\fP
+.SH DESCRIPTION
+The
+.B md 
+command is used to display the contents of memory.
+The \fIaddress-expression\fP may be a numeric value (decimal or
+hexidecimal), a symbol name, a register name preceeded by one or more
+percent symbols '%', an environment variable name preceeded by
+a currency symbol '$',  or a simple expression consisting of a 
+symbol name, an addition or subtraction character and a numeric
+value (decimal or hexidecimal).
+.P
+If an address is specified and the \fIline-count\fP or \fIradix\fP arguments
+are omitted, they default to the values of the \fBMDCOUNT\fP and \fBRADIX\fP
+environment variables respectively.  If the \fBMDCOUNT\fP or \fBRADIX\fP
+environment variables are unset, the appropriate defaults will be used [see
+\fBENVIRONMENT\fP below].  If no address is specified then md resumes
+after the last address printed, using the previous values of count and
+radix.  The start address is rounded down to a multiple of the
+BYTESPERWORD (md) or width (md\fIW\fR).
+.P
+md uses the current value of environment variable \fBBYTESPERWORD\fP to
+read the data.  When reading hardware registers that require special
+widths, it is more convenient to use md\fIW\fRc\fIn\fR where \fIW\fR is
+the width for this command and \fRc\fIn\fR is the number of entries to
+read.  For example, md1c20 reads 20 bytes, 1 at a time.  To continue
+printing just type md, the width and count apply to following md
+commands with no parameters.  \fBNote:\fR The count is the number of
+repeats of the width, unlike MDCOUNT which gives the number of md lines
+to print.
+.P
+The
+.B mdr
+command displays the raw contents of memory, starting at the specified
+address for the specified number of bytes.
+The data is printed in one line without a leading address and no
+trailing character conversion.
+.B mdr
+is intended for interfacing with external debuggers, it is of little
+use to humans.
+.P
+The
+.B mds
+command displays the contents of memory one word per line and
+attempts to correlate the contents of each word with a symbol
+in the symbol table.   If no symbol is found, the ascii representation
+of the word is printed, otherwise the symbol name and offset from
+symbol value are printed.
+By default the section data is printed for kernel symbols.
+.P
+The
+.B mm
+and
+\fBmm\fIW\fR
+commands allow modification of memory.   The bytes at the address
+represented by \fIaddress-expression\fP are changed to 
+\fInew-contents\fP.  \fInew-contents\fP is allowed to be an
+\fIaddress-expression\fP.
+.B mm
+changes a machine word, \fBmm\fIW\fR changes \fIW\fR bytes at that
+address.
+.SH LIMITATIONS
+None.
+.SH ENVIRONMENT
+.TP 8
+MDCOUNT
+This environment variable (default=8) defines the number of lines
+that will be displayed by each invocation of the \fBmd\fP command.
+
+.TP 8
+RADIX
+This environment variable (default=16) defines the radix used to
+print the memory contents.  
+
+.TP 8
+BYTESPERWORD
+This environment variable (default=4) selects the width of output
+data when printing memory contents.  Select the value two to get
+16-bit word output, select the value one to get byte output.
+
+.TP 8
+LINES
+This environment variable governs the number of lines of output 
+that will be presented before the kernel debugger built-in pager
+pauses the output.   This variable only affects the functioning
+of the \fBmd\fP and \fBmds\fP if the \fBMDCOUNT\fP variable 
+is set to a value greater than the \fBLINES\fP variable.
+
+.TP 8
+If the \fBNOSECT\fP environment variable is non-zero then the
+section information is suppressed.
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.TP 8
+md %edx
+Display memory starting at the address contained in register \fB%edx\fP.
+
+.TP 8
+mds %esp
+Display stack contents symbolically.   This command is quite useful
+in manual stack traceback.
+
+.TP 8
+mm 0xc0252110 0x25
+Change the memory location at 0xc0252110 to the value 0x25.
+
+.TP 8
+md chrdev_table 15
+Display 15 lines (at 16 bytes per line) starting at address 
+represented by the symbol \fIchrdev_table\fP.
diff -uNr linux.orig/Documentation/kdb/kdb_rd.man linux/Documentation/kdb/kdb_rd.man
--- linux.orig/Documentation/kdb/kdb_rd.man	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb_rd.man	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,114 @@
+.TH RD 1 "1 June 2003"
+.SH NAME
+rd, rm\- Register manipulation commands
+.SH SYNOPSIS
+rd [[c [n]]|d|u]
+.LP
+rm \fIregister-name\fP \fInew-contents\fP
+.LP
+ef <address>
+.SH DESCRIPTION
+The
+.B rd 
+command is used to display the contents of processor and coprocessor registers.
+Without any arguments, the rd command displays the contents of
+the general register set at the point at which the kernel debugger
+was entered. 'n' argumnet is only used for XScale platform to identify
+the want coprocessor number, while 'd' option is not valid for XScale platform.
+.P
+On IA32 and IA64, with the 'c' argument, the processor control registers
+%cr0, %cr1, %cr2 and %cr4 are displayed, while with the 'd' argument
+the processor debug registers are displayed.  If the 'u' argument
+is supplied, the registers for the current task as of the last
+time the current task entered the kernel are displayed.
+.P
+On XScale, 'c' argument is used to display the 
+all coprocessor control registers or specified coprocessor registers by 
+argumnet 'n'. Argument 'u' is used to display the 
+registers for the current task as of the last time the current task
+entered the kernel. Argument 'd' is not supported.
+.P
+On ix86, the
+.B rm
+command allows modification of a register.  The following 
+register names are valid:  \fB%eax\fP, \fB%ebx\fP, \fB%ecx\fP,
+\fB%edx\fP, \fB%esi\fP, \fB%edi\fP, \fB%esp\fP, \fB%eip\fP, 
+and \fB%ebp\fP.   Note that if two '%' symbols are used 
+consecutively, the register set displayed by the 'u' argument
+to the \fBrd\fP command is modified.
+.P
+The debug registers, \fBdr0\fP through \fBdr3\fP and both
+\fBdr6\fP and \fBdr7\fP can also be modified with the \fBrm\fP
+command.
+.P
+On sparc64, the valid registers are named \fB%g0\fP through
+\fB%g7\fP, \fB%l0\fP through \fB%l7\fP, \fB%o0\fP through
+\fB%o7\fP, and \fB%i0\fP through \fB%i7\fP, with the exceptions
+that \fB%o6\fP is called \fB%sp\fP and that \fB%i6\fP is called
+\fB%fp\fP. The registers \fB%tstate\fP, \fB%tpc\fP, \fB%tnpc\fP,
+\fB%y\fP, and \fB%fprs\fP provide state information at the time
+the system entered kdb. Additionally, when viewing registers, two
+convenience names are provided: \fB%&regs\fP shows the
+address on the stack of the current registers, and \fB%csp\fP
+shows the current stack pointer within kdb itself.
+.P
+While on XScale, both the cpu registers and most coprocessor
+registers can be be modified. \fIregister-name\fP can be followings like
+r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14,
+r15, cpsr to address  cpu registers. For the coprocessor registers in XSacle,
+either alias name or \fICpcc[CRndd[CRmbb[Opaa]]]\fP can be used to address
+the register in coprocessor cc with CRn=dd, CRm=bb and opcode2=aa. All aa, bb, cc, dd can be 
+1 or 2 decimal digitals, the default value is 0 when any of them is omitted. Name 
+acc0_h and acc0_l are used to identify the high byte and
+low word of accumulator in coprocessor 0.
+.P
+The
+.B ef
+command displays an exception frame at the specified address.
+.SH LIMITATIONS
+Currently the \fBrm\fP command will not allow modification of the
+control registers.
+.P
+Currently neither the \fBrd\fP command nor the \fBrm\fP command will
+display or modify the model specific registers on the Pentium
+and Pentium Pro families.
+.SH ENVIRONMENT
+None.
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.TP 8
+rd
+Display general register set.
+
+.TP 8
+rd c 0
+Display coprocessor 0 registers.
+
+.TP 8
+rm %eax 0
+Set the contents of \fB%eax\fP to zero.  This will be the
+value of %eax when kdb returns from the condition which 
+invoked it.
+
+.TP 8
+rm %%eax 0
+Set the value of the \fB%eax\fP register to zero.  This will
+be the value the user-mode application will see upon returning
+from the kernel.
+
+.TP 8
+rm %acc0_h 0
+Set the contents of high byte of accumulator to zero.
+
+.TP 8
+rm dr0 0xc1287220
+Set the value of the \fBdr0\fB register to \f(CW0xc1287220\fP.
+
+.TP 8
+rm %InVLD_BTB 0
+Write 0 to coprocessor 15 register with CRn=7, CRm=5, opcode2=6.
+
+.TP 8
+rm %CP15CRn7CRm5Op6 0
+Same with above.
diff -uNr linux.orig/Documentation/kdb/kdb_sr.man linux/Documentation/kdb/kdb_sr.man
--- linux.orig/Documentation/kdb/kdb_sr.man	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb_sr.man	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,68 @@
+.TH SR 1 "7 October 2002"
+.SH NAME
+sr \- invoke sysrq commands from kdb
+.SH SYNOPSIS
+sr \fIx\fP
+.SH DESCRIPTION
+.hy 0
+The
+.B sr 
+command invokes the existing sysrq handler code in the kernel.
+This command takes a single character which is passed to sysrq
+processing, as if you had entered the sysrq key sequence followed by
+that character.
+.P
+.B Caveats:
+.P
+kdb will always call the sysrq code but sysrq may be disabled.
+If you expect to use sysrq functions during debugging then
+.IP ""
+echo "1" > /proc/sys/kernel/sysrq
+.P
+before starting the debug session.
+Alternatively issue
+.IP ""
+mm4 sysrq_enabled 1
+.P
+during debugging.
+.P
+The sysrq code prints a heading using console loglevel 7 then reverts
+to the original loglevel for the rest of the sysrq processing.
+If the rest of the sysrq output is printed at a level below your
+current loglevel then you will not see the output on the kdb console,
+the output will only appear in the printk buffer.
+It is the user's responsibility to set the loglevel correctly if they
+want to see the sysrq output on the console.
+Issue
+.IP ""
+sr 7
+.P
+before any other
+.B sr
+commands if you want to see the output on the console.
+You may even have to adjust the default message loglevel in order to
+see any output from
+.BR sr .
+See Documentation/sysctl/kernel.txt for details on setting console
+loglevels via /proc.
+You can also adjust the loglevel variables via kdb
+.BR mm ;
+on older kernels there are variables such as default_message_level, on
+newer kernels all the loglevel variables are in array console_printk,
+see kernel/printk.c for your kernel.
+.P
+Operations that require interrupt driven I/O can be invoked from kdb
+.BR sr ,
+but they will not do anything until you type 'go' to exit from kdb
+(interrupts are disabled while in kdb).
+There is no guarantee that these operations will work, if the machine
+entered kdb because of an error then interrupt driven I/O may already
+be dead.
+Do not assume that
+.B sr\ s
+does anything useful.
+.P
+The sysrq handler uses locks and calls printk which also uses locks.
+If the sysrq handler or any of the sysrq functions have to wait for a
+lock then they will never return and kdb will appear to hang.
+Invoking sysrq code from kdb is inherently unsafe.
diff -uNr linux.orig/Documentation/kdb/kdb_ss.man linux/Documentation/kdb/kdb_ss.man
--- linux.orig/Documentation/kdb/kdb_ss.man	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/kdb_ss.man	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,109 @@
+.TH SS 1 "17 January 2002"
+.SH NAME
+ss, ssb \- Single Step 
+.SH SYNOPSIS
+ss
+.LP
+ssb 
+.SH DESCRIPTION
+The
+.B ss
+command is used to execute a single instruction and return
+to the kernel debugger.
+.P
+Both the instruction that was single-stepped and the next
+instruction to execute are printed. 
+.P
+The \fBssb\fP command will execute instructions from the
+current value of the instruction pointer.  Each instruction
+may be printed as it is executed, depending upon architecture;
+execution will stop at any instruction which would cause the flow 
+of control to change (e.g. branch, call, interrupt instruction, 
+return, etc.)
+.SH LIMITATIONS
+On sparc64, there are some circumstances where single-stepping
+can be dangerous. Do not single-step across an instruction which
+changes the interrupt-enable bit in %tstate. Do not single step
+through code which is invoked when entering or leaving the
+kernel, particularly any kernel entry code before %tl is set to
+0, or any kernel exit code after %tl is set to 1.
+.SH ENVIRONMENT
+None.
+.SH SMP CONSIDERATIONS
+Other processors are held in the kernel debugger when the instruction
+is traced.  Single stepping though code that requires a lock which is
+in use by another processor is an exercise in futility, it will never
+succeed.
+.SH INTERRUPT CONSIDERATIONS
+When a kdb event occurs, one cpu (the initial cpu) enters kdb state.
+It uses a cross system interrupt to interrupt the
+other cpus and bring them all into kdb state.  All cpus run with
+interrupts disabled while they are inside kdb, this prevents most
+external events from disturbing the kernel while kdb is running.
+.B Note:
+Disabled interrupts means that any I/O that relies on interrupts cannot
+proceed while kdb is in control, devices can time out.  The clock tick
+is also disabled, machines will lose track of time while they are
+inside kdb.
+.P
+Even with interrupts disabled, some non-maskable interrupt events
+will still occur, these can disturb the kernel while you are
+debugging it.  The initial cpu will still accept NMI events,
+assuming that kdb was not entered for an NMI event.  Any cpu
+where you use the SS or SSB commands will accept NMI events, even
+after the instruction has finished and the cpu is back in kdb.
+This is an unavoidable side effect of the fact that doing SS[B]
+requires the cpu to drop all the way out of kdb, including
+exiting from the NMI event that brought the cpu into kdb.  Under
+normal circumstances the only NMI event is for the NMI oopser and
+that is kdb aware so it does not disturb the kernel while kdb is
+running.
+.P
+Sometimes doing SS or SSB on ix86 will allow one interrupt to proceed,
+even though the cpu is disabled for interrupts.  I have not been able
+to track this one down but I suspect that the interrupt was pending
+when kdb was entered and it runs when kdb exits through IRET even
+though the popped flags are marked as cli().  If any ix86 hardware
+expert can shed some light on this problem, please notify the kdb
+maintainer.
+.SH EXAMPLES
+.nf
+.na
+.ft CW
+kdb> bp gendisk_head datar 4
+Data Access Breakpoint #0 at 0xc024ddf4 (gendisk_head) in dr0 is enabled on cpu 0
+for 4 bytes
+kdb> go
+...
+[root@host /root]# cat /proc/partitions
+Entering kdb on processor 0 due to Debug Exception @ 0xc01845e3
+Read/Write breakpoint #0 at 0xc024ddf4
+[0]kdb> ssb
+sd_finish+0x7b:  movzbl 0xc02565d4,%edx
+sd_finish+0x82:  leal   0xf(%edx),%eax
+sd_finish+0x85:  sarl   $0x4,%eax
+sd_finish+0x88:  movl   0xc0256654,%ecx
+sd_finish+0x8e:  leal   (%eax,%eax,4),%edx
+sd_finish+0x91:  leal   (%eax,%edx,2),%edx
+sd_finish+0x94:  movl   0xc0251108,%eax
+sd_finish+0x99:  movl   %eax,0xffffffc(%ecx,%edx,4)
+sd_finish+0x9d:  movl   %ecx,0xc0251108
+sd_finish+0xa3:  xorl   %ebx,%ebx
+sd_finish+0xa5:  cmpb   $0x0,0xc02565d4
+[0]kdb> go
+[root@host /root]# 
+
+[0]kdb> ss
+sys_read:   pushl  %ebp
+SS trap at 0xc01274c1
+sys_read+0x1:   movl   %esp,%ebp
+[0]kdb> ss
+sys_read+0x1:   movl   %esp,%ebp
+SS trap at 0xc01274c3
+sys_read+0x3:   subl   $0xc,%esp
+[0]kdb> ss
+sys_read+0x3:   subl   $0xc,%esp
+SS trap at 0xc01274c6
+sys_read+0x6:   pushl  %edi
+[0]kdb>
+
diff -uNr linux.orig/Documentation/kdb/slides linux/Documentation/kdb/slides
--- linux.orig/Documentation/kdb/slides	Thu Jan  1 08:00:00 1970
+++ linux/Documentation/kdb/slides	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,1383 @@
+#! /opt/cpg/bin/do-mgp
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%deffont "standard" tfont "comic.ttf"
+%deffont "thick" tfont "arialb.ttf"
+%deffont "typewriter" xfont "courier new-bold-r"
+%deffont "type2writer" xfont "arial narrow-bold-r"
+%%
+%% Default settings per each line numbers.
+%%
+#%default 1 leftfill, size 2, fore "black", back "LemonChiffon2", font "thick"
+%default 1 leftfill, size 2, fore "black", back "white", font "thick"
+%default 2 size 10, vgap 10, prefix " ", center
+%default 3 size 2, bar "gray70", vgap 10
+%default 4 size 6, fore "black", vgap 30, prefix " ", font "standard", left
+%%
+%% Default settings that are applied to TAB-indented lines.
+%%
+%tab 1 size 4, vgap 35, prefix "  ", icon arc "red" 40
+%tab 2 size 4, vgap 20, prefix "      ", icon delta3 "blue" 40
+%tab 3 size 4, vgap 20, prefix "            ", icon delta3 "green" 40 
+%%
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+KDB - Kernel Debugger
+
+
+
+%size 7,center, font "thick"
+Introduction
+
+And 
+
+Demonstration
+
+
+%size 3
+
+February 5, 2002                                   IBM Linux Technology Center                                   Paul Dorwin
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+IBM Legal 
+
+
+	IBM Legal requires this information:
+
+%size 3 
+
+        THE INFORMATION IN THE FOLLOWING PRESENTATION IS PREPARED 
+        SOLELY FOR THE INFORMATION OF THE READER, AND COMES "AS IS"
+        AND WITHOUT WARRANTY OR REPRESENATION OF ANY KIND.  
+
+        ANY PARTY USING THE MATERIALS IN THIS PRESENTATION DOES SO 
+        AT ITS OWN RISK LIABILITY AND THE PROVIDER OF THE MATERIALS 
+        ACCEPTS NO RISK OR LIABILITY FOR SUCH USE OR RESULTING FROM 
+        DISSEMINATION TO OR USE BY ANY OTHER PARTY
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Agenda
+
+%size 5
+
+        Installing and Configuring KDB
+
+        KDB Commands
+
+        Scull Demo
+
+                Setting Breakpoints 
+
+                Displaying Data Structures
+
+        Kernel Data structures
+
+                Take a walk through an IO operation
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Installing Configuring KDB
+
+
+	Install KDB patch.
+		Start with a clean source tree
+		Apply architecture specific patches
+		Obtain patch for your kernel version
+			see http://oss.sgi.com/projects/kdb/
+		Apply the kdb patch
+			patch -p 1 -N -u -i /path/to/patch
+		Apply any other patches
+		Build and reboot on your kdb enabled kernel
+		Man pages can be found at Documentation/kdb
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Configuring KDB
+
+
+	Config kernel with the following options:
+		These are documented in Documentation/Configure.help
+
+		CONFIG_KDB=y
+			Enable compilation of KDB in the kernel..
+			Setting this also sets CONFIG_KALLSYMS=y.
+		CONFIG_KDB_MODULES=n
+			KDB may be extended, compiling kdb/modules.
+		CONFIG_KDB_OFF=n
+			y = KDB is disabled  by default. 
+			boot with kdb=on to enable at boot.
+			/proc/sys/kernel/kdb to enable/disable when system is up.
+		CONFIG_KALLSYMS=y
+			This causes all symbols to be exported.
+		CONFIG_FRAME_POINTER=y
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Invoking KDB
+
+
+	KDB can be invoked in the following ways:
+
+		Early init with "kdb=early" lilo flag 
+			Hits breakpoint prior to fork_init() (init/main.c)
+
+		Serial console with CNTRL-A
+
+		Console with PAUSE key 
+
+		When a pre-set breakpoint is hit
+
+		On panic
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+KDB Commands
+
+
+	KDB environment
+		env				Show environment variables
+		set				Set environment variables
+		help			Display Help Message
+		?				Display Help Message
+
+	System related
+		sections			List kernel and module sections
+		lsmod			List loaded kernel modules
+		rmmod	<modname>	Remove a kernel module
+		reboot			Reboot the machine immediately
+		cpu		<cpunum>	Switch to new cpu
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+KDB Commands
+
+
+	Memory Manipulation
+		md		<vaddr>		Display Memory Contents
+		mdr	<vaddr> <bytes>	Display Raw Memory
+		mds	<vaddr>		Display Symbolically
+		mm	<vaddr> <value>	Modify Memory Contents
+		id		<vaddr>		Display Instructions
+
+	Register Manipulation
+		rd				Display Registers
+		rm		<reg> <value> 	Modify Registers
+		ef		 <vaddr>		Display exception frame
+
+	Stack
+		bt		[<vaddr>]	Stack traceback
+		btp		 <pid>		Display stack for <pid>
+		bta				Display all stacks
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+KDB Commands
+
+
+	Breakpoint
+		bc		 <bpnum>	Clear Breakpoint
+		bd		 <bpnum>	Disable Breakpoint
+		be		 <bpnum>	Enable Breakpoint
+		bl		[<vaddr>]	Display breakpoints
+		bp		[<vaddr>]	Set/Display breakpoints
+		bpa		[<vaddr>]	Set/Display global breakpoints
+		bph	[<vaddr>]	Set hardware breakpoint
+		bpha	[<vaddr>]	Set global hardware breakpoint
+		bp* modifiers:
+			instruction - break on instruction fetch (default)
+			datar - break on read  at vaddr
+			dataw - break on write at vaddr
+			IO - break on in or out op at vaddress
+
+	Execution control
+		go		  [<vaddr>]	Continue Execution
+		ss  		  [<#steps>]	Single Step
+		ssb				Single step to branch/call
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+KDB Commands
+
+
+	Kernel structures
+		ll <vaddr> <offset> <command>	Traverse list and execute command 
+		ps				Display active task list
+		vm		<vaddr>		Display vm_area_struct
+		dentry	<dentry>		Display interesting dentry stuff
+		filp		<filp>		Display interesting filp stuff
+		sh		<vaddr>		Show scsi_host
+		sd		<vaddr>		Show scsi_device
+		sc		<vaddr>		Show scsi_cmnd
+		kiobuf	<vaddr>		Display kiobuf
+		page	<vaddr>		Display page
+		inode	<vaddr>		Display inode
+		bh		<vaddr>		Display buffer head 
+		inode_pages	<inode *>	Display pages in an inode
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo
+
+
+	Objective
+		Find and display the data associated with a scull device
+
+	The sequence of events
+		Populate the scull device with data
+		Identify the breakpoints
+		Set breakpoint in the device read function
+		Identify the data structure elements
+		Identify device structures used to track data
+		Display data structures containing the data
+		Show the usage of the filp command
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: Populate Device
+
+
+	Obtain the code
+		Surf to http://examples.oreilly.com/linuxdrive2/
+		Download the tarball
+		Untar it to /usr/src
+
+	Build and install the module
+		cd /usr/src/ldd2-samples-1.0.1/scull
+		make
+		./scull.init start
+
+	Populate the scull device
+		cat main.c > /dev/scull0
+		cat /dev/scull0
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: Driver Details
+
+
+	cat /dev/scull0
+		fd = 
+%fore "blue", cont
+open
+%fore "black", cont
+("/dev/scull0", O_RDONLY);
+			Kernel finds the file_operations structure
+			Kernel then invokes the open function
+%fore "blue"
+		read
+%fore "black", cont
+(fd, buf, size);
+			Kernel finds the file_operations structure
+			Kernel then invokes the read function
+
+	Scull device file operations structure
+
+%font "typewriter", size 3
+    struct file_operations scull_fops = {
+        llseek:     scull_llseek,
+%fore "blue"
+        read:       scull_read,
+%fore "black"
+        write:      scull_write,
+        ioctl:      scull_ioctl,
+%fore "blue"
+        open:       scull_open,
+%fore "black"
+        release:    scull_release,
+    };
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: Driver Details
+
+%font "typewriter", size 3
+	scull_open code
+%font "typewriter", size 3
+    int 
+%fore "blue", cont
+scull_open
+%fore "black", cont
+(struct inode *inode, struct file *filp)
+    {
+        Scull_Dev *dev; /* device information */
+        int num = NUM(inode->i_rdev);
+
+        <snip>
+
+        dev = (Scull_Dev *)filp->private_data;
+        if (!dev) {
+            if (num >= scull_nr_devs) return -ENODEV;
+%fore "blue"
+            dev = &scull_devices[num];
+            filp->private_data = dev;
+%fore "black"
+        }
+
+        <snip>
+
+    }
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: Driver Details
+
+%font "typewriter", size 3
+	scull_read code
+%font "typewriter", size 3
+    ssize_t 
+%fore "blue", cont
+scull_read
+%fore "black", cont
+(struct file *filp, char *buf, size_t count,
+            loff_t *f_pos)
+    {
+
+%fore "blue", cont
+        Scull_Dev *dev = filp->private_data;
+%fore "black", cont
+ /* the first listitem */
+%fore "blue"
+        Scull_Dev *dptr;
+%fore "black"
+        int quantum = dev->quantum;
+        int qset = dev->qset;
+        int itemsize = quantum * qset;
+        if (down_interruptible(&dev->sem))
+                return -ERESTARTSYS;
+        if (*f_pos + count > dev->size)
+            count = dev->size - *f_pos;
+
+        /* find listitem, qset index, and offset in the quantum */
+        item = (long)*f_pos / itemsize;
+        rest = (long)*f_pos % itemsize;
+        s_pos = rest / quantum; q_pos = rest % quantum;
+
+        /* follow the list up to the right position */
+%fore "blue"
+        dptr = scull_follow(dev, item);
+%fore "black"
+
+        <snip>
+
+    }
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: Breakpoints
+
+
+%font "typewriter", size 3
+	Determine where to set breakpoint
+%font "typewriter", size 3
+%fore "blue"
+        dptr = scull_follow(dev, item);
+%fore "black"
+
+%font "typewriter", size 3
+	Disassemble scull_read
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+id scull_read
+%fore "black"
+    0xf8c083b4 scull_read:  push   %ebp
+    0xf8c083b5 scull_read+0x1:mov    %esp,%ebp
+    0xf8c083b7 scull_read+0x3:push   %edi
+            <snip>
+    0xf8c08465 scull_read+0xb1:sub    $0x8,%esp
+%fore "blue"
+    0xf8c08468 scull_read+0xb4:push   %ecx
+    0xf8c08469 scull_read+0xb5:push   %esi
+    0xf8c0846a scull_read+0xb6:call   0xf8c08364 scull_follow: 
+%fore "black"
+    0xf8c0846f scull_read+0xbb:mov    %eax,
+%fore "blue", cont
+ %edx 
+%fore "black"
+    0xf8c08471 
+%fore "blue", cont
+scull_read+0xbd
+%fore "black", cont
+:add    $0x10,%esp
+            <snip>
+
+	Set breakpoint in driver read
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue",cont
+bp scull_read+0xbd
+%fore "black"
+    Instruction(i) BP #0 at 0xf8c08471 ([scull]scull_read+0xbd)
+        is enabled globally adjust 1
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: Breakpoints
+
+
+%font "typewriter", size 3
+	Restart the system
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+go
+%fore "black"
+
+	Hit the Breakpoint
+%font "typewriter", size 3
+    [root@elm3b77 root]# 
+%fore "blue", cont
+cat /dev/scull0
+%fore "black"
+    Instruction(i) breakpoint #0 at 0xf8c08471 (adjusted)
+    0xf8c08471 scull_read+0xbd:int3   
+    Entering kdb (current=0xf73ec000, pid 1249) on processor 2 
+                  due to Breakpoint @ 0xf8c08471
+
+	Display the registers
+%font "typewriter", size 3
+    [2]kdb> 
+%fore "blue", cont
+rd
+%fore "black"
+    eax = 0xf77d7b60 ebx = 0x00000000 ecx = 0x00000000 edx = 
+%fore "blue", cont
+0xf77d7b60
+%fore "black"
+    esi = 
+%fore "blue", cont
+0xf77d7b60
+%fore "black", cont
+ edi = 0x00001000 esp = 0xf7415f40 eip = 0xf8c08471 
+    ebp = 0xf7415f78 xss = 0x00000018 xcs = 0x00000010 eflags = 0x00000246
+    xds = 0xf7590018 xes = 0x00000018 origeax = 0xffffffff &regs = 0xf7415f0c
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: Data Structures
+
+%font "typewriter", size 3
+	Display the Scull_Dev structure 
+%font "typewriter", size 3
+    [2]kdb> 
+%fore "blue", cont
+md 0xf77d7b60 2
+%fore "black"
+    0xf77d7b60 
+%fore "blue", cont
+f7400000
+%fore "black", cont
+ 00000000 00000fa0 000003e8   ..@w.... ...h...
+    0xf77d7b70 0000534e 00000000 00000000 00000000   NS..............
+
+	Scull Device Structure
+%font "typewriter", size 3
+    typedef struct Scull_Dev {
+%fore "blue"
+       void **data;
+%fore "black"
+       struct Scull_Dev *next;   /* next listitem */
+       int quantum;              /* the current quantum size */
+       int qset;                 /* the current array size */
+       unsigned long size;
+       devfs_handle_t handle;    /* only used if devfs is there */
+       unsigned int access_key;  /* used by sculluid and scullpriv */
+       struct semaphore sem;     /* mutual exclusion semaphore     */
+    } Scull_Dev;
+%size 6
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: Data Structures
+
+
+%font "typewriter", size 3
+	Display the quantum set (dev->data)
+%font "typewriter", size 3
+    [2]kdb> 
+%fore "blue", cont
+md f7400000 2
+%fore "black"
+    0xf7400000 
+%fore "blue", cont
+f73ea000
+%fore "black", cont
+ f73f1000 f740c000 f7ab4000   . >w..?w.@@w.@+w
+    0xf7400010 f73ef000 f755b000 00000000 00000000   .p>w.0Uw........
+
+	Display the first quantum (dev->data[0])
+%font "typewriter", size 3
+    [2]kdb> 
+%fore "blue", cont
+md f73ea000
+%fore "black"
+    0xf73ea000 200a2a2f 616d202a 632e6e69 202d2d20   /*. * main.c -- 
+    0xf73ea010 20656874 65726162 75637320 63206c6c   the bare scull c
+    0xf73ea020 20726168 75646f6d 200a656c 2a200a2a   har module. *. *
+    0xf73ea030 706f4320 67697279 28207468 32202943    Copyright (C) 2
+    0xf73ea040 20313030 73656c41 646e6173 52206f72   001 Alessandro R
+    0xf73ea050 6e696275 6e612069 6f4a2064 6874616e   ubini and Jonath
+    0xf73ea060 43206e61 6562726f 2a200a74 706f4320   an Corbet. * Cop
+    0xf73ea070 67697279 28207468 32202943 20313030   yright (C) 2001 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: filp command
+
+
+%font "typewriter", size 3
+	Show filp usage - here is the scull_read prototype
+%font "typewriter", size 3
+    ssize_t scull_read(
+%fore "blue", cont
+struct file *filp
+%fore "black", cont
+, char *buf, 
+                       size_t count, loff_t *f_pos);
+	Show the stack trace:
+%font "typewriter", size 3
+[2]kdb> 
+%fore "blue", cont
+bt
+%fore "black"
+    EBP       EIP         Function(args)
+    0xee9dbf78 0xf8c08471 [scull]scull_read+0xbd (
+%fore "blue", cont
+0xeaf6c0c0
+%fore "black", cont
+, 0x804e128, 
+                                          0x1000, 0xeaf6c0e0, 0x804f000)
+                     scull .text 0xf8c08060 0xf8c083b4 0xf8c084dc
+    0xee9dbfbc 0xc0136278 sys_read+0x98 (0x3, 0x804e128, 0x1000, ...
+                     kernel .text 0xc0100000 0xc01361e0 0xc01362b0
+               0xc010702b system_call+0x33
+                     kernel .text 0xc0100000 0xc0106ff8 0xc0107030
+	And show the filp output
+%font "typewriter", size 3
+    [2]kdb> 
+%fore "blue", cont
+filp 0xeaf6c0c0
+%fore "black"
+    name.name 0xe93889fc  name.len  6
+    File Pointer at 0xeaf6c0c0
+     f_list.nxt = 0xe42deca0 f_list.prv = 0xf7e69070
+%fore "blue"
+     f_dentry = 0xe93889a0
+%fore "black", cont
+ f_op = 0xf8c0a200
+     f_count = 2 f_flags = 0x8000 f_mode = 0x1
+     f_pos = 0 f_reada = 0 f_ramax = 0
+     f_raend = 0 f_ralen = 0 f_rawin = 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Scull Demo: filp command
+
+
+%font "typewriter", size 3
+	filp output - continued
+%font "typewriter", size 3
+%fore "blue"
+    Directory Entry at 0xe93889a0
+%fore "black"
+     d_name.len = 6 
+%fore "orange", cont
+d_name.name = 0xe93889fc
+%fore "black", cont
+>
+     d_count = 1 d_flags = 0x0 
+%fore "blue", cont
+d_inode = 0xe827b680
+%fore "black"
+     d_hash.nxt = 0xc215aec8 d_hash.prv = 0xc215aec8
+     d_lru.nxt = 0xe93889b8 d_lru.prv = 0xe93889b8
+     d_child.nxt = 0xe89e1e80 d_child.prv = 0xe9388940
+     d_subdirs.nxt = 0xe93889c8 d_subdirs.prv = 0xe93889c8
+     d_alias.nxt = 0xe827b690 d_alias.prv = 0xe827b690
+     d_op = 0x00000000 d_sb = 0xf7e69000
+
+%fore "blue"
+    Inode Entry at 0xe827b680
+%fore "black"
+     i_mode = 0x21a4  i_nlink = 1  i_rdev = 0xfe00
+     i_ino = 37182 i_count = 1 i_dev = 0x821
+     i_hash.nxt = 0xc20e6be8 i_hash.prv = 0xc20e6be8
+     i_list.nxt = 0xe827b2c8 i_list.prv = 0xe827b868
+     i_dentry.nxt = 0xe93889d0 i_dentry.prv = 0xe93889d0
+
+	Check the filename (display d_name.name)
+%font "typewriter", size 3
+    [2]kdb> 
+%fore "orange", cont
+md 0xe93889fc 1
+%fore "black"
+    0xe93889fc 6c756373 0000306c 00000000 00000000   scull0..........
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Kernel Structures
+
+
+	Objective
+		Show output from various kernel related kdb commands
+
+	Sequence of events
+		Simple Program
+			Write a simple program which allocates memory and hangs
+			Show usage of the ps, vm, and ll commands
+		Walk an IO operation
+			Hit a breakpoint in qlogic driver (isp1020_queuecommand)
+			Show usage of scsi related commands (sc, sh, and sd)
+			Show usage of vm related commands (bh, page, inode, inode_pages)
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Simple program
+
+%font "typewriter", size 3
+	simple.c - simple program which allocates memory
+%font "typewriter", size 3
+%fore "blue"
+    int foo_global[8192];
+%fore "black"
+    main()
+    {
+        int *
+%fore "blue", cont
+foo_malloc;
+%fore "black"
+        int i;
+        foo_malloc = (int *)malloc(0x8192);
+        for(i = 0; i < 0x100; i++) {
+            foo_global[i] = 0xdead0000 | i;
+            foo_malloc[i] = 0xbeef0000 | i;
+        }
+        printf("foo_global at %x\n", (int)foo_global);
+        printf("foo_malloc at %x\n", (int)foo_malloc);
+        printf("sleep forever\n");
+        sleep(2000000);
+    }
+
+	simple output
+%font "typewriter", size 3
+    [root@elm3b77 scull]# cc -o simple simple.c
+    [root@elm3b77 scull]# ./simple
+    foo_global at 
+%fore "blue", cont
+8049780
+%fore "black"
+    foo_malloc at 
+%fore "blue", cont
+8051788
+%fore "black"
+    sleep forever
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Simple Program
+
+%font "typewriter", size 3
+	Show the output of the ps command
+%font "typewriter", size 3
+    Entering kdb (current=0xc2010000, pid 0) on processor 3 due to
+                                             Keyboard Entry
+    [3]kdb> 
+%fore "blue", cont
+ps
+%fore "black"
+    Task Addr  Pid      Parent   [*] cpu  State Thread     Command
+    0xf7efe000 00000001 00000000  0  003  stop  0xf7efe370 init
+    0xf7ef0000 00000002 00000001  0  001  stop  0xf7ef0370 keventd
+    0xf7eec000 00000003 00000000  0  000  stop  0xf7eec370 ksoftirqd_CPU0
+    0xf7eea000 00000004 00000000  0  001  stop  0xf7eea370 ksoftirqd_CPU1
+    0xf7ee8000 00000005 00000000  0  002  stop  0xf7ee8370 ksoftirqd_CPU2
+    0xf7ee6000 00000006 00000000  0  003  stop  0xf7ee6370 ksoftirqd_CPU3
+
+                         <snip>
+
+    0xf7b46000 00001006 00000737  0  003  stop  0xf7b46370 sshd
+    0xf7ace000 00001007 00001006  0  000  stop  0xf7ace370 bash
+    0xef06a000 00001066 00001007  0  003  stop  0xef06a370 su
+    0xeef88000 00001067 00001066  0  000  stop  0xeef88370 bash
+    0xeef64000 00001119 00000770  0  001  stop  0xeef64370 in.ftpd
+%fore "blue"
+    0xeeeac000
+%fore "black", cont
+ 00001138 00001067  0  001  stop  0xeeeac370 
+%fore "blue", cont
+simple
+%fore "black"
+    [3]kdb>
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Simple Program
+
+%font "typewriter", size 3
+	Display the task struct
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+md 0xeeeac000
+%fore "black"
+    0xeeeac000 00000001 00000000 00000000 c0000000   ................
+    0xeeeac010 c0339880 00000000 00000000 ffffffff   ................
+    0xeeeac020 0000000a 00000000 00000000 
+%fore "blue", cont
+f7e10f00
+%fore "black", cont
+   ..............aw
+    0xeeeac030 00000001 ffffffff ffffffff 00000000   ................
+
+%font "typewriter", size 3
+	Determine offset of mm_struct ptr in task_struct
+%font "typewriter", size 3
+    struct task_struct {
+      [0]   volatile long state;      
+      [4]   unsigned long flags;      
+      [8]   int sigpending;
+      [c]   mm_segment_t addr_limit;  
+      [10]  struct exec_domain *exec_domain;
+      [14]  volatile long need_resched;
+      [18]  unsigned long ptrace;
+      [1c]  int lock_depth;           
+      [20]  long counter;
+      [24]  long nice;
+      [28]  unsigned long policy;
+%fore "blue"
+      [2c]  struct mm_struct *mm;
+%fore "black"
+      [30]  int processor;
+      [34]  unsigned long cpus_runnable, cpus_allowed;
+    	<snip>
+    };
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Simple Program
+
+
+%font "typewriter", size 3
+	Display the mm_struct associated with simple process
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+md f7e10f00
+%fore "black"
+    0xf7e10f00 
+%fore "blue", cont
+e8357a80
+%fore "black", cont
+ e8357978 f7ac77e0 eb15eac0   .z5hxy5h`w,w@j.k
+    0xf7e10f10 00000001 00000002 0000000b 00000000   ................
+    0xf7e10f20 00000001 f7e10f24 f7e10f24 00000001   ................
+    0xf7e10f30 f7e35e70 eea7e8f0 08048000 0804862b   ................
+    0xf7e10f40 0804962c 08049744 08051780 0805a000   ................
+    0xf7e10f50 bffffd10 bffffe00 bffffe09 bffffe09   ................
+    0xf7e10f60 bffffff3 0000005a 00000168 00000000   ................
+    0xf7e10f70 00000000 00000002 00000000 00000001   ................
+
+%font "typewriter", size 3
+	Determine offset of the first vma in the process
+%font "typewriter", size 3
+    struct mm_struct {
+%fore "blue"
+            struct vm_area_struct * mmap;	
+%fore "black"
+            rb_root_t mm_rb;
+            struct vm_area_struct * mmap_cache;	
+            <snip>
+    };
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Simple Program
+
+%font "typewriter", size 3
+	Display the first vma using md
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+md  e8357a80
+%fore "black"
+    0xe8357a80 f7e10f00 08048000 08049000 
+%fore "blue", cont
+e8727e00
+%fore "black",cont
+   ..aw.........~rh
+    0xe8357a90 00000025 00001875 e8727e18 00000001   %...u....~rh....
+
+	Display the first vma using vma
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+vma e8357a80
+%fore "black"
+    struct vm_area_struct at 0xe8357a80 for 68 bytes
+    vm_start = 0x8048000   vm_end = 0x8049000
+    page_prot = 0x25
+    flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE 
+%font "typewriter", size 3
+
+	Determine the offset to the vma list
+%font "typewriter", size 3
+    struct vm_area_struct {
+      [0]   struct mm_struct * vm_mm;
+      [4]   unsigned long vm_start;
+      [8]   unsigned long vm_end;
+%fore "blue"
+      [c]   struct vm_area_struct *vm_next;
+%fore "black"
+            <snip>
+    };
+	Display the next vma
+%font "typewriter", size 3
+    [3]kdb> vma e8727e00
+    struct vm_area_struct at 0xe8727e00 for 68 bytes
+    vm_start = 0x8049000   vm_end = 0x804a000
+    page_prot = 0x25
+    flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Simple Program
+
+%font "typewriter", size 3
+	Use the ll command to display the list of vma's
+%font "typewriter", size 3
+        [3]kdb> ll e8357a80 0xc vma
+.
+        struct vm_area_struct at 0xe8357a80 for 68 bytes
+        vm_start = 0x8048000   vm_end = 0x8049000
+        page_prot = 0x25
+        flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE 
+.
+        struct vm_area_struct at 0xe8727e00 for 68 bytes
+        vm_start = 
+%fore "orange", cont
+0x8049000
+%fore "black", cont
+   vm_end = 
+%fore "orange", cont
+0x804a000
+%fore "black"
+        page_prot = 0x25
+        flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE 
+.
+        struct vm_area_struct at 0xe8727c80 for 68 bytes
+        vm_start = 
+%fore "blue", cont
+0x804a000
+%fore "black", cont
+   vm_end = 
+%fore "blue", cont
+0x805a000
+%fore "black"
+        page_prot = 0x25
+        flags:  READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC 
+        <snip>
+        struct vm_area_struct at 0xe8357900 for 68 bytes
+        vm_start = 0xbfffe000   vm_end = 0xc0000000
+        page_prot = 0x25
+        flags:  READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC GROWSDOWN 
+
+	Match the vma to the displayed addresses
+%font "typewriter", size 3
+        foo_global  at 
+%fore "orange", cont
+8049780
+%fore "black"
+        foo_malloc at 
+%fore "blue", cont
+8051788
+%fore "black"
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+	Objective
+		Show usage of various scsi and vm related kdb commands
+
+	Sequence:
+		Set a breakpoint in the scsi driver
+			Stops when queueing a command to the controller
+		Cause IO on an idle disk
+		Show various IO stack traces
+		Display the IO data structures
+		Display vm information about the data
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Set the breakpoint
+
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+bp isp1020_queuecommand
+%fore "black"
+    Instruction(i) BP #0 at 0xc01ecfe0 (isp1020_queuecommand)
+        is enabled globally adjust 1
+
+%font "typewriter", size 3
+	Create some activity on a previously unused disk
+
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+go
+%fore "black"
+    [root@elm3b77 root]# 
+%fore "blue", cont
+ls /rh62
+%fore "black"
+
+    Instruction(i) breakpoint #0 at 0xc01ecfe0 (adjusted)
+    0xc01ecfe0 isp1020_queuecommand:int3   
+
+    Entering kdb (current=0xf75ba000, pid 1181) on processor 3 due to 
+                                                Breakpoint @ 0xc01ecfe0
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Show the stack.
+	This is a read of the /rh62 directory
+
+%font "typewriter", size 3
+    [1]kdb> 
+%fore "blue", cont
+bt
+%fore "black"
+        EBP       EIP         Function(args)
+    0xf75bbdf4 0xc01ecfe0 isp1020_queuecommand
+               0xc01e2c77 scsi_dispatch_cmd+0x1f7
+    0xf75bbe24 0xc01e99b1 scsi_request_fn+0x2f1
+    0xf75bbe34 0xc01c84fd generic_unplug_device+0x2d
+    0xf75bbe50 0xc011b3af __run_task_queue+0x5f
+    0xf75bbe6c 0xc013a63c block_sync_page+0x1c
+    0xf75bbe98 0xc0128127 __lock_page+0x77
+    0xf75bbea4 0xc0128178 lock_page+0x18
+    0xf75bbec8 0xc012a4b3 read_cache_page+0xc3
+    0xf75bbef4 0xc0168e23 ext2_get_page+0x23
+    0xf75bbf48 0xc0168fdd ext2_readdir+0xfd
+    0xf75bbf68 0xc0143d2e vfs_readdir+0x7e
+    0xf75bbfbc 0xc01442ed 
+%fore "blue", cont
+sys_getdents64+0x4d
+%fore "black"
+               0xc010702b system_call+0x33
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Allow the operation to complete
+
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+go
+%fore "black"
+    bench  build  etc   lib         mnt   oldsys  rh72  spv   usr
+    bin    data   h     linux       mnt1  opt     root  test  var
+    boot   dev    home  lost+found  mnt2  proc    sbin  tmp
+
+%font "typewriter", size 3
+	Force some more activity
+
+%font "typewriter", size 3
+    [root@elm3b77 root]# 
+%fore "blue", cont
+cd /rh62/tmp
+%fore "black"
+    Instruction(i) breakpoint #0 at 0xc01ecfe0 (adjusted)
+    0xc01ecfe0 isp1020_queuecommand:int3 
+
+    Entering kdb (current=0xf768a000, pid 981) on processor 3 due to 
+                                               Breakpoint @ 0xc01ecfe0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Show the stack. 
+	This is an inode read for /rh62/tmp
+
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+bt
+%fore "black"
+        EBP       EIP         Function(args)
+    0xf768bd68 0xc01ecfe0 isp1020_queuecommand
+               0xc01e2c77 scsi_dispatch_cmd+0x1f7
+    0xf768bd98 0xc01e99b1 scsi_request_fn+0x2f1
+    0xf768bda8 0xc01c84fd generic_unplug_device+0x2d
+    0xf768bdc4 0xc011b3af __run_task_queue+0x5f
+    0xf768bdfc 0xc0137216 __wait_on_buffer+0x56
+    0xf768be1c 0xc0138600 bread+0x50
+    0xf768be5c 0xc016b684 ext2_read_inode+0x114
+    0xf768bf0c 0xc013fbec real_lookup+0x7c
+    0xf768bf78 0xc014035d link_path_walk+0x5ad
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Create a new file, causing yet more disk activity
+
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+go
+%fore "black"
+
+    [root@elm3b77 tmp]# 
+%fore "blue", cont
+echo "Hello linux reading group" > j1;sync
+%fore "black"
+
+    Instruction(i) breakpoint #0 at 0xc01ecfe0 (adjusted)
+    0xc01ecfe0 isp1020_queuecommand:int3
+
+    Entering kdb (current=0xf768a000, pid 981) on processor 3 due to 
+                                               Breakpoint @ 0xc01ecfe0
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Show the stack 
+	This is an inode read in response to the open
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+bt
+%fore "black"
+        EBP       EIP         Function(args)
+    0xf768bd78 0xc01ecfe0 isp1020_queuecommand
+               0xc01e2c77 scsi_dispatch_cmd+0x1f7
+    0xf768bda8 0xc01e99b1 scsi_request_fn+0x2f1
+    0xf768bdb8 0xc01c84fd generic_unplug_device+0x2d
+    0xf768bdd4 0xc011b3af __run_task_queue+0x5f
+    0xf768bdf0 0xc013a63c block_sync_page+0x1c
+    0xf768be1c 0xc0128127 __lock_page+0x77
+    0xf768be28 0xc0128178 lock_page+0x18
+    0xf768be4c 0xc012a4b3 read_cache_page+0xc3
+    0xf768be78 0xc0168e23 ext2_get_page+0x23
+    0xf768beb8 0xc01691ed ext2_find_entry+0x8d
+    0xf768bed4 0xc016933a ext2_inode_by_name+0x1a
+    0xf768befc 0xc016c077 ext2_lookup+0x27
+    0xf768bf1c 0xc014094a lookup_hash+0x9a
+    0xf768bf64 0xc0140c4d open_namei+0xfd
+    0xf768bfa0 0xc0135907 filp_open+0x37
+    0xf768bfbc 0xc0135c64 sys_open+0x34
+               0xc010702b system_call+0x33
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Let the operation continue
+%font "typewriter", size 3
+    [3]kdb> 
+%fore "blue", cont
+go
+%fore "black"
+    Instruction(i) breakpoint #0 at 0xc01ecfe0 (adjusted)
+    0xc01ecfe0 isp1020_queuecommand: int3   
+    Entering kdb (current=0xc0352000, pid 0) on processor 0 due to 
+                                               Breakpoint @ 0xc01ecfe0
+	Show the stack
+	This is an io completion queuing the next request
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+bt
+%fore "black"
+        EBP       EIP         Function(args)
+    0xc0353df4 0xc01ecfe0 isp1020_queuecommand(
+%fore "blue", cont
+0xf7e63a00
+%fore "black", cont
+,0xc01e7fc0...
+               0xc01e2c77 scsi_dispatch_cmd+0x1f7
+    0xc0353e24 0xc01e99b1 scsi_request_fn+0x2f1
+    0xc0353e40 0xc01e8f6a 
+%fore "blue", cont
+scsi_queue_next_request+0x4a
+%fore "black"
+    0xc0353e5c 0xc01e9166 __scsi_end_request+0x116
+    0xc0353ea8 0xc01e93e0 
+%fore "blue", cont
+scsi_io_completion+0x170
+%fore "black"
+    0xc0353ecc 0xc01f658e rw_intr+0x14e
+    0xc0353ef8 0xc01e8668 scsi_old_done+0x6a8
+    0xc0353fd4 0xc01052c2 cpu_idle+0x52
+	Function prototype
+%font "typewriter", size 3
+        int isp1020_queuecommand(
+%fore "blue", cont
+Scsi_Cmnd *Cmnd, 
+%fore "black"
+                                 void (*done)(Scsi_Cmnd *))
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Show the command being queued
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+sc 0xf7e63a00
+%fore "black"
+    scsi_cmnd at 0xf7e63a00
+%fore "blue"
+    host = 0xf7e91400
+%fore "black", cont
+  state = 4099  owner = 258  
+%fore "blue", cont
+device = 0xf7ed5d80
+%fore "black"
+    bnext = 0x00000000  reset_chain = 0x00000000  eh_state = 0 
+                                                  done = 0xc01f6440
+    serial_number = 3402  serial_num_at_to = 0 retries = 0 timeout = 0
+    id/lun/cmnd = [0/0/0]  cmd_len = 10  old_cmd_len = 10
+    cmnd = [2a/00/00/28/00/3f/00/00/10/00/ef/f7]
+    data_cmnd = [2a/00/00/28/00/3f/00/00/10/00/ef/f7]
+    request_buffer = 0xc03fd000  bh_next = 0x00000000  
+                                 request_bufflen = 8192
+    use_sg = 2  old_use_sg = 2 sglist_len = 512 abore_reason = 0
+    bufflen = 8192  buffer = 0xc03fd000  underflow = 8192 
+                                         transfersize = 512
+    tag = 0 pid = 3401
+    request struct
+    rq_status = RQ_ACTIVE  rq_dev = [8/1]  errors = 1  cmd = 0
+    sector = 2621440  nr_sectors = 16  current_nr_sectors = 8
+    buffer = 0xf7599000 
+%fore "blue", cont
+bh = 0xf75ca300
+%fore "black", cont
+ bhtail = 0xf75ca3c0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Display the host adapter
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+sh 0xf7e91400
+%fore "black"
+    Scsi_Host at 0xf7e91400
+    next = 0x00000000   
+%fore "blue", cont
+host_queue = 0xf7ed5d80
+%fore "black"
+    ehandler = 0x00000000 eh_wait = 0x00000000  en_notify = 0x00000000 
+                                                eh_action = 0x00000000
+    h_active = 0x0 host_wait = 0xc0353ac4 hostt = 0xc034bce0 
+                                          host_busy = 1
+    host_failed = 0  extra_bytes = 524  host_no = 0 resetting = 0
+    max id/lun/channel = [16/8/0]  this_id = 7
+    can_queue = 64 cmd_per_lun = 1  sg_tablesize = 427 u_isa_dma = 0
+    host_blocked = 0  reverse_ordering = 0 
+
+%font "typewriter", size 3
+	Display the scsi device
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+sd 0xf7ed5d80
+%fore "black"
+    scsi_device at 0xf7ed5d80
+    next = 0xf7ed5c80   prev = 0x00000000  host = 0xf7e91400
+    device_busy = 1   
+%fore "blue", cont
+device_queue 0xf7e63a00
+%fore "black"
+    id/lun/chan = [0/0/0]  single_lun = 0  device_blocked = 0
+    queue_depth = 1 current_tag = 0  scsi_level = 4
+    IBM      DGHS18X          0360
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Display the Buffer header associated with the command
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+bh 0xf75ca300
+%fore "black"
+    buffer_head at 0xf75ca300
+      next 0x00000000 bno 327680 rsec 2621440 size 4096 
+                                      dev 0x801 rdev 0x801
+      count 2 state 0x1d [Uptodate Lock Req Mapped] ftime 0x7695e 
+                    b_list 1 b_reqnext 0xf75ca3c0 b_data 0xf7599000
+%fore "blue"
+      b_page 0xc1dd6640
+%fore "black", cont
+ b_this_page 0xf75ca300 b_private 0x00000000
+
+	Display the associated page structure 
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+page 0xc1dd6640
+%fore "black"
+    struct page at 0xc1dd6640
+      next 0xc1dd7300 prev 0xc1dd6240 
+%fore "blue", cont
+addr space 0xf7af04d0 
+%fore "black"
+                                      index 327680 (offset 0x50000000)
+      count 2 flags PG_referenced PG_lru virtual 0xf7599000
+      buffers 0xf75ca300
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Display the Address space associated with the page
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+md 0xf7af04d0
+%fore "black"
+    0xf7af04d0 c1dd6240 c1dea740 f7af04d8 f7af04d8   @b]A@'^AX./wX./w
+    0xf7af04e0 f7af04e0 f7af04e0 00000007 c033b700   `./w`./w.....73@
+    0xf7af04f0 
+%fore "blue", cont
+f7af0420
+%fore "black", cont
+ 00000000 00000000 00000001    ./w............
+    0xf7af0500 000001d0 00000000 00000000 f7af050c   P............./w
+    0xf7af0510 f7af050c 00000000 f7a8afa0 00000000   ../w.... /(w....
+
+	The structure looks like:
+%size 3
+    struct address_space {
+        struct list_head    clean_pages; /* list of clean pages */
+        struct list_head    dirty_pages; /* list of dirty pages */
+        struct list_head    locked_pages;/* list of locked pages */
+        unsigned long       nrpages;     /* number of total pages */
+        spinlock_t          page_lock;   /* spinlock protecting them*/
+        struct address_space_operations *a_ops;    /* methods */
+%fore "blue"
+        struct inode        *host;       /* owner: inode, block_dev */
+%fore "black"
+    <snip>
+    };
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Display the inode associated with the address space
+	I think htis is the inode for the block device.
+
+%font "typewriter", size 3
+    [1]kdb> 
+%fore "blue", cont
+inode f7af0420
+%fore "black"
+    struct inode at  0xf7af0420
+     i_ino = 289 i_count = 1 i_dev = 0x801 i_size 4301789184
+     i_mode = 0x8000  i_nlink = 1  i_rdev = 0x801
+     i_hash.nxt = 0xf7af0420 i_hash.prv = 0xf7af0420
+     i_list.nxt = 0xf7af0608 i_list.prv = 0xf7af0068
+     i_dentry.nxt = 0xf7af0430 i_dentry.prv = 0xf7af0430
+     i_dirty_buffers.nxt = 0xf7af0438 i_dirty_buffers.prv = 0xf7af0438
+     i_sb = 0xc201f200 i_op = 0xc03cfdc0 i_data = 0xf7af04d0 nrpages = 6
+     i_mapping = 0xf7af04d0
+     i_flags 0x0 i_state 0x0 []  fs specific info @ 0xf7af0540
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%page
+
+Walking IO structures
+
+
+%font "typewriter", size 3
+	Display the page list associated with the inode
+%font "typewriter", size 3
+    [0]kdb> 
+%fore "blue", cont
+inode_pages f7af0420
+%fore "black"
+CLEAN  page_struct   index  cnt  flags
+   0xc1dd6240    327735        2    0x44 bh 0xf75caae0 bno   327735 
+                                            [Lock Req Mapped]
+%fore "blue"
+   0xc1dd6640    327680        2    0x44 bh 0xf75ca300 bno   327680 
+                                            [Uptodate Lock Req Mapped]
+%fore "black"
+   0xc1dd7300    327681        2    0x44 bh 0xf75ca3c0 bno   327681 
+                                            [Uptodate Lock Req Mapped]
+   0xc1dd6e00    327684        2    0x44 bh 0xf75ca420 bno   327684 
+                                            [Uptodate Req Mapped]
+   0xc1de8fc0         4        2    0xc0 bh 0xf7b5ade0 bno        4 
+                                            [Uptodate Req Mapped]
+   0xc1dea700         1        2    0x44 bh 0xf7e02740 bno        1 
+                                            [Uptodate Req Mapped]
+   0xc1dea740         0        2    0x44 bh 0xf7e028c0 bno        0 
+                                            [Uptodate Req Mapped]
+DIRTY  page_struct   index  cnt  flags
+LOCKED page_struct   index  cnt  flags
diff -uNr linux.orig/Makefile linux/Makefile
--- linux.orig/Makefile	Mon Apr  5 15:02:44 2004
+++ linux/Makefile	Mon Apr  5 15:07:55 2004
@@ -38,13 +38,16 @@
 MAKEFILES	= $(TOPDIR)/.config
 GENKSYMS	= /sbin/genksyms
 DEPMOD		= /sbin/depmod
+KALLSYMS	= /sbin/kallsyms
 MODFLAGS	= -DMODULE
 CFLAGS_KERNEL	=
 PERL		= perl
+AWK		= awk
+TMPPREFIX	=
 
 export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
 	CONFIG_SHELL TOPDIR HPATH HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
-	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES GENKSYMS MODFLAGS PERL
+	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES GENKSYMS MODFLAGS PERL AWK
 
 all:	do-it-all
 
@@ -128,6 +131,11 @@
 LIBS		=$(TOPDIR)/lib/lib.a
 SUBDIRS		=kernel drivers mm fs net ipc lib
 
+ifeq ($(CONFIG_KDB),y)
+CORE_FILES	+= kdb/kdb.o
+SUBDIRS		+= kdb
+endif
+
 DRIVERS-n :=
 DRIVERS-y :=
 DRIVERS-m :=
@@ -206,7 +214,7 @@
 CLEAN_FILES = \
 	kernel/ksyms.lst include/linux/compile.h \
 	vmlinux System.map \
-	.tmp* \
+	$(TMPPREFIX).tmp* \
 	drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \
 	drivers/char/conmakehash \
 	drivers/char/drm/*-mod.c \
@@ -249,6 +257,7 @@
 	scripts/lxdialog/*.o scripts/lxdialog/lxdialog \
 	.menuconfig.log \
 	include/asm \
+	kdb/gen-kdb_cmds.c \
 	.hdepend scripts/mkdep scripts/split-include scripts/docproc \
 	$(TOPDIR)/include/linux/modversions.h \
 	kernel.spec
@@ -281,16 +290,42 @@
 boot: vmlinux
 	@$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot
 
+LD_VMLINUX	:= $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
+			--start-group \
+			$(CORE_FILES) \
+			$(DRIVERS) \
+			$(NETWORKS) \
+			$(LIBS) \
+			--end-group
+ifeq ($(CONFIG_KALLSYMS),y)
+LD_VMLINUX_KALLSYMS	:= $(TMPPREFIX).tmp_kallsyms3.o
+else
+LD_VMLINUX_KALLSYMS	:=
+endif
+
 vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs
-	$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
-		--start-group \
-		$(CORE_FILES) \
-		$(DRIVERS) \
-		$(NETWORKS) \
-		$(LIBS) \
-		--end-group \
-		-o vmlinux
+	@$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" kallsyms
+
+.PHONY:	kallsyms
+
+kallsyms:
+ifeq ($(CONFIG_KALLSYMS),y)
+	@echo kallsyms pass 1
+	$(LD_VMLINUX) -o $(TMPPREFIX).tmp_vmlinux1
+	@$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux1 > $(TMPPREFIX).tmp_kallsyms1.o
+	@echo kallsyms pass 2
+	@$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms1.o -o $(TMPPREFIX).tmp_vmlinux2
+	@$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux2 > $(TMPPREFIX).tmp_kallsyms2.o
+	@echo kallsyms pass 3
+	@$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms2.o -o $(TMPPREFIX).tmp_vmlinux3
+	@$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux3 > $(TMPPREFIX).tmp_kallsyms3.o
+endif
+	$(LD_VMLINUX) $(LD_VMLINUX_KALLSYMS) -o $(TMPPREFIX)vmlinux
+ifneq ($(TMPPREFIX),)
+	mv $(TMPPREFIX)vmlinux vmlinux
+endif
 	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
+	@rm -f $(TMPPREFIX).tmp_vmlinux* $(TMPPREFIX).tmp_kallsyms*
 
 symlinks:
 	rm -f include/asm
diff -uNr linux.orig/arch/arm/Makefile linux/arch/arm/Makefile
--- linux.orig/arch/arm/Makefile	Mon Apr  5 15:02:43 2004
+++ linux/arch/arm/Makefile	Mon Apr  5 15:07:54 2004
@@ -213,6 +213,11 @@
 CORE_FILES	:=arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
 LIBS		:=arch/arm/lib/lib.a $(LIBS)
 
+ifdef CONFIG_KDB
+LIBS := $(TOPDIR)/arch/arm/kdb/kdba.o $(LIBS)
+SUBDIRS := arch/arm/kdb $(SUBDIRS)
+endif
+
 ifeq ($(CONFIG_FPE_NWFPE),y)
 LIBS		:=arch/arm/nwfpe/math-emu.o $(LIBS)
 endif
diff -uNr linux.orig/arch/arm/config.in linux/arch/arm/config.in
--- linux.orig/arch/arm/config.in	Mon Apr  5 15:02:43 2004
+++ linux/arch/arm/config.in	Mon Apr  5 15:07:54 2004
@@ -809,6 +809,16 @@
 dep_bool '  Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
 dep_bool '    Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
 dep_bool '    Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
+dep_bool '  Built-in Kernel Debugger support' CONFIG_KDB $CONFIG_DEBUG_KERNEL
+   dep_tristate '    KDB modules' CONFIG_KDB_MODULES $CONFIG_KDB
+   if [ "$CONFIG_KDB" = "y" ]; then
+      bool '    KDB off by default' CONFIG_KDB_OFF
+      if [ "$CONFIG_USB" != "n" ] ; then
+      	bool '    Support for USB Keyboard in KDB' CONFIG_KDB_USB
+      fi
+      comment '  Load all symbols for debugging is required for KDB'
+      define_bool CONFIG_KALLSYMS y
+   fi
 endmenu
 
 source lib/Config.in
diff -uNr linux.orig/arch/arm/kdb/ChangeLog linux/arch/arm/kdb/ChangeLog
--- linux.orig/arch/arm/kdb/ChangeLog	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/ChangeLog	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,50 @@
+2003-06-01 Keith Owens <kaos@sgi.com>
+
+	* Fit patch against arm code in 2.4.20 kernel.
+	* kdb v4.3-2.4.20-xscale-1.
+
+2003-05-06 Eddie Dong <Eddie.dong@intel.com>
+	*
+	* Port to KDB4.2
+	* Add read/write access to user pages.  Vamsi Krishna S., IBM
+	* kdb v4.2-2.4.20-xscale-1.
+
+2003-04-15 Eddie Dong  <Eddie.dong@intel.com>
+	*
+	* Enable the memory access violation recovery in KDB,
+	* __kdba_copy_to_user is added for this purpose.
+	*
+
+2003-03-28 Eddie Dong  <Eddie.dong@intel.com>
+	*
+	* Port to KDB4.0
+	* Enable the coprocessor read/modify for xscale.
+	*
+
+2003-02-26 Eddie Dong  <Eddie.dong@intel.com>
+	*
+	* Move the entrance of kdb from do_PrefetchAbort and
+	* do_DataAbort to inside __pabt_svc and __dabt_svc to
+	* make sure the interrupt is disabled when entering kdb().
+	*
+
+2003-02-15 Eddie Dong  <Eddie.dong@intel.com>
+	*
+	* Add support for back trace
+	*
+
+2003-01-26 Eddie Dong  <Eddie.dong@intel.com>
+	*
+	* Add support for command SS, bph and KDB_HAVE_LONGJMP.
+	*
+
+2003-01-23 Eddie Dong  <Eddie.dong@intel.com>
+
+	* Add support for arm xscale architecture based on 
+	* 	kdb-v2.5-2.4.19-common-1.bz2.
+	* Only basic command is completed now, it includes:
+	*	bp,bc,bd,go,id,rd,rm,mdr,mds..
+	* Following command are still in progress: ss, bph, coprocessor
+	*	read/write,trace buffer, bt, full test of software single
+	*	step.
+
diff -uNr linux.orig/arch/arm/kdb/Makefile linux/arch/arm/kdb/Makefile
--- linux.orig/arch/arm/kdb/Makefile	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/Makefile	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 1999-2002 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+O_TARGET := kdba.o
+obj-y	 := kdba_bt.o kdba_bp.o kdba_io.o kdbasupport.o \
+	    arm-dis.o arm-tdep.o kdba_id.o kdba_cpy.o
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+EXTRA_CFLAGS += -I $(TOPDIR)/arch/$(ARCH)/kdb
+
+
+USE_STANDARD_AS_RULE	:= true
+include $(TOPDIR)/Rules.make
diff -uNr linux.orig/arch/arm/kdb/ansidecl.h linux/arch/arm/kdb/ansidecl.h
--- linux.orig/arch/arm/kdb/ansidecl.h	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/ansidecl.h	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,258 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro	ANSI C definition	Traditional C definition
+   -----	---- - ----------	----------- - ----------
+   PTR		`void *'		`char *'
+   LONG_DOUBLE	`long double'		`double'
+   VOLATILE	`volatile'		`'
+   SIGNED	`signed'		`'
+   PTRCONST	`void *const'		`char *'
+   ANSI_PROTOTYPES  1			not defined
+
+   CONST is also defined, but is obsolete.  Just use const.
+
+   obsolete --     DEFUN (name, arglist, args)
+
+	Defines function NAME.
+
+	ARGLIST lists the arguments, separated by commas and enclosed in
+	parentheses.  ARGLIST becomes the argument list in traditional C.
+
+	ARGS list the arguments with their types.  It becomes a prototype in
+	ANSI C, and the type declarations in traditional C.  Arguments should
+	be separated with `AND'.  For functions with a variable number of
+	arguments, the last thing listed should be `DOTS'.
+
+   obsolete --     DEFUN_VOID (name)
+
+	Defines a function NAME, which takes no arguments.
+
+   obsolete --     EXFUN (name, (prototype))	-- obsolete.
+
+	Replaced by PARAMS.  Do not use; will disappear someday soon.
+	Was used in external function declarations.
+	In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+	parentheses).  In traditional C it is `NAME()'.
+	For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+   obsolete --     PROTO (type, name, (prototype)    -- obsolete.
+
+	This one has also been replaced by PARAMS.  Do not use.
+
+   PARAMS ((args))
+
+	We could use the EXFUN macro to handle prototype declarations, but
+	the name is misleading and the result is ugly.  So we just define a
+	simple macro to handle the parameter lists, as in:
+
+	      static int foo PARAMS ((int, char));
+
+	This produces:  `static int foo();' or `static int foo (int, char);'
+
+	EXFUN would have done it like this:
+
+	      static int EXFUN (foo, (int, char));
+
+	but the function is not external...and it's hard to visually parse
+	the function name out of the mess.   EXFUN should be considered
+	obsolete; new code should be written to use PARAMS.
+
+   DOTS is also obsolete.
+
+   Examples:
+
+	extern int printf PARAMS ((const char *format, ...));
+*/
+
+/*
+ * Extracted from GDB CVS and modified for kdb use.
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#ifndef	_ANSIDECL_H
+
+#define	_ANSIDECL_H	1
+
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32)
+/* All known AIX compilers implement these things (but don't always
+   define __STDC__).  The RISC/OS MIPS compiler defines these things
+   in SVR4 mode, but does not define __STDC__.  */
+
+#define	PTR		void *
+#define	PTRCONST	void *CONST
+#define	LONG_DOUBLE	long double
+
+#ifndef IN_GCC
+#define	AND		,
+#define	NOARGS		void
+#define	VOLATILE	volatile
+#define	SIGNED		signed
+#endif /* ! IN_GCC */
+
+#ifndef PARAMS
+#define PARAMS(paramlist)		paramlist
+#endif
+#define ANSI_PROTOTYPES			1
+
+#define VPARAMS(ARGS)			ARGS
+#define VA_START(va_list,var)		va_start(va_list,var)
+
+/* These are obsolete.  Do not use.  */
+#ifndef IN_GCC
+#define CONST				const
+#define DOTS				, ...
+#define PROTO(type, name, arglist)	type name arglist
+#define EXFUN(name, proto)		name proto
+#define DEFUN(name, arglist, args)	name(args)
+#define DEFUN_VOID(name)		name(void)
+#endif /* ! IN_GCC */
+
+#else	/* Not ANSI C.  */
+
+#define	PTR		char *
+#define	PTRCONST	PTR
+#define	LONG_DOUBLE	double
+
+#ifndef IN_GCC
+#define	AND		;
+#define	NOARGS
+#define	VOLATILE
+#define	SIGNED
+#endif /* !IN_GCC */
+
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define	const
+#endif
+
+#define PARAMS(paramlist)		()
+
+#define VPARAMS(ARGS)			(va_alist) va_dcl
+#define VA_START(va_list,var)		va_start(va_list)
+
+/* These are obsolete.  Do not use.  */
+#ifndef IN_GCC
+#define CONST
+#define DOTS
+#define PROTO(type, name, arglist)	type name ()
+#define EXFUN(name, proto)		name()
+#define DEFUN(name, arglist, args)	name arglist args;
+#define DEFUN_VOID(name)		name()
+#endif /* ! IN_GCC */
+
+#endif	/* ANSI C.  */
+
+/* Using MACRO(x,y) in cpp #if conditionals does not work with some
+   older preprocessors.  Thus we can't define something like this:
+
+#define HAVE_GCC_VERSION(MAJOR, MINOR) \
+  (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
+
+and then test "#if HAVE_GCC_VERSION(2,7)".
+
+So instead we use the macro below and test it against specific values.  */
+
+/* This macro simplifies testing whether we are using gcc, and if it
+   is of a particular minimum version. (Both major & minor numbers are
+   significant.)  This macro will evaluate to 0 if we are not using
+   gcc at all.  */
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif /* GCC_VERSION */
+
+/* Define macros for some gcc attributes.  This permits us to use the
+   macros freely, and know that they will come into play for the
+   version of gcc in which they are supported.  */
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
+#ifndef ATTRIBUTE_MALLOC
+# if (GCC_VERSION >= 2096)
+#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define ATTRIBUTE_MALLOC
+# endif /* GNUC >= 2.96 */
+#endif /* ATTRIBUTE_MALLOC */
+
+/* Attributes on labels were valid as of gcc 2.93. */
+#ifndef ATTRIBUTE_UNUSED_LABEL
+# if (GCC_VERSION >= 2093)
+#  define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# else
+#  define ATTRIBUTE_UNUSED_LABEL
+# endif /* GNUC >= 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
+#ifndef ATTRIBUTE_PRINTF
+#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
+#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
+#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
+#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
+#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
+#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
+#endif /* ATTRIBUTE_PRINTF */
+
+/* We use __extension__ in some places to suppress -pedantic warnings
+   about GCC extensions.  This feature didn't work properly before
+   gcc 2.8.  */
+#if GCC_VERSION < 2008
+#define __extension__
+#endif
+
+/* Bootstrap support: Autoconf will possibly define the `inline' or
+   `const' keywords as macros, however this is only valid for the
+   stage1 compiler.  If we detect a modern version of gcc,
+   unconditionally reset the values.  This makes sure the right thing
+   happens in stage2 and later.  We need to do this very early;
+   i.e. before any header files that might use these keywords.
+   Otherwise conflicts might occur.  */
+
+#if (GCC_VERSION >= 2007)
+# ifdef __STDC__
+#  undef const
+# endif
+# undef inline
+# define inline __inline__  /* __inline__ prevents -pedantic warnings */
+# ifndef HAVE_LONG_DOUBLE
+#  define HAVE_LONG_DOUBLE 1
+# endif
+#endif /* GCC >= 2.7 */
+
+#endif	/* ansidecl.h	*/
diff -uNr linux.orig/arch/arm/kdb/arm-dis.c linux/arch/arm/kdb/arm-dis.c
--- linux.orig/arch/arm/kdb/arm-dis.c	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/arm-dis.c	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,1217 @@
+/* Instruction printing code for the ARM
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
+   Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+   Modification by James G. Smith (jsmith@cygnus.co.uk)
+   Extracted from GDB-5.2.1 and modified for kdb use by
+   Eddie Dong <Eddie.Dong@intel.com> 22 Jan 2003
+ 
+
+This file is part of libopcodes. 
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version. 
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+more details. 
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/*
+ * Extracted from GDB CVS and modified for kdb use.
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/dis-asm.h>
+#include <linux/kdb.h>
+#else	/* ! __KERNEL__ */
+#include "dis-asm.h"
+#include "sysdep.h"
+#define DEFINE_TABLE
+#include "opintl.h"
+#endif
+#include "arm-opc.h"
+//#include "coff/internal.h"
+//#include "libcoff.h"
+//#include "opintl.h"
+
+/* FIXME: This shouldn't be done here */
+//#include "elf-bfd.h"
+//#include "elf/internal.h"
+//#include "elf/arm.h"
+
+#define _(String)       String
+#ifndef streq
+#define streq(a,b)	(strcmp ((a), (b)) == 0)
+#endif
+
+#ifndef strneq
+#define strneq(a,b,n)	(strncmp ((a), (b), (n)) == 0)
+#endif
+
+#ifndef NUM_ELEM
+#define NUM_ELEM(a)     (sizeof (a) / sizeof (a)[0])
+#endif
+
+static char * arm_conditional[] =
+{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
+
+typedef struct
+{
+  const char * name;
+  const char * description;
+  const char * reg_names[16];
+}
+arm_regname;
+
+static arm_regname regnames[] =
+{
+  { "raw" , "Select raw register names",
+    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", 
+	    "r11", "r12", "r13", "r14", "r15"}},
+  { "gcc",  "Select register names used by GCC",
+    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", 
+	    "fp",  "ip",  "sp",  "lr",  "pc" }},
+  { "std",  "Select register names used in ARM's ISA documentation",
+    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+	    "r11", "r12", "sp",  "lr",  "pc" }},
+  { "apcs", "Select register names used in the APCS",
+    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl",
+	    "fp",  "ip",  "sp",  "lr",  "pc" }},
+  { "atpcs", "Select register names used in the ATPCS",
+    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+	    "v8",  "IP",  "SP",  "LR",  "PC" }},
+  { "special-atpcs", "Select special register names used in the ATPCS",
+    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL",
+	    "FP",  "IP",  "SP",  "LR",  "PC" }}
+};
+
+/* Default to GCC register name set.  */
+static unsigned int regname_selected = 1;
+
+#define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
+#define arm_regnames      regnames[regname_selected].reg_names
+
+static boolean force_thumb = false;
+
+static char * arm_fp_const[] =
+{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
+
+static char * arm_shift[] = 
+{"lsl", "lsr", "asr", "ror"};
+
+/* Forward declarations.  */
+static void arm_decode_shift PARAMS ((long, fprintf_ftype, void *));
+static int  print_insn_arm   PARAMS ((bfd_vma, struct disassemble_info *,
+		       	long));
+static int  print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *,
+		       	long));
+static void parse_disassembler_options PARAMS ((char *));
+static int  print_insn       PARAMS ((bfd_vma, struct disassemble_info *,
+		       	boolean));
+int get_arm_regname_num_options (void);
+int set_arm_regname_option (int option);
+int get_arm_regnames (int option, const char **setname,
+		      const char **setdescription,
+		      const char ***register_names);
+
+/* Functions. */
+int
+get_arm_regname_num_options (void)
+{
+  return NUM_ARM_REGNAMES;
+}
+
+int
+set_arm_regname_option (int option)
+{
+  int old = regname_selected;
+  regname_selected = option;
+  return old;
+}
+
+int
+get_arm_regnames (int option, const char **setname,
+		  const char **setdescription,
+                  const char ***register_names)
+{
+  *setname = regnames[option].name;
+  *setdescription = regnames[option].description;
+  *register_names = regnames[option].reg_names;
+  return 16;
+}
+
+static void
+arm_decode_shift (given, func, stream)
+     long given;
+     fprintf_ftype func;
+     void * stream;
+{
+  func (stream, "%s", arm_regnames[given & 0xf]);
+  
+  if ((given & 0xff0) != 0)
+    {
+      if ((given & 0x10) == 0)
+	{
+	  int amount = (given & 0xf80) >> 7;
+	  int shift = (given & 0x60) >> 5;
+	  
+	  if (amount == 0)
+	    {
+	      if (shift == 3)
+		{
+		  func (stream, ", rrx");
+		  return;
+		}
+	      
+	      amount = 32;
+	    }
+	  
+	  func (stream, ", %s #%d", arm_shift[shift], amount);
+	}
+      else
+	func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
+	      arm_regnames[(given & 0xf00) >> 8]);
+    }
+}
+
+/* Print one instruction from PC on INFO->STREAM.
+   Return the size of the instruction (always 4 on ARM). */
+static int
+print_insn_arm (pc, info, given)
+     bfd_vma                   pc;
+     struct disassemble_info * info;
+     long                      given;
+{
+  struct arm_opcode *  insn;
+  void *               stream = info->stream;
+  fprintf_ftype        func   = info->fprintf_func;
+
+  for (insn = arm_opcodes; insn->assembler; insn++)
+    {
+      if ((given & insn->mask) == insn->value)
+	{
+	  char * c;
+	  
+	  for (c = insn->assembler; *c; c++)
+	    {
+	      if (*c == '%')
+		{
+		  switch (*++c)
+		    {
+		    case '%':
+		      func (stream, "%%");
+		      break;
+
+		    case 'a':
+		      if (((given & 0x000f0000) == 0x000f0000)
+			  && ((given & 0x02000000) == 0))
+			{
+			  int offset = given & 0xfff;
+			  
+			  func (stream, "[pc");
+ 
+			  if (given & 0x01000000)
+			    {
+			      if ((given & 0x00800000) == 0)
+				offset = - offset;
+			  
+			      /* pre-indexed */
+			      func (stream, ", #%d]", offset);
+
+			      offset += pc + 8;
+
+			      /* Cope with the possibility of write-back
+				 being used.  Probably a very dangerous thing
+				 for the programmer to do, but who are we to
+				 argue ?  */
+			      if (given & 0x00200000)
+				func (stream, "!");
+			    }
+			  else
+			    {
+			      /* Post indexed.  */
+			      func (stream, "], #%d", offset);
+
+			      offset = pc + 8;  /* ie ignore the offset.  */
+			    }
+			  
+			  func (stream, "\t; ");
+			  info->print_address_func (offset, info);
+			}
+		      else
+			{
+			  func (stream, "[%s", 
+				arm_regnames[(given >> 16) & 0xf]);
+			  if ((given & 0x01000000) != 0)
+			    {
+			      if ((given & 0x02000000) == 0)
+				{
+				  int offset = given & 0xfff;
+				  if (offset)
+				    func (stream, ", %s#%d",
+					  (((given & 0x00800000) == 0)
+					   ? "-" : ""), offset);
+				}
+			      else
+				{
+				  func (stream, ", %s",
+					(((given & 0x00800000) == 0)
+					 ? "-" : ""));
+				  arm_decode_shift (given, func, stream);
+				}
+
+			      func (stream, "]%s", 
+				    ((given & 0x00200000) != 0) ? "!" : "");
+			    }
+			  else
+			    {
+			      if ((given & 0x02000000) == 0)
+				{
+				  int offset = given & 0xfff;
+				  if (offset)
+				    func (stream, "], %s#%d",
+					  (((given & 0x00800000) == 0)
+					   ? "-" : ""), offset);
+				  else 
+				    func (stream, "]");
+				}
+			      else
+				{
+				  func (stream, "], %s",
+					(((given & 0x00800000) == 0) 
+					 ? "-" : ""));
+				  arm_decode_shift (given, func, stream);
+				}
+			    }
+			}
+		      break;
+
+		    case 's':
+                      if ((given & 0x004f0000) == 0x004f0000)
+			{
+                          /* PC relative with immediate offset.  */
+			  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
+			  
+			  if ((given & 0x00800000) == 0)
+			    offset = -offset;
+			  
+			  func (stream, "[pc, #%d]\t; ", offset);
+			  
+			  (*info->print_address_func)
+			    (offset + pc + 8, info);
+			}
+		      else
+			{
+			  func (stream, "[%s", 
+				arm_regnames[(given >> 16) & 0xf]);
+			  if ((given & 0x01000000) != 0)
+			    {
+                              /* Pre-indexed.  */
+			      if ((given & 0x00400000) == 0x00400000)
+				{
+                                  /* Immediate.  */
+                                  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
+				  if (offset)
+				    func (stream, ", %s#%d",
+					  (((given & 0x00800000) == 0)
+					   ? "-" : ""), offset);
+				}
+			      else
+				{
+                                  /* Register.  */
+				  func (stream, ", %s%s",
+					(((given & 0x00800000) == 0)
+					 ? "-" : ""),
+                                        arm_regnames[given & 0xf]);
+				}
+
+			      func (stream, "]%s", 
+				    ((given & 0x00200000) != 0) ? "!" : "");
+			    }
+			  else
+			    {
+                              /* Post-indexed.  */
+			      if ((given & 0x00400000) == 0x00400000)
+				{
+                                  /* Immediate.  */
+                                  int offset = ((given & 0xf00) >> 4) | 
+					  (given & 0xf);
+				  if (offset)
+				    func (stream, "], %s#%d",
+					  (((given & 0x00800000) == 0)
+					   ? "-" : ""), offset);
+				  else 
+				    func (stream, "]");
+				}
+			      else
+				{
+                                  /* Register.  */
+				  func (stream, "], %s%s",
+					(((given & 0x00800000) == 0)
+					 ? "-" : ""),
+                                        arm_regnames[given & 0xf]);
+				}
+			    }
+			}
+		      break;
+			  
+		    case 'b':
+		      (*info->print_address_func)
+			(BDISP (given) * 4 + pc + 8, info);
+		      break;
+
+		    case 'c':
+		      func (stream, "%s",
+			    arm_conditional [(given >> 28) & 0xf]);
+		      break;
+
+		    case 'm':
+		      {
+			int started = 0;
+			int reg;
+
+			func (stream, "{");
+			for (reg = 0; reg < 16; reg++)
+			  if ((given & (1 << reg)) != 0)
+			    {
+			      if (started)
+				func (stream, ", ");
+			      started = 1;
+			      func (stream, "%s", arm_regnames[reg]);
+			    }
+			func (stream, "}");
+		      }
+		      break;
+
+		    case 'o':
+		      if ((given & 0x02000000) != 0)
+			{
+			  int rotate = (given & 0xf00) >> 7;
+			  int immed = (given & 0xff);
+			  immed = (((immed << (32 - rotate))
+				    | (immed >> rotate)) & 0xffffffff);
+			  func (stream, "#%d\t; 0x%x", immed, immed);
+			}
+		      else
+			arm_decode_shift (given, func, stream);
+		      break;
+
+		    case 'p':
+		      if ((given & 0x0000f000) == 0x0000f000)
+			func (stream, "p");
+		      break;
+
+		    case 't':
+		      if ((given & 0x01200000) == 0x00200000)
+			func (stream, "t");
+		      break;
+
+		    case 'A':
+		      func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+		      if ((given & 0x01000000) != 0)
+			{
+			  int offset = given & 0xff;
+			  if (offset)
+			    func (stream, ", %s#%d]%s",
+				  ((given & 0x00800000) == 0 ? "-" : ""),
+				  offset * 4,
+				  ((given & 0x00200000) != 0 ? "!" : ""));
+			  else
+			    func (stream, "]");
+			}
+		      else
+			{
+			  int offset = given & 0xff;
+			  if (offset)
+			    func (stream, "], %s#%d",
+				  ((given & 0x00800000) == 0 ? "-" : ""),
+				  offset * 4);
+			  else
+			    func (stream, "]");
+			}
+		      break;
+
+		    case 'B':
+		      /* Print ARM V5 BLX(1) address: pc+25 bits.  */
+		      {
+			bfd_vma address;
+			bfd_vma offset = 0;
+			
+			if (given & 0x00800000)
+			  /* Is signed, hi bits should be ones.  */
+			  offset = (-1) ^ 0x00ffffff;
+
+			/* Offset is (SignExtend(offset field)<<2).  */
+			offset += given & 0x00ffffff;
+			offset <<= 2;
+			address = offset + pc + 8;
+			
+			if (given & 0x01000000)
+			  /* H bit allows addressing to 2-byte boundaries.  */
+			  address += 2;
+
+		        info->print_address_func (address, info);
+		      }
+		      break;
+
+		    case 'I':
+		      /* Print a Cirrus/DSP shift immediate.  */
+		      /* Immediates are 7bit signed ints with bits 0..3 in
+			 bits 0..3 of opcode and bits 4..6 in bits 5..7
+			 of opcode.  */
+		      {
+			int imm;
+
+			imm = (given & 0xf) | ((given & 0xe0) >> 1);
+
+			/* Is ``imm'' a negative number?  */
+			if (imm & 0x40)
+			  imm |= (-1 << 7);
+
+			func (stream, "%d", imm);
+		      }
+
+		      break;
+
+		    case 'C':
+		      func (stream, "_");
+		      if (given & 0x80000)
+			func (stream, "f");
+		      if (given & 0x40000)
+			func (stream, "s");
+		      if (given & 0x20000)
+			func (stream, "x");
+		      if (given & 0x10000)
+			func (stream, "c");
+		      break;
+
+		    case 'F':
+		      switch (given & 0x00408000)
+			{
+			case 0:
+			  func (stream, "4");
+			  break;
+			case 0x8000:
+			  func (stream, "1");
+			  break;
+			case 0x00400000:
+			  func (stream, "2");
+			  break;
+			default:
+			  func (stream, "3");
+			}
+		      break;
+			
+		    case 'P':
+		      switch (given & 0x00080080)
+			{
+			case 0:
+			  func (stream, "s");
+			  break;
+			case 0x80:
+			  func (stream, "d");
+			  break;
+			case 0x00080000:
+			  func (stream, "e");
+			  break;
+			default:
+			  func (stream, _("<illegal precision>"));
+			  break;
+			}
+		      break;
+		    case 'Q':
+		      switch (given & 0x00408000)
+			{
+			case 0:
+			  func (stream, "s");
+			  break;
+			case 0x8000:
+			  func (stream, "d");
+			  break;
+			case 0x00400000:
+			  func (stream, "e");
+			  break;
+			default:
+			  func (stream, "p");
+			  break;
+			}
+		      break;
+		    case 'R':
+		      switch (given & 0x60)
+			{
+			case 0:
+			  break;
+			case 0x20:
+			  func (stream, "p");
+			  break;
+			case 0x40:
+			  func (stream, "m");
+			  break;
+			default:
+			  func (stream, "z");
+			  break;
+			}
+		      break;
+
+		    case '0': case '1': case '2': case '3': case '4': 
+		    case '5': case '6': case '7': case '8': case '9':
+		      {
+			int bitstart = *c++ - '0';
+			int bitend = 0;
+			while (*c >= '0' && *c <= '9')
+			  bitstart = (bitstart * 10) + *c++ - '0';
+
+			switch (*c)
+			  {
+			  case '-':
+			    c++;
+			    
+			    while (*c >= '0' && *c <= '9')
+			      bitend = (bitend * 10) + *c++ - '0';
+			    
+			    if (!bitend)
+			      abort ();
+			    
+			    switch (*c)
+			      {
+			      case 'r':
+				{
+				  long reg;
+				  
+				  reg = given >> bitstart;
+				  reg &= (2 << (bitend - bitstart)) - 1;
+				  
+				  func (stream, "%s", arm_regnames[reg]);
+				}
+				break;
+			      case 'd':
+				{
+				  long reg;
+				  
+				  reg = given >> bitstart;
+				  reg &= (2 << (bitend - bitstart)) - 1;
+				  
+				  func (stream, "%d", reg);
+				}
+				break;
+			      case 'x':
+				{
+				  long reg;
+				  
+				  reg = given >> bitstart;
+				  reg &= (2 << (bitend - bitstart)) - 1;
+				  
+				  func (stream, "0x%08x", reg);
+				  
+				  /* Some SWI instructions have special
+				     meanings.  */
+				  if ((given & 0x0fffffff) == 0x0FF00000)
+				    func (stream, "\t; IMB");
+				  else if ((given & 0x0fffffff) == 0x0FF00001)
+				    func (stream, "\t; IMBRange");
+				}
+				break;
+			      case 'X':
+				{
+				  long reg;
+				  
+				  reg = given >> bitstart;
+				  reg &= (2 << (bitend - bitstart)) - 1;
+				  
+				  func (stream, "%01x", reg & 0xf);
+				}
+				break;
+			      case 'f':
+				{
+				  long reg;
+				  
+				  reg = given >> bitstart;
+				  reg &= (2 << (bitend - bitstart)) - 1;
+				  
+				  if (reg > 7)
+				    func (stream, "#%s",
+					  arm_fp_const[reg & 7]);
+				  else
+				    func (stream, "f%d", reg);
+				}
+				break;
+			      default:
+				abort ();
+			      }
+			    break;
+
+			  case 'y':
+			  case 'z':
+			    {
+			      int single = *c == 'y';
+			      int regno;
+
+			      switch (bitstart)
+				{
+				case 4: /* Sm pair */
+				  func (stream, "{");
+				  /* Fall through.  */
+				case 0: /* Sm, Dm */
+				  regno = given & 0x0000000f;
+				  if (single)
+				    {
+				      regno <<= 1;
+				      regno += (given >> 5) & 1;
+				    }
+				  break;
+
+				case 1: /* Sd, Dd */
+				  regno = (given >> 12) & 0x0000000f;
+				  if (single)
+				    {
+				      regno <<= 1;
+				      regno += (given >> 22) & 1;
+				    }
+				  break;
+
+				case 2: /* Sn, Dn */
+				  regno = (given >> 16) & 0x0000000f;
+				  if (single)
+				    {
+				      regno <<= 1;
+				      regno += (given >> 7) & 1;
+				    }
+				  break;
+
+				case 3: /* List */
+				  func (stream, "{");
+				  regno = (given >> 12) & 0x0000000f;
+				  if (single)
+				    {
+				      regno <<= 1;
+				      regno += (given >> 22) & 1;
+				    }
+				  break;
+
+				  
+				default:
+				  abort ();
+				}
+
+			      func (stream, "%c%d", single ? 's' : 'd', regno);
+
+			      if (bitstart == 3)
+				{
+				  int count = given & 0xff;
+
+				  if (single == 0)
+				    count >>= 1;
+
+				  if (--count)
+				    {
+				      func (stream, "-%c%d",
+					    single ? 's' : 'd',
+					    regno + count);
+				    }
+
+				  func (stream, "}");
+				}
+			      else if (bitstart == 4)
+				func (stream, ", %c%d}", single ? 's' : 'd',
+				      regno + 1);
+
+			      break;
+			    }
+
+			  case '`':
+			    c++;
+			    if ((given & (1 << bitstart)) == 0)
+			      func (stream, "%c", *c);
+			    break;
+			  case '\'':
+			    c++;
+			    if ((given & (1 << bitstart)) != 0)
+			      func (stream, "%c", *c);
+			    break;
+			  case '?':
+			    ++c;
+			    if ((given & (1 << bitstart)) != 0)
+			      func (stream, "%c", *c++);
+			    else
+			      func (stream, "%c", *++c);
+			    break;
+			  default:
+			    abort ();
+			  }
+			break;
+
+		      default:
+			abort ();
+		      }
+		    }
+		}
+	      else
+		func (stream, "%c", *c);
+	    }
+	  return 4;
+	}
+    }
+  abort ();
+}
+
+/* Print one instruction from PC on INFO->STREAM.
+   Return the size of the instruction. */
+static int
+print_insn_thumb (pc, info, given)
+     bfd_vma                   pc;
+     struct disassemble_info * info;
+     long                      given;
+{
+  struct thumb_opcode * insn;
+  void *                stream = info->stream;
+  fprintf_ftype         func = info->fprintf_func;
+
+  for (insn = thumb_opcodes; insn->assembler; insn++)
+    {
+      if ((given & insn->mask) == insn->value)
+        {
+          char * c = insn->assembler;
+
+          /* Special processing for Thumb 2 instruction BL sequence:  */
+          if (!*c) /* Check for empty (not NULL) assembler string.  */
+            {
+	      long offset;
+	      
+	      info->bytes_per_chunk = 4;
+	      info->bytes_per_line  = 4;
+
+	      offset = BDISP23 (given);
+	      
+	      if ((given & 0x10000000) == 0)
+		{
+		  func (stream, "blx\t");
+
+		  /* The spec says that bit 1 of the branch's destination
+		     address comes from bit 1 of the instruction's
+		     address and not from the offset in the instruction.  */
+		  if (offset & 0x1)
+		    {
+		      /* func (stream, "*malformed!* "); */
+		      offset &= ~ 0x1;
+		    }
+
+		  offset |= ((pc & 0x2) >> 1);
+		}
+	      else
+		func (stream, "bl\t");
+
+	      info->print_address_func (offset * 2 + pc + 4, info);
+              return 4;
+            }
+          else
+            {
+	      info->bytes_per_chunk = 2;
+	      info->bytes_per_line  = 4;
+	  	      
+              given &= 0xffff;
+	      
+              for (; *c; c++)
+                {
+                  if (*c == '%')
+                    {
+                      int domaskpc = 0;
+                      int domasklr = 0;
+		      
+                      switch (*++c)
+                        {
+                        case '%':
+                          func (stream, "%%");
+                          break;
+
+                        case 'S':
+                          {
+                            long reg;
+			    
+                            reg = (given >> 3) & 0x7;
+                            if (given & (1 << 6))
+                              reg += 8;
+			    
+                            func (stream, "%s", arm_regnames[reg]);
+                          }
+                          break;
+
+                        case 'D':
+                          {
+                            long reg;
+			    
+                            reg = given & 0x7;
+                            if (given & (1 << 7))
+                             reg += 8;
+			    
+                            func (stream, "%s", arm_regnames[reg]);
+                          }
+                          break;
+
+                        case 'T':
+                          func (stream, "%s",
+                                arm_conditional [(given >> 8) & 0xf]);
+                          break;
+
+                        case 'N':
+                          if (given & (1 << 8))
+                            domasklr = 1;
+                          /* Fall through.  */
+                        case 'O':
+                          if (*c == 'O' && (given & (1 << 8)))
+                            domaskpc = 1;
+                          /* Fall through.  */
+                        case 'M':
+                          {
+                            int started = 0;
+                            int reg;
+			    
+                            func (stream, "{");
+			    
+                            /* It would be nice if we could spot
+                               ranges, and generate the rS-rE format: */
+                            for (reg = 0; (reg < 8); reg++)
+                              if ((given & (1 << reg)) != 0)
+                                {
+                                  if (started)
+                                    func (stream, ", ");
+                                  started = 1;
+                                  func (stream, "%s", arm_regnames[reg]);
+                                }
+
+                            if (domasklr)
+                              {
+                                if (started)
+                                  func (stream, ", ");
+                                started = 1;
+                                func (stream, arm_regnames[14] /* "lr" */);
+                              }
+
+                            if (domaskpc)
+                              {
+                                if (started)
+                                  func (stream, ", ");
+                                func (stream, arm_regnames[15] /* "pc" */);
+                              }
+
+                            func (stream, "}");
+                          }
+                          break;
+
+
+                        case '0': case '1': case '2': case '3': case '4': 
+                        case '5': case '6': case '7': case '8': case '9':
+                          {
+                            int bitstart = *c++ - '0';
+                            int bitend = 0;
+			    
+                            while (*c >= '0' && *c <= '9')
+                              bitstart = (bitstart * 10) + *c++ - '0';
+
+                            switch (*c)
+                              {
+                              case '-':
+                                {
+                                  long reg;
+				  
+                                  c++;
+                                  while (*c >= '0' && *c <= '9')
+                                    bitend = (bitend * 10) + *c++ - '0';
+                                  if (!bitend)
+                                    abort ();
+                                  reg = given >> bitstart;
+                                  reg &= (2 << (bitend - bitstart)) - 1;
+                                  switch (*c)
+                                    {
+                                    case 'r':
+                                      func (stream, "%s", arm_regnames[reg]);
+                                      break;
+
+                                    case 'd':
+                                      func (stream, "%d", reg);
+                                      break;
+
+                                    case 'H':
+                                      func (stream, "%d", reg << 1);
+                                      break;
+
+                                    case 'W':
+                                      func (stream, "%d", reg << 2);
+                                      break;
+
+                                    case 'a':
+				      /* PC-relative address -- the bottom two
+					 bits of the address are dropped
+					 before the calculation.  */
+                                      info->print_address_func
+					(((pc + 4) & ~3) + (reg << 2), info);
+                                      break;
+
+                                    case 'x':
+                                      func (stream, "0x%04x", reg);
+                                      break;
+
+                                    case 'I':
+                                      reg = ((reg ^ (1 << bitend)) -
+						      (1 << bitend));
+                                      func (stream, "%d", reg);
+                                      break;
+
+                                    case 'B':
+                                      reg = ((reg ^ (1 << bitend)) - 
+						      (1 << bitend));
+                                      (*info->print_address_func)
+                                        (reg * 2 + pc + 4, info);
+                                      break;
+
+                                    default:
+                                      abort ();
+                                    }
+                                }
+                                break;
+
+                              case '\'':
+                                c++;
+                                if ((given & (1 << bitstart)) != 0)
+                                  func (stream, "%c", *c);
+                                break;
+
+                              case '?':
+                                ++c;
+                                if ((given & (1 << bitstart)) != 0)
+                                  func (stream, "%c", *c++);
+                                else
+                                  func (stream, "%c", *++c);
+                                break;
+
+                              default:
+                                 abort ();
+                              }
+                          }
+                          break;
+
+                        default:
+                          abort ();
+                        }
+                    }
+                  else
+                    func (stream, "%c", *c);
+                }
+             }
+          return 2;
+       }
+    }
+
+  /* No match.  */
+  abort ();
+}
+
+/* Parse an individual disassembler option.  */
+void
+parse_arm_disassembler_option (option)
+     char * option;
+{
+  if (option == NULL)
+    return;
+      
+  if (strneq (option, "reg-names-", 10))
+    {
+      int i;
+	
+      option += 10;
+
+      for (i = NUM_ARM_REGNAMES; i--;)
+	if (streq (option, regnames[i].name))
+	  {
+	    regname_selected = i;
+	    break;
+	  }
+      
+      if (i < 0)
+	kdb_printf (_("Unrecognised register name set: %s\n"), option);
+    }
+  else if (streq (option, "force-thumb"))
+    force_thumb = 1;
+  else if (streq (option, "no-force-thumb"))
+    force_thumb = 0;
+  else
+    kdb_printf (_("Unrecognised disassembler option: %s\n"), option);
+  
+  return;
+}
+
+/* Parse the string of disassembler options, spliting it at whitespaces.  */
+static void
+parse_disassembler_options (options)
+     char * options;
+{
+  char * space;
+  
+  if (options == NULL)
+    return;
+
+  do
+    {
+      space = strchr (options, ' ');
+
+      if (space)
+	{
+	  * space = '\0';
+	  parse_arm_disassembler_option (options);
+	  * space = ' ';
+	  options = space + 1;
+	}
+      else
+	parse_arm_disassembler_option (options);
+    }
+  while (space);
+}
+
+/* NOTE: There are no checks in these routines that
+   the relevant number of data bytes exist.  */
+static int
+print_insn (pc, info, little)
+     bfd_vma pc;
+     struct disassemble_info * info;
+     boolean little;
+{
+  unsigned char      b[4];
+  long               given;
+  int                status;
+  int                is_thumb;
+
+  if (info->disassembler_options)
+    {
+      parse_disassembler_options (info->disassembler_options);
+      
+      /* To avoid repeated parsing of these options, we remove them here.  */
+      info->disassembler_options = NULL;
+    }
+  
+  is_thumb = 0;
+#if 0
+  is_thumb = force_thumb;
+  
+  if (!is_thumb && info->symbols != NULL)
+    {
+      if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
+	{
+	  coff_symbol_type * cs;
+	  
+	  cs = coffsymbol (*info->symbols);
+	  is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
+		      || cs->native->u.syment.n_sclass == C_THUMBSTAT
+		      || cs->native->u.syment.n_sclass == C_THUMBLABEL
+		      || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
+		      || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
+	}
+      else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
+	{
+	  elf_symbol_type *  es;
+	  unsigned int       type;
+	  
+	  es = *(elf_symbol_type **)(info->symbols);
+	  type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
+	  
+	  is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
+	}
+    }
+#endif
+  
+  info->bytes_per_chunk = 4;
+  info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
+
+  if (little)
+    {
+      status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
+      if (status != 0 && is_thumb)
+	{
+	  info->bytes_per_chunk = 2;
+	  
+	  status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
+	  b[3] = b[2] = 0;
+	}
+      
+      if (status != 0)
+	{
+	  info->memory_error_func (status, pc, info);
+	  return -1;
+	}
+      
+      given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
+    }
+  else
+    {
+      status = info->read_memory_func
+	(pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
+      if (status != 0)
+	{
+	  info->memory_error_func (status, pc, info);
+	  return -1;
+	}
+      
+      if (is_thumb)
+	{
+	  if (pc & 0x2)
+	    {
+	      given = (b[2] << 8) | b[3];
+	      
+	      status = info->read_memory_func
+		((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
+	      if (status != 0)
+		{
+		  info->memory_error_func (status, pc + 4, info);
+		  return -1;
+		}
+	      
+	      given |= (b[0] << 24) | (b[1] << 16);
+	    }
+	  else
+	    given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
+	}
+      else
+	given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
+    }
+  
+  if (info->flags & INSN_HAS_RELOC)
+    /* If the instruction has a reloc associated with it, then
+       the offset field in the instruction will actually be the
+       addend for the reloc.  (We are using REL type relocs).
+       In such cases, we can ignore the pc when computing
+       addresses, since the addend is not currently pc-relative.  */
+    pc = 0;
+  
+  if (is_thumb)
+    status = print_insn_thumb (pc, info, given);
+  else
+    status = print_insn_arm (pc, info, given);
+
+  return status;
+}
+
+int
+print_insn_big_arm (pc, info)
+     bfd_vma pc;
+     struct disassemble_info * info;
+{
+  return print_insn (pc, info, false);
+}
+
+int
+print_insn_little_arm (pc, info)
+     bfd_vma pc;
+     struct disassemble_info * info;
+{
+  return print_insn (pc, info, true);
+}
+
diff -uNr linux.orig/arch/arm/kdb/arm-opc.h linux/arch/arm/kdb/arm-opc.h
--- linux.orig/arch/arm/kdb/arm-opc.h	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/arm-opc.h	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,527 @@
+/* Opcode table for the ARM.
+
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/*
+ * Extracted from GDB CVS and modified for kdb use.
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+
+struct arm_opcode {
+    unsigned long value, mask;	/* recognise instruction if (op&mask)==value */
+    char *assembler;		/* how to disassemble this instruction */
+};
+
+struct thumb_opcode
+{
+    unsigned short value, mask;	/* recognise instruction if (op&mask)==value */
+    char * assembler;		/* how to disassemble this instruction */
+};
+
+/* format of the assembler string :
+   
+   %%			%
+   %<bitfield>d		print the bitfield in decimal
+   %<bitfield>x		print the bitfield in hex
+   %<bitfield>X		print the bitfield as 1 hex digit without leading "0x"
+   %<bitfield>r		print as an ARM register
+   %<bitfield>f		print a floating point constant if >7 else a
+			floating point register
+   %<code>y		print a single precision VFP reg.
+			  Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair
+   %<code>z		print a double precision VFP reg
+			  Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list
+   %c			print condition code (always bits 28-31)
+   %P			print floating point precision in arithmetic insn
+   %Q			print floating point precision in ldf/stf insn
+   %R			print floating point rounding mode
+   %<bitnum>'c		print specified char iff bit is one
+   %<bitnum>`c		print specified char iff bit is zero
+   %<bitnum>?ab		print a if bit is one else print b
+   %p			print 'p' iff bits 12-15 are 15
+   %t			print 't' iff bit 21 set and bit 24 clear
+   %o			print operand2 (immediate or register + shift)
+   %a			print address for ldr/str instruction
+   %s                   print address for ldr/str halfword/signextend instruction
+   %b			print branch destination
+   %B			print arm BLX(1) destination
+   %A			print address for ldc/stc/ldf/stf instruction
+   %m			print register mask for ldm/stm instruction
+   %C			print the PSR sub type.
+   %F			print the COUNT field of a LFM/SFM instruction.
+Thumb specific format options:
+   %D                   print Thumb register (bits 0..2 as high number if bit 7 set)
+   %S                   print Thumb register (bits 3..5 as high number if bit 6 set)
+   %<bitfield>I         print bitfield as a signed decimal
+   				(top bit of range being the sign bit)
+   %M                   print Thumb register mask
+   %N                   print Thumb register mask (with LR)
+   %O                   print Thumb register mask (with PC)
+   %T                   print Thumb condition code (always bits 8-11)
+   %I                   print cirrus signed shift immediate: bits 0..3|4..6
+   %<bitfield>B         print Thumb branch destination (signed displacement)
+   %<bitfield>W         print (bitfield * 4) as a decimal
+   %<bitfield>H         print (bitfield * 2) as a decimal
+   %<bitfield>a         print (bitfield * 4) as a pc-rel offset + decoded symbol
+*/
+
+/* Note: There is a partial ordering in this table - it must be searched from
+   the top to obtain a correct match. */
+
+static struct arm_opcode arm_opcodes[] =
+{
+    /* ARM instructions.  */
+    {0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"},
+    {0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
+    {0x00000090, 0x0fe000f0, "mul%c%20's\t%16-19r, %0-3r, %8-11r"},
+    {0x00200090, 0x0fe000f0, "mla%c%20's\t%16-19r, %0-3r, %8-11r, %12-15r"},
+    {0x01000090, 0x0fb00ff0, "swp%c%22'b\t%12-15r, %0-3r, [%16-19r]"},
+    {0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
+    {0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
+
+#ifndef CONFIG_CPU_XSCALE
+    /* V5J instruction.  */
+    {0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
+#endif	// !CONFIG_CPU_XSCALE
+
+    /* XScale instructions.  */
+    {0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"},
+    {0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"},
+    {0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"},
+    {0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
+    {0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
+    {0xf450f000, 0xfc70f000, "pld\t%a"},
+    
+    /* V5 Instructions.  */
+    {0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
+    {0xfa000000, 0xfe000000, "blx\t%B"},
+    {0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"},
+    {0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"},
+    {0xfc100000, 0xfe100000, "ldc2%22'l\t%8-11d, cr%12-15d, %A"},
+    {0xfc000000, 0xfe100000, "stc2%22'l\t%8-11d, cr%12-15d, %A"},
+    {0xfe000000, 0xff000010, "cdp2\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
+    {0xfe000010, 0xff100010, "mcr2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+    {0xfe100010, 0xff100010, "mrc2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+
+    /* V5E "El Segundo" Instructions.  */    
+    {0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
+    {0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
+    {0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+    {0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+    {0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+    {0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+
+    {0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+    {0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+
+    {0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+    {0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+    {0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+    {0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+
+    {0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"},
+    {0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"},
+    {0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"},
+    {0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"},
+
+    {0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
+    {0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
+
+    {0x01000050, 0x0ff00ff0,  "qadd%c\t%12-15r, %0-3r, %16-19r"},
+    {0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"},
+    {0x01200050, 0x0ff00ff0,  "qsub%c\t%12-15r, %0-3r, %16-19r"},
+    {0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"},
+
+    {0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
+    {0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
+
+    /* ARM Instructions.  */
+    {0x00000090, 0x0e100090, "str%c%6's%5?hb\t%12-15r, %s"},
+    {0x00100090, 0x0e100090, "ldr%c%6's%5?hb\t%12-15r, %s"},
+    {0x00000000, 0x0de00000, "and%c%20's\t%12-15r, %16-19r, %o"},
+    {0x00200000, 0x0de00000, "eor%c%20's\t%12-15r, %16-19r, %o"},
+    {0x00400000, 0x0de00000, "sub%c%20's\t%12-15r, %16-19r, %o"},
+    {0x00600000, 0x0de00000, "rsb%c%20's\t%12-15r, %16-19r, %o"},
+    {0x00800000, 0x0de00000, "add%c%20's\t%12-15r, %16-19r, %o"},
+    {0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
+    {0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
+    {0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
+    {0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
+    {0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
+    {0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
+    {0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
+    {0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
+    {0x01600000, 0x0de00000, "cmn%c%p\t%16-19r, %o"},
+    {0x01800000, 0x0de00000, "orr%c%20's\t%12-15r, %16-19r, %o"},
+    {0x01a00000, 0x0de00000, "mov%c%20's\t%12-15r, %o"},
+    {0x01c00000, 0x0de00000, "bic%c%20's\t%12-15r, %16-19r, %o"},
+    {0x01e00000, 0x0de00000, "mvn%c%20's\t%12-15r, %o"},
+    {0x04000000, 0x0e100000, "str%c%22'b%t\t%12-15r, %a"},
+    {0x06000000, 0x0e100ff0, "str%c%22'b%t\t%12-15r, %a"},
+    {0x04000000, 0x0c100010, "str%c%22'b%t\t%12-15r, %a"},
+    {0x06000010, 0x0e000010, "undefined"},
+    {0x04100000, 0x0c100000, "ldr%c%22'b%t\t%12-15r, %a"},
+    {0x08000000, 0x0e100000, "stm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
+    {0x08100000, 0x0e100000, "ldm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
+    {0x0a000000, 0x0e000000, "b%24'l%c\t%b"},
+    {0x0f000000, 0x0f000000, "swi%c\t%0-23x"},
+
+#ifndef CONFIG_CPU_XSCALE
+    /* Floating point coprocessor (FPA) instructions */
+    {0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"},
+    {0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"},
+    {0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"},
+    {0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"},
+    {0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"},
+    {0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"},
+    {0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"},
+    {0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"},
+    {0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"},
+    {0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"},
+    {0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"},
+    {0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"},
+    {0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"},
+    {0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"},
+    {0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"},
+    {0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"},
+    {0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"},
+    {0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"},
+    {0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"},
+    {0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"},
+    {0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"},
+    {0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"},
+    {0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"},
+    {0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"},
+    {0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"},
+    {0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"},
+    {0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"},
+    {0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"},
+    {0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"},
+    {0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"},
+    {0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"},
+
+    /* Floating point coprocessor (VFP) instructions */
+    {0x0eb00bc0, 0x0fff0ff0, "fabsd%c\t%1z, %0z"},
+    {0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%1y, %0y"},
+    {0x0e300b00, 0x0ff00ff0, "faddd%c\t%1z, %2z, %0z"},
+    {0x0e300a00, 0x0fb00f50, "fadds%c\t%1y, %2y, %1y"},
+    {0x0eb40b40, 0x0fff0f70, "fcmp%7'ed%c\t%1z, %0z"},
+    {0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%1y, %0y"},
+    {0x0eb50b40, 0x0fff0f70, "fcmp%7'ezd%c\t%1z"},
+    {0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%1y"},
+    {0x0eb00b40, 0x0fff0ff0, "fcpyd%c\t%1z, %0z"},
+    {0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%1y, %0y"},
+    {0x0eb70ac0, 0x0fff0fd0, "fcvtds%c\t%1z, %0y"},
+    {0x0eb70bc0, 0x0fbf0ff0, "fcvtsd%c\t%1y, %0z"},
+    {0x0e800b00, 0x0ff00ff0, "fdivd%c\t%1z, %2z, %0z"},
+    {0x0e800a00, 0x0fb00f50, "fdivs%c\t%1y, %2y, %0y"},
+    {0x0d100b00, 0x0f700f00, "fldd%c\t%1z, %A"},
+    {0x0c900b00, 0x0fd00f00, "fldmia%0?xd%c\t%16-19r%21'!, %3z"},
+    {0x0d300b00, 0x0ff00f00, "fldmdb%0?xd%c\t%16-19r!, %3z"},
+    {0x0d100a00, 0x0f300f00, "flds%c\t%1y, %A"},
+    {0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %3y"},
+    {0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %3y"},
+    {0x0e000b00, 0x0ff00ff0, "fmacd%c\t%1z, %2z, %0z"},
+    {0x0e000a00, 0x0fb00f50, "fmacs%c\t%1y, %2y, %0y"},
+    {0x0e200b10, 0x0ff00fff, "fmdhr%c\t%2z, %12-15r"},
+    {0x0e000b10, 0x0ff00fff, "fmdlr%c\t%2z, %12-15r"},
+    {0x0c400b10, 0x0ff00ff0, "fmdrr%c\t%0z, %12-15r, %16-19r"},
+    {0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %2z"},
+    {0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %2z"},
+    {0x0c500b10, 0x0ff00ff0, "fmrrd%c\t%12-15r, %16-19r, %0z"},
+    {0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %4y"},
+    {0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %2y"},
+    {0x0ef1fa10, 0x0fffffff, "fmstat%c"},
+    {0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"},
+    {0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"},
+    {0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"},
+    {0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"},
+    {0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"},
+    {0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, <impl def 0x%16-19x>"},
+    {0x0e100b00, 0x0ff00ff0, "fmscd%c\t%1z, %2z, %0z"},
+    {0x0e100a00, 0x0fb00f50, "fmscs%c\t%1y, %2y, %0y"},
+    {0x0e000a10, 0x0ff00f7f, "fmsr%c\t%2y, %12-15r"},
+    {0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%12-15r, %16-19r, %4y"},
+    {0x0e200b00, 0x0ff00ff0, "fmuld%c\t%1z, %2z, %0z"},
+    {0x0e200a00, 0x0fb00f50, "fmuls%c\t%1y, %2y, %0y"},
+    {0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"},
+    {0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"},
+    {0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"},
+    {0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"},
+    {0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"},
+    {0x0ee00a10, 0x0ff00fff, "fmxr%c\t<impl def 0x%16-19x>, %12-15r"},
+    {0x0eb10b40, 0x0fff0ff0, "fnegd%c\t%1z, %0z"},
+    {0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%1y, %0y"},
+    {0x0e000b40, 0x0ff00ff0, "fnmacd%c\t%1z, %2z, %0z"},
+    {0x0e000a40, 0x0fb00f50, "fnmacs%c\t%1y, %2y, %0y"},
+    {0x0e100b40, 0x0ff00ff0, "fnmscd%c\t%1z, %2z, %0z"},
+    {0x0e100a40, 0x0fb00f50, "fnmscs%c\t%1y, %2y, %0y"},
+    {0x0e200b40, 0x0ff00ff0, "fnmuld%c\t%1z, %2z, %0z"},
+    {0x0e200a40, 0x0fb00f50, "fnmuls%c\t%1y, %2y, %0y"},
+    {0x0eb80bc0, 0x0fff0fd0, "fsitod%c\t%1z, %0y"},
+    {0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%1y, %0y"},
+    {0x0eb10bc0, 0x0fff0ff0, "fsqrtd%c\t%1z, %0z"},
+    {0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%1y, %0y"},
+    {0x0d000b00, 0x0f700f00, "fstd%c\t%1z, %A"},
+    {0x0c800b00, 0x0fd00f00, "fstmia%0?xd%c\t%16-19r%21'!, %3z"},
+    {0x0d200b00, 0x0ff00f00, "fstmdb%0?xd%c\t%16-19r!, %3z"},
+    {0x0d000a00, 0x0f300f00, "fsts%c\t%1y, %A"},
+    {0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %3y"},
+    {0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %3y"},
+    {0x0e300b40, 0x0ff00ff0, "fsubd%c\t%1z, %2z, %0z"},
+    {0x0e300a40, 0x0fb00f50, "fsubs%c\t%1y, %2y, %0y"},
+    {0x0ebc0b40, 0x0fbe0f70, "fto%16?sui%7'zd%c\t%1y, %0z"},
+    {0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%1y, %0y"},
+    {0x0eb80b40, 0x0fff0fd0, "fuitod%c\t%1z, %0y"},
+    {0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%1y, %0y"},
+
+    /* Cirrus coprocessor instructions.  */
+    {0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
+    {0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
+    {0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
+    {0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"}, 
+    {0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
+    {0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
+    {0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
+    {0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
+    {0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
+    {0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
+    {0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
+    {0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
+    {0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
+    {0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
+    {0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
+    {0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
+    {0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"},
+    {0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"},
+    {0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"},
+    {0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"},
+    {0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"},
+    {0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"},
+    {0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"},
+    {0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"},
+    {0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"},
+    {0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"},
+    {0x0e100610, 0x0ff0fff0, "cfmval32%c\tmvax%0-3d, mvfx%16-19d"},
+    {0x0e000610, 0x0ff0fff0, "cfmv32al%c\tmvfx%0-3d, mvax%16-19d"},
+    {0x0e100630, 0x0ff0fff0, "cfmvam32%c\tmvax%0-3d, mvfx%16-19d"},
+    {0x0e000630, 0x0ff0fff0, "cfmv32am%c\tmvfx%0-3d, mvax%16-19d"},
+    {0x0e100650, 0x0ff0fff0, "cfmvah32%c\tmvax%0-3d, mvfx%16-19d"},
+    {0x0e000650, 0x0ff0fff0, "cfmv32ah%c\tmvfx%0-3d, mvax%16-19d"},
+    {0x0e000670, 0x0ff0fff0, "cfmv32a%c\tmvfx%0-3d, mvax%16-19d"},
+    {0x0e100670, 0x0ff0fff0, "cfmva32%c\tmvax%0-3d, mvfx%16-19d"},
+    {0x0e000690, 0x0ff0fff0, "cfmv64a%c\tmvdx%0-3d, mvax%16-19d"},
+    {0x0e100690, 0x0ff0fff0, "cfmva64%c\tmvax%0-3d, mvdx%16-19d"},
+    {0x0e1006b0, 0x0ff0fff0, "cfmvsc32%c\tdspsc, mvfx%16-19d"},
+    {0x0e0006b0, 0x0ff0fff0, "cfmv32sc%c\tmvfx%0-3d, dspsc"},
+    {0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"},
+    {0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"},
+    {0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"},
+    {0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"},
+    {0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"},
+    {0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"},
+    {0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"},
+    {0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"},
+    {0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"},
+    {0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"},
+    {0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"},
+    {0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"},
+    {0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"},
+    {0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"},
+    {0x0e000500, 0x0ff00f00, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"},
+    {0x0e200500, 0x0ff00f00, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"},
+    {0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"},
+    {0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"},
+    {0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"},
+    {0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"},
+    {0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"},
+    {0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"},
+    {0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"},
+    {0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+    {0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+    {0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+    {0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+    {0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+    {0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+    {0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"},
+    {0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"},
+    {0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"},
+    {0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"},
+    {0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+    {0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+    {0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+    {0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e000600, 0x0ff00f00, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e100600, 0x0ff00f00, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e200600, 0x0ff00f00, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
+    {0x0e300600, 0x0ff00f00, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
+#endif	// !CONFIG_CPU_XSCALE
+
+    /* Generic coprocessor instructions */
+    {0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
+    {0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+    {0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+    {0x0c000000, 0x0e100000, "stc%c%22'l\t%8-11d, cr%12-15d, %A"},
+    {0x0c100000, 0x0e100000, "ldc%c%22'l\t%8-11d, cr%12-15d, %A"},
+
+    /* The rest.  */
+    {0x00000000, 0x00000000, "undefined instruction %0-31x"},
+    {0x00000000, 0x00000000, 0}
+};
+
+#define BDISP(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000) /* 26 bit */
+
+static struct thumb_opcode thumb_opcodes[] =
+{
+  /* Thumb instructions.  */
+
+  /* ARM V5 ISA extends Thumb.  */
+  {0xbe00, 0xff00, "bkpt\t%0-7x"},
+  {0x4780, 0xff87, "blx\t%3-6r"},	/* note: 4 bit register number.  */
+  /* Note: this is BLX(2).  BLX(1) is done in arm-dis.c/print_insn_thumb()
+     as an extension of the special processing there for Thumb BL.
+     BL and BLX(1) involve 2 successive 16-bit instructions, which must
+     always appear together in the correct order.  So, the empty
+     string is put in this table, and the string interpreter takes <empty>
+     to mean it has a pair of BL-ish instructions.  */
+  {0x46C0, 0xFFFF, "nop\t\t\t(mov r8, r8)"},
+  /* Format 5 instructions do not update the PSR.  */
+  {0x1C00, 0xFFC0, "mov\t%0-2r, %3-5r\t\t(add %0-2r, %3-5r, #%6-8d)"},
+  /* Format 4.  */
+  {0x4000, 0xFFC0, "and\t%0-2r, %3-5r"},
+  {0x4040, 0xFFC0, "eor\t%0-2r, %3-5r"},
+  {0x4080, 0xFFC0, "lsl\t%0-2r, %3-5r"},
+  {0x40C0, 0xFFC0, "lsr\t%0-2r, %3-5r"},
+  {0x4100, 0xFFC0, "asr\t%0-2r, %3-5r"},
+  {0x4140, 0xFFC0, "adc\t%0-2r, %3-5r"},
+  {0x4180, 0xFFC0, "sbc\t%0-2r, %3-5r"},
+  {0x41C0, 0xFFC0, "ror\t%0-2r, %3-5r"},
+  {0x4200, 0xFFC0, "tst\t%0-2r, %3-5r"},
+  {0x4240, 0xFFC0, "neg\t%0-2r, %3-5r"},
+  {0x4280, 0xFFC0, "cmp\t%0-2r, %3-5r"},
+  {0x42C0, 0xFFC0, "cmn\t%0-2r, %3-5r"},
+  {0x4300, 0xFFC0, "orr\t%0-2r, %3-5r"},
+  {0x4340, 0xFFC0, "mul\t%0-2r, %3-5r"},
+  {0x4380, 0xFFC0, "bic\t%0-2r, %3-5r"},
+  {0x43C0, 0xFFC0, "mvn\t%0-2r, %3-5r"},
+  /* format 13 */
+  {0xB000, 0xFF80, "add\tsp, #%0-6W"},
+  {0xB080, 0xFF80, "sub\tsp, #%0-6W"},
+  /* format 5 */
+  {0x4700, 0xFF80, "bx\t%S"},
+  {0x4400, 0xFF00, "add\t%D, %S"},
+  {0x4500, 0xFF00, "cmp\t%D, %S"},
+  {0x4600, 0xFF00, "mov\t%D, %S"},
+  /* format 14 */
+  {0xB400, 0xFE00, "push\t%N"},
+  {0xBC00, 0xFE00, "pop\t%O"},
+  /* format 2 */
+  {0x1800, 0xFE00, "add\t%0-2r, %3-5r, %6-8r"},
+  {0x1A00, 0xFE00, "sub\t%0-2r, %3-5r, %6-8r"},
+  {0x1C00, 0xFE00, "add\t%0-2r, %3-5r, #%6-8d"},
+  {0x1E00, 0xFE00, "sub\t%0-2r, %3-5r, #%6-8d"},
+  /* format 8 */
+  {0x5200, 0xFE00, "strh\t%0-2r, [%3-5r, %6-8r]"},
+  {0x5A00, 0xFE00, "ldrh\t%0-2r, [%3-5r, %6-8r]"},
+  {0x5600, 0xF600, "ldrs%11?hb\t%0-2r, [%3-5r, %6-8r]"},
+  /* format 7 */
+  {0x5000, 0xFA00, "str%10'b\t%0-2r, [%3-5r, %6-8r]"},
+  {0x5800, 0xFA00, "ldr%10'b\t%0-2r, [%3-5r, %6-8r]"},
+  /* format 1 */
+  {0x0000, 0xF800, "lsl\t%0-2r, %3-5r, #%6-10d"},
+  {0x0800, 0xF800, "lsr\t%0-2r, %3-5r, #%6-10d"},
+  {0x1000, 0xF800, "asr\t%0-2r, %3-5r, #%6-10d"},
+  /* format 3 */
+  {0x2000, 0xF800, "mov\t%8-10r, #%0-7d"},
+  {0x2800, 0xF800, "cmp\t%8-10r, #%0-7d"},
+  {0x3000, 0xF800, "add\t%8-10r, #%0-7d"},
+  {0x3800, 0xF800, "sub\t%8-10r, #%0-7d"},
+  /* format 6 */
+  {0x4800, 0xF800, "ldr\t%8-10r, [pc, #%0-7W]\t(%0-7a)"},  /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
+  /* format 9 */
+  {0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
+  {0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
+  {0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
+  {0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
+  /* format 10 */
+  {0x8000, 0xF800, "strh\t%0-2r, [%3-5r, #%6-10H]"},
+  {0x8800, 0xF800, "ldrh\t%0-2r, [%3-5r, #%6-10H]"},
+  /* format 11 */
+  {0x9000, 0xF800, "str\t%8-10r, [sp, #%0-7W]"},
+  {0x9800, 0xF800, "ldr\t%8-10r, [sp, #%0-7W]"},
+  /* format 12 */
+  {0xA000, 0xF800, "add\t%8-10r, pc, #%0-7W\t(adr %8-10r,%0-7a)"},
+  {0xA800, 0xF800, "add\t%8-10r, sp, #%0-7W"},
+  /* format 15 */
+  {0xC000, 0xF800, "stmia\t%8-10r!,%M"},
+  {0xC800, 0xF800, "ldmia\t%8-10r!,%M"},
+  /* format 18 */
+  {0xE000, 0xF800, "b\t%0-10B"},
+  {0xE800, 0xF800, "undefined"},
+  /* format 19 */
+  {0xF000, 0xF800, ""}, /* special processing required in disassembler */
+  {0xF800, 0xF800, "second half of BL instruction %0-15x"},
+  /* format 16 */
+  {0xD000, 0xFF00, "beq\t%0-7B"},
+  {0xD100, 0xFF00, "bne\t%0-7B"},
+  {0xD200, 0xFF00, "bcs\t%0-7B"},
+  {0xD300, 0xFF00, "bcc\t%0-7B"},
+  {0xD400, 0xFF00, "bmi\t%0-7B"},
+  {0xD500, 0xFF00, "bpl\t%0-7B"},
+  {0xD600, 0xFF00, "bvs\t%0-7B"},
+  {0xD700, 0xFF00, "bvc\t%0-7B"},
+  {0xD800, 0xFF00, "bhi\t%0-7B"},
+  {0xD900, 0xFF00, "bls\t%0-7B"},
+  {0xDA00, 0xFF00, "bge\t%0-7B"},
+  {0xDB00, 0xFF00, "blt\t%0-7B"},
+  {0xDC00, 0xFF00, "bgt\t%0-7B"},
+  {0xDD00, 0xFF00, "ble\t%0-7B"},
+  /* format 17 */
+  {0xDE00, 0xFF00, "bal\t%0-7B"},
+  {0xDF00, 0xFF00, "swi\t%0-7d"},
+  /* format 9 */
+  {0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
+  {0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
+  {0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
+  {0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
+  /* the rest */
+  {0x0000, 0x0000, "undefined instruction %0-15x"},
+  {0x0000, 0x0000, 0}
+};
+
+#define BDISP23(x) ((((((x) & 0x07ff) << 11) | (((x) & 0x07ff0000) >> 16)) \
+                     ^ 0x200000) - 0x200000) /* 23bit */
+
diff -uNr linux.orig/arch/arm/kdb/arm-tdep.c linux/arch/arm/kdb/arm-tdep.c
--- linux.orig/arch/arm/kdb/arm-tdep.c	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/arm-tdep.c	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,812 @@
+/* Common target dependent code for GDB on ARM systems.
+   Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999, 2000,
+   2001, 2002 Free Software Foundation, Inc.
+   Extracted from GDB-5.2.1 and modified for kdb use by
+   Eddie Dong <Eddie.Dong@intel.com> 22 Jan 2003
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/*
+ * Extracted from GDB CVS and modified for kdb use.
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/dis-asm.h>
+#include <linux/kdb.h>
+#endif	/* __KERNEL__ */
+
+#include  "arm-tdep.h"
+#if    defined(CONFIG_CPU_XSCALE) && !defined(ARM_V5T)
+	#define  ARM_V5T
+#endif
+
+#if   defined(ARM_V5T) && !defined(ARM_V4T)
+	#define  ARM_V4T
+#endif
+
+
+/* Set to true if the 32-bit mode is in use. */
+int arm_apcs_32 = 1;
+#define fprintf_filtered(x,y)	kdb_printf(y)
+CORE_ADDR thumb_get_next_pc (CORE_ADDR pc)
+{
+    return 0;
+}
+int arm_pc_is_thumb (CORE_ADDR memaddr)
+{
+    return 0;
+}
+
+unsigned long read_memory_integer(CORE_ADDR addr, int nr)
+{
+    unsigned long data;
+    if ( nr > 4 ) return 0;
+    
+    kdb_getarea_size(&data, addr, nr);
+    return data;
+}
+
+/*
+ * Returns:
+ *	1 for success, 0 for error.
+ */
+int safe_read_memory_integer (CORE_ADDR addr, int len,  LONGEST *return_value)
+{
+	if ( len > 4 ) return 0;
+	return kdb_getarea_size(return_value, addr, len) == 0;	
+}
+
+static CORE_ADDR arm_addr_bits_remove (CORE_ADDR val);
+#define  ADDR_BITS_REMOVE       arm_addr_bits_remove
+#define  read_memory_unsigned_integer	read_memory_integer
+
+
+
+/* This function decodes an ARM function prologue to determine:
+   1) the size of the stack frame
+   2) which registers are saved on it
+   3) the offsets of saved regs
+   4) the offset from the stack pointer to the frame pointer
+   This information is stored in the "extra" fields of the frame_info.
+
+   There are two basic forms for the ARM prologue.  The fixed argument
+   function call will look like:
+
+   mov    ip, sp
+   stmfd  sp!, {fp, ip, lr, pc}
+   sub    fp, ip, #4
+   [sub sp, sp, #4]
+
+   Which would create this stack frame (offsets relative to FP):
+   IP ->   4    (caller's stack)
+   FP ->   0    PC (points to address of stmfd instruction + 8 in callee)
+   -4   LR (return address in caller)
+   -8   IP (copy of caller's SP)
+   -12  FP (caller's FP)
+   SP -> -28    Local variables
+
+   The frame size would thus be 32 bytes, and the frame offset would be
+   28 bytes.  The stmfd call can also save any of the vN registers it
+   plans to use, which increases the frame size accordingly.
+
+   Note: The stored PC is 8 off of the STMFD instruction that stored it
+   because the ARM Store instructions always store PC + 8 when you read
+   the PC register.
+
+   A variable argument function call will look like:
+
+   mov    ip, sp
+   stmfd  sp!, {a1, a2, a3, a4}
+   stmfd  sp!, {fp, ip, lr, pc}
+   sub    fp, ip, #20
+
+   Which would create this stack frame (offsets relative to FP):
+   IP ->  20    (caller's stack)
+   16  A4
+   12  A3
+   8  A2
+   4  A1
+   FP ->   0    PC (points to address of stmfd instruction + 8 in callee)
+   -4   LR (return address in caller)
+   -8   IP (copy of caller's SP)
+   -12  FP (caller's FP)
+   SP -> -28    Local variables
+
+   The frame size would thus be 48 bytes, and the frame offset would be
+   28 bytes.
+
+   There is another potential complication, which is that the optimizer
+   will try to separate the store of fp in the "stmfd" instruction from
+   the "sub fp, ip, #NN" instruction.  Almost anything can be there, so
+   we just key on the stmfd, and then scan for the "sub fp, ip, #NN"...
+
+   Also, note, the original version of the ARM toolchain claimed that there
+   should be an
+
+   instruction at the end of the prologue.  I have never seen GCC produce
+   this, and the ARM docs don't mention it.  We still test for it below in
+   case it happens...
+
+ */
+
+void arm_scan_prologue (struct frame_info *fi)
+{
+  int regno, sp_offset, fp_offset;
+  LONGEST return_value;
+  CORE_ADDR prologue_start, prologue_end, current_pc;
+
+  /* Assume there is no frame until proven otherwise.  */
+  fi->extra_info.framereg = ARM_SP_REGNUM;
+  fi->extra_info.framesize = 0;
+  fi->extra_info.frameoffset = 0;
+
+  /* Find the function prologue.  If we can't find the function in
+     the symbol table, peek in the stack frame to find the PC.  */
+  if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
+    {
+      /* One way to find the end of the prologue (which works well
+         for unoptimized code) is to do the following:
+
+	    struct symtab_and_line sal = find_pc_line (prologue_start, 0);
+
+	    if (sal.line == 0)
+	      prologue_end = fi->pc;
+	    else if (sal.end < prologue_end)
+	      prologue_end = sal.end;
+
+	 This mechanism is very accurate so long as the optimizer
+	 doesn't move any instructions from the function body into the
+	 prologue.  If this happens, sal.end will be the last
+	 instruction in the first hunk of prologue code just before
+	 the first instruction that the scheduler has moved from
+	 the body to the prologue.
+
+	 In order to make sure that we scan all of the prologue
+	 instructions, we use a slightly less accurate mechanism which
+	 may scan more than necessary.  To help compensate for this
+	 lack of accuracy, the prologue scanning loop below contains
+	 several clauses which'll cause the loop to terminate early if
+	 an implausible prologue instruction is encountered.  
+	 
+	 The expression
+	 
+	      prologue_start + 64
+	    
+	 is a suitable endpoint since it accounts for the largest
+	 possible prologue plus up to five instructions inserted by
+	 the scheduler. */
+         
+      if (prologue_end > prologue_start + 64)
+	{
+	  prologue_end = prologue_start + 64;	/* See above. */
+	}
+    }
+  else
+    {
+      /* Get address of the stmfd in the prologue of the callee; the saved
+         PC is the address of the stmfd + 8.  */
+      if (!safe_read_memory_integer (fi->frame, 4,  &return_value)) 
+        return;
+      else
+        {
+          prologue_start = ADDR_BITS_REMOVE (return_value) - 8;
+          prologue_end = prologue_start + 64;   /* See above. */
+        }
+    }
+
+  /* Now search the prologue looking for instructions that set up the
+     frame pointer, adjust the stack pointer, and save registers.
+
+     Be careful, however, and if it doesn't look like a prologue,
+     don't try to scan it.  If, for instance, a frameless function
+     begins with stmfd sp!, then we will tell ourselves there is
+     a frame, which will confuse stack traceback, as well ad"finish" 
+     and other operations that rely on a knowledge of the stack
+     traceback.
+
+     In the APCS, the prologue should start with  "mov ip, sp" so
+     if we don't see this as the first insn, we will stop.  [Note:
+     This doesn't seem to be true any longer, so it's now an optional
+     part of the prologue.  - Kevin Buettner, 2001-11-20]  */
+
+  sp_offset = fp_offset = 0;
+
+  if (read_memory_unsigned_integer (prologue_start, 4)
+      == 0xe1a0c00d)		/* mov ip, sp */
+    current_pc = prologue_start + 4;
+  else
+    current_pc = prologue_start;
+
+  for (; current_pc < prologue_end && current_pc < fi->pc ; current_pc += 4)
+    {
+      unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
+
+      if ((insn & 0xffff0000) == 0xe92d0000)
+	/* stmfd sp!, {..., fp, ip, lr, pc}
+	   or
+	   stmfd sp!, {a1, a2, a3, a4}  */
+	{
+	  int mask = insn & 0xffff;
+
+	  /* Calculate offsets of saved registers. */
+	  for (regno = ARM_PC_REGNUM; regno >= 0; regno--)
+	    if (mask & (1 << regno))
+	      {
+		sp_offset -= 4;
+		fi->saved_regs[regno] = sp_offset;
+	      }
+	}
+      else if ((insn & 0xfffff000) == 0xe24cb000)	/* sub fp, ip #n */
+	{
+	  unsigned imm = insn & 0xff;	/* immediate value */
+	  unsigned rot = (insn & 0xf00) >> 7;	/* rotate amount */
+	  imm = (imm >> rot) | (imm << (32 - rot));
+	  fp_offset = -imm;
+	  fi->extra_info.framereg = ARM_FP_REGNUM;
+	}
+      else if ((insn & 0xfffff000) == 0xe24dd000)	/* sub sp, sp #n */
+	{
+	  unsigned imm = insn & 0xff;	/* immediate value */
+	  unsigned rot = (insn & 0xf00) >> 7;	/* rotate amount */
+	  imm = (imm >> rot) | (imm << (32 - rot));
+	  sp_offset -= imm;
+	}
+#ifndef CONFIG_CPU_XSCALE
+      else if ((insn & 0xffff7fff) == 0xed6d0103)	/* stfe f?, [sp, -#c]! */
+	{
+	  sp_offset -= 12;
+	  regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
+	  fi->saved_regs[regno] = sp_offset;
+	}
+      else if ((insn & 0xffbf0fff) == 0xec2d0200)	/* sfmfd f0, 4, [sp!] */
+	{
+	  int n_saved_fp_regs;
+	  unsigned int fp_start_reg, fp_bound_reg;
+
+	  if ((insn & 0x800) == 0x800)	/* N0 is set */
+	    {
+	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
+		n_saved_fp_regs = 3;
+	      else
+		n_saved_fp_regs = 1;
+	    }
+	  else
+	    {
+	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
+		n_saved_fp_regs = 2;
+	      else
+		n_saved_fp_regs = 4;
+	    }
+
+	  fp_start_reg = ARM_F0_REGNUM + ((insn >> 12) & 0x7);
+	  fp_bound_reg = fp_start_reg + n_saved_fp_regs;
+	  for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
+	    {
+	      sp_offset -= 12;
+	      fi->saved_regs[fp_start_reg++] = sp_offset;
+	    }
+	}
+#endif	// !CONFIG_CPU_XSCALE
+      else if ((insn & 0xf0000000) != 0xe0000000) {
+	break;	/* Condition not true, exit early */
+      }
+      else if ((insn & 0xfe200000) == 0xe8200000) { /* ldm? */
+	break;	/* Don't scan past a block load */
+      }
+      else if ( is_branch(insn) ) {
+      	break;
+      }
+      else
+	/* The optimizer might shove anything into the prologue,
+	   so we just skip what we don't recognize. */
+	continue;
+    }
+
+  /* The frame size is just the negative of the offset (from the original SP)
+     of the last thing thing we pushed on the stack.  The frame offset is
+     [new FP] - [new SP].  */
+  fi->extra_info.framesize = -sp_offset;
+  if (fi->extra_info.framereg == ARM_FP_REGNUM)
+    fi->extra_info.frameoffset = fp_offset - sp_offset;
+  else
+    fi->extra_info.frameoffset = 0;
+    
+    return ;
+
+}
+
+
+
+
+/* Remove useless bits from addresses in a running program.  */
+static CORE_ADDR
+arm_addr_bits_remove (CORE_ADDR val)
+{
+  if (arm_pc_is_thumb (val))
+    return (val & (arm_apcs_32 ? 0xfffffffe : 0x03fffffe));
+  else
+    return (val & (arm_apcs_32 ? 0xfffffffc : 0x03fffffc));
+}
+
+static int
+condition_true (unsigned long cond, unsigned long status_reg)
+{
+  if (cond == INST_AL || cond == INST_NV)
+    return 1;
+
+  switch (cond)
+    {
+    case INST_EQ:
+      return ((status_reg & FLAG_Z) != 0);
+    case INST_NE:
+      return ((status_reg & FLAG_Z) == 0);
+    case INST_CS:
+      return ((status_reg & FLAG_C) != 0);
+    case INST_CC:
+      return ((status_reg & FLAG_C) == 0);
+    case INST_MI:
+      return ((status_reg & FLAG_N) != 0);
+    case INST_PL:
+      return ((status_reg & FLAG_N) == 0);
+    case INST_VS:
+      return ((status_reg & FLAG_V) != 0);
+    case INST_VC:
+      return ((status_reg & FLAG_V) == 0);
+    case INST_HI:
+      return ((status_reg & (FLAG_C | FLAG_Z)) == FLAG_C);
+    case INST_LS:
+      return ((status_reg & (FLAG_C | FLAG_Z)) != FLAG_C);
+    case INST_GE:
+      return (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0));
+    case INST_LT:
+      return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0));
+    case INST_GT:
+      return (((status_reg & FLAG_Z) == 0) &&
+	      (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0)));
+    case INST_LE:
+      return (((status_reg & FLAG_Z) != 0) ||
+	      (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0)));
+    }
+  return 1;
+}
+
+/* Support routines for single stepping.  Calculate the next PC value.  */
+#define submask(x) ((1L << ((x) + 1)) - 1)
+#define bit(obj,st) (((obj) >> (st)) & 1)
+#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
+#define sbits(obj,st,fn) \
+  ((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st))))
+#define BranchDest(addr,instr) \
+  ((CORE_ADDR) (((long) (addr)) + 8 + (sbits (instr, 0, 23) << 2)))
+#define ARM_PC_32 1
+unsigned long read_register(int regno, struct pt_regs *regs)
+{
+    if ( regno <= ARM_PC_REGNUM ) {
+        return regs->uregs[regno];
+    }
+    else if ( regno == ARM_PS_REGNUM ) {
+        return regs->ARM_cpsr;
+    }
+    else if ( regno == ARM_SPS_REGNUM ) {
+	kdb_printf ( "Unkown how to read spsr now\n");
+	return 0;
+    }
+    else {
+	kdb_printf ( "Unrecognised register number: %d\n", regno);
+        return 0;
+    }
+}
+
+static unsigned long
+shifted_reg_val (unsigned long inst, int carry, unsigned long pc_val,
+		 unsigned long status_reg,struct pt_regs *regs)
+{
+  unsigned long res, shift;
+  int rm = bits (inst, 0, 3);
+  unsigned long shifttype = bits (inst, 5, 6);
+
+  if (bit (inst, 4))
+    {
+      int rs = bits (inst, 8, 11);
+      shift = (rs == 15 ? pc_val + 8 : read_register (rs,regs)) & 0xFF;
+    }
+  else
+    shift = bits (inst, 7, 11);
+
+  res = (rm == 15
+	 ? ((pc_val | (ARM_PC_32 ? 0 : status_reg))
+	    + (bit (inst, 4) ? 12 : 8))
+	 : read_register (rm,regs));
+
+  switch (shifttype)
+    {
+    case 0:			/* LSL */
+      res = shift >= 32 ? 0 : res << shift;
+      break;
+
+    case 1:			/* LSR */
+      res = shift >= 32 ? 0 : res >> shift;
+      break;
+
+    case 2:			/* ASR */
+      if (shift >= 32)
+	shift = 31;
+      res = ((res & 0x80000000L)
+	     ? ~((~res) >> shift) : res >> shift);
+      break;
+
+    case 3:			/* ROR/RRX */
+      shift &= 31;
+      if (shift == 0)
+	res = (res >> 1) | (carry ? 0x80000000L : 0);
+      else
+	res = (res >> shift) | (res << (32 - shift));
+      break;
+    }
+
+  return res & 0xffffffff;
+}
+
+/* Return number of 1-bits in VAL.  */
+
+static int
+bitcount (unsigned long val)
+{
+  int nbits;
+  for (nbits = 0; val != 0; nbits++)
+    val &= val - 1;		/* delete rightmost 1-bit in val */
+  return nbits;
+}
+
+CORE_ADDR arm_get_next_pc (CORE_ADDR pc,struct pt_regs *regs)
+{
+  unsigned long pc_val;
+  unsigned long this_instr;
+  unsigned long status;
+  CORE_ADDR nextpc;
+
+  if (arm_pc_is_thumb (pc))
+    return thumb_get_next_pc (pc);
+
+  pc_val = (unsigned long) pc;
+  this_instr = read_memory_integer (pc, 4);
+  status = read_register (ARM_PS_REGNUM,regs);
+  nextpc = (CORE_ADDR) (pc_val + 4);	/* Default case */
+
+  if (condition_true (bits (this_instr, 28, 31), status))
+    {
+#ifdef  ARM_V5
+	  if (  (bits (this_instr, 28, 31) == 0xf) && 
+		    ( ( !bit(this_instr,27) ) || 
+		      ( bits(this_instr, 25, 27) == 4 ) ||
+		      ( bits(this_instr, 24, 27) == 0xf )
+		    ) 
+	      )	  {
+		  // undefined instruction
+		  return nextpc;
+	  }
+#endif
+
+      switch (bits (this_instr, 24, 27))
+	{
+	case 0x0:
+	case 0x1:		/* data processing */
+	case 0x2:
+	case 0x3:
+	  {
+	    unsigned long operand1, operand2, result = 0;
+	    unsigned long rn;
+	    int c;
+
+	    if (bits (this_instr, 12, 15) != 15)
+	      break;
+
+	    if ( bits (this_instr, 22, 25) == 0 
+		&& bits (this_instr, 4, 7) == 9)	/* multiply */
+	      kdb_printf ("Illegal update to pc in instruction\n");
+#ifdef ARM_V5T
+		if ( bits(this_instr, 25, 27) == 0 && 
+			 bit(this_instr, 4) && bit(this_instr,7) ) {
+			/*
+			 * miscellaneous instructions.
+			 * refer to Fig 3-2 of ARM Architecture Reference Manual.
+			 */
+			break;
+		}
+		if ( (bits (this_instr, 23, 27) == 2) && !bit(this_instr,20) 
+			&& (!bit(this_instr, 4) || !bit(this_instr, 7)) ) {
+			/*
+			 * miscellaneous instructions.
+			 * refer to Fig 3-3 of ARM Architecture Reference Manual.
+			 */
+			if ( bits(this_instr,4,27) != 0x12FFF1 
+				&& bits(this_instr,4,27) != 0x12FFF3) {
+				// Only BX Rm, BLX Rm may change PC
+				break;
+			}
+		}
+#endif
+
+	    /* Multiply into PC */
+	    c = (status & FLAG_C) ? 1 : 0;
+	    rn = bits (this_instr, 16, 19);
+	    operand1 = (rn == 15) ? pc_val + 8 : read_register (rn,regs);
+
+	    if (bit (this_instr, 25))
+	      {
+		unsigned long immval = bits (this_instr, 0, 7);
+		unsigned long rotate = 2 * bits (this_instr, 8, 11);
+		operand2 = ((immval >> rotate) | (immval << (32 - rotate)))
+		  & 0xffffffff;
+	      }
+	    else		/* operand 2 is a shifted register */
+	      operand2 = shifted_reg_val (this_instr, c, pc_val, status,regs);
+
+	    switch (bits (this_instr, 21, 24))
+	      {
+	      case 0x0:	/*and */
+		result = operand1 & operand2;
+		break;
+
+	      case 0x1:	/*eor */
+		result = operand1 ^ operand2;
+		break;
+
+	      case 0x2:	/*sub */
+		result = operand1 - operand2;
+		break;
+
+	      case 0x3:	/*rsb */
+		result = operand2 - operand1;
+		break;
+
+	      case 0x4:	/*add */
+		result = operand1 + operand2;
+		break;
+
+	      case 0x5:	/*adc */
+		result = operand1 + operand2 + c;
+		break;
+
+	      case 0x6:	/*sbc */
+		result = operand1 - operand2 + c;
+		break;
+
+	      case 0x7:	/*rsc */
+		result = operand2 - operand1 + c;
+		break;
+
+	      case 0x8:
+	      case 0x9:
+	      case 0xa:
+	      case 0xb:	/* tst, teq, cmp, cmn */
+			  /*
+			   * Rd should be zero for TST and CMP instruction, 
+			   * never enter here for TST and CMP instruction
+			   * MRS/MSR may come here
+			   * Some undefined instruction of ARM_V5T may 
+			   * come here too.
+			   */
+			  if ( bits(this_instr, 24, 27) == 1 
+			  	&& bits(this_instr, 20, 21) == 0 
+				&& bits(this_instr, 16, 19)==0xf 
+				&& bits(this_instr, 0, 11) == 0 )
+
+			  {	// mrs pc, cpsr/spsr
+			  	kdb_printf("Instruction %08lx at %08lx is"
+			  			" Unpredictable\n",
+			  			this_instr, pc);
+				result = nextpc;
+				/*
+				result = read_register( this_instr&(1<<22) ? 
+					      ARM_SPS_REGNUM : ARM_PS_REGNUM,
+				 	      regs);
+				 	      **/
+			  }
+#ifdef  ARM_V4T
+			  else if ( bits(this_instr, 4, 27) == 0x12FFF1 ) {
+				  // BX Rm
+				  unsigned int Rm;
+				  Rm = read_register( this_instr & 0xf,regs);
+				  if ( (Rm & 1) == 0 ) {
+					// Still in ARM mode
+					result = Rm;
+				  }
+				  else {
+					  // will go to thumb mode
+			  		kdb_printf("Don't support "
+			  			    "ARM/THUMB exchange\n");
+					result = nextpc;
+				  }
+			  }
+#endif
+
+#ifdef  ARM_V5T
+			  else if ( bits(this_instr,4,27) == 0x12FFF3 ) {
+				  // BXL Rm
+				  unsigned int Rm;
+				  Rm = read_register(this_instr&0xf,regs);
+				  if ( (Rm & 1) == 0 ) {
+					  // Still in ARM mode
+					  result = Rm;
+				  }
+				  else {
+					// will go to thumb mode
+			  		kdb_printf("Don't support "
+			  			    "ARM/THUMB exchange\n");
+					result = nextpc;
+				  }
+			  }
+#endif
+			  else {
+				result = (unsigned long) nextpc;
+			  }
+		break;
+
+	      case 0xc:	/*orr */
+		result = operand1 | operand2;
+		break;
+
+	      case 0xd:	/*mov */
+		/* Always step into a function.  */
+		result = operand2;
+		break;
+
+	      case 0xe:	/*bic */
+		result = operand1 & ~operand2;
+		break;
+
+	      case 0xf:	/*mvn */
+		result = ~operand2;
+		break;
+	      }
+	    nextpc = (CORE_ADDR) ADDR_BITS_REMOVE (result);
+
+	    if (nextpc == pc)
+	      kdb_printf ("Infinite loop detected\n");
+	    break;
+	  }
+
+	case 0x4:
+	case 0x5:		/* data transfer */
+	case 0x6:
+	case 0x7:
+#ifdef  ARM_V5T
+	    if ( bit(this_instr,4) && (bits(this_instr,25,27)==3) ) {
+		// undefined instruction
+		break; 
+	    }
+#endif
+	    if (bit (this_instr, 20))
+	    {
+	      /* load */
+	      if (bits (this_instr, 12, 15) == 15)
+		{
+		  /* rd == pc */
+		  unsigned long rn;
+		  unsigned long base;
+
+		  if (bit (this_instr, 22))
+		    kdb_printf ("Illegal update to pc in instruction\n");
+
+		  /* byte write to PC */
+		  rn = bits (this_instr, 16, 19);
+		  base = (rn == 15) ? pc_val + 8 : read_register(rn,regs);
+		  if (bit (this_instr, 24))
+		    {
+		      /* pre-indexed */
+		      int c = (status & FLAG_C) ? 1 : 0;
+		      unsigned long offset =
+		      (bit (this_instr, 25)
+		       ? shifted_reg_val(this_instr,c,pc_val,status,regs)
+		       : bits (this_instr, 0, 11));
+
+		      if (bit (this_instr, 23))
+			base += offset;
+		      else
+			base -= offset;
+		    }
+		  nextpc = (CORE_ADDR)read_memory_integer (
+				  (CORE_ADDR) base,4);
+
+		  nextpc = ADDR_BITS_REMOVE (nextpc);
+
+		  if (nextpc == pc)
+		    kdb_printf ("Infinite loop detected\n");
+		}
+	    }
+	  break;
+
+	case 0x8:
+	case 0x9:		/* block transfer */
+	  if (bit (this_instr, 20))
+	    {
+	      /* LDM */
+	      if (bit (this_instr, 15))
+		{
+		  /* loading pc */
+		  int offset = 0;
+
+		  if (bit (this_instr, 23))
+		    {
+		      /* up */
+		      unsigned long reglist = bits (this_instr, 0, 14);
+		      offset = bitcount (reglist) * 4;
+		      if (bit (this_instr, 24))		/* pre */
+			offset += 4;
+		    }
+		  else if (bit (this_instr, 24)) {
+			  // ?? FIXME ??
+			  if ( bit (this_instr, 24) ) {
+				offset = -8;
+			  }
+			  else {
+				offset = -4;
+			  }
+
+		  }
+		  else
+		  {
+		    unsigned long rn_val =
+		    read_register (bits (this_instr, 16, 19),regs);
+		    nextpc = (CORE_ADDR) read_memory_integer (
+		      		(CORE_ADDR) (rn_val+ offset),
+				4);
+		  }
+		  nextpc = ADDR_BITS_REMOVE (nextpc);
+		  if (nextpc == pc)
+		    kdb_printf ("Infinite loop detected\n");
+		}
+	    }
+	  break;
+
+	case 0xb:		/* branch & link */
+	case 0xa:		/* branch */
+	  {
+#ifdef ARM_V5
+		if ( bits (this_instr, 28, 31) == 0xf ) {
+			// FIXME...
+	        	kdb_printf ("Thumb mode not supported yet!\n");
+			break;
+		}
+#endif
+	    nextpc = BranchDest (pc, this_instr);
+
+	    nextpc = ADDR_BITS_REMOVE (nextpc);
+	    if (nextpc == pc)
+		kdb_printf ("Infinite loop detected\n");
+	    break;
+	  }
+
+	case 0xc:
+	case 0xd:
+	case 0xe:		/* coproc ops */
+	case 0xf:		/* SWI */
+	  break;
+
+	default:
+	  fprintf_filtered (gdb_stderr, "Bad bit-field extraction\n");
+	  return (pc);
+	}
+    }
+
+  return nextpc;
+}
diff -uNr linux.orig/arch/arm/kdb/arm-tdep.h linux/arch/arm/kdb/arm-tdep.h
--- linux.orig/arch/arm/kdb/arm-tdep.h	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/arm-tdep.h	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,234 @@
+/* Common target dependent code for GDB on ARM systems.
+   Copyright 2002 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* Register numbers of various important registers.  Note that some of
+   these values are "real" register numbers, and correspond to the
+   general registers of the machine, and some are "phony" register
+   numbers which are too large to be actual register numbers as far as
+   the user is concerned but do serve to get the desired values when
+   passed to read_register.  */
+
+/*
+ * Extracted from GDB CVS and modified for kdb use.
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#define   CORE_ADDR     unsigned int
+#define   LONGEST	long long
+
+#define ARM_A1_REGNUM 0		/* first integer-like argument */
+#define ARM_A4_REGNUM 3		/* last integer-like argument */
+#define ARM_AP_REGNUM 11
+#define ARM_IP_REGNUM 12	/* temp register used to save sp in prologue */
+#define ARM_SP_REGNUM 13	/* Contains address of top of stack */
+#define ARM_LR_REGNUM 14	/* address to return to from a function call */
+#define ARM_PC_REGNUM 15	/* Contains program counter */
+#define ARM_F0_REGNUM 16	/* first floating point register */
+#define ARM_F3_REGNUM 19	/* last floating point argument register */
+#define ARM_F7_REGNUM 23	/* last floating point register */
+#define ARM_FPS_REGNUM 24	/* floating point status register */
+#define ARM_PS_REGNUM 25	/* Contains processor status */
+#define ARM_SPS_REGNUM 26	/* Contains spsr */
+
+#define ARM_FP_REGNUM 11	/* Frame register in ARM code, if used.  */
+#define THUMB_FP_REGNUM 7	/* Frame register in Thumb code, if used.  */
+
+#define ARM_NUM_ARG_REGS 	4
+#define ARM_LAST_ARG_REGNUM 	ARM_A4_REGNUM
+#define ARM_NUM_FP_ARG_REGS 	4
+#define ARM_LAST_FP_ARG_REGNUM	ARM_F3_REGNUM
+
+/* Size of integer registers.  */
+#define INT_REGISTER_RAW_SIZE		4
+#define INT_REGISTER_VIRTUAL_SIZE	4
+
+/* Say how long FP registers are.  Used for documentation purposes and
+   code readability in this header.  IEEE extended doubles are 80
+   bits.  DWORD aligned they use 96 bits.  */
+#define FP_REGISTER_RAW_SIZE	12
+
+/* GCC doesn't support long doubles (extended IEEE values).  The FP
+   register virtual size is therefore 64 bits.  Used for documentation
+   purposes and code readability in this header.  */
+#define FP_REGISTER_VIRTUAL_SIZE	8
+
+/* Status registers are the same size as general purpose registers.
+   Used for documentation purposes and code readability in this
+   header.  */
+#define STATUS_REGISTER_SIZE	4
+
+/* Number of machine registers.  The only define actually required 
+   is NUM_REGS.  The other definitions are used for documentation
+   purposes and code readability.  */
+/* For 26 bit ARM code, a fake copy of the PC is placed in register 25 (PS)
+   (and called PS for processor status) so the status bits can be cleared
+   from the PC (register 15).  For 32 bit ARM code, a copy of CPSR is placed
+   in PS.  */
+#define NUM_FREGS	8	/* Number of floating point registers.  */
+#define NUM_SREGS	2	/* Number of status registers.  */
+#define NUM_GREGS	16	/* Number of general purpose registers.  */
+
+
+/* Instruction condition field values.  */
+#define INST_EQ		0x0
+#define INST_NE		0x1
+#define INST_CS		0x2
+#define INST_CC		0x3
+#define INST_MI		0x4
+#define INST_PL		0x5
+#define INST_VS		0x6
+#define INST_VC		0x7
+#define INST_HI		0x8
+#define INST_LS		0x9
+#define INST_GE		0xa
+#define INST_LT		0xb
+#define INST_GT		0xc
+#define INST_LE		0xd
+#define INST_AL		0xe
+#define INST_NV		0xf
+
+#define FLAG_N		0x80000000
+#define FLAG_Z		0x40000000
+#define FLAG_C		0x20000000
+#define FLAG_V		0x10000000
+
+/* ABI variants that we know about.  If you add to this enum, please 
+   update the table of names in tm-arm.c.  */
+enum arm_abi
+{
+  ARM_ABI_UNKNOWN = 0,
+  ARM_ABI_EABI_V1,
+  ARM_ABI_EABI_V2,
+  ARM_ABI_LINUX,
+  ARM_ABI_NETBSD_AOUT,
+  ARM_ABI_NETBSD_ELF,
+  ARM_ABI_APCS,
+  ARM_ABI_FREEBSD,
+  ARM_ABI_WINCE,
+
+  ARM_ABI_INVALID	/* Keep this last.  */
+};
+
+/* Type of floating-point code in use by inferior.  There are really 3 models
+   that are traditionally supported (plus the endianness issue), but gcc can
+   only generate 2 of those.  The third is APCS_FLOAT, where arguments to
+   functions are passed in floating-point registers.  
+
+   In addition to the traditional models, VFP adds two more.  */
+
+enum arm_float_model
+{
+  ARM_FLOAT_SOFT,
+  ARM_FLOAT_FPA,
+  ARM_FLOAT_SOFT_VFP,
+  ARM_FLOAT_VFP
+};
+
+/* Target-dependent structure in gdbarch.  */
+struct gdbarch_tdep
+{
+  enum arm_abi arm_abi;		/* OS/ABI of inferior.  */
+  const char *abi_name;		/* Name of the above.  */
+
+  enum arm_float_model fp_model; /* Floating point calling conventions.  */
+
+  CORE_ADDR lowest_pc;		/* Lowest address at which instructions 
+				   will appear.  */
+
+  const char *arm_breakpoint;	/* Breakpoint pattern for an ARM insn.  */
+  int arm_breakpoint_size;	/* And its size.  */
+  const char *thumb_breakpoint;	/* Breakpoint pattern for an ARM insn.  */
+  int thumb_breakpoint_size;	/* And its size.  */
+
+  int jb_pc;			/* Offset to PC value in jump buffer. 
+				   If this is negative, longjmp support
+				   will be disabled.  */
+};
+
+#ifndef LOWEST_PC
+#define LOWEST_PC (gdbarch_tdep (current_gdbarch)->lowest_pc)
+#endif
+
+/* Prototypes for internal interfaces needed by more than one MD file.  */
+int arm_pc_is_thumb_dummy (CORE_ADDR);
+
+int arm_pc_is_thumb (CORE_ADDR);
+
+extern CORE_ADDR arm_get_next_pc (CORE_ADDR, struct pt_regs *regs);
+
+CORE_ADDR thumb_get_next_pc (CORE_ADDR);
+
+/* Define other aspects of the stack frame.  We keep the offsets of
+   all saved registers, 'cause we need 'em a lot!  We also keep the
+   current size of the stack frame, and the offset of the frame
+   pointer from the stack pointer (for frameless functions, and when
+   we're still in the prologue of a function with a frame) */
+
+struct frame_extra_info
+{
+  int framesize;
+  int frameoffset;
+  int framereg;
+};
+
+typedef struct frame_reg_para {
+	kdb_machreg_t	a1[ARM_NUM_ARG_REGS];	// save the parameter a1-a4
+} frame_reg_para_t;
+
+#define  NUM_REGS	(1+ARM_PC_REGNUM)
+struct frame_info
+  {
+    CORE_ADDR frame;
+
+    /* Address at which execution is occurring in this frame.
+       For the innermost frame, it's the current pc.
+       For other frames, it is a pc saved in the next frame.  */
+    kdb_machreg_t pc;
+    kdb_machreg_t sp;
+    
+    //kdb_machreg_t lr;
+    kdb_machreg_t ret_pc;		// return address to caller
+    //frame_reg_para_t	para;
+    struct pt_regs *pregs;		// context of pt_regs
+
+    /* For each register, address of where it was saved on entry to
+       the frame, or zero if it was not saved on entry to this frame.
+       This includes special registers such as pc and fp saved in
+       special ways in the stack frame.  The SP_REGNUM is even more
+       special, the address here is the sp for the previous frame, not
+       the address where the sp was saved.  */
+
+    kdb_machreg_t saved_regs[NUM_REGS];
+
+    /* Anything extra for this structure that may have been defined
+       in the machine dependent files. */
+    /* Allocated by frame_obstack_alloc () which is called /
+       initialized by INIT_EXTRA_FRAME_INFO */
+    struct frame_extra_info extra_info;
+    
+    kdb_machreg_t	fi_start,fi_end;	// start >= end
+    unsigned long	args;		// bytes allocated for argument 
+    					// not include possible a1-a4  ???
+
+  };
+  
+extern int find_pc_partial_function (CORE_ADDR pc, char **name, 
+		CORE_ADDR *address, CORE_ADDR *endaddr);
+		
diff -uNr linux.orig/arch/arm/kdb/bfd.h linux/arch/arm/kdb/bfd.h
--- linux.orig/arch/arm/kdb/bfd.h	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/bfd.h	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,3616 @@
+/* Main header file for the bfd library -- portable access to object files.
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001
+   Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+** NOTE: bfd.h and bfd-in2.h are GENERATED files.  Don't change them;
+** instead, change bfd-in.h or the other BFD source files processed to
+** generate these files.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* bfd.h -- The only header file required by users of the bfd library
+
+The bfd.h file is generated from bfd-in.h and various .c files; if you
+change it, your changes will probably be lost.
+
+All the prototypes and definitions following the comment "THE FOLLOWING
+IS EXTRACTED FROM THE SOURCE" are extracted from the source files for
+BFD.  If you change it, someone oneday will extract it from the source
+again, and your changes will be lost.  To save yourself from this bind,
+change the definitions in the source in the bfd directory.  Type "make
+docs" and then "make headers" in that directory, and magically this file
+will change to reflect your changes.
+
+If you don't have the tools to perform the extraction, then you are
+safe from someone on your system trampling over your header files.
+You should still maintain the equivalence between the source and this
+file though; every change you make to the .c file should be reflected
+here.  */
+
+/*
+ * Extracted from GDB CVS and modified for kdb use.
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+
+/* These two lines get substitutions done by commands in Makefile.in.  */
+#define BFD_VERSION  "2.11.90.0.8"
+#define BFD_ARCH_SIZE 32
+#define BFD_HOST_64BIT_LONG 0
+#if 0
+#define BFD_HOST_64_BIT
+#define BFD_HOST_U_64_BIT
+#endif
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* forward declaration */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+   combination") from the SVR3 compiler, we would like to typedef
+   boolean to int (it doesn't like functions which return boolean.
+   Making sure they are never implicitly declared to return int
+   doesn't seem to help).  But this file is not configured based on
+   the host.  */
+/* General rules: functions which are boolean return true on success
+   and false on failure (unless they're a predicate).   -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+   force me to change it.  */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h>  -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+#if defined (__GNUG__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum.  */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else.  */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* A pointer to a position in a file.  */
+/* FIXME:  This should be using off_t from <sys/types.h>.
+   For now, try to avoid breaking stuff by not including <sys/types.h> here.
+   This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+   Probably the best long-term answer is to avoid using file_ptr AND off_t
+   in this header file, and to handle this in the BFD implementation
+   rather than in its interface.  */
+/* typedef off_t	file_ptr; */
+typedef long int file_ptr;
+
+/* Support for different sizes of target format ints and addresses.
+   If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+   set to 1 above.  Otherwise, if gcc is being used, this code will
+   use gcc's "long long" type.  Otherwise, BFD_HOST_64_BIT must be
+   defined above.  */
+
+#ifndef BFD_HOST_64_BIT
+# if BFD_HOST_64BIT_LONG
+#  define BFD_HOST_64_BIT long
+#  define BFD_HOST_U_64_BIT unsigned long
+# else
+#  ifdef __GNUC__
+#   if __GNUC__ >= 2
+#    define BFD_HOST_64_BIT long long
+#    define BFD_HOST_U_64_BIT unsigned long long
+#   endif /* __GNUC__ >= 2 */
+#  endif /* ! defined (__GNUC__) */
+# endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+ #error No 64 bit integer type available
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+typedef BFD_HOST_U_64_BIT bfd_vma;
+typedef BFD_HOST_64_BIT bfd_signed_vma;
+typedef BFD_HOST_U_64_BIT bfd_size_type;
+typedef BFD_HOST_U_64_BIT symvalue;
+
+#ifndef fprintf_vma
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+  fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+  sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64  */
+
+/* Represent a target address.  Also used as a generic unsigned type
+   which is guaranteed to be big enough to hold any arithmetic types
+   we need to deal with.  */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+   arithmetic types we need to deal with.  Can be assumed to be compatible
+   with bfd_vma in the same way that signed and unsigned ints are compatible
+   (as parameters, in assignment, etc).  */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s.  */
+#define fprintf_vma(s,x) fprintf (s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf (s, "%08lx", x)
+
+#endif /* not BFD64  */
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+
+typedef unsigned int flagword;	/* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/** File formats */
+
+typedef enum bfd_format {
+	      bfd_unknown = 0,	/* file format is unknown */
+	      bfd_object,	/* linker/assember/compiler output */
+	      bfd_archive,	/* object archive file */
+	      bfd_core,		/* core dump */
+	      bfd_type_end}	/* marks the end; don't use it! */
+         bfd_format;
+
+/* Values that may appear in the flags field of a BFD.  These also
+   appear in the object_flags field of the bfd_target structure, where
+   they indicate the set of flags used by that backend (not all flags
+   are meaningful for all object file formats) (FIXME: at the moment,
+   the object_flags values have mostly just been copied from backend
+   to another, and are not necessarily correct).  */
+
+/* No flags.  */
+#define BFD_NO_FLAGS   	0x00
+
+/* BFD contains relocation entries.  */
+#define HAS_RELOC   	0x01
+
+/* BFD is directly executable.  */
+#define EXEC_P      	0x02
+
+/* BFD has line number information (basically used for F_LNNO in a
+   COFF header).  */
+#define HAS_LINENO  	0x04
+
+/* BFD has debugging information.  */
+#define HAS_DEBUG   	0x08
+
+/* BFD has symbols.  */
+#define HAS_SYMS    	0x10
+
+/* BFD has local symbols (basically used for F_LSYMS in a COFF
+   header).  */
+#define HAS_LOCALS  	0x20
+
+/* BFD is a dynamic object.  */
+#define DYNAMIC     	0x40
+
+/* Text section is write protected (if D_PAGED is not set, this is
+   like an a.out NMAGIC file) (the linker sets this by default, but
+   clears it for -r or -N).  */
+#define WP_TEXT     	0x80
+
+/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+   linker sets this by default, but clears it for -r or -n or -N).  */
+#define D_PAGED     	0x100
+
+/* BFD is relaxable (this means that bfd_relax_section may be able to
+   do something) (sometimes bfd_relax_section can do something even if
+   this is not set).  */
+#define BFD_IS_RELAXABLE 0x200
+
+/* This may be set before writing out a BFD to request using a
+   traditional format.  For example, this is used to request that when
+   writing out an a.out object the symbols not be hashed to eliminate
+   duplicates.  */
+#define BFD_TRADITIONAL_FORMAT 0x400
+
+/* This flag indicates that the BFD contents are actually cached in
+   memory.  If this is set, iostream points to a bfd_in_memory struct.  */
+#define BFD_IN_MEMORY 0x800
+
+/* symbols and relocation */
+
+/* A count of carsyms (canonical archive symbols).  */
+typedef unsigned long symindex;
+
+/* How to perform a relocation.  */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* General purpose part of a symbol X;
+   target specific parts are in libcoff.h, libaout.h, etc.  */
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* A canonical archive symbol.  */
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym {
+  char *name;
+  file_ptr file_offset;		/* look here to find the file */
+} carsym;			/* to make these you call a carsymogen */
+
+/* Used in generating armaps (archive tables of contents).
+   Perhaps just a forward definition would do? */
+struct orl {			/* output ranlib */
+  char **name;			/* symbol name */
+  file_ptr pos;			/* bfd* or file position */
+  int namidx;			/* index into string table */
+};
+
+/* Linenumber stuff */
+typedef struct lineno_cache_entry {
+  unsigned int line_number;	/* Linenumber from start of function*/
+  union {
+    struct symbol_cache_entry *sym; /* Function name */
+    unsigned long offset;	/* Offset into section */
+  } u;
+} alent;
+
+/* object and core file sections */
+
+#define	align_power(addr, align)	\
+	( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+  bfd_print_symbol_name,
+  bfd_print_symbol_more,
+  bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs.  */
+
+typedef struct _symbol_info
+{
+  symvalue value;
+  char type;
+  CONST char *name;            /* Symbol name.  */
+  unsigned char stab_type;     /* Stab type.  */
+  char stab_other;             /* Stab other.  */
+  short stab_desc;             /* Stab desc.  */
+  CONST char *stab_name;       /* String for stab type.  */
+} symbol_info;
+
+/* Get the name of a stabs type code.  */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* Hash table routines.  There is no way to free up a hash table.  */
+
+/* An element in the hash table.  Most uses will actually use a larger
+   structure, and an instance of this will be the first field.  */
+
+struct bfd_hash_entry
+{
+  /* Next entry for this hash code.  */
+  struct bfd_hash_entry *next;
+  /* String being hashed.  */
+  const char *string;
+  /* Hash code.  This is the full hash code, not the index into the
+     table.  */
+  unsigned long hash;
+};
+
+/* A hash table.  */
+
+struct bfd_hash_table
+{
+  /* The hash array.  */
+  struct bfd_hash_entry **table;
+  /* The number of slots in the hash table.  */
+  unsigned int size;
+  /* A function used to create new elements in the hash table.  The
+     first entry is itself a pointer to an element.  When this
+     function is first invoked, this pointer will be NULL.  However,
+     having the pointer permits a hierarchy of method functions to be
+     built each of which calls the function in the superclass.  Thus
+     each function should be written to allocate a new block of memory
+     only if the argument is NULL.  */
+  struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+					     struct bfd_hash_table *,
+					     const char *));
+   /* An objalloc for this hash table.  This is a struct objalloc *,
+     but we use PTR to avoid requiring the inclusion of objalloc.h.  */
+  PTR memory;
+};
+
+/* Initialize a hash table.  */
+extern boolean bfd_hash_table_init
+  PARAMS ((struct bfd_hash_table *,
+	   struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+				       struct bfd_hash_table *,
+				       const char *)));
+
+/* Initialize a hash table specifying a size.  */
+extern boolean bfd_hash_table_init_n
+  PARAMS ((struct bfd_hash_table *,
+	   struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+				       struct bfd_hash_table *,
+				       const char *),
+	   unsigned int size));
+
+/* Free up a hash table.  */
+extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+
+/* Look up a string in a hash table.  If CREATE is true, a new entry
+   will be created for this string if one does not already exist.  The
+   COPY argument must be true if this routine should copy the string
+   into newly allocated memory when adding an entry.  */
+extern struct bfd_hash_entry *bfd_hash_lookup
+  PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+	   boolean copy));
+
+/* Replace an entry in a hash table.  */
+extern void bfd_hash_replace
+  PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+	   struct bfd_hash_entry *nw));
+
+/* Base method for creating a hash table entry.  */
+extern struct bfd_hash_entry *bfd_hash_newfunc
+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+	   const char *));
+
+/* Grab some space for a hash table entry.  */
+extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+				      unsigned int));
+
+/* Traverse a hash table in a random order, calling a function on each
+   element.  If the function returns false, the traversal stops.  The
+   INFO argument is passed to the function.  */
+extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+				       boolean (*) (struct bfd_hash_entry *,
+						    PTR),
+				       PTR info));
+
+/* Semi-portable string concatenation in cpp.
+   The CAT4 hack is to avoid a problem with some strict ANSI C preprocessors.
+   The problem is, "32_" is not a valid preprocessing token, and we don't
+   want extra underscores (e.g., "nlm_32_").  The XCAT2 macro will cause the
+   inner CAT macros to be evaluated first, producing still-valid pp-tokens.
+   Then the final concatenation can be done.  (Sigh.)  */
+#ifndef CAT
+#ifdef SABER
+#define CAT(a,b)	a##b
+#define CAT3(a,b,c)	a##b##c
+#define CAT4(a,b,c,d)	a##b##c##d
+#else
+#if defined(__STDC__) || defined(ALMOST_STDC)
+#define CAT(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#define XCAT2(a,b)	CAT(a,b)
+#define CAT4(a,b,c,d)	XCAT2(CAT(a,b),CAT(c,d))
+#else
+#define CAT(a,b) a/**/b
+#define CAT3(a,b,c) a/**/b/**/c
+#define CAT4(a,b,c,d)	a/**/b/**/c/**/d
+#endif
+#endif
+#endif
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities */
+
+/* Direct I/O routines, for programs which know more about the object
+   file than BFD does.  Use higher level routines if possible.  */
+
+extern bfd_size_type bfd_read
+  PARAMS ((PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+extern bfd_size_type bfd_write
+  PARAMS ((const PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+extern int bfd_seek PARAMS ((bfd *abfd, file_ptr fp, int direction));
+extern long bfd_tell PARAMS ((bfd *abfd));
+extern int bfd_flush PARAMS ((bfd *abfd));
+extern int bfd_stat PARAMS ((bfd *abfd, struct stat *));
+
+/* Cast from const char * to char * so that caller can assign to
+   a char * without a warning.  */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+#define bfd_family_coff(abfd) \
+  (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+   bfd_get_flavour (abfd) == bfd_target_xcoff_flavour)
+#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+  ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+  ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean) (bool)), true)
+
+extern boolean bfd_cache_close PARAMS ((bfd *abfd));
+/* NB: This declaration should match the autogenerated one in libbfd.h.  */
+
+extern boolean bfd_record_phdr
+  PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+	   boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines.  */
+
+bfd_vma		bfd_getb64	   PARAMS ((const unsigned char *));
+bfd_vma 	bfd_getl64	   PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getb_signed_64 PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getl_signed_64 PARAMS ((const unsigned char *));
+bfd_vma		bfd_getb32	   PARAMS ((const unsigned char *));
+bfd_vma		bfd_getl32	   PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getb_signed_32 PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getl_signed_32 PARAMS ((const unsigned char *));
+bfd_vma		bfd_getb16	   PARAMS ((const unsigned char *));
+bfd_vma		bfd_getl16	   PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getb_signed_16 PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getl_signed_16 PARAMS ((const unsigned char *));
+void		bfd_putb64	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putl64	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putb32	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putl32	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putb16	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putl16	   PARAMS ((bfd_vma, unsigned char *));
+
+/* Byte swapping routines which take size and endiannes as arguments.  */
+
+bfd_vma         bfd_get_bits       PARAMS ((bfd_byte *, int, boolean));
+void            bfd_put_bits       PARAMS ((bfd_vma, bfd_byte *, int, boolean));
+
+/* Externally visible ECOFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct symbol_cache_entry;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+extern boolean bfd_ecoff_set_regmasks
+  PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+	   unsigned long *cprmask));
+extern PTR bfd_ecoff_debug_init
+  PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+	   const struct ecoff_debug_swap *output_swap,
+	   struct bfd_link_info *));
+extern void bfd_ecoff_debug_free
+  PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+	   const struct ecoff_debug_swap *output_swap,
+	   struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate
+  PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+	   const struct ecoff_debug_swap *output_swap,
+	   bfd *input_bfd, struct ecoff_debug_info *input_debug,
+	   const struct ecoff_debug_swap *input_swap,
+	   struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate_other
+  PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+	   const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+	   struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_externals
+  PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap,
+	   boolean relocateable,
+	   boolean (*get_extr) (struct symbol_cache_entry *,
+				struct ecoff_extr *),
+	   void (*set_index) (struct symbol_cache_entry *,
+			      bfd_size_type)));
+extern boolean bfd_ecoff_debug_one_external
+  PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap,
+	   const char *name, struct ecoff_extr *esym));
+extern bfd_size_type bfd_ecoff_debug_size
+  PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap));
+extern boolean bfd_ecoff_write_debug
+  PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap, file_ptr where));
+extern boolean bfd_ecoff_write_accumulated_debug
+  PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap,
+	   struct bfd_link_info *info, file_ptr where));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+	   char **));
+
+/* Externally visible ELF routines.  */
+
+struct bfd_link_needed_list
+{
+  struct bfd_link_needed_list *next;
+  bfd *by;
+  const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf_get_bfd_needed_list
+  PARAMS ((bfd *, struct bfd_link_needed_list **));
+extern boolean bfd_elf32_size_dynamic_sections
+  PARAMS ((bfd *, const char *, const char *, boolean, const char *,
+	   const char * const *, struct bfd_link_info *, struct sec **,
+	   struct bfd_elf_version_tree *));
+extern boolean bfd_elf64_size_dynamic_sections
+  PARAMS ((bfd *, const char *, const char *, boolean, const char *,
+	   const char * const *, struct bfd_link_info *, struct sec **,
+	   struct bfd_elf_version_tree *));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Return an upper bound on the number of bytes required to store a
+   copy of ABFD's program header table entries.  Return -1 if an error
+   occurs; bfd_get_error will return an appropriate code.  */
+extern long bfd_get_elf_phdr_upper_bound PARAMS ((bfd *abfd));
+
+/* Copy ABFD's program header table entries to *PHDRS.  The entries
+   will be stored as an array of Elf_Internal_Phdr structures, as
+   defined in include/elf/internal.h.  To find out how large the
+   buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+   Return the number of program header table entries read, or -1 if an
+   error occurs; bfd_get_error will return an appropriate code.  */
+extern int bfd_get_elf_phdrs PARAMS ((bfd *abfd, void *phdrs));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf.  */
+extern int bfd_get_arch_size PARAMS ((bfd *));
+
+/* Return true if address "naturally" sign extends, or -1 if not elf.  */
+extern int bfd_get_sign_extend_vma PARAMS ((bfd *));
+
+extern boolean bfd_m68k_elf32_create_embedded_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+	   char **));
+
+/* SunOS shared library support routines for the linker.  */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sunos_record_link_assignment
+  PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_sunos_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+	   struct sec **));
+
+/* Linux shared library support routines for the linker.  */
+
+extern boolean bfd_i386linux_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sparclinux_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window {
+  /* What the user asked for.  */
+  PTR data;
+  bfd_size_type size;
+  /* The actual window used by BFD.  Small user-requested read-only
+     regions sharing a page may share a single window into the object
+     file.  Read-write versions shouldn't until I've fixed things to
+     keep track of which portions have been claimed by the
+     application; don't want to give the same region back when the
+     application wants two writable copies!  */
+  struct _bfd_window_internal *i;
+} bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+  PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker.  */
+
+extern boolean bfd_xcoff_link_record_set
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+	   bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+	   bfd_vma, const char *, const char *, const char *));
+extern boolean bfd_xcoff_export_symbol
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+	   boolean));
+extern boolean bfd_xcoff_link_count_reloc
+  PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+  PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+	   unsigned long, unsigned long, unsigned long, boolean,
+	   int, boolean, boolean, struct sec **));
+
+/* Externally visible COFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern boolean bfd_coff_get_syment
+  PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+
+extern boolean bfd_coff_get_auxent
+  PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+
+extern boolean bfd_coff_set_symbol_class
+  PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+
+extern boolean bfd_m68k_coff_create_embedded_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+	   char **));
+
+/* ARM Interworking support.  Called from linker.  */
+extern boolean bfd_arm_allocate_interworking_sections
+  PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_process_before_allocation
+  PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_get_bfd_for_interworking
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+/* PE ARM Interworking support.  Called from linker.  */
+extern boolean bfd_arm_pe_allocate_interworking_sections
+  PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_pe_process_before_allocation
+  PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_pe_get_bfd_for_interworking
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+/* ELF ARM Interworking support.  Called from linker.  */
+extern boolean bfd_elf32_arm_allocate_interworking_sections
+  PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_elf32_arm_process_before_allocation
+  PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_elf32_arm_get_bfd_for_interworking
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+/* TI COFF load page support.  */
+extern void bfd_ticoff_set_section_load_page
+  PARAMS ((struct sec *, int));
+
+extern int bfd_ticoff_get_section_load_page
+  PARAMS ((struct sec *));
+
+/* And more from the source.  */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((CONST char *filename, CONST char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((CONST char *filename, CONST char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+
+bfd *
+bfd_openw PARAMS ((CONST char *filename, CONST char *target));
+
+boolean
+bfd_close PARAMS ((bfd *abfd));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd *
+bfd_create PARAMS ((CONST char *filename, bfd *templ));
+
+boolean
+bfd_make_writable PARAMS ((bfd *abfd));
+
+boolean
+bfd_make_readable PARAMS ((bfd *abfd));
+
+
+/* Byte swapping macros for user section data.  */
+
+#define bfd_put_8(abfd, val, ptr) \
+                ((void) (*((unsigned char *) (ptr)) = (unsigned char) (val)))
+#define bfd_put_signed_8 \
+               bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+                (*(unsigned char *) (ptr))
+#define bfd_get_signed_8(abfd, ptr) \
+               ((*(unsigned char *) (ptr) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+                bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+                BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+                bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+                bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+#define bfd_get(bits, abfd, ptr)                               \
+                ((bits) == 8 ? bfd_get_8 (abfd, ptr)           \
+                : (bits) == 16 ? bfd_get_16 (abfd, ptr)        \
+                : (bits) == 32 ? bfd_get_32 (abfd, ptr)        \
+                : (bits) == 64 ? bfd_get_64 (abfd, ptr)        \
+                : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr)                          \
+                ((bits) == 8 ? bfd_put_8 (abfd, val, ptr)      \
+                : (bits) == 16 ? bfd_put_16 (abfd, val, ptr)   \
+                : (bits) == 32 ? bfd_put_32 (abfd, val, ptr)   \
+                : (bits) == 64 ? bfd_put_64 (abfd, val, ptr)   \
+                : (abort (), (void) 0))
+
+
+/* Byte swapping macros for file header data.  */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+               bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+               bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+               bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+               bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_h_putx16,(val,ptr))
+#define bfd_h_put_signed_16 \
+                bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx16,(ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_h_putx32,(val,ptr))
+#define bfd_h_put_signed_32 \
+                bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx32,(ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_h_putx64,(val, ptr))
+#define bfd_h_put_signed_64 \
+                bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx64,(ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr))
+
+/* This structure is used for a comdat section, as in PE.  A comdat
+   section is associated with a particular symbol.  When the linker
+   sees a comdat section, it keeps only one of the sections with a
+   given name and associated with a given symbol.  */
+
+struct bfd_comdat_info
+{
+  /* The name of the symbol associated with a comdat section.  */
+  const char *name;
+
+  /* The local symbol table index of the symbol associated with a
+     comdat section.  This is only meaningful to the object file format
+     specific code; it is not an index into the list returned by
+     bfd_canonicalize_symtab.  */
+  long symbol;
+};
+
+typedef struct sec
+{
+  /* The name of the section; the name isn't a copy, the pointer is
+     the same as that passed to bfd_make_section.  */
+
+  const char *name;
+
+  /* A unique sequence number.  */
+
+  int id;
+
+  /* Which section is it; 0..nth.  */
+
+  int index;
+
+  /* The next section in the list belonging to the BFD, or NULL.  */
+
+  struct sec *next;
+
+  /* The field flags contains attributes of the section. Some
+     flags are read in from the object file, and some are
+     synthesized from other information.  */
+
+  flagword flags;
+
+#define SEC_NO_FLAGS   0x000
+
+  /* Tells the OS to allocate space for this section when loading.
+     This is clear for a section containing debug information only.  */
+#define SEC_ALLOC      0x001
+
+  /* Tells the OS to load the section from the file when loading.
+     This is clear for a .bss section.  */
+#define SEC_LOAD       0x002
+
+  /* The section contains data still to be relocated, so there is
+     some relocation information too.  */
+#define SEC_RELOC      0x004
+
+#if 0   /* Obsolete ? */
+#define SEC_BALIGN     0x008
+#endif
+
+  /* A signal to the OS that the section contains read only data.  */
+#define SEC_READONLY   0x010
+
+  /* The section contains code only.  */
+#define SEC_CODE       0x020
+
+  /* The section contains data only.  */
+#define SEC_DATA       0x040
+
+  /* The section will reside in ROM.  */
+#define SEC_ROM        0x080
+
+  /* The section contains constructor information. This section
+     type is used by the linker to create lists of constructors and
+     destructors used by <<g++>>. When a back end sees a symbol
+     which should be used in a constructor list, it creates a new
+     section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+     the symbol to it, and builds a relocation. To build the lists
+     of constructors, all the linker has to do is catenate all the
+     sections called <<__CTOR_LIST__>> and relocate the data
+     contained within - exactly the operations it would peform on
+     standard data.  */
+#define SEC_CONSTRUCTOR 0x100
+
+  /* The section is a constructor, and should be placed at the
+     end of the text, data, or bss section(?).  */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS  0x3100
+
+  /* The section has contents - a data section could be
+     <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+     <<SEC_HAS_CONTENTS>>  */
+#define SEC_HAS_CONTENTS 0x200
+
+  /* An instruction to the linker to not output the section
+     even if it has information which would normally be written.  */
+#define SEC_NEVER_LOAD 0x400
+
+  /* The section is a COFF shared library section.  This flag is
+     only for the linker.  If this type of section appears in
+     the input file, the linker must copy it to the output file
+     without changing the vma or size.  FIXME: Although this
+     was originally intended to be general, it really is COFF
+     specific (and the flag was renamed to indicate this).  It
+     might be cleaner to have some more general mechanism to
+     allow the back end to control what the linker does with
+     sections.  */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+  /* The section has GOT references.  This flag is only for the
+     linker, and is currently only used by the elf32-hppa back end.
+     It will be set if global offset table references were detected
+     in this section, which indicate to the linker that the section
+     contains PIC code, and must be handled specially when doing a
+     static link.  */
+#define SEC_HAS_GOT_REF 0x4000
+
+  /* The section contains common symbols (symbols may be defined
+     multiple times, the value of a symbol is the amount of
+     space it requires, and the largest symbol value is the one
+     used).  Most targets have exactly one of these (which we
+     translate to bfd_com_section_ptr), but ECOFF has two.  */
+#define SEC_IS_COMMON 0x8000
+
+  /* The section contains only debugging information.  For
+     example, this is set for ELF .debug and .stab sections.
+     strip tests this flag to see if a section can be
+     discarded.  */
+#define SEC_DEBUGGING 0x10000
+
+  /* The contents of this section are held in memory pointed to
+     by the contents field.  This is checked by bfd_get_section_contents,
+     and the data is retrieved from memory if appropriate.  */
+#define SEC_IN_MEMORY 0x20000
+
+  /* The contents of this section are to be excluded by the
+     linker for executable and shared objects unless those
+     objects are to be further relocated.  */
+#define SEC_EXCLUDE 0x40000
+
+  /* The contents of this section are to be sorted by the
+     based on the address specified in the associated symbol
+     table.  */
+#define SEC_SORT_ENTRIES 0x80000
+
+  /* When linking, duplicate sections of the same name should be
+     discarded, rather than being combined into a single section as
+     is usually done.  This is similar to how common symbols are
+     handled.  See SEC_LINK_DUPLICATES below.  */
+#define SEC_LINK_ONCE 0x100000
+
+  /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+     should handle duplicate sections.  */
+#define SEC_LINK_DUPLICATES 0x600000
+
+  /* This value for SEC_LINK_DUPLICATES means that duplicate
+     sections with the same name should simply be discarded.  */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+  /* This value for SEC_LINK_DUPLICATES means that the linker
+     should warn if there are any duplicate sections, although
+     it should still only link one copy.  */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+  /* This value for SEC_LINK_DUPLICATES means that the linker
+     should warn if any duplicate sections are a different size.  */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+  /* This value for SEC_LINK_DUPLICATES means that the linker
+     should warn if any duplicate sections contain different
+     contents.  */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+  /* This section was created by the linker as part of dynamic
+     relocation or other arcane processing.  It is skipped when
+     going through the first-pass output, trusting that someone
+     else up the line will take care of it later.  */
+#define SEC_LINKER_CREATED 0x800000
+
+  /* This section should not be subject to garbage collection.  */
+#define SEC_KEEP 0x1000000
+
+  /* This section contains "short" data, and should be placed
+     "near" the GP.  */
+#define SEC_SMALL_DATA 0x2000000
+
+  /* This section contains data which may be shared with other
+     executables or shared objects.  */
+#define SEC_SHARED 0x4000000
+
+  /* When a section with this flag is being linked, then if the size of
+     the input section is less than a page, it should not cross a page
+     boundary.  If the size of the input section is one page or more, it
+     should be aligned on a page boundary.  */
+#define SEC_BLOCK 0x8000000
+
+  /* Conditionally link this section; do not link if there are no
+     references found to any symbol in the section.  */
+#define SEC_CLINK 0x10000000
+
+  /* Attempt to merge identical entities in the section.
+     Entity size is given in the entsize field.  */
+#define SEC_MERGE 0x20000000
+
+  /* If given with SEC_MERGE, entities to merge are zero terminated
+     strings where entsize specifies character size instead of fixed
+     size entries.  */
+#define SEC_STRINGS 0x40000000
+
+  /*  End of section flags.  */
+
+  /* Some internal packed boolean fields.  */
+
+  /* See the vma field.  */
+  unsigned int user_set_vma : 1;
+
+  /* Whether relocations have been processed.  */
+  unsigned int reloc_done : 1;
+
+  /* A mark flag used by some of the linker backends.  */
+  unsigned int linker_mark : 1;
+
+  /* A mark flag used by some linker backends for garbage collection.  */
+  unsigned int gc_mark : 1;
+
+  /* Used by the ELF code to mark sections which have been allocated to segments.  */
+  unsigned int segment_mark : 1;
+
+  /* End of internal packed boolean fields.  */
+
+  /*  The virtual memory address of the section - where it will be
+      at run time.  The symbols are relocated against this.  The
+      user_set_vma flag is maintained by bfd; if it's not set, the
+      backend can assign addresses (for example, in <<a.out>>, where
+      the default address for <<.data>> is dependent on the specific
+      target and various flags).  */
+
+  bfd_vma vma;
+
+  /*  The load address of the section - where it would be in a
+      rom image; really only used for writing section header
+      information. */
+
+  bfd_vma lma;
+
+  /* The size of the section in octets, as it will be output.
+     Contains a value even if the section has no contents (e.g., the
+     size of <<.bss>>).  This will be filled in after relocation.  */
+
+  bfd_size_type _cooked_size;
+
+  /* The original size on disk of the section, in octets.  Normally this
+     value is the same as the size, but if some relaxing has
+     been done, then this value will be bigger.  */
+
+  bfd_size_type _raw_size;
+
+  /* If this section is going to be output, then this value is the
+     offset in *bytes* into the output section of the first byte in the
+     input section (byte ==> smallest addressable unit on the
+     target).  In most cases, if this was going to start at the
+     100th octet (8-bit quantity) in the output section, this value
+     would be 100.  However, if the target byte size is 16 bits
+     (bfd_octets_per_byte is "2"), this value would be 50.  */
+
+  bfd_vma output_offset;
+
+  /* The output section through which to map on output.  */
+
+  struct sec *output_section;
+
+  /* The alignment requirement of the section, as an exponent of 2 -
+     e.g., 3 aligns to 2^3 (or 8).  */
+
+  unsigned int alignment_power;
+
+  /* If an input section, a pointer to a vector of relocation
+     records for the data in this section.  */
+
+  struct reloc_cache_entry *relocation;
+
+  /* If an output section, a pointer to a vector of pointers to
+     relocation records for the data in this section.  */
+
+  struct reloc_cache_entry **orelocation;
+
+  /* The number of relocation records in one of the above  */
+
+  unsigned reloc_count;
+
+  /* Information below is back end specific - and not always used
+     or updated.  */
+
+  /* File position of section data.  */
+
+  file_ptr filepos;
+
+  /* File position of relocation info.  */
+
+  file_ptr rel_filepos;
+
+  /* File position of line data.  */
+
+  file_ptr line_filepos;
+
+  /* Pointer to data for applications.  */
+
+  PTR userdata;
+
+  /* If the SEC_IN_MEMORY flag is set, this points to the actual
+     contents.  */
+  unsigned char *contents;
+
+  /* Attached line number information.  */
+
+  alent *lineno;
+
+  /* Number of line number records.  */
+
+  unsigned int lineno_count;
+
+  /* Entity size for merging purposes.  */
+
+  unsigned int entsize;
+
+  /* Optional information about a COMDAT entry; NULL if not COMDAT.  */
+
+  struct bfd_comdat_info *comdat;
+
+  /* Points to the kept section if this section is a link-once section,
+     and is discarded.  */
+  struct sec *kept_section;
+
+  /* When a section is being output, this value changes as more
+     linenumbers are written out.  */
+
+  file_ptr moving_line_filepos;
+
+  /* What the section number is in the target world.  */
+
+  int target_index;
+
+  PTR used_by_bfd;
+
+  /* If this is a constructor section then here is a list of the
+     relocations created to relocate items within it.  */
+
+  struct relent_chain *constructor_chain;
+
+  /* The BFD which owns the section.  */
+
+  bfd *owner;
+
+  /* A symbol which points at this section only */
+  struct symbol_cache_entry *symbol;
+  struct symbol_cache_entry **symbol_ptr_ptr;
+
+  struct bfd_link_order *link_order_head;
+  struct bfd_link_order *link_order_tail;
+} asection ;
+
+/* These sections are global, and are managed by BFD.  The application
+   and target back end are not permitted to change the values in
+   these sections.  New code should use the section_ptr macros rather
+   than referring directly to the const sections.  The const sections
+   may eventually vanish.  */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+/* the absolute section */
+extern const asection bfd_abs_section;
+#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+/* Pointer to the undefined section */
+extern const asection bfd_und_section;
+#define bfd_und_section_ptr ((asection *) &bfd_und_section)
+#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+/* Pointer to the common section */
+extern const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section */
+extern const asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+extern const struct symbol_cache_entry * const bfd_abs_symbol;
+extern const struct symbol_cache_entry * const bfd_com_symbol;
+extern const struct symbol_cache_entry * const bfd_und_symbol;
+extern const struct symbol_cache_entry * const bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+     ((section)->reloc_done ? (abort (), (bfd_size_type) 1) \
+                            : (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+     ((section)->reloc_done ? (section)->_cooked_size \
+                            : (abort (), (bfd_size_type) 1))
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, const char *name));
+
+char *
+bfd_get_unique_section_name PARAMS ((bfd *abfd,
+    const char *templat,
+    int *count));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, const char *name));
+
+boolean
+bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+    void (*func) (bfd *abfd,
+    asection *sect,
+    PTR obj),
+    PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean
+bfd_set_section_contents PARAMS ((bfd *abfd,
+    asection *section,
+    PTR data,
+    file_ptr offset,
+    bfd_size_type count));
+
+boolean
+bfd_get_section_contents PARAMS ((bfd *abfd, asection *section, PTR location,
+    file_ptr offset, bfd_size_type count));
+
+boolean
+bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec, bfd *obfd, asection *osec));
+
+#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+     BFD_SEND (obfd, _bfd_copy_private_section_data, \
+               (ibfd, isection, obfd, osection))
+void
+_bfd_strip_section_from_output PARAMS ((struct bfd_link_info *info, asection *section));
+
+enum bfd_architecture
+{
+  bfd_arch_unknown,   /* File arch not known */
+  bfd_arch_obscure,   /* Arch known, not one of these */
+  bfd_arch_m68k,      /* Motorola 68xxx */
+#define bfd_mach_m68000 1
+#define bfd_mach_m68008 2
+#define bfd_mach_m68010 3
+#define bfd_mach_m68020 4
+#define bfd_mach_m68030 5
+#define bfd_mach_m68040 6
+#define bfd_mach_m68060 7
+#define bfd_mach_cpu32  8
+#define bfd_mach_mcf5200  9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307  11
+#define bfd_mach_mcf5407  12
+  bfd_arch_vax,       /* DEC Vax */
+  bfd_arch_i960,      /* Intel 960 */
+    /* The order of the following is important.
+       lower number indicates a machine type that
+       only accepts a subset of the instructions
+       available to machines with higher numbers.
+       The exception is the "ca", which is
+       incompatible with all other machines except
+       "core". */
+
+#define bfd_mach_i960_core      1
+#define bfd_mach_i960_ka_sa     2
+#define bfd_mach_i960_kb_sb     3
+#define bfd_mach_i960_mc        4
+#define bfd_mach_i960_xa        5
+#define bfd_mach_i960_ca        6
+#define bfd_mach_i960_jx        7
+#define bfd_mach_i960_hx        8
+
+  bfd_arch_a29k,      /* AMD 29000 */
+  bfd_arch_sparc,     /* SPARC */
+#define bfd_mach_sparc                 1
+/* The difference between v8plus and v9 is that v9 is a true 64 bit env.  */
+#define bfd_mach_sparc_sparclet        2
+#define bfd_mach_sparc_sparclite       3
+#define bfd_mach_sparc_v8plus          4
+#define bfd_mach_sparc_v8plusa         5 /* with ultrasparc add'ns */
+#define bfd_mach_sparc_sparclite_le    6
+#define bfd_mach_sparc_v9              7
+#define bfd_mach_sparc_v9a             8 /* with ultrasparc add'ns */
+#define bfd_mach_sparc_v8plusb         9 /* with cheetah add'ns */
+#define bfd_mach_sparc_v9b             10 /* with cheetah add'ns */
+/* Nonzero if MACH has the v9 instruction set.  */
+#define bfd_mach_sparc_v9_p(mach) \
+  ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
+   && (mach) != bfd_mach_sparc_sparclite_le)
+  bfd_arch_mips,      /* MIPS Rxxxx */
+#define bfd_mach_mips3000              3000
+#define bfd_mach_mips3900              3900
+#define bfd_mach_mips4000              4000
+#define bfd_mach_mips4010              4010
+#define bfd_mach_mips4100              4100
+#define bfd_mach_mips4111              4111
+#define bfd_mach_mips4300              4300
+#define bfd_mach_mips4400              4400
+#define bfd_mach_mips4600              4600
+#define bfd_mach_mips4650              4650
+#define bfd_mach_mips5000              5000
+#define bfd_mach_mips6000              6000
+#define bfd_mach_mips8000              8000
+#define bfd_mach_mips10000             10000
+#define bfd_mach_mips16                16
+#define bfd_mach_mips32                32
+#define bfd_mach_mips32_4k             3204113 /* 32, 04, octal 'K' */
+#define bfd_mach_mips5                 5
+#define bfd_mach_mips64                64
+#define bfd_mach_mips_sb1              12310201 /* octal 'SB', 01 */
+  bfd_arch_i386,      /* Intel 386 */
+#define bfd_mach_i386_i386 0
+#define bfd_mach_i386_i8086 1
+#define bfd_mach_i386_i386_intel_syntax 2
+#define bfd_mach_x86_64 3
+#define bfd_mach_x86_64_intel_syntax 4
+  bfd_arch_we32k,     /* AT&T WE32xxx */
+  bfd_arch_tahoe,     /* CCI/Harris Tahoe */
+  bfd_arch_i860,      /* Intel 860 */
+  bfd_arch_i370,      /* IBM 360/370 Mainframes */
+  bfd_arch_romp,      /* IBM ROMP PC/RT */
+  bfd_arch_alliant,   /* Alliant */
+  bfd_arch_convex,    /* Convex */
+  bfd_arch_m88k,      /* Motorola 88xxx */
+  bfd_arch_pyramid,   /* Pyramid Technology */
+  bfd_arch_h8300,     /* Hitachi H8/300 */
+#define bfd_mach_h8300   1
+#define bfd_mach_h8300h  2
+#define bfd_mach_h8300s  3
+  bfd_arch_pdp11,     /* DEC PDP-11 */
+  bfd_arch_powerpc,   /* PowerPC */
+#define bfd_mach_ppc           0
+#define bfd_mach_ppc_403       403
+#define bfd_mach_ppc_403gc     4030
+#define bfd_mach_ppc_505       505
+#define bfd_mach_ppc_601       601
+#define bfd_mach_ppc_602       602
+#define bfd_mach_ppc_603       603
+#define bfd_mach_ppc_ec603e    6031
+#define bfd_mach_ppc_604       604
+#define bfd_mach_ppc_620       620
+#define bfd_mach_ppc_630       630
+#define bfd_mach_ppc_750       750
+#define bfd_mach_ppc_860       860
+#define bfd_mach_ppc_a35       35
+#define bfd_mach_ppc_rs64ii    642
+#define bfd_mach_ppc_rs64iii   643
+#define bfd_mach_ppc_7400      7400
+  bfd_arch_rs6000,    /* IBM RS/6000 */
+#define bfd_mach_rs6k          0
+#define bfd_mach_rs6k_rs1      6001
+#define bfd_mach_rs6k_rsc      6003
+#define bfd_mach_rs6k_rs2      6002
+  bfd_arch_hppa,      /* HP PA RISC */
+  bfd_arch_d10v,      /* Mitsubishi D10V */
+#define bfd_mach_d10v          0
+#define bfd_mach_d10v_ts2      2
+#define bfd_mach_d10v_ts3      3
+  bfd_arch_d30v,      /* Mitsubishi D30V */
+  bfd_arch_m68hc11,   /* Motorola 68HC11 */
+  bfd_arch_m68hc12,   /* Motorola 68HC12 */
+  bfd_arch_z8k,       /* Zilog Z8000 */
+#define bfd_mach_z8001         1
+#define bfd_mach_z8002         2
+  bfd_arch_h8500,     /* Hitachi H8/500 */
+  bfd_arch_sh,        /* Hitachi SH */
+#define bfd_mach_sh            0
+#define bfd_mach_sh2        0x20
+#define bfd_mach_sh_dsp     0x2d
+#define bfd_mach_sh3        0x30
+#define bfd_mach_sh3_dsp    0x3d
+#define bfd_mach_sh3e       0x3e
+#define bfd_mach_sh4        0x40
+  bfd_arch_alpha,     /* Dec Alpha */
+#define bfd_mach_alpha_ev4  0x10
+#define bfd_mach_alpha_ev5  0x20
+#define bfd_mach_alpha_ev6  0x30
+  bfd_arch_arm,       /* Advanced Risc Machines ARM */
+#define bfd_mach_arm_2         1
+#define bfd_mach_arm_2a        2
+#define bfd_mach_arm_3         3
+#define bfd_mach_arm_3M        4
+#define bfd_mach_arm_4         5
+#define bfd_mach_arm_4T        6
+#define bfd_mach_arm_5         7
+#define bfd_mach_arm_5T        8
+#define bfd_mach_arm_5TE       9
+#define bfd_mach_arm_XScale    10
+  bfd_arch_ns32k,     /* National Semiconductors ns32000 */
+  bfd_arch_w65,       /* WDC 65816 */
+  bfd_arch_tic30,     /* Texas Instruments TMS320C30 */
+  bfd_arch_tic54x,    /* Texas Instruments TMS320C54X */
+  bfd_arch_tic80,     /* TI TMS320c80 (MVP) */
+  bfd_arch_v850,      /* NEC V850 */
+#define bfd_mach_v850          0
+#define bfd_mach_v850e         'E'
+#define bfd_mach_v850ea        'A'
+  bfd_arch_arc,       /* ARC Cores */
+#define bfd_mach_arc_5         0
+#define bfd_mach_arc_6         1
+#define bfd_mach_arc_7         2
+#define bfd_mach_arc_8         3
+  bfd_arch_m32r,      /* Mitsubishi M32R/D */
+#define bfd_mach_m32r          0 /* backwards compatibility */
+#define bfd_mach_m32rx         'x'
+  bfd_arch_mn10200,   /* Matsushita MN10200 */
+  bfd_arch_mn10300,   /* Matsushita MN10300 */
+#define bfd_mach_mn10300               300
+#define bfd_mach_am33          330
+  bfd_arch_fr30,
+#define bfd_mach_fr30          0x46523330
+  bfd_arch_mcore,
+  bfd_arch_ia64,      /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64    0
+#define bfd_mach_ia64_elf32    1
+  bfd_arch_pj,
+  bfd_arch_avr,       /* Atmel AVR microcontrollers */
+#define bfd_mach_avr1          1
+#define bfd_mach_avr2          2
+#define bfd_mach_avr3          3
+#define bfd_mach_avr4          4
+#define bfd_mach_avr5          5
+  bfd_arch_cris,      /* Axis CRIS */
+  bfd_arch_s390,      /* IBM s390 */
+#define bfd_mach_s390_esa      0
+#define bfd_mach_s390_esame    1
+  bfd_arch_openrisc,  /* OpenRISC */
+  bfd_arch_last
+  };
+
+typedef struct bfd_arch_info
+{
+  int bits_per_word;
+  int bits_per_address;
+  int bits_per_byte;
+  enum bfd_architecture arch;
+  unsigned long mach;
+  const char *arch_name;
+  const char *printable_name;
+  unsigned int section_align_power;
+  /* True if this is the default machine for the architecture.  */
+  boolean the_default;
+  const struct bfd_arch_info * (*compatible)
+       PARAMS ((const struct bfd_arch_info *a,
+                const struct bfd_arch_info *b));
+
+  boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+  const struct bfd_arch_info *next;
+} bfd_arch_info_type;
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const char **
+bfd_arch_list PARAMS ((void));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+    const bfd *abfd,
+    const bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch PARAMS ((enum bfd_architecture
+    arch,
+    unsigned long machine));
+
+const char *
+bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+unsigned int
+bfd_octets_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_mach_octets_per_byte PARAMS ((enum bfd_architecture arch,
+    unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+       /* No errors detected */
+  bfd_reloc_ok,
+
+       /* The relocation was performed, but there was an overflow. */
+  bfd_reloc_overflow,
+
+       /* The address to relocate was not within the section supplied. */
+  bfd_reloc_outofrange,
+
+       /* Used by special functions */
+  bfd_reloc_continue,
+
+       /* Unsupported relocation size requested. */
+  bfd_reloc_notsupported,
+
+       /* Unused */
+  bfd_reloc_other,
+
+       /* The symbol to relocate against was undefined. */
+  bfd_reloc_undefined,
+
+       /* The relocation was performed, but may not be ok - presently
+          generated only when linking i960 coff files with i960 b.out
+          symbols.  If this type is returned, the error_message argument
+          to bfd_perform_relocation will be set.  */
+  bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+       /* A pointer into the canonical table of pointers  */
+  struct symbol_cache_entry **sym_ptr_ptr;
+
+       /* offset in section */
+  bfd_size_type address;
+
+       /* addend for relocation value */
+  bfd_vma addend;
+
+       /* Pointer to how to perform the required relocation */
+  reloc_howto_type *howto;
+
+} arelent;
+enum complain_overflow
+{
+       /* Do not complain on overflow. */
+  complain_overflow_dont,
+
+       /* Complain if the bitfield overflows, whether it is considered
+          as signed or unsigned. */
+  complain_overflow_bitfield,
+
+       /* Complain if the value overflows when considered as signed
+          number. */
+  complain_overflow_signed,
+
+       /* Complain if the value overflows when considered as an
+          unsigned number. */
+  complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+       /*  The type field has mainly a documentary use - the back end can
+           do what it wants with it, though normally the back end's
+           external idea of what a reloc number is stored
+           in this field. For example, a PC relative word relocation
+           in a coff environment has the type 023 - because that's
+           what the outside world calls a R_PCRWORD reloc. */
+  unsigned int type;
+
+       /*  The value the final relocation is shifted right by. This drops
+           unwanted data from the relocation.  */
+  unsigned int rightshift;
+
+       /*  The size of the item to be relocated.  This is *not* a
+           power-of-two measure.  To get the number of bytes operated
+           on by a type of relocation, use bfd_get_reloc_size.  */
+  int size;
+
+       /*  The number of bits in the item to be relocated.  This is used
+           when doing overflow checking.  */
+  unsigned int bitsize;
+
+       /*  Notes that the relocation is relative to the location in the
+           data section of the addend. The relocation function will
+           subtract from the relocation value the address of the location
+           being relocated. */
+  boolean pc_relative;
+
+       /*  The bit position of the reloc value in the destination.
+           The relocated value is left shifted by this amount. */
+  unsigned int bitpos;
+
+       /* What type of overflow error should be checked for when
+          relocating. */
+  enum complain_overflow complain_on_overflow;
+
+       /* If this field is non null, then the supplied function is
+          called rather than the normal function. This allows really
+          strange relocation methods to be accomodated (e.g., i960 callj
+          instructions). */
+  bfd_reloc_status_type (*special_function)
+                                   PARAMS ((bfd *abfd,
+                                            arelent *reloc_entry,
+                                            struct symbol_cache_entry *symbol,
+                                            PTR data,
+                                            asection *input_section,
+                                            bfd *output_bfd,
+                                            char **error_message));
+
+       /* The textual name of the relocation type. */
+  char *name;
+
+       /* Some formats record a relocation addend in the section contents
+          rather than with the relocation.  For ELF formats this is the
+          distinction between USE_REL and USE_RELA (though the code checks
+          for USE_REL == 1/0).  The value of this field is TRUE if the
+          addend is recorded with the section contents; when performing a
+          partial link (ld -r) the section contents (the data) will be
+          modified.  The value of this field is FALSE if addends are
+          recorded with the relocation (in arelent.addend); when performing
+          a partial link the relocation will be modified.
+          All relocations for all ELF USE_RELA targets should set this field
+          to FALSE (values of TRUE should be looked on with suspicion).
+          However, the converse is not true: not all relocations of all ELF
+          USE_REL targets set this field to TRUE.  Why this is so is peculiar
+          to each particular target.  For relocs that aren't used in partial
+          links (e.g. GOT stuff) it doesn't matter what this is set to.  */
+  boolean partial_inplace;
+
+       /* The src_mask selects which parts of the read in data
+          are to be used in the relocation sum.  E.g., if this was an 8 bit
+          byte of data which we read and relocated, this would be
+          0x000000ff. When we have relocs which have an addend, such as
+          sun4 extended relocs, the value in the offset part of a
+          relocating field is garbage so we never use it. In this case
+          the mask would be 0x00000000. */
+  bfd_vma src_mask;
+
+       /* The dst_mask selects which parts of the instruction are replaced
+          into the instruction. In most cases src_mask == dst_mask,
+          except in the above special case, where dst_mask would be
+          0x000000ff, and src_mask would be 0x00000000.   */
+  bfd_vma dst_mask;
+
+       /* When some formats create PC relative instructions, they leave
+          the value of the pc of the place being relocated in the offset
+          slot of the instruction, so that a PC relative relocation can
+          be made just by adding in an ordinary offset (e.g., sun3 a.out).
+          Some formats leave the displacement part of an instruction
+          empty (e.g., m88k bcs); this flag signals the fact.*/
+  boolean pcrel_offset;
+
+};
+#define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+  {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC}
+#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN)
+
+#define EMPTY_HOWTO(C) \
+  HOWTO((C),0,0,0,false,0,complain_overflow_dont,NULL,NULL,false,0,0,false)
+
+#define HOWTO_PREPARE(relocation, symbol)      \
+  {                                            \
+  if (symbol != (asymbol *)NULL) {             \
+    if (bfd_is_com_section (symbol->section)) { \
+      relocation = 0;                          \
+    }                                          \
+    else {                                     \
+      relocation = symbol->value;              \
+    }                                          \
+  }                                            \
+}
+unsigned int
+bfd_get_reloc_size PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain {
+  arelent relent;
+  struct   relent_chain *next;
+} arelent_chain;
+bfd_reloc_status_type
+bfd_check_overflow PARAMS ((enum complain_overflow how,
+    unsigned int bitsize,
+    unsigned int rightshift,
+    unsigned int addrsize,
+    bfd_vma relocation));
+
+bfd_reloc_status_type
+bfd_perform_relocation PARAMS ((bfd *abfd,
+    arelent *reloc_entry,
+    PTR data,
+    asection *input_section,
+    bfd *output_bfd,
+    char **error_message));
+
+bfd_reloc_status_type
+bfd_install_relocation PARAMS ((bfd *abfd,
+    arelent *reloc_entry,
+    PTR data, bfd_vma data_start,
+    asection *input_section,
+    char **error_message));
+
+enum bfd_reloc_code_real {
+  _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+  BFD_RELOC_64,
+  BFD_RELOC_32,
+  BFD_RELOC_26,
+  BFD_RELOC_24,
+  BFD_RELOC_16,
+  BFD_RELOC_14,
+  BFD_RELOC_8,
+
+/* PC-relative relocations.  Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation.  It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+  BFD_RELOC_64_PCREL,
+  BFD_RELOC_32_PCREL,
+  BFD_RELOC_24_PCREL,
+  BFD_RELOC_16_PCREL,
+  BFD_RELOC_12_PCREL,
+  BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+  BFD_RELOC_32_GOT_PCREL,
+  BFD_RELOC_16_GOT_PCREL,
+  BFD_RELOC_8_GOT_PCREL,
+  BFD_RELOC_32_GOTOFF,
+  BFD_RELOC_16_GOTOFF,
+  BFD_RELOC_LO16_GOTOFF,
+  BFD_RELOC_HI16_GOTOFF,
+  BFD_RELOC_HI16_S_GOTOFF,
+  BFD_RELOC_8_GOTOFF,
+  BFD_RELOC_32_PLT_PCREL,
+  BFD_RELOC_24_PLT_PCREL,
+  BFD_RELOC_16_PLT_PCREL,
+  BFD_RELOC_8_PLT_PCREL,
+  BFD_RELOC_32_PLTOFF,
+  BFD_RELOC_16_PLTOFF,
+  BFD_RELOC_LO16_PLTOFF,
+  BFD_RELOC_HI16_PLTOFF,
+  BFD_RELOC_HI16_S_PLTOFF,
+  BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+  BFD_RELOC_68K_GLOB_DAT,
+  BFD_RELOC_68K_JMP_SLOT,
+  BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+  BFD_RELOC_32_BASEREL,
+  BFD_RELOC_16_BASEREL,
+  BFD_RELOC_LO16_BASEREL,
+  BFD_RELOC_HI16_BASEREL,
+  BFD_RELOC_HI16_S_BASEREL,
+  BFD_RELOC_8_BASEREL,
+  BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+  BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits.  The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC.  (SPARC tools generally refer to this as <<WDISP30>>.)  The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+  BFD_RELOC_32_PCREL_S2,
+  BFD_RELOC_16_PCREL_S2,
+  BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word.  These are used on the SPARC. */
+  BFD_RELOC_HI22,
+  BFD_RELOC_LO10,
+
+/* For systems that allocate a Global Pointer register, these are
+displacements off that register.  These relocation types are
+handled specially, because the value the register will have is
+decided relatively late. */
+  BFD_RELOC_GPREL16,
+  BFD_RELOC_GPREL32,
+
+/* Reloc types used for i960/b.out. */
+  BFD_RELOC_I960_CALLJ,
+
+/* SPARC ELF relocations.  There is probably some overlap with other
+relocation types already defined. */
+  BFD_RELOC_NONE,
+  BFD_RELOC_SPARC_WDISP22,
+  BFD_RELOC_SPARC22,
+  BFD_RELOC_SPARC13,
+  BFD_RELOC_SPARC_GOT10,
+  BFD_RELOC_SPARC_GOT13,
+  BFD_RELOC_SPARC_GOT22,
+  BFD_RELOC_SPARC_PC10,
+  BFD_RELOC_SPARC_PC22,
+  BFD_RELOC_SPARC_WPLT30,
+  BFD_RELOC_SPARC_COPY,
+  BFD_RELOC_SPARC_GLOB_DAT,
+  BFD_RELOC_SPARC_JMP_SLOT,
+  BFD_RELOC_SPARC_RELATIVE,
+  BFD_RELOC_SPARC_UA32,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+  BFD_RELOC_SPARC_BASE13,
+  BFD_RELOC_SPARC_BASE22,
+
+/* SPARC64 relocations */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+  BFD_RELOC_SPARC_10,
+  BFD_RELOC_SPARC_11,
+  BFD_RELOC_SPARC_OLO10,
+  BFD_RELOC_SPARC_HH22,
+  BFD_RELOC_SPARC_HM10,
+  BFD_RELOC_SPARC_LM22,
+  BFD_RELOC_SPARC_PC_HH22,
+  BFD_RELOC_SPARC_PC_HM10,
+  BFD_RELOC_SPARC_PC_LM22,
+  BFD_RELOC_SPARC_WDISP16,
+  BFD_RELOC_SPARC_WDISP19,
+  BFD_RELOC_SPARC_7,
+  BFD_RELOC_SPARC_6,
+  BFD_RELOC_SPARC_5,
+#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+  BFD_RELOC_SPARC_PLT64,
+  BFD_RELOC_SPARC_HIX22,
+  BFD_RELOC_SPARC_LOX10,
+  BFD_RELOC_SPARC_H44,
+  BFD_RELOC_SPARC_M44,
+  BFD_RELOC_SPARC_L44,
+  BFD_RELOC_SPARC_REGISTER,
+
+/* SPARC little endian relocation */
+  BFD_RELOC_SPARC_REV32,
+
+/* Alpha ECOFF and ELF relocations.  Some of these treat the symbol or
+"addend" in some special way.
+For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+writing; when reading, it will be the absolute section symbol.  The
+addend is the displacement in bytes of the "lda" instruction from
+the "ldah" instruction (which is at the address of this reloc). */
+  BFD_RELOC_ALPHA_GPDISP_HI16,
+
+/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+with GPDISP_HI16 relocs.  The addend is ignored when writing the
+relocations out, and is filled in with the file's GP value on
+reading, for convenience. */
+  BFD_RELOC_ALPHA_GPDISP_LO16,
+
+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+relocation except that there is no accompanying GPDISP_LO16
+relocation. */
+  BFD_RELOC_ALPHA_GPDISP,
+
+/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+the assembler turns it into a LDQ instruction to load the address of
+the symbol, and then fills in a register in the real instruction.
+
+The LITERAL reloc, at the LDQ instruction, refers to the .lita
+section symbol.  The addend is ignored when writing, but is filled
+in with the file's GP value on reading, for convenience, as with the
+GPDISP_LO16 reloc.
+
+The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+It should refer to the symbol to be referenced, as with 16_GOTOFF,
+but it generates output not based on the position within the .got
+section, but relative to the GP value chosen for the file during the
+final link stage.
+
+The LITUSE reloc, on the instruction using the loaded address, gives
+information to the linker that it might be able to use to optimize
+away some literal section references.  The symbol is ignored (read
+as the absolute section symbol), and the "addend" indicates the type
+of instruction using the register:
+1 - "memory" fmt insn
+2 - byte-manipulation (byte offset reg)
+3 - jsr (target of branch)
+
+The GNU linker currently doesn't do any of this optimizing. */
+  BFD_RELOC_ALPHA_LITERAL,
+  BFD_RELOC_ALPHA_ELF_LITERAL,
+  BFD_RELOC_ALPHA_LITUSE,
+
+/* The BFD_RELOC_ALPHA_USER_* relocations are used by the assembler to
+process the explicit !<reloc>!sequence relocations, and are mapped
+into the normal relocations at the end of processing. */
+  BFD_RELOC_ALPHA_USER_LITERAL,
+  BFD_RELOC_ALPHA_USER_LITUSE_BASE,
+  BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF,
+  BFD_RELOC_ALPHA_USER_LITUSE_JSR,
+  BFD_RELOC_ALPHA_USER_GPDISP,
+  BFD_RELOC_ALPHA_USER_GPRELHIGH,
+  BFD_RELOC_ALPHA_USER_GPRELLOW,
+
+/* The HINT relocation indicates a value that should be filled into the
+"hint" field of a jmp/jsr/ret instruction, for possible branch-
+prediction logic which may be provided on some processors. */
+  BFD_RELOC_ALPHA_HINT,
+
+/* The LINKAGE relocation outputs a linkage pair in the object file,
+which is filled by the linker. */
+  BFD_RELOC_ALPHA_LINKAGE,
+
+/* The CODEADDR relocation outputs a STO_CA in the object file,
+which is filled by the linker. */
+  BFD_RELOC_ALPHA_CODEADDR,
+
+/* Bits 27..2 of the relocation address shifted right 2 bits;
+simple reloc otherwise. */
+  BFD_RELOC_MIPS_JMP,
+
+/* The MIPS16 jump instruction. */
+  BFD_RELOC_MIPS16_JMP,
+
+/* MIPS16 GP relative reloc. */
+  BFD_RELOC_MIPS16_GPREL,
+
+/* High 16 bits of 32-bit value; simple reloc. */
+  BFD_RELOC_HI16,
+
+/* High 16 bits of 32-bit value but the low 16 bits will be sign
+extended and added to form the final result.  If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+  BFD_RELOC_HI16_S,
+
+/* Low 16 bits. */
+  BFD_RELOC_LO16,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+  BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+  BFD_RELOC_PCREL_LO16,
+
+/* Relocation relative to the global pointer. */
+#define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16
+
+/* Relocation against a MIPS literal section. */
+  BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+  BFD_RELOC_MIPS_GOT16,
+  BFD_RELOC_MIPS_CALL16,
+#define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32
+  BFD_RELOC_MIPS_GOT_HI16,
+  BFD_RELOC_MIPS_GOT_LO16,
+  BFD_RELOC_MIPS_CALL_HI16,
+  BFD_RELOC_MIPS_CALL_LO16,
+  BFD_RELOC_MIPS_SUB,
+  BFD_RELOC_MIPS_GOT_PAGE,
+  BFD_RELOC_MIPS_GOT_OFST,
+  BFD_RELOC_MIPS_GOT_DISP,
+
+
+/* i386/elf relocations */
+  BFD_RELOC_386_GOT32,
+  BFD_RELOC_386_PLT32,
+  BFD_RELOC_386_COPY,
+  BFD_RELOC_386_GLOB_DAT,
+  BFD_RELOC_386_JUMP_SLOT,
+  BFD_RELOC_386_RELATIVE,
+  BFD_RELOC_386_GOTOFF,
+  BFD_RELOC_386_GOTPC,
+
+/* x86-64/elf relocations */
+  BFD_RELOC_X86_64_GOT32,
+  BFD_RELOC_X86_64_PLT32,
+  BFD_RELOC_X86_64_COPY,
+  BFD_RELOC_X86_64_GLOB_DAT,
+  BFD_RELOC_X86_64_JUMP_SLOT,
+  BFD_RELOC_X86_64_RELATIVE,
+  BFD_RELOC_X86_64_GOTPCREL,
+  BFD_RELOC_X86_64_32S,
+
+/* ns32k relocations */
+  BFD_RELOC_NS32K_IMM_8,
+  BFD_RELOC_NS32K_IMM_16,
+  BFD_RELOC_NS32K_IMM_32,
+  BFD_RELOC_NS32K_IMM_8_PCREL,
+  BFD_RELOC_NS32K_IMM_16_PCREL,
+  BFD_RELOC_NS32K_IMM_32_PCREL,
+  BFD_RELOC_NS32K_DISP_8,
+  BFD_RELOC_NS32K_DISP_16,
+  BFD_RELOC_NS32K_DISP_32,
+  BFD_RELOC_NS32K_DISP_8_PCREL,
+  BFD_RELOC_NS32K_DISP_16_PCREL,
+  BFD_RELOC_NS32K_DISP_32_PCREL,
+
+/* PDP11 relocations */
+  BFD_RELOC_PDP11_DISP_8_PCREL,
+  BFD_RELOC_PDP11_DISP_6_PCREL,
+
+/* Picojava relocs.  Not all of these appear in object files. */
+  BFD_RELOC_PJ_CODE_HI16,
+  BFD_RELOC_PJ_CODE_LO16,
+  BFD_RELOC_PJ_CODE_DIR16,
+  BFD_RELOC_PJ_CODE_DIR32,
+  BFD_RELOC_PJ_CODE_REL16,
+  BFD_RELOC_PJ_CODE_REL32,
+
+/* Power(rs6000) and PowerPC relocations. */
+  BFD_RELOC_PPC_B26,
+  BFD_RELOC_PPC_BA26,
+  BFD_RELOC_PPC_TOC16,
+  BFD_RELOC_PPC_B16,
+  BFD_RELOC_PPC_B16_BRTAKEN,
+  BFD_RELOC_PPC_B16_BRNTAKEN,
+  BFD_RELOC_PPC_BA16,
+  BFD_RELOC_PPC_BA16_BRTAKEN,
+  BFD_RELOC_PPC_BA16_BRNTAKEN,
+  BFD_RELOC_PPC_COPY,
+  BFD_RELOC_PPC_GLOB_DAT,
+  BFD_RELOC_PPC_JMP_SLOT,
+  BFD_RELOC_PPC_RELATIVE,
+  BFD_RELOC_PPC_LOCAL24PC,
+  BFD_RELOC_PPC_EMB_NADDR32,
+  BFD_RELOC_PPC_EMB_NADDR16,
+  BFD_RELOC_PPC_EMB_NADDR16_LO,
+  BFD_RELOC_PPC_EMB_NADDR16_HI,
+  BFD_RELOC_PPC_EMB_NADDR16_HA,
+  BFD_RELOC_PPC_EMB_SDAI16,
+  BFD_RELOC_PPC_EMB_SDA2I16,
+  BFD_RELOC_PPC_EMB_SDA2REL,
+  BFD_RELOC_PPC_EMB_SDA21,
+  BFD_RELOC_PPC_EMB_MRKREF,
+  BFD_RELOC_PPC_EMB_RELSEC16,
+  BFD_RELOC_PPC_EMB_RELST_LO,
+  BFD_RELOC_PPC_EMB_RELST_HI,
+  BFD_RELOC_PPC_EMB_RELST_HA,
+  BFD_RELOC_PPC_EMB_BIT_FLD,
+  BFD_RELOC_PPC_EMB_RELSDA,
+
+/* IBM 370/390 relocations */
+  BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+  BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch.  The lowest two bits must be zero and are
+not stored in the instruction. */
+  BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* ARM 26 bit pc-relative branch.  The lowest bit must be zero and is
+not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+  BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch.  The lowest bit must be zero and is
+not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+  BFD_RELOC_THUMB_PCREL_BLX,
+
+/* These relocs are only used within the ARM assembler.  They are not
+(at present) written to any object files. */
+  BFD_RELOC_ARM_IMMEDIATE,
+  BFD_RELOC_ARM_ADRL_IMMEDIATE,
+  BFD_RELOC_ARM_OFFSET_IMM,
+  BFD_RELOC_ARM_SHIFT_IMM,
+  BFD_RELOC_ARM_SWI,
+  BFD_RELOC_ARM_MULTI,
+  BFD_RELOC_ARM_CP_OFF_IMM,
+  BFD_RELOC_ARM_ADR_IMM,
+  BFD_RELOC_ARM_LDR_IMM,
+  BFD_RELOC_ARM_LITERAL,
+  BFD_RELOC_ARM_IN_POOL,
+  BFD_RELOC_ARM_OFFSET_IMM8,
+  BFD_RELOC_ARM_HWLITERAL,
+  BFD_RELOC_ARM_THUMB_ADD,
+  BFD_RELOC_ARM_THUMB_IMM,
+  BFD_RELOC_ARM_THUMB_SHIFT,
+  BFD_RELOC_ARM_THUMB_OFFSET,
+  BFD_RELOC_ARM_GOT12,
+  BFD_RELOC_ARM_GOT32,
+  BFD_RELOC_ARM_JUMP_SLOT,
+  BFD_RELOC_ARM_COPY,
+  BFD_RELOC_ARM_GLOB_DAT,
+  BFD_RELOC_ARM_PLT32,
+  BFD_RELOC_ARM_RELATIVE,
+  BFD_RELOC_ARM_GOTOFF,
+  BFD_RELOC_ARM_GOTPC,
+
+/* Hitachi SH relocs.  Not all of these appear in object files. */
+  BFD_RELOC_SH_PCDISP8BY2,
+  BFD_RELOC_SH_PCDISP12BY2,
+  BFD_RELOC_SH_IMM4,
+  BFD_RELOC_SH_IMM4BY2,
+  BFD_RELOC_SH_IMM4BY4,
+  BFD_RELOC_SH_IMM8,
+  BFD_RELOC_SH_IMM8BY2,
+  BFD_RELOC_SH_IMM8BY4,
+  BFD_RELOC_SH_PCRELIMM8BY2,
+  BFD_RELOC_SH_PCRELIMM8BY4,
+  BFD_RELOC_SH_SWITCH16,
+  BFD_RELOC_SH_SWITCH32,
+  BFD_RELOC_SH_USES,
+  BFD_RELOC_SH_COUNT,
+  BFD_RELOC_SH_ALIGN,
+  BFD_RELOC_SH_CODE,
+  BFD_RELOC_SH_DATA,
+  BFD_RELOC_SH_LABEL,
+  BFD_RELOC_SH_LOOP_START,
+  BFD_RELOC_SH_LOOP_END,
+  BFD_RELOC_SH_COPY,
+  BFD_RELOC_SH_GLOB_DAT,
+  BFD_RELOC_SH_JMP_SLOT,
+  BFD_RELOC_SH_RELATIVE,
+  BFD_RELOC_SH_GOTPC,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches.  The lowest bit must
+be zero and is not stored in the instruction. */
+  BFD_RELOC_THUMB_PCREL_BRANCH9,
+  BFD_RELOC_THUMB_PCREL_BRANCH12,
+  BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* ARC Cores relocs.
+ARC 22 bit pc-relative branch.  The lowest two bits must be zero and are
+not stored in the instruction.  The high 20 bits are installed in bits 26
+through 7 of the instruction. */
+  BFD_RELOC_ARC_B22_PCREL,
+
+/* ARC 26 bit absolute branch.  The lowest two bits must be zero and are not
+stored in the instruction.  The high 24 bits are installed in bits 23
+through 0. */
+  BFD_RELOC_ARC_B26,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. */
+  BFD_RELOC_D10V_10_PCREL_R,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0.  This is the same as the previous reloc
+except it is in the left container, i.e.,
+shifted left 15 bits. */
+  BFD_RELOC_D10V_10_PCREL_L,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+  BFD_RELOC_D10V_18,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+  BFD_RELOC_D10V_18_PCREL,
+
+/* Mitsubishi D30V relocs.
+This is a 6-bit absolute reloc. */
+  BFD_RELOC_D30V_6,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+  BFD_RELOC_D30V_9_PCREL,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+  BFD_RELOC_D30V_9_PCREL_R,
+
+/* This is a 12-bit absolute reloc with the
+right 3 bitsassumed to be 0. */
+  BFD_RELOC_D30V_15,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+  BFD_RELOC_D30V_15_PCREL,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+  BFD_RELOC_D30V_15_PCREL_R,
+
+/* This is an 18-bit absolute reloc with
+the right 3 bits assumed to be 0. */
+  BFD_RELOC_D30V_21,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+  BFD_RELOC_D30V_21_PCREL,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+  BFD_RELOC_D30V_21_PCREL_R,
+
+/* This is a 32-bit absolute reloc. */
+  BFD_RELOC_D30V_32,
+
+/* This is a 32-bit pc-relative reloc. */
+  BFD_RELOC_D30V_32_PCREL,
+
+/* Mitsubishi M32R relocs.
+This is a 24 bit absolute address. */
+  BFD_RELOC_M32R_24,
+
+/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+  BFD_RELOC_M32R_10_PCREL,
+
+/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+  BFD_RELOC_M32R_18_PCREL,
+
+/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+  BFD_RELOC_M32R_26_PCREL,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as unsigned. */
+  BFD_RELOC_M32R_HI16_ULO,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as signed. */
+  BFD_RELOC_M32R_HI16_SLO,
+
+/* This is a 16-bit reloc containing the lower 16 bits of an address. */
+  BFD_RELOC_M32R_LO16,
+
+/* This is a 16-bit reloc containing the small data area offset for use in
+add3, load, and store instructions. */
+  BFD_RELOC_M32R_SDA16,
+
+/* This is a 9-bit reloc */
+  BFD_RELOC_V850_9_PCREL,
+
+/* This is a 22-bit reloc */
+  BFD_RELOC_V850_22_PCREL,
+
+/* This is a 16 bit offset from the short data area pointer. */
+  BFD_RELOC_V850_SDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+short data area pointer. */
+  BFD_RELOC_V850_SDA_15_16_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer. */
+  BFD_RELOC_V850_ZDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+zero data area pointer. */
+  BFD_RELOC_V850_ZDA_15_16_OFFSET,
+
+/* This is an 8 bit offset (of which only 6 bits are used) from the
+tiny data area pointer. */
+  BFD_RELOC_V850_TDA_6_8_OFFSET,
+
+/* This is an 8bit offset (of which only 7 bits are used) from the tiny
+data area pointer. */
+  BFD_RELOC_V850_TDA_7_8_OFFSET,
+
+/* This is a 7 bit offset from the tiny data area pointer. */
+  BFD_RELOC_V850_TDA_7_7_OFFSET,
+
+/* This is a 16 bit offset from the tiny data area pointer. */
+  BFD_RELOC_V850_TDA_16_16_OFFSET,
+
+/* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+data area pointer. */
+  BFD_RELOC_V850_TDA_4_5_OFFSET,
+
+/* This is a 4 bit offset from the tiny data area pointer. */
+  BFD_RELOC_V850_TDA_4_4_OFFSET,
+
+/* This is a 16 bit offset from the short data area pointer, with the
+bits placed non-contigously in the instruction. */
+  BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer, with the
+bits placed non-contigously in the instruction. */
+  BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+
+/* This is a 6 bit offset from the call table base pointer. */
+  BFD_RELOC_V850_CALLT_6_7_OFFSET,
+
+/* This is a 16 bit offset from the call table base pointer. */
+  BFD_RELOC_V850_CALLT_16_16_OFFSET,
+
+
+/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+  BFD_RELOC_MN10300_32_PCREL,
+
+/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+  BFD_RELOC_MN10300_16_PCREL,
+
+/* This is a 8bit DP reloc for the tms320c30, where the most
+significant 8 bits of a 24 bit word are placed into the least
+significant 8 bits of the opcode. */
+  BFD_RELOC_TIC30_LDP,
+
+/* This is a 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode. */
+  BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode. */
+  BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x. */
+  BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode. */
+  BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode. */
+  BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+  BFD_RELOC_FR30_48,
+
+/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+two sections. */
+  BFD_RELOC_FR30_20,
+
+/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+4 bits. */
+  BFD_RELOC_FR30_6_IN_4,
+
+/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+into 8 bits. */
+  BFD_RELOC_FR30_8_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+into 8 bits. */
+  BFD_RELOC_FR30_9_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+into 8 bits. */
+  BFD_RELOC_FR30_10_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+short offset into 8 bits. */
+  BFD_RELOC_FR30_9_PCREL,
+
+/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+short offset into 11 bits. */
+  BFD_RELOC_FR30_12_PCREL,
+
+/* Motorola Mcore relocations. */
+  BFD_RELOC_MCORE_PCREL_IMM8BY4,
+  BFD_RELOC_MCORE_PCREL_IMM11BY2,
+  BFD_RELOC_MCORE_PCREL_IMM4BY2,
+  BFD_RELOC_MCORE_PCREL_32,
+  BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+  BFD_RELOC_MCORE_RVA,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits. */
+  BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits. */
+  BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits. */
+  BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn. */
+  BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn. */
+  BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn. */
+  BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn. */
+  BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn. */
+  BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn. */
+  BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn. */
+  BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+  BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+  BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn. */
+  BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn. */
+  BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn. */
+  BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits. */
+  BFD_RELOC_AVR_CALL,
+
+/* Direct 12 bit. */
+  BFD_RELOC_390_12,
+
+/* 12 bit GOT offset. */
+  BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address. */
+  BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime. */
+  BFD_RELOC_390_COPY,
+
+/* Create GOT entry. */
+  BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry. */
+  BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base. */
+  BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT. */
+  BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset. */
+  BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1. */
+  BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1. */
+  BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1. */
+  BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1. */
+  BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1. */
+  BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset. */
+  BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address. */
+  BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry. */
+  BFD_RELOC_390_GOTENT,
+
+/* These two relocations are used by the linker to determine which of
+the entries in a C++ virtual function table are actually used.  When
+the --gc-sections option is given, the linker will zero out the entries
+that are not used, so that the code for those functions need not be
+included in the output.
+
+VTABLE_INHERIT is a zero-space relocation used to describe to the
+linker the inheritence tree of a C++ virtual function table.  The
+relocation's symbol should be the parent class' vtable, and the
+relocation should be located at the child vtable.
+
+VTABLE_ENTRY is a zero-space relocation that describes the use of a
+virtual function table entry.  The reloc's symbol should refer to the
+table of the class mentioned in the code.  Off of that base, an offset
+describes the entry that is being used.  For Rela hosts, this offset
+is stored in the reloc's addend.  For Rel hosts, we are forced to put
+this offset in the reloc's section offset. */
+  BFD_RELOC_VTABLE_INHERIT,
+  BFD_RELOC_VTABLE_ENTRY,
+
+/* Intel IA64 Relocations. */
+  BFD_RELOC_IA64_IMM14,
+  BFD_RELOC_IA64_IMM22,
+  BFD_RELOC_IA64_IMM64,
+  BFD_RELOC_IA64_DIR32MSB,
+  BFD_RELOC_IA64_DIR32LSB,
+  BFD_RELOC_IA64_DIR64MSB,
+  BFD_RELOC_IA64_DIR64LSB,
+  BFD_RELOC_IA64_GPREL22,
+  BFD_RELOC_IA64_GPREL64I,
+  BFD_RELOC_IA64_GPREL32MSB,
+  BFD_RELOC_IA64_GPREL32LSB,
+  BFD_RELOC_IA64_GPREL64MSB,
+  BFD_RELOC_IA64_GPREL64LSB,
+  BFD_RELOC_IA64_LTOFF22,
+  BFD_RELOC_IA64_LTOFF64I,
+  BFD_RELOC_IA64_PLTOFF22,
+  BFD_RELOC_IA64_PLTOFF64I,
+  BFD_RELOC_IA64_PLTOFF64MSB,
+  BFD_RELOC_IA64_PLTOFF64LSB,
+  BFD_RELOC_IA64_FPTR64I,
+  BFD_RELOC_IA64_FPTR32MSB,
+  BFD_RELOC_IA64_FPTR32LSB,
+  BFD_RELOC_IA64_FPTR64MSB,
+  BFD_RELOC_IA64_FPTR64LSB,
+  BFD_RELOC_IA64_PCREL21B,
+  BFD_RELOC_IA64_PCREL21BI,
+  BFD_RELOC_IA64_PCREL21M,
+  BFD_RELOC_IA64_PCREL21F,
+  BFD_RELOC_IA64_PCREL22,
+  BFD_RELOC_IA64_PCREL60B,
+  BFD_RELOC_IA64_PCREL64I,
+  BFD_RELOC_IA64_PCREL32MSB,
+  BFD_RELOC_IA64_PCREL32LSB,
+  BFD_RELOC_IA64_PCREL64MSB,
+  BFD_RELOC_IA64_PCREL64LSB,
+  BFD_RELOC_IA64_LTOFF_FPTR22,
+  BFD_RELOC_IA64_LTOFF_FPTR64I,
+  BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+  BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+  BFD_RELOC_IA64_SEGREL32MSB,
+  BFD_RELOC_IA64_SEGREL32LSB,
+  BFD_RELOC_IA64_SEGREL64MSB,
+  BFD_RELOC_IA64_SEGREL64LSB,
+  BFD_RELOC_IA64_SECREL32MSB,
+  BFD_RELOC_IA64_SECREL32LSB,
+  BFD_RELOC_IA64_SECREL64MSB,
+  BFD_RELOC_IA64_SECREL64LSB,
+  BFD_RELOC_IA64_REL32MSB,
+  BFD_RELOC_IA64_REL32LSB,
+  BFD_RELOC_IA64_REL64MSB,
+  BFD_RELOC_IA64_REL64LSB,
+  BFD_RELOC_IA64_LTV32MSB,
+  BFD_RELOC_IA64_LTV32LSB,
+  BFD_RELOC_IA64_LTV64MSB,
+  BFD_RELOC_IA64_LTV64LSB,
+  BFD_RELOC_IA64_IPLTMSB,
+  BFD_RELOC_IA64_IPLTLSB,
+  BFD_RELOC_IA64_COPY,
+  BFD_RELOC_IA64_TPREL22,
+  BFD_RELOC_IA64_TPREL64MSB,
+  BFD_RELOC_IA64_TPREL64LSB,
+  BFD_RELOC_IA64_LTOFF_TP22,
+  BFD_RELOC_IA64_LTOFF22X,
+  BFD_RELOC_IA64_LDXMOV,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits high part of an absolute address. */
+  BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits low part of an absolute address. */
+  BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bits of a value. */
+  BFD_RELOC_M68HC11_3B,
+
+/* These relocs are only used within the CRIS assembler.  They are not
+(at present) written to any object files. */
+  BFD_RELOC_CRIS_BDISP8,
+  BFD_RELOC_CRIS_UNSIGNED_5,
+  BFD_RELOC_CRIS_SIGNED_6,
+  BFD_RELOC_CRIS_UNSIGNED_6,
+  BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS. */
+  BFD_RELOC_CRIS_COPY,
+  BFD_RELOC_CRIS_GLOB_DAT,
+  BFD_RELOC_CRIS_JUMP_SLOT,
+  BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT. */
+  BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT. */
+  BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling. */
+  BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling. */
+  BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT. */
+  BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT. */
+  BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation. */
+  BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations. */
+  BFD_RELOC_860_COPY,
+  BFD_RELOC_860_GLOB_DAT,
+  BFD_RELOC_860_JUMP_SLOT,
+  BFD_RELOC_860_RELATIVE,
+  BFD_RELOC_860_PC26,
+  BFD_RELOC_860_PLT26,
+  BFD_RELOC_860_PC16,
+  BFD_RELOC_860_LOW0,
+  BFD_RELOC_860_SPLIT0,
+  BFD_RELOC_860_LOW1,
+  BFD_RELOC_860_SPLIT1,
+  BFD_RELOC_860_LOW2,
+  BFD_RELOC_860_SPLIT2,
+  BFD_RELOC_860_LOW3,
+  BFD_RELOC_860_LOGOT0,
+  BFD_RELOC_860_SPGOT0,
+  BFD_RELOC_860_LOGOT1,
+  BFD_RELOC_860_SPGOT1,
+  BFD_RELOC_860_LOGOTOFF0,
+  BFD_RELOC_860_SPGOTOFF0,
+  BFD_RELOC_860_LOGOTOFF1,
+  BFD_RELOC_860_SPGOTOFF1,
+  BFD_RELOC_860_LOGOTOFF2,
+  BFD_RELOC_860_LOGOTOFF3,
+  BFD_RELOC_860_LOPC,
+  BFD_RELOC_860_HIGHADJ,
+  BFD_RELOC_860_HAGOT,
+  BFD_RELOC_860_HAGOTOFF,
+  BFD_RELOC_860_HAPC,
+  BFD_RELOC_860_HIGH,
+  BFD_RELOC_860_HIGOT,
+  BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations. */
+  BFD_RELOC_OPENRISC_ABS_26,
+  BFD_RELOC_OPENRISC_REL_26,
+  BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name PARAMS ((bfd_reloc_code_real_type code));
+
+typedef struct symbol_cache_entry
+{
+       /* A pointer to the BFD which owns the symbol. This information
+          is necessary so that a back end can work out what additional
+          information (invisible to the application writer) is carried
+          with the symbol.
+
+          This field is *almost* redundant, since you can use section->owner
+          instead, except that some symbols point to the global sections
+          bfd_{abs,com,und}_section.  This could be fixed by making
+          these globals be per-bfd (or per-target-flavor).  FIXME. */
+
+  struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+       /* The text of the symbol. The name is left alone, and not copied; the
+          application may not alter it. */
+  CONST char *name;
+
+       /* The value of the symbol.  This really should be a union of a
+          numeric value with a pointer, since some flags indicate that
+          a pointer to another symbol is stored here.  */
+  symvalue value;
+
+       /* Attributes of a symbol: */
+
+#define BSF_NO_FLAGS    0x00
+
+       /* The symbol has local scope; <<static>> in <<C>>. The value
+          is the offset into the section of the data. */
+#define BSF_LOCAL      0x01
+
+       /* The symbol has global scope; initialized data in <<C>>. The
+          value is the offset into the section of the data. */
+#define BSF_GLOBAL     0x02
+
+       /* The symbol has global scope and is exported. The value is
+          the offset into the section of the data. */
+#define BSF_EXPORT     BSF_GLOBAL /* no real difference */
+
+       /* A normal C symbol would be one of:
+          <<BSF_LOCAL>>, <<BSF_FORT_COMM>>,  <<BSF_UNDEFINED>> or
+          <<BSF_GLOBAL>> */
+
+       /* The symbol is a debugging record. The value has an arbitary
+          meaning, unless BSF_DEBUGGING_RELOC is also set.  */
+#define BSF_DEBUGGING  0x08
+
+       /* The symbol denotes a function entry point.  Used in ELF,
+          perhaps others someday.  */
+#define BSF_FUNCTION    0x10
+
+       /* Used by the linker. */
+#define BSF_KEEP        0x20
+#define BSF_KEEP_G      0x40
+
+       /* A weak global symbol, overridable without warnings by
+          a regular global symbol of the same name.  */
+#define BSF_WEAK        0x80
+
+       /* This symbol was created to point to a section, e.g. ELF's
+          STT_SECTION symbols.  */
+#define BSF_SECTION_SYM 0x100
+
+       /* The symbol used to be a common symbol, but now it is
+          allocated. */
+#define BSF_OLD_COMMON  0x200
+
+       /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+       /* In some files the type of a symbol sometimes alters its
+          location in an output file - ie in coff a <<ISFCN>> symbol
+          which is also <<C_EXT>> symbol appears where it was
+          declared and not at the end of a section.  This bit is set
+          by the target BFD part to convey this information. */
+
+#define BSF_NOT_AT_END    0x400
+
+       /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR   0x800
+
+       /* Signal that the symbol is a warning symbol.  The name is a
+          warning.  The name of the next symbol is the one to warn about;
+          if a reference is made to a symbol with the same name as the next
+          symbol, a warning is issued by the linker. */
+#define BSF_WARNING       0x1000
+
+       /* Signal that the symbol is indirect.  This symbol is an indirect
+          pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT      0x2000
+
+       /* BSF_FILE marks symbols that contain a file name.  This is used
+          for ELF STT_FILE symbols.  */
+#define BSF_FILE          0x4000
+
+       /* Symbol is from dynamic linking information.  */
+#define BSF_DYNAMIC       0x8000
+
+       /* The symbol denotes a data object.  Used in ELF, and perhaps
+          others someday.  */
+#define BSF_OBJECT        0x10000
+
+       /* This symbol is a debugging symbol.  The value is the offset
+          into the section of the data.  BSF_DEBUGGING should be set
+          as well.  */
+#define BSF_DEBUGGING_RELOC 0x20000
+
+  flagword flags;
+
+       /* A pointer to the section to which this symbol is
+          relative.  This will always be non NULL, there are special
+          sections for undefined and absolute symbols.  */
+  struct sec *section;
+
+       /* Back end special data.  */
+  union
+    {
+      PTR p;
+      bfd_vma i;
+    } udata;
+
+} asymbol;
+#define bfd_get_symtab_upper_bound(abfd) \
+     BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+boolean
+bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+
+boolean
+bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+
+#define bfd_is_local_label_name(abfd, name) \
+     BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+#define bfd_canonicalize_symtab(abfd, location) \
+     BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+                  (abfd, location))
+boolean
+bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+
+void
+bfd_print_symbol_vandf PARAMS ((PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+     BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+        BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+boolean
+bfd_is_undefined_symclass PARAMS ((int symclass));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+     BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+               (ibfd, isymbol, obfd, osymbol))
+struct _bfd
+{
+    /* The filename the application opened the BFD with.  */
+    CONST char *filename;
+
+    /* A pointer to the target jump table.             */
+    const struct bfd_target *xvec;
+
+    /* To avoid dragging too many header files into every file that
+       includes `<<bfd.h>>', IOSTREAM has been declared as a "char
+       *", and MTIME as a "long".  Their correct types, to which they
+       are cast when used, are "FILE *" and "time_t".    The iostream
+       is the result of an fopen on the filename.  However, if the
+       BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+       to a bfd_in_memory struct.  */
+    PTR iostream;
+
+    /* Is the file descriptor being cached?  That is, can it be closed as
+       needed, and re-opened when accessed later?  */
+
+    boolean cacheable;
+
+    /* Marks whether there was a default target specified when the
+       BFD was opened. This is used to select which matching algorithm
+       to use to choose the back end. */
+
+    boolean target_defaulted;
+
+    /* The caching routines use these to maintain a
+       least-recently-used list of BFDs */
+
+    struct _bfd *lru_prev, *lru_next;
+
+    /* When a file is closed by the caching routines, BFD retains
+       state information on the file here: */
+
+    file_ptr where;
+
+    /* and here: (``once'' means at least once) */
+
+    boolean opened_once;
+
+    /* Set if we have a locally maintained mtime value, rather than
+       getting it from the file each time: */
+
+    boolean mtime_set;
+
+    /* File modified time, if mtime_set is true: */
+
+    long mtime;
+
+    /* Reserved for an unimplemented file locking extension.*/
+
+    int ifd;
+
+    /* The format which belongs to the BFD. (object, core, etc.) */
+
+    bfd_format format;
+
+    /* The direction the BFD was opened with*/
+
+    enum bfd_direction {no_direction = 0,
+                        read_direction = 1,
+                        write_direction = 2,
+                        both_direction = 3} direction;
+
+    /* Format_specific flags*/
+
+    flagword flags;
+
+    /* Currently my_archive is tested before adding origin to
+       anything. I believe that this can become always an add of
+       origin, with origin set to 0 for non archive files.   */
+
+    file_ptr origin;
+
+    /* Remember when output has begun, to stop strange things
+       from happening. */
+    boolean output_has_begun;
+
+    /* Pointer to linked list of sections*/
+    struct sec  *sections;
+
+    /* The number of sections */
+    unsigned int section_count;
+
+    /* Stuff only useful for object files:
+       The start address. */
+    bfd_vma start_address;
+
+    /* Used for input and output*/
+    unsigned int symcount;
+
+    /* Symbol table for output BFD (with symcount entries) */
+    struct symbol_cache_entry  **outsymbols;
+
+    /* Pointer to structure which contains architecture information*/
+    const struct bfd_arch_info *arch_info;
+
+    /* Stuff only useful for archives:*/
+    PTR arelt_data;
+    struct _bfd *my_archive;     /* The containing archive BFD.  */
+    struct _bfd *next;           /* The next BFD in the archive.  */
+    struct _bfd *archive_head;   /* The first BFD in the archive.  */
+    boolean has_armap;
+
+    /* A chain of BFD structures involved in a link.  */
+    struct _bfd *link_next;
+
+    /* A field used by _bfd_generic_link_add_archive_symbols.  This will
+       be used only for archive elements.  */
+    int archive_pass;
+
+    /* Used by the back end to hold private data. */
+
+    union
+      {
+      struct aout_data_struct *aout_data;
+      struct artdata *aout_ar_data;
+      struct _oasys_data *oasys_obj_data;
+      struct _oasys_ar_data *oasys_ar_data;
+      struct coff_tdata *coff_obj_data;
+      struct pe_tdata *pe_obj_data;
+      struct xcoff_tdata *xcoff_obj_data;
+      struct ecoff_tdata *ecoff_obj_data;
+      struct ieee_data_struct *ieee_data;
+      struct ieee_ar_data_struct *ieee_ar_data;
+      struct srec_data_struct *srec_data;
+      struct ihex_data_struct *ihex_data;
+      struct tekhex_data_struct *tekhex_data;
+      struct elf_obj_tdata *elf_obj_data;
+      struct nlm_obj_tdata *nlm_obj_data;
+      struct bout_data_struct *bout_data;
+      struct sun_core_struct *sun_core_data;
+      struct sco5_core_struct *sco5_core_data;
+      struct trad_core_struct *trad_core_data;
+      struct som_data_struct *som_data;
+      struct hpux_core_struct *hpux_core_data;
+      struct hppabsd_core_struct *hppabsd_core_data;
+      struct sgi_core_struct *sgi_core_data;
+      struct lynx_core_struct *lynx_core_data;
+      struct osf_core_struct *osf_core_data;
+      struct cisco_core_struct *cisco_core_data;
+      struct versados_data_struct *versados_data;
+      struct netbsd_core_struct *netbsd_core_data;
+      PTR any;
+      } tdata;
+
+    /* Used by the application to hold private data*/
+    PTR usrdata;
+
+  /* Where all the allocated stuff under this BFD goes.  This is a
+     struct objalloc *, but we use PTR to avoid requiring the inclusion of
+     objalloc.h.  */
+    PTR memory;
+};
+
+typedef enum bfd_error
+{
+  bfd_error_no_error = 0,
+  bfd_error_system_call,
+  bfd_error_invalid_target,
+  bfd_error_wrong_format,
+  bfd_error_invalid_operation,
+  bfd_error_no_memory,
+  bfd_error_no_symbols,
+  bfd_error_no_armap,
+  bfd_error_no_more_archived_files,
+  bfd_error_malformed_archive,
+  bfd_error_file_not_recognized,
+  bfd_error_file_ambiguously_recognized,
+  bfd_error_no_contents,
+  bfd_error_nonrepresentable_section,
+  bfd_error_no_debug_section,
+  bfd_error_bad_value,
+  bfd_error_file_truncated,
+  bfd_error_file_too_big,
+  bfd_error_invalid_error_code
+} bfd_error_type;
+
+bfd_error_type
+bfd_get_error PARAMS ((void));
+
+void
+bfd_set_error PARAMS ((bfd_error_type error_tag));
+
+CONST char *
+bfd_errmsg PARAMS ((bfd_error_type error_tag));
+
+void
+bfd_perror PARAMS ((CONST char *message));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type
+bfd_set_error_handler PARAMS ((bfd_error_handler_type));
+
+void
+bfd_set_error_program_name PARAMS ((const char *));
+
+bfd_error_handler_type
+bfd_get_error_handler PARAMS ((void));
+
+long
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long
+bfd_canonicalize_reloc PARAMS ((bfd *abfd,
+    asection *sec,
+    arelent **loc,
+    asymbol **syms));
+
+void
+bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+
+    );
+
+boolean
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+int
+bfd_get_arch_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_sign_extend_vma PARAMS ((bfd *abfd));
+
+boolean
+bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+
+long
+bfd_get_mtime PARAMS ((bfd *abfd));
+
+long
+bfd_get_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void
+bfd_set_gp_size PARAMS ((bfd *abfd, int i));
+
+bfd_vma
+bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base));
+
+boolean
+bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+               (ibfd, obfd))
+boolean
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+               (ibfd, obfd))
+boolean
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+     BFD_SEND (abfd, _bfd_set_private_flags, \
+               (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+     BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+     BFD_SEND (abfd, _bfd_find_nearest_line,  (abfd, sec, syms, off, file, func, line))
+
+       /* Do these three do anything useful at all, for any back end?  */
+#define bfd_debug_info_start(abfd) \
+        BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+        BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+        BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+        BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+        BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+        BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_relax_section(abfd, section, link_info, again) \
+       BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+
+#define bfd_gc_sections(abfd, link_info) \
+       BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+
+#define bfd_merge_sections(abfd, link_info) \
+       BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_link_hash_table_create(abfd) \
+       BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_add_symbols(abfd, info) \
+       BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_final_link(abfd, info) \
+       BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+
+#define bfd_free_cached_info(abfd) \
+       BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+
+#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+       BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+
+#define bfd_print_private_bfd_data(abfd, file)\
+       BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+       BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+
+#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+       BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+
+#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+       BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+       PARAMS ((bfd *, struct bfd_link_info *,
+                 struct bfd_link_order *, bfd_byte *,
+                 boolean, asymbol **));
+
+symindex
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+CONST char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean
+core_file_matches_executable_p PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+               ((*((bfd)->xvec->message)) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND
+#define BFD_SEND(bfd, message, arglist) \
+  (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+    ((*((bfd)->xvec->message)) arglist) : \
+    (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+#define BFD_SEND_FMT(bfd, message, arglist) \
+            (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND_FMT
+#define BFD_SEND_FMT(bfd, message, arglist) \
+  (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+   (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \
+   (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+enum bfd_flavour {
+  bfd_target_unknown_flavour,
+  bfd_target_aout_flavour,
+  bfd_target_coff_flavour,
+  bfd_target_ecoff_flavour,
+  bfd_target_xcoff_flavour,
+  bfd_target_elf_flavour,
+  bfd_target_ieee_flavour,
+  bfd_target_nlm_flavour,
+  bfd_target_oasys_flavour,
+  bfd_target_tekhex_flavour,
+  bfd_target_srec_flavour,
+  bfd_target_ihex_flavour,
+  bfd_target_som_flavour,
+  bfd_target_os9k_flavour,
+  bfd_target_versados_flavour,
+  bfd_target_msdos_flavour,
+  bfd_target_ovax_flavour,
+  bfd_target_evax_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+/* Forward declaration.  */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+  char *name;
+  enum bfd_flavour flavour;
+  enum bfd_endian byteorder;
+  enum bfd_endian header_byteorder;
+  flagword object_flags;
+  flagword section_flags;
+  char symbol_leading_char;
+  char ar_pad_char;
+  unsigned short ar_max_namelen;
+  bfd_vma      (*bfd_getx64) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+  void         (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_getx32) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+  void         (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_getx16) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+  void         (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+  void         (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+  void         (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+  void         (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+  const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+  boolean             (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+  boolean             (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+  /* Generic entry points.  */
+#define BFD_JUMP_TABLE_GENERIC(NAME)\
+CAT(NAME,_close_and_cleanup),\
+CAT(NAME,_bfd_free_cached_info),\
+CAT(NAME,_new_section_hook),\
+CAT(NAME,_get_section_contents),\
+CAT(NAME,_get_section_contents_in_window)
+
+  /* Called when the BFD is being closed to do any necessary cleanup.  */
+  boolean       (*_close_and_cleanup) PARAMS ((bfd *));
+  /* Ask the BFD to free all cached information.  */
+  boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+  /* Called when a new section is created.  */
+  boolean       (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+  /* Read the contents of a section.  */
+  boolean       (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+                                            file_ptr, bfd_size_type));
+  boolean       (*_bfd_get_section_contents_in_window)
+                          PARAMS ((bfd *, sec_ptr, bfd_window *,
+                                   file_ptr, bfd_size_type));
+
+  /* Entry points to copy private data.  */
+#define BFD_JUMP_TABLE_COPY(NAME)\
+CAT(NAME,_bfd_copy_private_bfd_data),\
+CAT(NAME,_bfd_merge_private_bfd_data),\
+CAT(NAME,_bfd_copy_private_section_data),\
+CAT(NAME,_bfd_copy_private_symbol_data),\
+CAT(NAME,_bfd_set_private_flags),\
+CAT(NAME,_bfd_print_private_bfd_data)\
+  /* Called to copy BFD general private data from one object file
+     to another.  */
+  boolean       (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+  /* Called to merge BFD general private data from one object file
+     to a common output file when linking.  */
+  boolean       (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+  /* Called to copy BFD private section data from one object file
+     to another.  */
+  boolean       (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+                                                       bfd *, sec_ptr));
+  /* Called to copy BFD private symbol data from one symbol
+     to another.  */
+  boolean       (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+                                                          bfd *, asymbol *));
+  /* Called to set private backend flags */
+  boolean       (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+  /* Called to print private BFD data */
+  boolean       (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+
+  /* Core file entry points.  */
+#define BFD_JUMP_TABLE_CORE(NAME)\
+CAT(NAME,_core_file_failing_command),\
+CAT(NAME,_core_file_failing_signal),\
+CAT(NAME,_core_file_matches_executable_p)
+  char *   (*_core_file_failing_command) PARAMS ((bfd *));
+  int      (*_core_file_failing_signal) PARAMS ((bfd *));
+  boolean  (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+  /* Archive entry points.  */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME)\
+CAT(NAME,_slurp_armap),\
+CAT(NAME,_slurp_extended_name_table),\
+CAT(NAME,_construct_extended_name_table),\
+CAT(NAME,_truncate_arname),\
+CAT(NAME,_write_armap),\
+CAT(NAME,_read_ar_hdr),\
+CAT(NAME,_openr_next_archived_file),\
+CAT(NAME,_get_elt_at_index),\
+CAT(NAME,_generic_stat_arch_elt),\
+CAT(NAME,_update_armap_timestamp)
+  boolean  (*_bfd_slurp_armap) PARAMS ((bfd *));
+  boolean  (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+  boolean  (*_bfd_construct_extended_name_table)
+             PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+  void     (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *));
+  boolean  (*write_armap) PARAMS ((bfd *arch,
+                              unsigned int elength,
+                              struct orl *map,
+                              unsigned int orl_count,
+                              int stridx));
+  PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+  bfd *    (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+  bfd *    (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+  int      (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+  boolean  (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+  /* Entry points used for symbols.  */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME)\
+CAT(NAME,_get_symtab_upper_bound),\
+CAT(NAME,_get_symtab),\
+CAT(NAME,_make_empty_symbol),\
+CAT(NAME,_print_symbol),\
+CAT(NAME,_get_symbol_info),\
+CAT(NAME,_bfd_is_local_label_name),\
+CAT(NAME,_get_lineno),\
+CAT(NAME,_find_nearest_line),\
+CAT(NAME,_bfd_make_debug_symbol),\
+CAT(NAME,_read_minisymbols),\
+CAT(NAME,_minisymbol_to_symbol)
+  long  (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+  long  (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+                                             struct symbol_cache_entry **));
+  struct symbol_cache_entry  *
+                (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+  void          (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+                                      struct symbol_cache_entry *,
+                                      bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+  void          (*_bfd_get_symbol_info) PARAMS ((bfd *,
+                                      struct symbol_cache_entry *,
+                                      symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+  boolean       (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+
+  alent *    (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+  boolean    (*_bfd_find_nearest_line) PARAMS ((bfd *abfd,
+                    struct sec *section, struct symbol_cache_entry **symbols,
+                    bfd_vma offset, CONST char **file, CONST char **func,
+                    unsigned int *line));
+ /* Back-door to allow format-aware applications to create debug symbols
+    while using BFD for everything else.  Currently used by the assembler
+    when creating COFF files.  */
+  asymbol *  (*_bfd_make_debug_symbol) PARAMS ((
+       bfd *abfd,
+       void *ptr,
+       unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+  BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+  long  (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+                                      unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+  BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+  asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+                                             asymbol *));
+
+  /* Routines for relocs.  */
+#define BFD_JUMP_TABLE_RELOCS(NAME)\
+CAT(NAME,_get_reloc_upper_bound),\
+CAT(NAME,_canonicalize_reloc),\
+CAT(NAME,_bfd_reloc_type_lookup)
+  long  (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+  long  (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+                                            struct symbol_cache_entry **));
+  /* See documentation on reloc types.  */
+  reloc_howto_type *
+       (*reloc_type_lookup) PARAMS ((bfd *abfd,
+                                     bfd_reloc_code_real_type code));
+
+  /* Routines used when writing an object file.  */
+#define BFD_JUMP_TABLE_WRITE(NAME)\
+CAT(NAME,_set_arch_mach),\
+CAT(NAME,_set_section_contents)
+  boolean    (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+                    unsigned long));
+  boolean       (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+                                            file_ptr, bfd_size_type));
+
+  /* Routines used by the linker.  */
+#define BFD_JUMP_TABLE_LINK(NAME)\
+CAT(NAME,_sizeof_headers),\
+CAT(NAME,_bfd_get_relocated_section_contents),\
+CAT(NAME,_bfd_relax_section),\
+CAT(NAME,_bfd_link_hash_table_create),\
+CAT(NAME,_bfd_link_add_symbols),\
+CAT(NAME,_bfd_final_link),\
+CAT(NAME,_bfd_link_split_section),\
+CAT(NAME,_bfd_gc_sections),\
+CAT(NAME,_bfd_merge_sections)
+  int        (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+  bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
+                    struct bfd_link_info *, struct bfd_link_order *,
+                    bfd_byte *data, boolean relocateable,
+                    struct symbol_cache_entry **));
+
+  boolean    (*_bfd_relax_section) PARAMS ((bfd *, struct sec *,
+                    struct bfd_link_info *, boolean *again));
+
+  /* Create a hash table for the linker.  Different backends store
+     different information in this table.  */
+  struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+
+  /* Add symbols from this object file into the hash table.  */
+  boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+
+  /* Do a link based on the link_order structures attached to each
+     section of the BFD.  */
+  boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+
+  /* Should this section be split up into smaller pieces during linking.  */
+  boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+  /* Remove sections that are not referenced from the output.  */
+  boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+  /* Attempt to merge SEC_MERGE sections.  */
+  boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+  /* Routines to handle dynamic symbols and relocs.  */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME)\
+CAT(NAME,_get_dynamic_symtab_upper_bound),\
+CAT(NAME,_canonicalize_dynamic_symtab),\
+CAT(NAME,_get_dynamic_reloc_upper_bound),\
+CAT(NAME,_canonicalize_dynamic_reloc)
+  /* Get the amount of memory required to hold the dynamic symbols. */
+  long  (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+  /* Read in the dynamic symbols.  */
+  long  (*_bfd_canonicalize_dynamic_symtab)
+    PARAMS ((bfd *, struct symbol_cache_entry **));
+  /* Get the amount of memory required to hold the dynamic relocs.  */
+  long  (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+  /* Read in the dynamic relocs.  */
+  long  (*_bfd_canonicalize_dynamic_reloc)
+    PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+
+ /* Opposite endian version of this target.  */
+ const struct bfd_target * alternative_target;
+
+ PTR backend_data;
+
+} bfd_target;
+boolean
+bfd_set_default_target PARAMS ((const char *name));
+
+const bfd_target *
+bfd_find_target PARAMS ((CONST char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+const bfd_target *
+bfd_search_for_target PARAMS ((int (* search_func) (const bfd_target *, void *), void *));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+
+boolean
+bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+
+CONST char *
+bfd_format_string PARAMS ((bfd_format format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff -uNr linux.orig/arch/arm/kdb/kdba_bp.c linux/arch/arm/kdb/kdba_bp.c
--- linux.orig/arch/arm/kdb/kdba_bp.c	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/kdba_bp.c	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,795 @@
+/*
+ * Kernel Debugger Architecture Dependent Breakpoint Handling
+ *
+ * Copyright (C) 1999-2002 Silicon Graphics, Inc.  All Rights Reserved
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+ 
+/*
+ * Updated for Xscale (R) architecture support 
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include "arm-tdep.h"
+#include <asm/pgalloc.h>
+
+
+static char *kdba_rwtypes[] = { "Disabled", "Store only",
+			"Load or store", "Load only"};
+static char *kdba_instypes[] = { "Instruction(register)" };
+
+/*
+ * Table describing processor architecture hardware
+ * breakpoint registers.
+ */
+
+kdbhard_bp_t	kdb_hardbreaks[KDB_MAXHARDBPT];
+
+/*
+ * kdba_db_trap
+ *
+ * 	Perform breakpoint processing upon entry to the
+ *	processor debugger fault.   Determine and print
+ *	the active breakpoint.
+ *	Enter due to data breakpoint or instruction 
+ *	breakpoint.
+ *
+ * Parameters:
+ *	regs	Exception frame containing machine register state
+ *	error	Error number passed to kdb.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	KDB_DB_BPT	Standard instruction or data breakpoint encountered
+ *	KDB_DB_SS	Single Step fault ('ss' command or end of 'ssb' command)
+ *	KDB_DB_SSB	Single Step fault, caller should continue ('ssb' command)
+ *	KDB_DB_SSBPT	Single step over breakpoint
+ *	KDB_DB_NOBPT	No existing kdb breakpoint matches this debug exception
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Yup, there be goto's here.
+ *
+ *	If multiple processors receive debug exceptions simultaneously,
+ *	one may be waiting at the kdb fence in kdb() while the user
+ *	issues a 'bc' command to clear the breakpoint the processor
+ *	which is waiting has already encountered.  If this is the case,
+ *	the debug registers will no longer match any entry in the
+ *	breakpoint table, and we'll return the value KDB_DB_NOBPT.
+ *	This can cause a panic in die_if_kernel().  It is safer to
+ *	disable the breakpoint (bd), go until all processors are past
+ *	the breakpoint then clear the breakpoint (bc).  This code
+ *	recognises a breakpoint even when disabled but not when it has
+ *	been cleared.
+ *
+ *	WARNING: This routine clears the debug state.  It should be called
+ *		 once per debug and the result cached.
+ */
+
+kdb_dbtrap_t
+kdba_db_trap(struct pt_regs *regs, int error)
+{
+    	int i,moe,installed=0;
+	kdb_dbtrap_t rv = KDB_DB_BPT;
+	kdb_bp_t *bp;
+	unsigned int ss_ibcr;       // IBCRn used for single step
+
+	if (KDB_NULL_REGS(regs))
+		return KDB_DB_NOBPT;
+
+	if (KDB_DEBUG(BP))
+		kdb_printf("kdba_db_trap: error %d\n", error);
+	moe = (read_xsc_dcsr() & DCSR_MOE_MASK)>> DCSR_MOE;
+
+	if ( moe == MOE_DBP ) {
+        	/*
+         	 * data break point after the access is issued.
+	         */
+        	 return rv;
+    	}
+	/* instruction breakpoint */
+        ss_ibcr = read_xsc_ibcr(SS_IBCRN);
+	if ( KDB_STATE(SSBPT) && ss_ibcr == (regs->ARM_pc | IBCR_EN_MSK) ) {
+		/*
+		 * single step go through bp fault (SSBPT).
+		 * KDB_STATE_SSBPT is set when the kernel debugger 
+		 * stops at the breakpoint caused by global bp or 
+		 * hardware instrucion bp that need to set another
+		 * hardware ibp at next instruction to go through
+		 * the current bp.
+		 * 
+		 */
+		if (KDB_DEBUG(BP))
+			kdb_printf("ssbpt\n");
+	    	KDB_STATE_CLEAR(SSBPT);
+	    	for(i=0,bp=kdb_breakpoints;
+				i < KDB_MAXBPT;
+				i++, bp++) {
+		    	if (KDB_DEBUG(BP))
+				kdb_printf("bp 0x%p enabled %d delayed %d"
+					"global %d cpu %d\n", bp,
+					 bp->bp_enabled, 
+					 bp->bp_delayed, bp->bp_global, 
+					 bp->bp_cpu);
+		    if (!bp->bp_enabled)
+			continue;
+		    if (!bp->bp_global && bp->bp_cpu != smp_processor_id())
+			continue;
+		    if (KDB_DEBUG(BP))
+			kdb_printf("bp for this cpu\n");
+		    if (bp->bp_delayed) {
+			bp->bp_delayed = 0;
+			if ( bp->bp_hardtype ) {
+				kdb_printf("Stranger!!! Why enter here...\n");
+			}
+	 	        if (KDB_DEBUG(BP))
+			    kdb_printf("kdba_installbp\n");
+		        kdba_installbp(regs, bp);
+		        installed++;
+		    }
+	    	}   /* for */
+	    	kdba_clearsinglestep(regs);
+			
+	    	if (!KDB_STATE(DOING_SS) ) {
+		        return KDB_DB_SSBPT;
+	    	}
+	    	else {
+	    		kdb_printf("stranger! Why get here?\n");
+		}
+	}
+    	else if ( KDB_STATE(DOING_SS) && 
+    		  ss_ibcr == (regs->ARM_pc | IBCR_EN_MSK) ) {
+		/*
+		 * single step fault (DOING_SS). 
+		 * KDB_STATE_DOING_SS is set when the kernel debugger set a
+		 * hardware instruction breakpoint at next instruction.
+		 * 
+		 */
+
+		rv = KDB_DB_SS;		/* Indicate single step */
+		if (KDB_STATE(DOING_SSB)) {
+			/* SSB - stop till branch */
+			unsigned long opcode;
+			
+			kdb_id1(regs->ARM_pc);
+			kdb_getarea(opcode, regs->ARM_pc);
+			
+			if ( is_branch(opcode) ) {
+				/*
+				 * End the ssb command here.
+				 */
+				KDB_STATE_CLEAR(DOING_SSB);
+				KDB_STATE_CLEAR(DOING_SS);				
+			} else {
+				rv = KDB_DB_SSB; /* Indicate ssb - dismiss immediately */
+			}
+
+		} else {
+			/*
+			 * Print current insn
+			 */
+			kdb_printf("SS trap at ");
+			kdb_symbol_print(regs->ARM_pc, NULL,
+					 KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+			kdb_id1(regs->ARM_pc);
+			KDB_STATE_CLEAR(DOING_SS);
+		}
+		kdba_clearsinglestep(regs);
+	}
+        else {
+	    // normal instruction break
+	    if (KDB_DEBUG(BP))
+		kdb_printf("kdba_db_trap invoke kdba_bp_trap\n");
+	    return kdba_bp_trap(regs,error);
+	}
+
+	return(rv);
+}
+
+/*
+ * kdba_bp_trap
+ *
+ * 	Perform breakpoint processing upon entry to the
+ *	processor breakpoint instruction fault.   Determine and print
+ *	the active breakpoint.
+ *	Only user ibp (neither for DOING_SS nor for SSBPT) and BKPT 0
+ *	break may enter here.
+ *
+ * Parameters:
+ *	regs	Exception frame containing machine register state
+ *	error	Error number passed to kdb.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	KDB_DB_NOBPT:
+ 		No existing kdb breakpoint matches this debug exception.
+ *	KDB_DB_BPT:
+ *		Standard global instruction breakpoint (BKPT 0)
+ 		or hardware instruction breakpoint encountered.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ * 	If multiple processors receive debug exceptions simultaneously,
+ *	one may be waiting at the kdb fence in kdb() while the user
+ *	issues a 'bc' command to clear the breakpoint the processor which
+ * 	is waiting has already encountered.   If this is the case, the
+ *	debug registers will no longer match any entry in the breakpoint
+ *	table, and we'll return the value '3'.  This can cause a panic
+ *	in die_if_kernel().  It is safer to disable the breakpoint (bd),
+ *	'go' until all processors are past the breakpoint then clear the
+ *	breakpoint (bc).  This code recognises a breakpoint even when
+ *	disabled but not when it has been cleared.
+ *
+ *	WARNING: This routine resets the ip.  It should be called
+ *		 once per breakpoint and the result cached.
+ */
+
+kdb_dbtrap_t
+kdba_bp_trap(struct pt_regs *regs, int error)
+{
+	int i; 
+	kdb_dbtrap_t rv;
+	kdb_bp_t *bp;
+
+	if (KDB_NULL_REGS(regs))
+		return KDB_DB_NOBPT;
+
+	/*
+	 * Determine which breakpoint was encountered.
+	 */
+	if (KDB_DEBUG(BP))
+		kdb_printf("kdba_bp_trap: pc=0x%lx "
+			   "regs=0x%p sp=0x%lx\n",
+			   regs->ARM_pc, regs, regs->ARM_sp);
+
+	rv = KDB_DB_NOBPT;	/* Cause kdb() to return */
+
+	for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+		if (bp->bp_free)
+			continue;
+		if (!bp->bp_global && bp->bp_cpu != smp_processor_id())
+			continue;
+		 if (bp->bp_addr == regs->ARM_pc) {
+			/* Hit this breakpoint. (SW BKPT or instruction hbp) */
+                        if (KDB_DEBUG(BP)) {
+			    kdb_printf("Instruction breakpoint #%d at 0x%lx\n",
+				  i, bp->bp_addr);
+			}
+			/*
+			 * Restore the instruction if it is a soft break point
+			 * to make the following disassembly right.
+			 *
+			 */
+			if ( !bp->bp_hardtype ) {
+				/* not hardware instruction bp */
+				kdba_removebp(bp);
+			}
+			bp->bp_delay = 1;
+			
+			kdb_id1(regs->ARM_pc);
+			rv = KDB_DB_BPT;
+			/* SSBPT is set when the kernel debugger must single
+			 * step a point in order to re-establish an instruction
+			 * breakpoint which uses the instruction replacement
+			 * mechanism or hardware instruction breakpoint.
+			 * It is cleared by any action that removes
+			 * the need to single-step the breakpoint.
+			 */
+			KDB_STATE_SET(SSBPT);
+			break;
+		}
+	}
+	return rv;
+}
+
+/*
+ * kdba_handle_bp
+ *
+ *	Handle an instruction-breakpoint trap.  Called when re-installing
+ *	an enabled breakpoint which has has the bp_delay bit set.
+ *
+ * Parameters:
+ * Returns:
+ * Locking:
+ * Remarks:
+ *
+ * Ok, we really need to:
+ *	1) Restore the original instruction byte(s)
+ *	2) Single Step
+ *	3) Restore breakpoint instruction
+ *	4) Continue.
+ *
+ *
+ */
+
+static void
+kdba_handle_bp(struct pt_regs *regs, kdb_bp_t *bp)
+{
+	if (KDB_NULL_REGS(regs))
+		return;
+
+	if (KDB_DEBUG(BP))
+		kdb_printf("regs->ARM_pc = 0x%lx\n", regs->ARM_pc);
+
+	/*
+	 * Setup single step
+	 */
+	kdba_setsinglestep(regs);
+
+	/*
+	 * Reset delay attribute
+	 */
+	bp->bp_delay = 0;
+	bp->bp_delayed = 1;
+}
+
+
+/*
+ * kdba_bptype
+ *
+ *	Return a string describing type of breakpoint.
+ *
+ * Parameters:
+ *	bph	Pointer to hardware breakpoint description
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Character string.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+char *
+kdba_bptype(kdbhard_bp_t *bph)
+{
+	char *mode;
+
+	if ( bph->bph_b_inst ) 
+	    	mode = kdba_instypes[0];
+	else 
+		mode = kdba_rwtypes[bph->bph_mode];
+	
+
+	return mode;
+}
+
+/*
+ * kdba_printbpreg
+ *
+ *	Print register name assigned to breakpoint
+ *
+ * Parameters:
+ *	bph	Pointer hardware breakpoint structure
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdba_printbpreg(kdbhard_bp_t *bph)
+{
+    if ( bph->bph_r_inst ) {
+        // IBCR
+	kdb_printf(" in ibcr%ld", bph->bph_reg);
+    }
+    else {
+        // DBR
+	kdb_printf(" in dbr%ld", bph->bph_reg);
+    }
+	
+}
+
+/*
+ * kdba_printbp
+ *
+ *	Print string describing hardware breakpoint.
+ *
+ * Parameters:
+ *	bph	Pointer to breakpoint description
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdba_printbp(kdb_bp_t *bp)
+{
+	kdb_printf("\n    is enabled");
+	if (bp->bp_hardtype) {
+		kdba_printbpreg(bp->bp_hard);
+	}
+}
+
+/*
+ * kdba_parsebp
+ *
+ *	Parse architecture dependent portion of the
+ *	breakpoint command.
+ *
+ * Parameters:
+ *	argc	Pass down parameter number in argv[]
+ *	argv	Pass down parameter pointer array.
+ *	nextargp	Pointer of next available parameter.
+ *	bp	Breakpoint description for the parsed one.
+ * Outputs:
+ *	nextargp	Point to next available parameter.
+ *	bp	Breakpoint information created.
+ * Returns:
+ *	Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *	None.
+ * Remarks:
+ *	for XScale architure, data read,  data write, and 
+ *	data access can all be tracked by hardware debug 
+ *	unit in addition to instruction breakpoints.
+ *	The command line options for bph/bpha are:
+ *	{[datar|dataw|dataa|inst]}
+ *	The default option is "inst" for instruction bp.
+ */
+
+int
+kdba_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp)
+{
+	int		nextarg = *nextargp;
+	kdbhard_bp_t 	*bph = &bp->bp_template;
+
+	bph->bph_mode = DBR_DISABLE;		/* Default for ibp */
+	bph->bph_b_inst = 0;
+	if ((argc + 1) != nextarg) {
+		if (!strnicmp(argv[nextarg],"datar",sizeof("datar"))){
+			bph->bph_mode = DBR_LOAD_BRK;
+		} else if (!strnicmp(argv[nextarg],"dataw",sizeof("dataw"))){
+			bph->bph_mode = DBR_STORE_BRK;
+		} else if(!strnicmp(argv[nextarg],"dataa",sizeof("dataa"))){
+			bph->bph_mode = DBR_ACCESS_BRK;
+		} else if(!strnicmp(argv[nextarg],"inst",sizeof("inst"))){
+			bph->bph_b_inst = 1;
+		} else {
+			return KDB_ARGCOUNT;
+		}
+		nextarg++;
+
+
+		if ((argc + 1) != nextarg)
+			return KDB_ARGCOUNT;
+
+		/*
+		 * Indicate to architecture independent level that
+		 * a hardware register assignment is required to enable
+		 * this breakpoint.
+		 */
+
+		bph->bph_free = 0;
+	} else {
+		if (KDB_DEBUG(BP))
+			kdb_printf("kdba_bp: no args, forcehw is %d\n", 
+					bp->bp_forcehw);
+		if (bp->bp_forcehw) {
+			/*
+			 * We are forced to use a hardware register for this
+			 * breakpoint because either the bph or bpha
+			 * commands were used to establish this breakpoint.
+			 */
+			bph->bph_free = 0;
+			bph->bph_b_inst=1;
+		} else {
+			/*
+			 * Indicate to architecture dependent level that
+			 * the instruction replacement breakpoint technique
+			 * should be used for this breakpoint.
+			 */
+			bph->bph_free = 1;
+			bp->bp_adjust = 0;	/* not used for ARM*/
+		}
+	}
+
+	if (!bph->bph_b_inst && bph->bph_mode != 0 
+		&& kdba_verify_rw(bp->bp_addr, 4)) {
+		kdb_printf("Invalid address for breakpoint,"
+			   " ignoring bp command\n");
+		return KDB_BADADDR;
+	}
+
+	*nextargp = nextarg;
+	return 0;
+}
+
+/*
+ * kdba_allocbp
+ *
+ *	Associate a hardware register with a breakpoint.
+ *
+ * Parameters:
+ * Outputs:
+ * Returns:
+ *	A pointer to the allocated register kdbhard_bp_t structure for
+ *	success, Null and a non-zero diagnostic for failure.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+kdbhard_bp_t *
+kdba_allocbp(kdbhard_bp_t *bph, int *diagp)
+{
+	int i;
+	kdbhard_bp_t *newbph;
+
+	for(i=0,newbph=kdb_hardbreaks; i < KDB_MAXHARDBPT; i++, newbph++) {
+		if (newbph->bph_free && bph->bph_b_inst==newbph->bph_r_inst){
+			break;
+		}
+	}
+
+	if (i == KDB_MAXHARDBPT) {
+		*diagp = KDB_TOOMANYDBREGS;
+		return NULL;
+	}
+
+	*diagp = 0;
+
+	/*
+	 * Copy data from template.  Can't just copy the entire template
+	 * here because the register number in kdb_hardbreaks must be
+	 * preserved.
+	 */
+	newbph->bph_b_inst = bph->bph_b_inst;
+	newbph->bph_mode = bph->bph_mode;       // only for word protect
+
+	/*
+	 * Mark entry allocated.
+	 */
+	newbph->bph_free = 0;
+
+	return newbph;
+}
+
+/*
+ * kdba_freebp
+ *
+ *	Deallocate a hardware breakpoint
+ *
+ * Parameters:
+ * Outputs:
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdba_freebp(kdbhard_bp_t *bph)
+{
+	bph->bph_free = 1;
+}
+
+/*
+ * kdba_initbp
+ *
+ *	Initialize the breakpoint table for the hardware breakpoint
+ *	register.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ */
+
+void
+kdba_initbp(void)
+{
+	int i;
+	kdbhard_bp_t *bph;
+
+	/*
+	 * Clear the hardware breakpoint table
+	 */
+
+	memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks));
+
+	for(i=0,bph=kdb_hardbreaks; i<KDB_MAXHARDBPT; i++, bph++) {
+	    if ( i < KDB_NUM_IBCR ) {
+	        // for IBCR register
+		bph->bph_reg = i;
+		bph->bph_free = 1;
+		bph->bph_b_inst = 1;
+		bph->bph_r_inst = 1;	// IBCRn register
+	    }
+	    else {
+	        // for DBR register
+		bph->bph_reg = i-KDB_NUM_IBCR;
+		bph->bph_free = 1;
+		bph->bph_b_inst = 0;
+		bph->bph_r_inst = 0;	// DBRn register
+	    }
+		
+	}
+}
+
+/*
+ * kdba_installbp
+ *
+ *	Install a breakpoint
+ *
+ * Parameters:
+ *	regs	Exception frame
+ *	bp	Breakpoint structure for the breakpoint to be installed
+ * Outputs:
+ *	None.
+ * Returns:
+ *	0 if breakpoint set, otherwise error.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	For hardware breakpoints, set the allocated debug register 
+ *	to the breakpoint.  
+ *
+ *	For instruction replacement breakpoints, we must single-step
+ *	over the replaced instruction at this point so we can re-install
+ *	the breakpoint instruction after the single-step.  SSBPT is set
+ *	when the breakpoint is initially hit and is cleared by any action
+ *	that removes the need for single-step over the breakpoint.
+ */
+
+int
+kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp)
+{
+	/*
+	 * Install the breakpoint, if it is not already installed.
+	 */
+
+	if (KDB_DEBUG(BP)) {
+		kdb_printf("kdba_installbp bp_installed %d\n", 
+				bp->bp_installed);
+	}
+	if (!KDB_STATE(SSBPT)) {
+		bp->bp_delay = 0;
+	}
+	if (!bp->bp_installed) {
+		if (bp->bp_hardtype ) {
+			if (KDB_DEBUG(BP)) {
+				kdb_printf("want to install %s%ld at " 
+					   kdb_bfd_vma_fmt0 "\n",
+					   bp->bp_hard->bph_r_inst ? 
+					   		"ibcr" : "dbr",
+					   bp->bp_hard->bph_reg, bp->bp_addr);
+			}
+		        kdba_installdbreg(bp);
+		        bp->bp_installed = 1;
+		} else if (bp->bp_delay) {
+			if (KDB_DEBUG(BP))
+				kdb_printf("kdba_installbp delayed bp\n");
+			kdba_handle_bp(regs, bp);
+		} else {
+                        /* Software breakpoints always use ARM_BREAK_INSTR.
+			 */
+			kdb_machinst_t break_inst;
+			if (kdb_getarea_size(bp->bp_inst.inst, 
+					     bp->bp_addr, 
+					     sizeof(break_inst))) {
+				kdb_printf("kdba_installbp failed to read "
+					   "software breakpoint at 0x%lx\n",
+					    bp->bp_addr);
+				return(1);
+			}
+			// use BKPT KDB_BREAK_BREAK instruction
+			break_inst.inst[0] = ARM_BREAK_INSTR;
+			if (kdb_putarea_size(bp->bp_addr, &break_inst, 
+					     sizeof(break_inst))) {
+				kdb_printf("kdba_installbp failed to set "
+					   "software breakpoint at 0x%lx\n", 
+					   bp->bp_addr);
+				return(1);
+			}
+			if (KDB_DEBUG(BP))
+				kdb_printf("kdba_installbp instruction BKPT "
+					   "0x%x at " kdb_bfd_vma_fmt0 "\n",
+					   KDB_BREAK_BREAK, bp->bp_addr);
+			bp->bp_installed = 1;
+			flush_icache_range(bp->bp_addr, 
+					   bp->bp_addr+sizeof(break_inst)+1);
+		}
+	}
+	return(0);
+}
+
+/*
+ * kdba_removebp
+ *
+ *	Make a breakpoint ineffective.
+ *
+ * Parameters:
+ * Outputs:
+ * Returns:
+ *	0 if breakpoint removed.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdba_removebp(kdb_bp_t *bp)
+{
+	/*
+	 * For hardware breakpoints, remove it from the active register,
+	 * for software breakpoints, restore the instruction stream.
+	 */
+	if (KDB_DEBUG(BP)) {
+		kdb_printf("kdba_removebp bp_installed %d\n", bp->bp_installed);
+	}
+	if (bp->bp_installed) {
+		if (bp->bp_hardtype) {
+			if (KDB_DEBUG(BP)) {
+				kdb_printf("kdb: removing hardware reg %ld at "
+					   kdb_bfd_vma_fmt0 "\n",
+					   bp->bp_hard->bph_reg, bp->bp_addr);
+			}
+			kdba_removedbreg(bp);
+		} else {
+			if (KDB_DEBUG(BP))
+				kdb_printf("kdb: restoring instruction 0x%08lx"
+					   " at " kdb_bfd_vma_fmt0 "\n",
+					   bp->bp_inst.inst[0], bp->bp_addr);
+			if (kdba_putarea_size(bp->bp_addr, bp->bp_inst.inst,
+					      sizeof(bp->bp_inst.inst)))
+				return(1);
+			flush_icache_range(bp->bp_addr, 
+				   bp->bp_addr+sizeof(bp->bp_inst.inst)+1);
+		}
+		bp->bp_installed = 0;
+	}
+	return(0);
+}
+
diff -uNr linux.orig/arch/arm/kdb/kdba_bt.c linux/arch/arm/kdb/kdba_bt.c
--- linux.orig/arch/arm/kdb/kdba_bt.c	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/kdba_bt.c	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,405 @@
+/*
+ * Kernel Debugger Architecture Dependent Stack Traceback
+ *
+ * Copyright (C) 1999-2002 Silicon Graphics, Inc.  All Rights Reserved
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+/*
+ * Updated for Xscale (R) architecture support 
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#include <linux/config.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kallsyms.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <asm/system.h>
+#include  "arm-tdep.h"
+
+#ifdef CONFIG_FRAME_POINTER
+#define EFPSTR	"FP"
+#define NOBP	0
+#else
+#define EFPSTR	"SP"
+#define NOBP	sp
+#endif
+
+
+/*
+ * bt_print_one
+ *
+ *	Print one back trace entry.
+ *
+ * Inputs:
+ *	pc	Current program counter, or return address.
+ *	fp	#ifdef CONFIG_FRAME_POINTER: Previous frame pointer fp,
+ *		0 if not valid; #else: Frame pointer sp when at pc.
+ *	fi	Pointer of frame_info.
+ *	symtab	Information about symbol that pc falls within.
+ *	argcount Maximum number of arguments to print.
+ * Outputs:
+ *	fi	Updated frame information.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	None.
+ */
+static void
+bt_print_one(kdb_machreg_t pc, kdb_machreg_t fp, struct frame_info *fi,
+	     const kdb_symtab_t *symtab, int argcount)
+{
+	int	btsymarg = 0;
+	int	nosect = 0;
+	kdb_machreg_t word;
+
+	kdbgetintenv("BTSYMARG", &btsymarg);
+	kdbgetintenv("NOSECT", &nosect);
+
+	if (fp)
+		kdb_printf("0x%08lx", fp);
+	else
+		kdb_printf("          ");
+	kdb_symbol_print(pc, symtab, KDB_SP_SPACEB|KDB_SP_VALUE);
+	if (argcount) {
+		int i, argc = fi->args / 4;
+
+		kdb_printf(" (");
+		if (argc > argcount)
+			argc = argcount;
+
+		for(i=1; i<=argc; i++){
+			//kdb_machreg_t argp = ar->arg0 - ar->args + 4*i;
+
+			if (i != 1)
+				kdb_printf(", ");
+			if ( i < 5 ) {
+				kdba_get_fi_reg(fi, 
+						ARM_A1_REGNUM+(i-1), &word);
+				
+			}
+			else {
+				kdb_getword(&word, fi->fi_start+4*(i-5), 4);
+			}
+			kdb_printf("0x%lx", word);
+		}
+		kdb_printf(")");
+	}
+	if (symtab->sym_name) {
+		if (!nosect) {
+			kdb_printf("\n");
+			kdb_printf("                               %s %s 0x%lx 0x%lx 0x%lx",
+				symtab->mod_name,
+				symtab->sec_name,
+				symtab->sec_start,
+				symtab->sym_start,
+				symtab->sym_end);
+		}
+	}
+	kdb_printf("\n");
+	if (argcount && btsymarg) {
+		int i, argc = fi->args / 4 ;
+		kdb_symtab_t	arg_symtab;
+		kdb_machreg_t	arg;
+		for(i=1; i<=argc; i++){
+			if ( i < 5 ) {
+				kdba_get_fi_reg(fi,
+						ARM_A1_REGNUM+(i-1), &arg);
+			}
+			else {
+				kdb_getword(&arg, fi->fi_start+4*(i-5), 4);
+			}
+			if (kdbnearsym(arg, &arg_symtab)) {
+				kdb_printf("                               ");
+				kdb_symbol_print(arg, &arg_symtab, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+			}
+		}
+	}
+}
+
+/*
+ * kdba_bt_stack
+ *
+ * Inputs:
+ *	addr	Pointer to Address provided to 'bt' command, if any.
+ *		0: start from current task context.
+ *	argcount
+ *	p	Pointer to task for 'btp' command.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	mds comes in handy when examining the stack to do a manual
+ *	traceback.
+ */
+ 
+int
+kdba_bt_stack(kdb_machreg_t addr, int argcount, struct task_struct *p)
+{
+	kdb_machreg_t	pc, sp, fp;
+	kdb_machreg_t	ss;		/* stop of stack */
+	kdb_symtab_t	symtab;
+	struct frame_info	fi;
+	int   count;
+	struct pt_regs *regs=NULL;
+
+	/*
+	 * The caller may have supplied an address at which the
+	 * stack traceback operation should begin.  This address
+	 * is assumed by this code to be the frame pointer of the
+	 * callee function that points to following structure:
+		 *    ---------------
+		 *    |  .........  |
+		 *    ---------------
+		 *    |      pc     |		pc of certain instruction in callee.
+		 *    --------------  callee_fp
+		 *    |  caller_ret |		return address in caller.
+		 *    |  caller_sp  |
+		 *    |  caller_fp  |
+		 *    |  .........  |
+		 *    ---------------
+	 *
+	 * The end result of this will make it appear as if a function
+	 * entitled '<unknown>' that contain the caller_fp was called
+	 * from the function which contains return-address.
+	 */
+	if (addr) {
+		/* Trace from user specified frame pointer */
+#ifdef CONFIG_FRAME_POINTER
+		pc = 0;
+		sp = 0;
+		fp = addr;
+		ss = fp & -THREAD_SIZE;
+#else
+		// FIXME... how to get the return pc from stack?
+		kdb_printf("Unsupported feature in no frame_point environment\n");
+		return 0;
+#endif
+	} else {
+		if (kdb_task_has_cpu(p)) {
+			struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+			if (!krp->seqno) {
+				kdb_printf("Process did not save state, cannot backtrace\n");
+				kdb_ps1(p);
+				return 0;
+			}
+			regs = krp->regs;
+			if (KDB_NULL_REGS(regs))
+				return KDB_BADREG;
+			kdba_getregcontents("r15", regs, &pc);
+			kdba_getregcontents("r11", regs, &fp);
+			kdba_getregcontents("r13", regs, &sp);
+			if ( regs && ((regs->ARM_cpsr & MODE_MASK) != SVC_MODE) ) {
+				kdb_printf("Stack is not in kernel space, backtrace not available\n");
+				return 0;
+			}
+		}
+		else {
+			/* Not on cpu, assume blocked.  Blocked tasks do
+			 * not have pt_regs.  p->thread.save{pc,fp} are set, 
+			 * sp points to the p->thread.save+..., assume kernel space.
+			 */
+			if ( !p || !p->thread.save ) {
+				/*
+				 * Wrong task struct contents, probably it 
+				 * lacks a kernel patch, refer to Keith mail.
+				 *
+				 */
+				kdb_printf("Task struct is not fully established,"
+					   "check to see why it is wrong\n");
+				return 0;
+			}
+			pc = p->thread.save->pc;
+			sp = (kdb_machreg_t)p->thread.save + sizeof(*(p->thread.save));
+			fp = p->thread.save->fp;
+		}
+		ss = sp & -THREAD_SIZE;
+		if (sp < (unsigned long)p || sp >= (unsigned long)p + THREAD_SIZE) {
+			kdb_printf("Stack is not in task_struct, backtrace not available\n");
+			return(0);
+		}
+	}
+
+	kdb_printf(EFPSTR "        PC         Function (args)\n");
+
+	/*
+	 * Run through the activation records and print them.
+	 */
+	 
+	memset ( &fi, 0, sizeof(fi) );
+	fi.pregs = regs;
+
+	for (count = 0; count < 200; ++count) {
+		if ( !kdbnearsym(pc, &symtab) ) {
+			symtab.sym_name = symtab.sec_name = "<unknown>";
+			symtab.mod_name = "kernel";
+		}
+
+		if (strcmp("__irq_svc", symtab.sym_name) == 0 ) {
+			/*
+			 * Non-standard frame.  18 registers are pushed
+			 * on the stack as the struct pt_regs described.
+			 */
+			/* Print the non-standard entry without args */
+			bt_print_one(pc, NOBP, &fi, &symtab, 0);
+			kdb_printf("Interrupt registers:\n");
+			if ( sp ) {
+				kdba_dumpregs((struct pt_regs *)(sp), NULL, NULL);
+				/* Step the frame to the interrupted code */
+				fi.pregs = (struct pt_regs *) sp;
+				pc = ((struct pt_regs *)(sp))->ARM_pc;
+				fp = ((struct pt_regs *)(sp))->ARM_fp;
+				sp = ((struct pt_regs *)(sp))->ARM_sp;
+				continue;
+			}
+			else {
+				if ( KDB_DEBUG(ARA) )
+					print_fi(&fi,"NULL SP in SVC IRQ");
+				break;
+			}
+		}
+		if (strcmp("__dabt_svc", symtab.sym_name) == 0 ||
+		    strcmp("__pabt_svc", symtab.sym_name) == 0 ||
+		    strcmp("__und_svc", symtab.sym_name) == 0 ) {
+			/*
+			 * Non-standard frame.  18 registers are pushed
+			 * on the stack as the struct pt_regs described.
+			 */
+			/* Print the non-standard entry without args */
+			bt_print_one(pc, NOBP, &fi, &symtab, 0);
+			kdb_printf("Interrupt registers:\n");
+			if ( sp ) {
+				kdba_dumpregs((struct pt_regs *)(sp), NULL, NULL);
+				/* Step the frame to the interrupted code */
+				fi.pregs = (struct pt_regs *)sp;
+				pc = ((struct pt_regs *)(sp))->ARM_pc;
+				fp = ((struct pt_regs *)(sp))->ARM_fp;
+				sp = ((struct pt_regs *)(sp))->ARM_sp;
+				continue;
+			}
+			else {
+				if ( KDB_DEBUG(ARA) )
+					print_fi(&fi,"NULL SP in SVC exception");
+				break;
+			}
+		}
+		/* FIXME for termination in ASM source code */
+
+		fi.frame = fp;
+		fi.pc = pc;
+		fi.sp = sp;
+		memset(fi.saved_regs, 0, sizeof(fi.saved_regs) );
+		if ( !kdba_arm_prologue(&symtab,&fi,ss) ) {
+			if ( KDB_DEBUG(ARA) )
+				kdb_printf("Failure from arm_prologue\n");
+			break;
+		}
+
+		if ( fi.extra_info.framereg == ARM_SP_REGNUM ) fp = 0;
+
+		bt_print_one(pc, fp, &fi, &symtab, argcount);
+		
+		if (fi.ret_pc == 0) {
+			if ( KDB_DEBUG(ARA) )
+				print_fi(&fi,"End by ret_pc");
+			break;	/* End of frames */
+		}
+
+
+		pc = fi.ret_pc;
+		kdba_get_fi_reg(&fi, ARM_FP_REGNUM, &fp);
+		kdba_get_fi_reg(&fi, ARM_SP_REGNUM, &sp);
+		fi.pregs = NULL;
+	}
+	if (count >= 200)
+		kdb_printf("bt truncated, count limit reached\n");
+
+	return 0;
+}
+
+/*
+ * kdba_bt_address
+ *
+ *	Do a backtrace starting at a specified stack address.  Use this if the
+ *	heuristics get the stack decode wrong.
+ *
+ * Inputs:
+ *	addr	Address provided to 'bt' command.
+ *		It should be a valid frame pointer and is enabled
+ *		only when CONFIG_FRAME_POINTER is defined.
+ *	argcount
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	mds %R12 comes in handy when examining the stack to do a manual
+ *	traceback.
+ */
+
+int
+kdba_bt_address(kdb_machreg_t addr, int argcount)
+{
+	return kdba_bt_stack(addr, argcount, NULL);
+}
+
+/*
+ * kdba_bt_process
+ *
+ *	Do a backtrace for a specified process.
+ *
+ * Inputs:
+ *	p	Struct task pointer extracted by 'bt' command.
+ *	argcount
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ */
+ 
+int
+kdba_bt_process(struct task_struct *p, int argcount)
+{
+	return kdba_bt_stack(0, argcount, p);
+}
diff -uNr linux.orig/arch/arm/kdb/kdba_cpy.S linux/arch/arm/kdb/kdba_cpy.S
--- linux.orig/arch/arm/kdb/kdba_cpy.S	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/kdba_cpy.S	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,68 @@
+
+
+/*
+ *
+ * Copyright (C) 2003 Intel Corporation.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Eddie Dong <eddie.dong@intel.com> 15 April 03
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+		.text
+
+
+/*
+ * unsigned long __kdba_copy_to_user(void *to,void *from,unsigned long n);
+ *
+ * Copy date form source to destination with recovery on violation of
+ * accessing.
+ *
+ * return:
+ *	the number of bytes that are still not copied.
+ *
+ */
+ 
+ENTRY(__kdba_copy_to_user)
+		stmfd	sp!, {lr}
+0:
+		subs	r2, r2, #4		@ n-=4
+		addmi	ip, r2, #4
+		bmi	c2u_noword
+		@ word copy
+10:		ldr	r3, [r1], #4		@ may fault
+11:		str	r3, [r0], #4		@ may fault
+		b	0b
+c2u_noword:
+		movs	r2, ip
+		beq	c2u_nobyte		@ no byte needed
+31:		ldrb	r3, [r1], #1		@ may fault
+32:		strb	r3, [r0], #1		@ may fault
+		subs	r2, r2, #1
+		bne	31b
+c2u_nobyte:
+
+c2u_end:
+		mov	r0, r2
+		@ return with the remained bytes
+		
+		LOADREGS(fd,sp!,{pc})
+
+		.section	.fixup, "ax"
+		.align	0
+01:		add	r2, r2, #4
+03:		B	c2u_end
+		.previous
+		
+		.section __ex_table, "a"
+		.align 3
+		.long   10b, 01b
+		.long	11b, 01b
+		.long	31b, 03b
+		.long	32b, 03b
+		.previous
diff -uNr linux.orig/arch/arm/kdb/kdba_id.c linux/arch/arm/kdb/kdba_id.c
--- linux.orig/arch/arm/kdb/kdba_id.c	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/kdba_id.c	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,289 @@
+/*
+ * Kernel Debugger Architecture Dependent Instruction Disassembly
+ *
+ * Copyright (C) 1999-2002 Silicon Graphics, Inc.  All Rights Reserved
+ * Copyright (C) 2000 Hewlett-Packard Co
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+ 
+/*
+ * Updated for Xscale (R) architecture support 
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+#define KDBA_PRINTBUF_LEN	64	/* buffer len to print a single instr */
+#define KDBA_READBUFFER_LEN	256	/* buffer for BFD disassembler */
+
+#define BUNDLE_MULTIPLIER	3	/* how many instr/bundle */
+#define BUNDLE_SIZE		16	/* how many bytes/bundle */
+#define KDBA_DEFAULT_IDLEN	3	/* default number of bundles to disassemble */
+
+/*
+ * kdba_dis_getsym
+ *
+ *	Get a symbol for the disassembler.
+ *
+ * Parameters:
+ *	addr	Address for which to get symbol
+ *	dip	Pointer to disassemble_info
+ * Returns:
+ *	0
+ * Locking:
+ * Remarks:
+ *	Not used for kdb.
+ */
+
+/* ARGSUSED */
+static int
+kdba_dis_getsym(bfd_vma addr, disassemble_info *dip)
+{
+
+	return 0;
+}
+
+/*
+ * kdba_printaddress
+ *
+ *	Print (symbolically) an address.
+ *
+ * Parameters:
+ *	addr	Address for which to get symbol
+ *	dip	Pointer to disassemble_info
+ *	flag	True if a ":<tab>" sequence should follow the address
+ * Returns:
+ *	None.
+ * Locking:
+ * Remarks:
+ *
+ */
+
+/* ARGSUSED */
+void
+kdba_printaddress(kdb_machreg_t addr, disassemble_info *dip, int flag)
+{
+	kdb_symtab_t symtab;
+	int spaces = 5;
+	unsigned int offset;
+
+	/*
+	 * Print a symbol name or address as necessary.
+	 */
+	dip->fprintf_func(dip->stream, "0x%0*lx ", 2*sizeof(addr), addr);
+	kdbnearsym(addr, &symtab);
+	if (symtab.sym_name) {
+		/* Do not use kdb_symbol_print here, it always does
+		 * kdb_printf but we want dip->fprintf_func.
+		 */
+		dip->fprintf_func(dip->stream, "%s", symtab.sym_name);
+		if ((offset = addr - symtab.sym_start) == 0) {
+			spaces += 4;
+		}
+		else {
+			unsigned int o = offset;
+			while (o >>= 4)
+				--spaces;
+			dip->fprintf_func(dip->stream, "+0x%x", offset);
+		}
+	}
+
+	if (flag) {
+		if (spaces < 1) {
+			spaces = 1;
+		}
+		dip->fprintf_func(dip->stream, ":%*s", spaces, " ");
+	}
+}
+
+/*
+ * kdba_dis_printaddr
+ *
+ *	Print (symbolically) an address.  Called by GNU disassembly
+ *	code via disassemble_info structure.
+ *
+ * Parameters:
+ *	addr	Address for which to get symbol
+ *	dip	Pointer to disassemble_info
+ * Returns:
+ *	None.
+ * Locking:
+ * Remarks:
+ *	This function will never append ":<tab>" to the printed
+ *	symbolic address.
+ */
+
+static void
+kdba_dis_printaddr(bfd_vma addr, disassemble_info *dip)
+{
+	kdba_printaddress(addr, dip, 0);
+}
+
+/*
+ * kdba_dis_getmem
+ *
+ *	Fetch 'length' bytes from 'addr' into 'buf'.
+ *
+ * Parameters:
+ *	addr	Address for which to get symbol
+ *	buf	Address of buffer to fill with bytes from 'addr'
+ *	length	Number of bytes to fetch
+ *	dip	Pointer to disassemble_info
+ * Returns:
+ *	Unread bytes.
+ * Locking:
+ * Remarks:
+ *
+ */
+
+static int
+kdba_dis_getmem(bfd_vma addr, bfd_byte *buf, unsigned int length, disassemble_info *dip)
+{
+	return kdb_getarea_size(buf, addr, length);
+}
+
+/*
+ * kdba_id_parsemode
+ *
+ * 	Parse IDMODE environment variable string and
+ *	set appropriate value into "disassemble_info" structure.
+ *
+ * Parameters:
+ *	mode	Mode string
+ *	dip	Disassemble_info structure pointer
+ * Returns:
+ * Locking:
+ * Remarks:
+ *	No mode supported yet.
+ */
+
+int
+kdba_id_parsemode(const char *mode, disassemble_info *dip)
+{
+	if (mode) {
+		if ( !strcmp(mode, "XScale") ) {
+			dip->mach=bfd_mach_arm_XScale;
+		}
+		else {
+        		kdb_printf("kdba_id_parsemode: error, mode=%s\n", mode);
+			return KDB_BADMODE;
+		}
+	}
+	return 0;
+}
+
+/*
+ * kdba_check_pc
+ *
+ * 	Check that the pc is satisfactory.
+ *
+ * Parameters:
+ *	pc	Program Counter Value.
+ * Returns:
+ *	None
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Can change pc.
+ */
+
+void
+kdba_check_pc(kdb_machreg_t *pc)
+{
+	(*pc) &= ~0x3;	/* pc must be 4 byte aligned */
+}
+
+/*
+ * kdba_id_printinsn
+ *
+ * 	Format and print a single bundle at 'pc'. Return the
+ *	length of the bundle.
+ *
+ * Parameters:
+ *	pc	Program Counter Value.
+ *	dip	Disassemble_info structure pointer
+ * Returns:
+ *	Length of instruction, -1 for error.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	None.
+ */
+
+int
+kdba_id_printinsn(kdb_machreg_t pc, disassemble_info *dip)
+{
+	kdba_printaddress(pc, dip, 1);
+	if ( arm_endian_bit() ) {
+		return print_insn_big_arm(pc, dip);
+	}else {
+		return print_insn_little_arm(pc, dip);
+	}
+}
+
+/*
+ * kdba_id_init
+ *
+ * 	Initialize the architecture dependent elements of
+ *	the disassembly information structure
+ *	for the GNU disassembler.
+ *
+ * Parameters:
+ *	dip	pointer of disassemble_info
+ * Outputs:
+ *	dip	Contents initialized.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void __init
+kdba_id_init(disassemble_info *dip)
+{
+	dip->read_memory_func       = kdba_dis_getmem;
+	dip->print_address_func     = kdba_dis_printaddr;
+	dip->symbol_at_address_func = kdba_dis_getsym;
+
+	dip->flavour                = bfd_target_elf_flavour;
+	dip->arch		    = bfd_arch_arm;
+	dip->mach		    = bfd_mach_arm_XScale;
+	dip->endian = arm_endian_bit() ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
+	dip->display_endian         = dip->endian;
+}
diff -uNr linux.orig/arch/arm/kdb/kdba_io.c linux/arch/arm/kdb/kdba_io.c
--- linux.orig/arch/arm/kdb/kdba_io.c	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/kdba_io.c	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,494 @@
+/*
+ * Kernel Debugger Architecture Dependent Console I/O handler
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+/*
+ * Updated for Xscale (R) architecture support 
+ * Eddie Dong <eddie.dong@intel.com> 25 Mar 03
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/pc_keyb.h>
+#include <linux/console.h>
+#include <linux/ctype.h>
+#include <linux/keyboard.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <asm/keyboard.h>	/* ashishk@sco.com */
+
+#ifdef	CONFIG_VT_CONSOLE
+//#define KDB_BLINK_LED 1
+#else
+#undef	KDB_BLINK_LED
+#endif
+
+#ifdef CONFIG_KDB_USB
+struct kdb_usb_exchange kdb_usb_infos = { NULL, NULL, NULL, NULL, NULL, 0};
+
+static unsigned char kdb_usb_keycode[256] = {
+	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
+	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
+	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
+	120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
+	115,114,  0,  0,  0,124,  0,181,182,183,184,185,186,187,188,189,
+	190,191,192,193,194,195,196,197,198,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+	150,158,159,128,136,177,178,176,142,152,173,140
+};
+
+/* get_usb_char
+ * This function drives the UHCI controller,
+ * fetch the USB scancode and decode it
+ */
+static int get_usb_char(void)
+{
+	static int usb_lock;
+	unsigned char keycode, spec;
+	extern u_short  plain_map[], shift_map[], ctrl_map[];
+
+	/* Is USB initialized ? */
+	if(!kdb_usb_infos.poll_func)
+    		return -1;
+
+	/* Transfer char if they are present */
+	(*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb);
+
+	spec = kdb_usb_infos.buffer[0];
+	keycode = kdb_usb_infos.buffer[2];
+	kdb_usb_infos.buffer[0] = (char)0;
+	kdb_usb_infos.buffer[2] = (char)0;
+
+	if(kdb_usb_infos.buffer[3])
+  		return -1;
+
+	/* A normal key is pressed, decode it */
+	if(keycode)
+		keycode = kdb_usb_keycode[keycode];
+
+	/* 2 Keys pressed at one time ? */
+	if (spec && keycode) {
+		switch(spec)
+  		{
+  			case 0x2:
+  			case 0x20: /* Shift */
+    				return shift_map[keycode];
+	  		case 0x1:
+  			case 0x10: /* Ctrl */
+    				return ctrl_map[keycode];
+			case 0x4:
+			case 0x40: /* Alt */
+    				break;
+  		}
+	}
+	else {
+    		if(keycode) { /* If only one key pressed */
+      			switch(keycode)
+			{
+				case 0x1C: /* Enter */
+	  				return 13;
+
+				case 0x3A: /* Capslock */
+	  				usb_lock ? (usb_lock = 0) : (usb_lock = 1);
+	  				break;
+				case 0x0E: /* Backspace */
+	  				return 8;
+				case 0x0F: /* TAB */
+					return 9;
+				case 0x77: /* Pause */
+	  				break ;
+				default:
+	  				if(!usb_lock) {
+	    					return plain_map[keycode];
+					}
+					else {
+	    					return shift_map[keycode];
+	  				}
+			}
+    		}
+   	}
+	return -1;
+}
+#endif
+
+/*
+ * This module contains code to read characters from the keyboard or a serial
+ * port.
+ *
+ * It is used by the kernel debugger, and is polled, not interrupt driven.
+ *
+ */
+
+#ifdef	KDB_BLINK_LED
+/*
+ * send:  Send a byte to the keyboard controller.  Used primarily to
+ * 	  alter LED settings.
+ */
+
+static void
+kdb_kbdsend(unsigned char byte)
+{
+	while (inb(KBD_STATUS_REG) & KBD_STAT_IBF)
+		;
+	outb(byte, KBD_DATA_REG);
+}
+
+static void
+kdb_toggleled(int led)
+{
+	static int leds;
+
+	leds ^= led;
+
+	kdb_kbdsend(KBD_CMD_SET_LEDS);
+	kdb_kbdsend((unsigned char)leds);
+}
+#endif	/* KDB_BLINK_LED */
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+
+struct kdb_serial kdb_serial;
+
+static inline unsigned int
+serial_inp(struct kdb_serial *kdb_serial, unsigned long offset)
+{
+	offset <<= kdb_serial->ioreg_shift;
+
+	switch (kdb_serial->io_type) {
+	case SERIAL_IO_MEM:
+		return readb(kdb_serial->iobase + offset);
+		break;
+	case SERIAL_IO_MEM32:
+		return readl(kdb_serial->iobase + offset);
+		break;
+	default:
+		return inb(kdb_serial->iobase + offset);
+		break;
+	}
+}
+
+/* Check if there is a byte ready at the serial port */
+static int get_serial_char(void)
+{
+	unsigned char ch;
+
+	if (kdb_serial.iobase == 0)
+		return -1;
+
+	if (serial_inp(&kdb_serial, UART_LSR) & UART_LSR_DR) {
+		ch = serial_inp(&kdb_serial, UART_RX);
+		if (ch == 0x7f)
+			ch = 8;
+		return ch;
+	}
+	return -1;
+}
+#endif /* CONFIG_SERIAL_CONSOLE */
+
+#ifdef	CONFIG_VT_CONSOLE
+
+static int kbd_exists = -1;
+
+/*
+ * Check if the keyboard controller has a keypress for us.
+ * Some parts (Enter Release, LED change) are still blocking polled here,
+ * but hopefully they are all short.
+ */
+static int get_kbd_char(void)
+{
+	int	scancode, scanstatus;
+	static int shift_lock;	/* CAPS LOCK state (0-off, 1-on) */
+	static int shift_key;	/* Shift next keypress */
+	static int ctrl_key;
+	u_short keychar;
+	extern u_short plain_map[], shift_map[], ctrl_map[];
+
+	if (kbd_exists <= 0) {
+		if (kbd_exists == 0)
+			return -1;
+
+		if (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff) {
+			kbd_exists = 0;
+			return -1;
+		}
+		kbd_exists = 1;
+	}
+
+	if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+		return -1;
+
+	/*
+	 * Fetch the scancode
+	 */
+	scancode = inb(KBD_DATA_REG);
+	scanstatus = inb(KBD_STATUS_REG);
+
+	/*
+	 * Ignore mouse events.
+	 */
+	if (scanstatus & KBD_STAT_MOUSE_OBF)
+		return -1;
+
+	/*
+	 * Ignore release, trigger on make
+	 * (except for shift keys, where we want to
+	 *  keep the shift state so long as the key is
+	 *  held down).
+	 */
+
+	if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
+		/*
+		 * Next key may use shift table
+		 */
+		if ((scancode & 0x80) == 0) {
+			shift_key=1;
+		} else {
+			shift_key=0;
+		}
+		return -1;
+	}
+
+	if ((scancode&0x7f) == 0x1d) {
+		/*
+		 * Left ctrl key
+		 */
+		if ((scancode & 0x80) == 0) {
+			ctrl_key = 1;
+		} else {
+			ctrl_key = 0;
+		}
+		return -1;
+	}
+
+	if ((scancode & 0x80) != 0)
+		return -1;
+
+	scancode &= 0x7f;
+
+	/*
+	 * Translate scancode
+	 */
+
+	if (scancode == 0x3a) {
+		/*
+		 * Toggle caps lock
+		 */
+		shift_lock ^= 1;
+
+#ifdef	KDB_BLINK_LED
+		kdb_toggleled(0x4);
+#endif
+		return -1;
+	}
+
+	if (scancode == 0x0e) {
+		/*
+		 * Backspace
+		 */
+		return 8;
+	}
+
+	/* Special Key */
+	switch (scancode) {
+	case 0xF: /* Tab */
+		return 9;
+	case 0x53: /* Del */
+		return 4;
+	case 0x47: /* Home */
+		return 1;
+	case 0x4F: /* End */
+		return 5;
+	case 0x4B: /* Left */
+		return 2;
+	case 0x48: /* Up */
+		return 16;
+	case 0x50: /* Down */
+		return 14;
+	case 0x4D: /* Right */
+		return 6;
+	}
+
+	if (scancode == 0xe0) {
+		return -1;
+	}
+
+	/*
+	 * For Japanese 86/106 keyboards
+	 * 	See comment in drivers/char/pc_keyb.c.
+	 * 	- Masahiro Adegawa
+	 */
+	if (scancode == 0x73) {
+		scancode = 0x59;
+	} else if (scancode == 0x7d) {
+		scancode = 0x7c;
+	}
+
+	if (!shift_lock && !shift_key && !ctrl_key) {
+		keychar = plain_map[scancode];
+	} else if (shift_lock || shift_key) {
+		keychar = shift_map[scancode];
+	} else if (ctrl_key) {
+		keychar = ctrl_map[scancode];
+	} else {
+		keychar = 0x0020;
+		kdb_printf("Unknown state/scancode (%d)\n", scancode);
+	}
+	keychar &= 0x0fff;
+	if (keychar == '\t')
+		keychar = ' ';
+	switch (KTYP(keychar)) {
+	case KT_LETTER:
+	case KT_LATIN:
+		if (isprint(keychar))
+			break;		/* printable characters */
+		/* drop through */
+	case KT_SPEC:
+		if (keychar == K_ENTER)
+			break;
+		/* drop through */
+	default:
+		return(-1);	/* ignore unprintables */
+	}
+
+	if ((scancode & 0x7f) == 0x1c) {
+		/*
+		 * enter key.  All done.  Absorb the release scancode.
+		 */
+		while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+			;
+
+		/*
+		 * Fetch the scancode
+		 */
+		scancode = inb(KBD_DATA_REG);
+		scanstatus = inb(KBD_STATUS_REG);
+
+		while (scanstatus & KBD_STAT_MOUSE_OBF) {
+			scancode = inb(KBD_DATA_REG);
+			scanstatus = inb(KBD_STATUS_REG);
+		}
+
+		if (scancode != 0x9c) {
+			/*
+			 * Wasn't an enter-release,  why not?
+			 */
+			kdb_printf("kdb: expected enter got 0x%x status 0x%x\n",
+			       scancode, scanstatus);
+		}
+
+		kdb_printf("\n");
+		return 13;
+	}
+
+	return keychar & 0xff;
+}
+#endif	/* CONFIG_VT_CONSOLE */
+
+#ifdef KDB_BLINK_LED
+
+/* Leave numlock alone, setting it messes up laptop keyboards with the keypad
+ * mapped over normal keys.
+ */
+int kdba_blink_mask = 0x1 | 0x4;
+
+#define BOGOMIPS (boot_cpu_data.loops_per_jiffy/(500000/HZ))
+static int blink_led(void)
+{
+	static long delay;
+
+	if (kbd_exists == 0)
+		return -1;
+
+	if (--delay < 0) {
+		if (BOGOMIPS == 0)	/* early kdb */
+			delay = 150000000/1000;     /* arbitrary bogomips */
+		else
+			delay = 150000000/BOGOMIPS; /* Roughly 1 second when polling */
+		kdb_toggleled(kdba_blink_mask);
+	}
+	return -1;
+}
+#endif
+
+get_char_func poll_funcs[] = {
+#if defined(CONFIG_VT_CONSOLE)
+	get_kbd_char,
+#endif
+#if defined(CONFIG_SERIAL_CONSOLE)
+	get_serial_char,
+#endif
+#ifdef KDB_BLINK_LED
+	blink_led,
+#endif
+#ifdef CONFIG_KDB_USB
+	get_usb_char,
+#endif
+	NULL
+};
+
+/* 
+ * On some Compaq Deskpro's, there is a keyboard freeze many times after
+ * exiting from the kdb. As kdb's keyboard handler is not interrupt-driven and 
+ * uses a polled interface, it makes more sense to disable motherboard keyboard
+ * controller's OBF interrupts during kdb's polling.In case, of interrupts 
+ * remaining enabled during kdb's polling, it may cause un-necessary 
+ * interrupts being signalled during keypresses, which are also sometimes seen
+ * as spurious interrupts after exiting from kdb. This hack to disable OBF
+ * interrupts before entry to kdb and re-enabling them at kdb exit point also 
+ * solves the keyboard freeze issue. These functions are called from
+ * kdb_local(), hence these are arch. specific setup and cleanup functions
+ * executing only on the local processor - ashishk@sco.com 
+ */
+
+void kdba_local_arch_setup(void)
+{
+}
+
+void kdba_local_arch_cleanup(void)
+{
+}
diff -uNr linux.orig/arch/arm/kdb/kdbasupport.c linux/arch/arm/kdb/kdbasupport.c
--- linux.orig/arch/arm/kdb/kdbasupport.c	Thu Jan  1 08:00:00 1970
+++ linux/arch/arm/kdb/kdbasupport.c	Mon Apr  5 15:07:54 2004
@@ -0,0 +1,1465 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * Copyright (C) 1999-2002 Silicon Graphics, Inc.  All Rights Reserved
+ * Copyright (C) David Mosberger-Tang <davidm@hpl.hp.com>
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+/*
+ * Updated for Xscale (R) architecture support 
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/kdb.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/kdbprivate.h>
+#include <asm/kdbprivate.h>
+#include <linux/ctype.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+#ifdef CONFIG_SMP
+#include <asm/hw_irq.h>
+#endif
+#include  "arm-tdep.h"
+#include <asm/pgalloc.h>
+
+#if defined(CONFIG_SMP)
+unsigned long smp_kdb_wait;
+#endif
+
+
+#ifndef CORE_ADDR
+#define   CORE_ADDR     unsigned int
+#endif
+static int kdba_parse_cpreg(char *cpname,unsigned int *cpnum, 
+		unsigned int *CRn, unsigned int *CRm, 
+		unsigned int *op2 );
+
+int
+kdba_prologue(const kdb_symtab_t *symtab, kdb_machreg_t pc, kdb_machreg_t sp,
+	      kdb_machreg_t fp, kdb_machreg_t ss, int caller, kdb_ar_t *ar)
+{
+	return(1);
+}
+
+void
+kdba_installdbreg(kdb_bp_t *bp)
+{
+        unsigned int dbcon;
+
+	if ( bp->bp_hard->bph_r_inst ) {
+		// hardware instruction breakpoint
+		write_xsc_ibcr(bp->bp_hard->bph_reg,bp->bp_addr | 1);   
+		if (KDB_DEBUG(BP)) {
+			kdb_printf("IBCR%ld register is set at "
+				    kdb_bfd_vma_fmt0 "\n",
+				    bp->bp_hard->bph_reg, bp->bp_addr);
+		}
+	} else {
+		write_xsc_dbr(bp->bp_hard->bph_reg,bp->bp_addr);
+		dbcon = read_xsc_dcon();
+		dbcon &= ~(1<<DBCON_M);     // uses as data address breakpoint
+		dbcon |= ( bp->bp_hard->bph_mode
+			   << (bp->bp_hard->bph_reg ? DBCON_E1 : DBCON_E0));
+		write_xsc_dcon( dbcon );
+		if (KDB_DEBUG(BP)) {
+			kdb_printf("DBR%ld register is set at "
+				    kdb_bfd_vma_fmt0 "\n",
+				    bp->bp_hard->bph_reg, bp->bp_addr);
+		}
+	}
+}
+
+void
+kdba_removedbreg(kdb_bp_t *bp)
+{
+	int 		regnum;
+        unsigned int dbcon;
+
+	if (!bp->bp_hard)
+		return;
+
+	regnum = bp->bp_hard->bph_reg;
+
+	if ( bp->bp_hard->bph_r_inst ) {
+		// IBCRn
+		write_xsc_ibcr(regnum, 0);
+	} else {
+		// DBRn
+		dbcon = read_xsc_dcon();
+		dbcon &= ~(regnum ? (3<<DBCON_E1) : (3<<DBCON_E0) );
+		write_xsc_dcon( dbcon );
+	}
+}
+
+
+static int
+show_cur_stack_frame(struct pt_regs *regs, int regno, unsigned long *contents)
+{
+	return 0 ;
+}
+
+static struct kdbregs {
+	char   *reg_name;
+	size_t	reg_offset;
+} kdbreglist[] = {
+	{ "r0",	offsetof(struct pt_regs, ARM_r0) },
+	{ "r1",	offsetof(struct pt_regs, ARM_r1) },
+	{ "r2",	offsetof(struct pt_regs, ARM_r2) },
+
+	{ "r3", offsetof(struct pt_regs, ARM_r3) },
+	{ "r4",	offsetof(struct pt_regs, ARM_r4) },
+	{ "r5", offsetof(struct pt_regs, ARM_r5) },
+
+	{ "r6",	offsetof(struct pt_regs, ARM_r6) },
+	{ "r7",	offsetof(struct pt_regs, ARM_r7) },
+	{ "r8",	offsetof(struct pt_regs, ARM_r8) },
+
+	{ "r9",	offsetof(struct pt_regs, ARM_r9) },
+	{ "r10",offsetof(struct pt_regs, ARM_r10) },
+	{ "r11",offsetof(struct pt_regs, ARM_fp) },
+
+	{ "r12",offsetof(struct pt_regs, ARM_ip) },
+	{ "r13",offsetof(struct pt_regs, ARM_sp) },
+	{ "r14",offsetof(struct pt_regs, ARM_lr) },
+
+	{ "r15",offsetof(struct pt_regs, ARM_pc) },
+	{ "cpsr",offsetof(struct pt_regs, ARM_cpsr) },
+	{ "orig_r0",offsetof(struct pt_regs, ARM_ORIG_r0) },
+
+};
+static struct kdbthreadregs {
+	char   *reg_name;
+	size_t	reg_offset;
+	size_t  bytes;
+} kdbthreadreglist[] = {
+#if (defined(CONFIG_CPU_XSCALE) && (!defined(CONFIG_CPU_BULVERDE)))
+	{ "acc0",	offsetof(struct context_save_struct, acc0), 8 },
+#endif
+	{ "cpsr",	offsetof(struct context_save_struct, cpsr), 4 },
+	{ "r4",	offsetof(struct context_save_struct, r4), 4 },
+	{ "r5",	offsetof(struct context_save_struct, r5), 4 },
+	{ "r6",	offsetof(struct context_save_struct, r6), 4 },
+	{ "r7",	offsetof(struct context_save_struct, r7), 4 },
+	{ "r8",	offsetof(struct context_save_struct, r8), 4 },
+	{ "r9",	offsetof(struct context_save_struct, r9), 4 },
+	{ "sl",	offsetof(struct context_save_struct, sl), 4 },
+	{ "fp",	offsetof(struct context_save_struct, fp), 4 },
+	{ "pc",	offsetof(struct context_save_struct, pc), 4 },
+} ;
+static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs);
+#define  KDB_THREAD_REGNUM   (sizeof(kdbthreadreglist) / sizeof(struct kdbthreadregs))
+
+#define  CP_R_BIT	1
+#define  CP_W_BIT	2
+static struct coprocessor_regs {
+	char *alias;
+	unsigned char cpnum;
+	unsigned char cr_m_n;	/* low 4 bits for coprocessor register number
+				   CRn and high 4 bits for function bits CRm */
+	unsigned char opcode_2;		/* opcode for this register */
+	unsigned char attribute;	/* attribute of read/write */
+	
+} coprocessor_reglist[] = {
+/* coprocessor 15 */
+	{ "ID",15, 0,0, CP_R_BIT},
+	{ "CacheType",15, 0,1, CP_R_BIT},
+	{ "Control",15, 1,0, CP_R_BIT|CP_W_BIT},
+	{ "Auxiliary",15, 1,1, CP_R_BIT|CP_W_BIT},
+	{ "TTB",15, 2,0, CP_R_BIT|CP_W_BIT},
+	{ "DAC",15, 3,0, CP_R_BIT|CP_W_BIT},
+	{ "FaultStatus",15, 5,0, CP_R_BIT|CP_W_BIT},
+	{ "FaultAddress",15, 6,0, CP_R_BIT|CP_W_BIT},
+	/* cache functions(7) */
+	{ "InVLD_ID_BTB",15, 7|(7 <<4),0, CP_W_BIT},
+	{ "InVLD_I_BTB",15, 7|(5 <<4),0, CP_W_BIT},
+	{ "InVLD_I_LINE",15, 7|(5 <<4),1, CP_W_BIT},
+	{ "InVLD_D_CACHE",15, 7|(6 <<4),0, CP_W_BIT},
+	{ "InVLD_D_LINE",15, 7|(6 <<4),1, CP_W_BIT},
+	{ "CLEAN_D_LINE",15, 7|(0xa <<4),1, CP_W_BIT},
+	{ "DRAIN_W_BUF",15, 7|(0xa <<4),4, CP_W_BIT},
+	{ "InVLD_BTB",15, 7|(5 <<4),6, CP_W_BIT},
+	{ "ALLOC_D_LINE",15, 7|(2 <<4),5, CP_W_BIT},
+	/* TLB operations(8) */
+	{ "InVLD_ID_TLB",15, 8|(7 <<4),0, CP_W_BIT},
+	{ "InVLD_I_TLB",15, 8|(5 <<4),0, CP_W_BIT},
+	{ "InVLD_I_ENTRY",15, 8|(5 <<4),1, CP_W_BIT},
+	{ "InVLD_D_TLB",15, 8|(6 <<4),0, CP_W_BIT},
+	{ "InVLD_D_ENTRY",15, 8|(6 <<4),1, CP_W_BIT},
+	/* cache lock down (9) */
+	{ "FL_I_LINE",15, 9|(1 <<4),0, CP_W_BIT},	
+				/* fetch and lock I cache line */
+	{ "ULOCK_I_CACHE",15, 9|(1 <<4),1, CP_W_BIT},	
+	{ "D_CACHE_LREG",15, 9|(2 <<4),0, CP_R_BIT|CP_W_BIT},
+				/* read/write data cache lock register */
+	{ "ULOCK_D_CACHE",15, 9|(2 <<4),1, CP_W_BIT},
+	/* TLB lock down(10) */
+	{ "TL_I_TLB",15, 10|(4 <<4),0, CP_W_BIT},	
+				/* Translate and lock I TLB entry */
+	{ "TL_D_TLB",15, 10|(8 <<4),0, CP_W_BIT},	
+				/* Translate and lock D TLB entry */
+	{ "ULOCK_I_TLB",15, 10|(4 <<4),1, CP_W_BIT},	
+				/* Unlock I TLB entry */
+	{ "ULOCK_D_TLB",15, 10|(8 <<4),1, CP_W_BIT},	
+				/* Unlock D TLB entry */
+	/* Processor ID (13) */
+	{ "PID",15, 13,0, CP_R_BIT|CP_W_BIT},
+	/* Breakpoint Register (14) */
+	{ "IBCR0",15, 14|(8<<4),0, CP_R_BIT|CP_W_BIT},
+	{ "IBCR1",15, 14|(9<<4),0, CP_R_BIT|CP_W_BIT},
+	{ "DBR0",15, 14|(0<<4),0, CP_R_BIT|CP_W_BIT},
+	{ "DBR1",15, 14|(3<<4),0, CP_R_BIT|CP_W_BIT},
+	{ "DBCON",15, 14|(4<<4),0, CP_R_BIT|CP_W_BIT},
+	/* Coprocessor Access Register (15) */
+	{ "CAR",15, 15|(1<<4),0, CP_R_BIT|CP_W_BIT},
+/* coprocessor 14 */
+	{ "PMNC",14, 0,0, CP_R_BIT|CP_W_BIT},
+	{ "CCNT",14, 1,0, CP_R_BIT|CP_W_BIT},
+	{ "PMN0",14, 2,0, CP_R_BIT|CP_W_BIT},
+	{ "PMN1",14, 3,0, CP_R_BIT|CP_W_BIT},
+	{ "CCLKCFG",14, 6,0, CP_R_BIT|CP_W_BIT},/* Core Clock Configuration */
+	{ "PWRMODE",14, 7,0, CP_R_BIT|CP_W_BIT},/* Power mode register */
+	{ "TX",14, 8,0, CP_R_BIT|CP_W_BIT},	/* Transmit Debug Register */
+	{ "RX",14, 9,0, CP_R_BIT|CP_W_BIT},	/* Receive Debug Register */
+	{ "DBGCSR",14, 10,0, CP_R_BIT|CP_W_BIT},/* Debug Control and Status Reg */
+	{ "TBREG",14, 11,0, CP_R_BIT|CP_W_BIT},	/* Trace Buffer Reg */
+	{ "CHKPT0",14, 12,0, CP_R_BIT|CP_W_BIT},	/* Checkpoint 0 Reg */
+	{ "CHKPT1",14, 13,0, CP_R_BIT|CP_W_BIT},	/* Checkpoint 1 Reg */
+	{ "TXRXCTRL",14, 14,0, CP_R_BIT|CP_W_BIT},	
+				/* Transmit/Receive Control Reg */
+};
+#define  KDB_CP_REGFUN_NUM   (sizeof(coprocessor_reglist) / sizeof(struct coprocessor_regs))
+typedef int (*coprocessor_op_r)(void);
+typedef void (*coprocessor_op_w)(int);
+
+static void dump_coprocessor(unsigned char cpnum)
+{
+	int  i,banner=0;
+	unsigned long  rd,ins[2];
+	coprocessor_op_r fn;
+	
+	if ( cpnum == 0 ) {	// XSCALE CP0
+		unsigned long acc0_h,acc0_l;
+		kdb_printf("Dump coprocessor %d:\n",cpnum);
+		kdb_printf("  RegID  FuncBits   opcode_2"
+				"       alias        value\n\n");
+                xsc_get_acc0(&acc0_h,&acc0_l);
+                kdb_printf("acc0=0x%02lx%08lx\n\n",acc0_h,acc0_l);
+                return ;
+	}
+	for (i=0; i< KDB_CP_REGFUN_NUM; i++ ) {
+		if ( coprocessor_reglist[i].cpnum == cpnum &&
+		     (coprocessor_reglist[i].attribute & CP_R_BIT) ) {
+		     	if ( !banner ) {
+		     		banner = 1;
+				kdb_printf("Dump coprocessor %d:\n",cpnum);
+				kdb_printf("  RegID  FuncBits   opcode_2"
+					"       alias        value\n\n");
+		     	}
+		     	/* create instruction MRC pn, 0,r0,Cn, Cm,0 */
+		     	ins[0] = (INST_AL<<28) | (0xe1<<20/*MRC*/) |
+		     		((coprocessor_reglist[i].cr_m_n&0xf)<<16/*CRn*/) |
+		     		((coprocessor_reglist[i].cr_m_n>>4)/*CRm*/) |
+		     		(0<<12 /*Rd=R0*/) | (1<<4) |
+		     		(cpnum<<8) | 
+		     		((coprocessor_reglist[i].opcode_2&0x7)<<5);
+		     	ins[1] = 0xe1a0f00e;	/* mov pc,lr */
+			flush_icache_range( (unsigned long)ins, 
+					    (unsigned long)(ins+2) + 1);
+		     	
+		     	fn = (coprocessor_op_r)ins;
+		     	rd = (fn)();
+		     	kdb_printf("  reg:%02d func:%02d opcode_2:%02d(%16s)"
+		     		   "=0x%08lx\n", 
+		     		   coprocessor_reglist[i].cr_m_n&0xf,
+		     		   coprocessor_reglist[i].cr_m_n>>4,
+		     		   coprocessor_reglist[i].opcode_2,
+		     		   coprocessor_reglist[i].alias, rd);
+		}
+	}
+	if ( banner ) 
+		kdb_printf("\n");
+}
+
+
+/*
+ * kdba_getregcontents
+ *
+ *	Get the contents of the register specified by the
+ *	input string argument.   Return an error if the string
+ *	does not match a machine register.
+ *
+ *	Supports modification of user-mode registers via
+ *	%<register-name>
+ *
+ * Parameters:
+ *	regname		Pointer to string naming register
+ *	regs		Pointer to structure containing registers.
+ *	contents	Unsigned long containing new register contents
+ * Outputs:
+ * Returns:
+ *	0		Success
+ *	KDB_BADREG	Invalid register name
+ * Locking:
+ * 	None.
+ * Remarks:
+ */
+int
+kdba_getregcontents(const char *regname, struct pt_regs *regs, unsigned long *contents)
+{
+	int i;
+
+	if (strcmp(regname, "spsr") == 0) {
+		unsigned int  spsr_r;
+		__asm__ volatile ("mrs %0,spsr" :"=r"(spsr_r));
+		*contents = spsr_r;
+		return 0 ;
+	}
+
+	if (!regs) {
+		kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+		return KDB_BADREG;
+	}
+
+	if (strcmp(regname, "&regs") == 0) {
+		*contents = (unsigned long)regs;
+		return 0;
+	}
+
+
+	for (i=0; i<nkdbreglist; i++) {
+		if (strstr(kdbreglist[i].reg_name, regname))
+			break;
+	}
+
+	if (i == nkdbreglist) {
+		return KDB_BADREG;
+	}
+	*contents = *(unsigned long *)((unsigned long)regs +
+			kdbreglist[i].reg_offset);
+
+	return 0;
+}
+
+/*
+ * kdba_setregcontents
+ *
+ *	Set the contents of the register specified by the
+ *	input string argument.   Return an error if the string
+ *	does not match a machine register.
+ *
+ * Parameters:
+ *	regname		Pointer to string naming register
+ *	regs		Pointer to structure containing registers.
+ *	contents	Unsigned long containing new register contents
+ * Outputs:
+ * Returns:
+ *	0		Success
+ *	KDB_BADREG	Invalid register name
+ * Locking:
+ * 	None.
+ * Remarks:
+ */
+
+int
+kdba_setregcontents(const char *regname,
+		  struct pt_regs *regs,
+		  unsigned long contents)
+{
+	int  i;
+	unsigned long  ins[2];
+	coprocessor_op_w fn;
+
+	if (!regs) {
+		kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+		return KDB_BADREG;
+	}
+
+	/* fixed registers */
+	for (i=0; i<nkdbreglist; i++) {
+		if (strnicmp(kdbreglist[i].reg_name,
+			     regname,
+			     strlen(regname)) == 0) {
+			break;
+		}
+	}
+	if ( (i < nkdbreglist) && 
+	     (strlen(kdbreglist[i].reg_name) == strlen(regname)) ) {
+
+		/* just in case of "standard" register */
+		*(unsigned long *)((unsigned long)regs + kdbreglist[i].reg_offset) =
+			contents;
+
+		return 0;
+	}
+	else {
+		char *name_acc0_h="acc0_h",*name_acc0_l="acc0_l";
+		int  len = strlen(name_acc0_h);
+		unsigned long acc0_h, acc0_l;
+		unsigned int CRn, CRm,op2,cpnum;
+		
+		/* check for coprocessor register */
+		if ( strlen(regname) == len && 
+		     0 == strnicmp(regname, name_acc0_h, len) ) {
+		     	/* for acc0_h */
+			xsc_get_acc0(&acc0_h,&acc0_l);
+			acc0_h = (contents & 0xff);	/* only 8 bits */
+			xsc_put_acc0 (acc0_h,acc0_l);
+			return 0;
+		}
+		else if ( strlen(regname) == len && 
+		     0 == strnicmp(regname, name_acc0_l, len) ) {
+		     	/* for acc0_l */
+			xsc_get_acc0(&acc0_h,&acc0_l);
+			acc0_l = contents;
+			xsc_put_acc0 (acc0_h,acc0_l);
+			return 0;
+		}
+		/* search for all other coprocessor register */
+		for (i=0; i<KDB_CP_REGFUN_NUM; i++) {
+			if ( (strnicmp(coprocessor_reglist[i].alias,
+			     	regname, strlen(regname)) == 0 ) &&
+			        (coprocessor_reglist[i].attribute & CP_W_BIT)
+			        ) {
+				CRn = coprocessor_reglist[i].cr_m_n&0xf;
+				CRm = coprocessor_reglist[i].cr_m_n>>4;
+				op2 = coprocessor_reglist[i].opcode_2&0x7;
+				cpnum = coprocessor_reglist[i].cpnum;
+				break;
+			}
+		}
+		if ( i == KDB_CP_REGFUN_NUM ) {
+			/* 
+			 * try to see if it is a general cp_reg format,
+			 * Cpcc<CRndd<CRmbb<Opaa>>>
+			 */
+			if ( 0 == kdba_parse_cpreg(regname,&cpnum, &CRn,
+						&CRm, &op2 ) ) {
+				i = 0;		/* give a random cp register index */
+			}
+		}
+		if ( i < KDB_CP_REGFUN_NUM ) {
+			if ( KDB_DEBUG(ARA) ) {
+				kdb_printf("coprocessor modify: CP%02d "
+					"CRn(%02d) CRm(%02d) "
+					"opcode2(%02d)\n", cpnum, CRn,
+					CRm, op2);
+			}
+		     	ins[0] = (INST_AL<<28) | (0xe0<<20/*MCR*/) |
+		     		(CRn<<16/*CRn*/) |
+		     		(CRm/*CRm*/) |
+		     		(0<<12 /*Rd=R0*/) | (1<<4) |
+		     		(cpnum<<8) | 
+		     		(op2<<5);
+		     	ins[1] = 0xe1a0f00e;	/* mov pc,lr */
+			flush_icache_range( (unsigned long)ins, 
+					    (unsigned long)(ins+2) + 1);
+		     	
+		     	fn = (coprocessor_op_w)ins;
+		     	(fn)(contents);
+		     	return 0;
+
+		}
+		return KDB_BADREG;
+	}
+}
+
+/*
+ * kdba_dumpregs
+ *
+ *	Dump the specified register set to the display.
+ *
+ * Parameters:
+ *	regs		Pointer to structure containing registers.
+ *	type		Character string identifying register set to dump
+ *	extra		string further identifying register (optional)
+ * Outputs:
+ * Returns:
+ *	Zero for success, a kdb diagnostic for failure
+ * Locking:
+ * 	None.
+ * Remarks:
+ *	This function will dump the general register set if the type
+ *	argument is NULL (struct pt_regs).   The alternate register
+ *	set types supported by this function:
+ *
+ *	c		Control registers
+ *	u		User registers at most recent entry to kernel
+ *			for the process currently selected with "pid" command.
+ * Following not yet implemented:
+ *	m		Model Specific Registers (extra defines register #)
+ *	r		Memory Type Range Registers (extra defines register)
+ *
+ *	For now, all registers are covered as follows:
+ *
+ * 	rd 		- dumps all regs
+ *	rd	c	- dump all readable coprocessor regs
+ *	rd	c  n	- dump all readable regs in coprocessor reg n.
+ *	rd	u	- dump all user registers of current task.
+ *
+ *
+ */
+
+int
+kdba_dumpregs(struct pt_regs *regs,
+	    const char *type,
+	    const char *extra)
+
+{
+	int i;
+	int count = 0;
+
+	if (type
+	 && (type[0] == 'u')) {
+	 	struct context_save_struct  *pSave;
+		type = NULL;
+		pSave = kdb_current_task->thread.save;
+		if ( !pSave ) {
+			kdb_printf("Uninitialized current->thread.save (pid=%d)!!!\n", kdb_current_task->pid);
+			return 0;
+		}
+		for (i=0; i<KDB_THREAD_REGNUM; i++) {
+			switch ( kdbthreadreglist[i].bytes ) {
+				case 4:
+				kdb_printf("%4s: 0x%8.8lx  ",
+					kdbthreadreglist[i].reg_name,
+				   	*(unsigned long *)((unsigned long)pSave +
+						  kdbthreadreglist[i].reg_offset));
+				++count;
+				break;
+				case 8:
+				kdb_printf("%4s: 0x%16.16llx " "           ",
+					kdbthreadreglist[i].reg_name,
+				   	*(unsigned long long*)((unsigned long)pSave +
+						  kdbthreadreglist[i].reg_offset));				
+				
+				count+=2;
+				break;
+			}
+			if ((count % 4) == 0)
+				kdb_printf("\n");
+		}
+		return 0;
+	}
+
+	if (type == NULL) {
+		if (!regs) {
+			kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+			return KDB_BADREG;
+		}
+		for (i=0; i<nkdbreglist; i++) {
+			kdb_printf("%4s: 0x%8.8lx  ",
+				   kdbreglist[i].reg_name,
+				   *(unsigned long *)((unsigned long)regs +
+						  kdbreglist[i].reg_offset));
+
+			if ((++count % 4) == 0)
+				kdb_printf("\n");
+		}
+
+		kdb_printf("&regs = %p\n", (void *)regs);
+
+		return 0;
+	}
+
+	switch (type[0]) {
+	case 'c':
+	{
+		/* dump coprocessor */
+		unsigned long cpnum;
+		int diag;
+		
+		if ( extra == NULL) {
+			/* dump all coprocessors */
+			for (cpnum=0; cpnum<16; cpnum++ ) {
+				dump_coprocessor((unsigned char)cpnum);
+			}
+		}
+		else {
+			diag = kdbgetularg(extra, &cpnum);
+			if (diag) {
+				return diag;
+			}
+			dump_coprocessor((unsigned char)cpnum);
+		}
+		return 0;
+	}
+	case 'm':
+		break;
+	case 'r':
+		break;
+
+	case 's':
+	{
+		if (!regs) {
+			kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+			return KDB_BADREG;
+		}
+		show_cur_stack_frame(regs, 0, NULL) ;
+
+		return 0 ;
+	}
+
+	case '%':
+	{
+		unsigned long contents ;
+
+		if (!kdba_getregcontents(type+1, regs, &contents))
+			kdb_printf("%s = 0x%16.16lx\n", type+1, contents) ;
+		else
+			kdb_printf("diag: Invalid register %s\n", type+1) ;
+
+		return 0 ;
+	}
+
+	default:
+		return KDB_BADREG;
+	}
+
+	return 0;
+}
+
+kdb_machreg_t
+kdba_getpc(struct pt_regs *regs)
+{
+	return regs ? regs->ARM_pc : 0;
+}
+
+int
+kdba_setpc(struct pt_regs *regs, kdb_machreg_t newpc)
+{
+	if (KDB_NULL_REGS(regs))
+		return KDB_BADREG;
+	regs->ARM_pc = newpc;
+	KDB_STATE_SET(IP_ADJUSTED);
+	return 0;
+}
+
+
+struct switch_stack *kdb_sw[NR_CPUS];
+
+/*
+ * kdba_main_loop
+ *
+ *	Do any architecture specific set up before entering the main kdb loop.
+ *	The primary function of this routine is to make all processes look the
+ *	same to kdb, kdb must be able to list a process without worrying if the
+ *	process is running or blocked, so make all process look as though they
+ *	are blocked.
+ *
+ * Inputs:
+ *	reason		The reason KDB was invoked
+ *	reason2		kdb's current reason code.  Initially error but can change
+ *			acording to kdb state.
+ *	error		The hardware-defined error code
+ *	db_result	Result from break or debug point.
+ *	regs		The exception frame at time of fault/breakpoint.  If reason
+ *			is KDB_REASON_SILENT then regs is NULL, otherwise it should
+ *			always be valid.
+ * Returns:
+ *	0	KDB was invoked for an event which it wasn't responsible
+ *	1	KDB handled the event for which it was invoked.
+ * Outputs:
+ *	Sets pc,fp in current->thread.save.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	none.
+ */
+
+int
+kdba_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
+	       kdb_dbtrap_t db_result, struct pt_regs *regs)
+{
+	int ret;
+	kdb_save_running(regs);
+	ret = kdb_main_loop(reason, reason2, error, db_result, regs);
+	kdb_unsave_running(regs);
+	return ret;
+}
+
+void
+kdba_disableint(kdb_intstate_t *state)
+{
+	int *fp = (int *)state;
+	int   flags;
+
+	__save_flags(flags);
+	__cli();
+
+	*fp = flags;
+}
+
+void
+kdba_restoreint(kdb_intstate_t *state)
+{
+	int flags = *(int *)state;
+	__restore_flags(flags);
+}
+
+/*
+ * Disable the IRQ enable bit in stack frame to 
+ * disable the IRQ when the KDB returns.
+ *
+ * Return:
+ * 	Original IRQ status bit.
+ *	!0: I_BIT = 1;
+ *	 0: I_BIT = 0;
+ */
+int kdba_disable_retirq(struct pt_regs *regs)
+{
+	unsigned int cpsr;
+	cpsr = regs->ARM_cpsr;
+	regs->ARM_cpsr |= I_BIT;
+	return cpsr & I_BIT;
+}
+
+
+/*
+ * Restore the IRQ enable bit in stack frame to 
+ * restore the IRQ enable status when the KDB returns.
+ */
+void kdba_restore_retirq(struct pt_regs *regs, int irq_status)
+{
+	if ( irq_status ) {
+		regs->ARM_cpsr |= I_BIT;
+	} else {
+		regs->ARM_cpsr &= ~I_BIT;
+	}
+}
+
+/*
+ * kdba_setsinglestep
+ *
+ * 	Set an hardware instruction breakpoint at next instruction,
+ *	and 
+ *
+ * Parameters:
+ *	regs	Exception frame containing machine register state
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+void
+kdba_setsinglestep(struct pt_regs *regs)
+{
+    CORE_ADDR  next;
+    
+    if (KDB_NULL_REGS(regs))
+	return;
+    next = arm_get_next_pc ((CORE_ADDR)regs->ARM_pc,regs);
+    write_xsc_ibcr(SS_IBCRN, next|1);   // set SS_IBCRN
+    if (KDB_DEBUG(BP))
+	kdb_printf("kdb: set single step(IBCR%d) at 0x%08x\n",
+		    SS_IBCRN, next);
+
+}
+
+/*
+ * Clear the single step breakpoint set in IBCRN
+ *
+ */
+void
+kdba_clearsinglestep(struct pt_regs *regs)
+{   
+    if (KDB_NULL_REGS(regs))
+	return;
+    write_xsc_ibcr(SS_IBCRN,0);   // clear SS_IBCRN
+    if (KDB_DEBUG(BP))
+	kdb_printf("kdb: clear single step(IBCR%d) at 0x%08lx\n",
+		    SS_IBCRN, regs->ARM_pc);
+}
+
+#ifdef KDB_HAVE_LONGJMP
+int
+kdba_setjmp(kdb_jmp_buf *jb)
+{
+	__asm__ volatile ("stmia r0, {r4-r11,sp,lr}\n\t");
+	KDB_STATE_SET(LONGJMP);
+	return 0;
+}
+
+void
+kdba_longjmp(kdb_jmp_buf *jb, int reason)
+{
+	__asm__ volatile ("ldmia r0, {r4-r11,sp,pc}\n\t");
+}
+#endif	/* KDB_HAVE_LONGJMP */
+
+/*
+ * kdba_enable_mce
+ *
+ *	This function is called once on each CPU to enable machine
+ *	check exception handling.
+ *
+ * Inputs:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ */
+
+void
+kdba_enable_mce(void)
+{
+}
+
+/*
+ * kdba_enable_lbr
+ *
+ *	Enable last branch recording.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None
+ * Locking:
+ *	None
+ * Remarks:
+ *	None.
+ */
+
+void
+kdba_enable_lbr(void)
+{
+}
+
+/*
+ * kdba_disable_lbr
+ *
+ *	disable last branch recording.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None
+ * Locking:
+ *	None
+ * Remarks:
+ *	None.
+ */
+
+void
+kdba_disable_lbr(void)
+{
+}
+
+/*
+ * kdba_print_lbr
+ *
+ *	Print last branch and last exception addresses
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None
+ * Locking:
+ *	None
+ * Remarks:
+ *	None.
+ */
+
+void
+kdba_print_lbr(void)
+{
+}
+
+/*
+ * Enable the XScae debug unit, and set it 
+ * to work in monitor mode.
+ */
+void kdba_enable_debug_unit(void)
+{
+    unsigned  int  dcsr;
+    
+    dcsr = read_xsc_dcsr();
+    if ( dcsr & (1<<DCSR_H) ) {
+        // not in monitor mode after reset, we can't deal with it
+        kdb_printf("Error status of dcsr=%x\n", dcsr);
+        return ;
+    }
+    dcsr &= ~(DCSR_RSV_MASK);          // all reserved bits need to be 0
+    dcsr |= (1<<DCSR_GE);                // enable debug unit
+    dcsr &= ~((1<<DCSR_M) | (1<<DCSR_E));
+    write_xsc_dcsr (dcsr);
+}
+
+
+/*
+ * kdba_pt_regs
+ *
+ *	Format a struct pt_regs
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	If no address is supplied, it uses regs.
+ */
+
+static int
+kdba_pt_regs(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	kdb_machreg_t addr;
+	long offset = 0;
+	int nextarg;
+	struct pt_regs *p;
+
+	if (argc == 0) {
+		addr = (kdb_machreg_t) regs;
+	} else if (argc == 1) {
+		nextarg = 1;
+		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+		if (diag)
+			return diag;
+	} else {
+		return KDB_ARGCOUNT;
+	}
+
+	p = (struct pt_regs *) addr;
+	kdb_printf("struct pt_regs %p-%p\n", p, (unsigned char *)p + sizeof(*p) - 1);
+	kdb_print_nameval("r0", p->ARM_r0);
+	kdb_print_nameval("r1", p->ARM_r1);
+	kdb_print_nameval("r2", p->ARM_r2);
+	kdb_print_nameval("r3", p->ARM_r3);
+	kdb_print_nameval("r4", p->ARM_r4);
+	kdb_print_nameval("r5", p->ARM_r5);
+	kdb_print_nameval("r6", p->ARM_r6);
+	kdb_print_nameval("r7", p->ARM_r7);
+	kdb_print_nameval("r8", p->ARM_r8);
+	kdb_print_nameval("r9", p->ARM_r9);
+	kdb_print_nameval("fp", p->ARM_fp);
+	kdb_print_nameval("ip", p->ARM_ip);
+	kdb_print_nameval("sp", p->ARM_sp);
+	kdb_print_nameval("lr", p->ARM_lr);
+	kdb_print_nameval("pc", p->ARM_pc);
+	kdb_print_nameval("cpsr", p->ARM_cpsr);
+	kdb_print_nameval("orig_r0", p->ARM_ORIG_r0);
+	return 0;
+}
+
+/*
+ * kdba_init
+ *
+ * 	Architecture specific initialization.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	None.
+ */
+
+void
+kdba_init(void)
+{
+	kdba_enable_lbr();
+	kdb_register("pt_regs", kdba_pt_regs, "address", "Format struct pt_regs", 0);
+	kdba_enable_debug_unit();
+	return;
+}
+
+/*
+ * kdba_adjust_ip
+ *
+ * 	Architecture specific adjustment of instruction pointer before leaving
+ *	kdb.
+ *
+ * Parameters:
+ *	reason		The reason KDB was invoked
+ *	error		The hardware-defined error code
+ *	regs		The exception frame at time of fault/breakpoint.  If reason
+ *			is KDB_REASON_SILENT then regs is NULL, otherwise it should
+ *			always be valid.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdba_adjust_ip(kdb_reason_t reason, int error, struct pt_regs *regs)
+{
+}
+
+
+#define  BITS_0_3       0xf
+#define  BITS_8_19      (0xfff<<8)
+
+/*
+ * do_debug
+ *		Common entry of kernel debugger from data abort or 
+ *		prefetch abort from SVC mode.
+ * Input:
+ *	regs:	pointer of stack frame.
+ *
+ * Returns:
+ *		void
+ */
+
+asmlinkage void do_debug(struct pt_regs *regs)
+{
+	unsigned int  ins,moe;
+	int           error_code=0;
+
+	switch ( moe=(read_xsc_dcsr() & DCSR_MOE_MASK)>> DCSR_MOE ) {
+        case MOE_DBP:
+		KDB_DEBUG_STATE("MOE_DBP",-1);
+		kdba_setpc(regs, regs->ARM_pc+4);	// to next ins.
+		kdb(KDB_REASON_DEBUG, error_code, regs);
+		break;
+        case MOE_BKPT:
+		// get immediate of BKPT instruction
+		kdb_getarea_size(&ins, /*addr*/ regs->ARM_pc, 4);
+		ins = ((ins & BITS_8_19) >> 4) | (ins & BITS_0_3);
+		switch ( ins ) {
+                case KDB_BREAK_ENTER:
+			KDB_DEBUG_STATE("BKPT 1",-1);
+			kdb(KDB_REASON_ENTER, 0, regs);
+			kdba_setpc(regs, regs->ARM_pc+4);	// to next ins.
+			return ;
+                case KDB_BREAK_BREAK:
+			KDB_DEBUG_STATE("BKPT 0",-1);
+			kdb(KDB_REASON_BREAK, error_code, regs);
+			break;
+                default:
+			kdb_printf("Unsupported BKPT 0x%4x instruction\n",
+					ins);
+			break;
+		}
+		break;
+        case MOE_IBP:
+		KDB_DEBUG_STATE("MOE_IBP",-1);
+		kdb(KDB_REASON_DEBUG, error_code, regs);
+		break;
+        default:
+		// give error message here.
+		kdb_printf("Unknown DCSR type %x, error found\n", moe);
+	}
+}
+
+/* Finds the "function" (text symbol) that is smaller than PC but
+   greatest of all of the potential text symbols in SECTION.  Sets
+   *NAME and/or *ADDRESS conditionally if that pointer is non-null.
+   If ENDADDR is non-null, then set *ENDADDR to be the end of the
+   function (exclusive), but passing ENDADDR as non-null means that
+   the function might cause symbols to be read.  This function either
+   succeeds or fails (not halfway succeeds).  If it succeeds, it sets
+   *NAME, *ADDRESS, and *ENDADDR to real information and returns 1.
+   If it fails, it sets *NAME, *ADDRESS, and *ENDADDR to zero and
+   returns 0.  */
+int
+find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address,
+			  CORE_ADDR *endaddr)
+{
+	kdb_symtab_t	symtab;
+	if ( kdbnearsym(pc, &symtab) ) {
+		if ( name != NULL ) 
+			*name = symtab.sym_name;
+		*address = symtab.sym_start;
+		*endaddr = symtab.sym_end;
+		return 1;
+	}
+	else {
+		// No sections contain this address, break
+		if ( name != NULL ) 
+			*name = NULL;
+		*address = 0;
+		*endaddr = 0;
+		return 0;
+	}
+	
+}
+
+int kdba_arm_prologue(kdb_symtab_t *symtab,struct frame_info *fi, kdb_machreg_t ss)
+{
+	fi->args = 0;
+	
+	if ( fi->pc == 0 ) {
+		/* Assume 4 valid registers(pc, lr,ip(sp),fp)
+		 * are in frame, and they are valid for fp 
+		 * based addressing */
+		fi->extra_info.frameoffset = 3*4;
+		fi->extra_info.framesize = fi->extra_info.frameoffset+4;
+		fi->extra_info.framereg = ARM_FP_REGNUM;
+		fi->fi_start = fi->frame+4;
+		fi->fi_end = fi->fi_start - fi->extra_info.framesize;
+
+		fi->saved_regs[ARM_LR_REGNUM] = -(4+4);		// base on fi->start
+		fi->saved_regs[ARM_IP_REGNUM] = -(8+4);
+		fi->saved_regs[ARM_FP_REGNUM] = -(12+4);
+
+		kdba_get_fi_reg(fi, ARM_LR_REGNUM, &fi->ret_pc);
+		return 1;
+	}
+	if ( (fi->sp & -THREAD_SIZE) != ss ) {
+		return 0;
+	}
+	if (strcmp("__irq_usr", symtab->sym_name) == 0 ||
+	    strcmp("__dabt_usr", symtab->sym_name) == 0 ||
+	    strcmp("__pabt_usr", symtab->sym_name) == 0 ||
+	    strcmp("__und_usr", symtab->sym_name) == 0 ) {
+		kdb_printf("Interrupt from user space, end of kernel trace\n");
+		goto no_further_parse;
+	}
+	if ( strcmp("ret_from_exception", symtab->sym_name) == 0 ||
+	     strcmp("vector_swi", symtab->sym_name) == 0 || 
+	     strcmp("ret_fast_syscall", symtab->sym_name) == 0 || 
+	     strcmp("vector_swi", symtab->sym_name) == 0 || 
+	     strcmp("__csum_ipv6_magic", symtab->sym_name) == 0 || 
+	     strcmp("csum_partial", symtab->sym_name) == 0 || 
+	     strcmp("__raw_readsw", symtab->sym_name) == 0 || 
+	     strcmp("__raw_readsb", symtab->sym_name) == 0 || 
+	     strcmp("__raw_writesw", symtab->sym_name) == 0 || 
+	     strcmp("__udivsi3", symtab->sym_name) == 0 || 
+	     strcmp("__raw_writesb", symtab->sym_name) == 0 || 
+	     strcmp("memset", symtab->sym_name) == 0 || 
+	     strcmp("__memzero", symtab->sym_name) == 0 || 
+	     strcmp("csum_partial", symtab->sym_name) == 0 || 
+	     strcmp("ret_to_user", symtab->sym_name) == 0 ) {
+	    	/* stop further parse */
+		goto no_further_parse;
+	}
+
+	arm_scan_prologue(fi);
+	if ( fi->extra_info.framereg == ARM_SP_REGNUM ) {
+		fi->fi_start = fi->sp+fi->extra_info.framesize;
+		fi->fi_end = fi->sp;	// not a compelete frame
+		kdba_get_fi_reg(fi, ARM_LR_REGNUM, &fi->ret_pc);
+	}
+	else if ( fi->extra_info.framereg == ARM_FP_REGNUM ) {
+		// ARM_FP_REGNUM
+		fi->fi_start = fi->frame - fi->extra_info.frameoffset
+				+ fi->extra_info.framesize;
+		fi->fi_end = fi->frame-fi->extra_info.frameoffset;
+		kdba_get_fi_reg(fi, ARM_LR_REGNUM, &fi->ret_pc);
+	}
+	else {
+		kdb_printf ("Error type of framereg(%d) at %s\n",
+				fi->extra_info.framereg,
+				 __FUNCTION__);
+	}
+	if (strcmp("start_kernel", symtab->sym_name) == 0 ||
+	    strcmp("kernel_thread", symtab->sym_name) == 0 ) {
+	    	/* stop further parse */
+		goto no_further_parse;
+	}
+	return 1;
+no_further_parse:
+	fi->ret_pc = 0;
+	return 1;
+}
+
+/*
+ * Get caller register from the satcked frame if it is saved in stack or get
+ * directly from register
+ *
+ * Returns:
+ *	0 for success, < 0 for error.
+ */
+int kdba_get_fi_reg (struct frame_info *fi, int reg_num, kdb_machreg_t *reg_value)
+{
+	CORE_ADDR  addr;
+	int  reg_instack=reg_num;	// describe the stack register means for.
+	
+	if ( reg_num == ARM_SP_REGNUM ) {
+		// we uses ip register in prologue to stand for sp
+		reg_instack = ARM_IP_REGNUM;
+	}
+	else if ( reg_num == ARM_IP_REGNUM ) {
+		if ( KDB_DEBUG(ARA) )
+			kdb_printf("Wrong reg_num(%d) to read\n",reg_num);
+	}
+	if ( fi->saved_regs[reg_instack] ) {
+		addr = fi->fi_start + fi->saved_regs[reg_instack];
+		if ( fi->fi_start == 0 ) {
+			if ( KDB_DEBUG(ARA) )
+				kdb_printf("Frame information is not established, error!\n");
+			*reg_value=0;
+			return -1;
+		}
+		return kdb_getarea_size(reg_value, addr, sizeof(*reg_value));
+	}
+	else if ( fi->pregs ) {
+		*reg_value = fi->pregs->uregs[reg_num];
+		return 0;
+	}
+	else {
+		if ( KDB_DEBUG(ARA) )
+			kdb_printf("No right data for reg(%d), 0 is returned\n",reg_num);
+		*reg_value = 0;
+		return 0;
+	}
+}
+
+
+/* 
+ * Used to print the frame information 
+ * Debug use only
+ */
+void print_fi(struct frame_info *fi, char *str)
+{
+	kdb_printf("Extract frameinfo: ----%s fi=%p\n",str,fi);
+	kdb_printf("  frame=%x  args=%ld\n",fi->frame, fi->args);
+	kdb_printf("  extra->framesize = %d\n", fi->extra_info.framesize);
+	kdb_printf("  extra->frameoffset = %d\n", fi->extra_info.frameoffset);
+	kdb_printf("  extra->framereg = %d\n", fi->extra_info.framereg);
+	kdb_printf("  fi_start=%lx  fi_end=%lx\n",fi->fi_start, fi->fi_end);
+	kdb_printf("  pc=%lx  sp=%lx\n",fi->pc, fi->sp);
+	kdb_printf("  ret_pc=%lx\n  ", fi->ret_pc);
+}
+
+#define CONST_FALSE	0
+#define CONST_TRUE	1
+#define SOURCE_OPERAND	2
+#define DEST_OPERAND	4
+#define DEST_REGLIST	8
+#define DEST_ALT_OP 	16
+#define I_BIT_VARIANT	32
+
+#define BIT_25		0x02000000
+#define BIT_4_7		0x00000090
+
+struct instr_info{
+	unsigned long mask;
+	unsigned long value;
+	int flag;
+};
+
+struct instr_info branch_instr[ ] = {
+	{0x0c500000, 0x04100000, DEST_OPERAND}, /* LDR, bit 12-15 */
+	{0x0de00000, 0x01a00000, 
+	 DEST_OPERAND | I_BIT_VARIANT}, 	/* MOV, bit 12-15 */
+	{0x0de00000, 0x01e00000, 
+	 DEST_OPERAND | I_BIT_VARIANT}, 	/* MVN, bit 12-15 */
+	{0x0de00000, 0x01800000, 
+	 DEST_OPERAND | I_BIT_VARIANT}, 	/* ORR, bit 12-15 */
+	{0x0de00000, 0x00600000, 
+	 DEST_OPERAND | I_BIT_VARIANT},		/* RSB, bit 12-15 */
+	{0x0de00000, 0x00e00000, 
+	 DEST_OPERAND | I_BIT_VARIANT},		/* RSC, bit 12-15 */
+	{0x0de00000, 0x00c00000, 
+	 DEST_OPERAND | I_BIT_VARIANT}, 	/* SBC, bit 12-15 */
+	{0x0de00000, 0x00400000, 
+	 DEST_OPERAND | I_BIT_VARIANT},		/* SUB, bit 12-15 */
+	{0x0de00000, 0x00a00000, 
+	 DEST_OPERAND | I_BIT_VARIANT}, 	/* ADC, bit 12-15 */
+	{0x0de00000, 0x00800000, 
+	 DEST_OPERAND | I_BIT_VARIANT}, 	/* ADD, bit 12-15 */
+	{0x0de00000, 0x00000000, 
+	 DEST_OPERAND | I_BIT_VARIANT}, 	/* AND, bit 12-15 */
+	{0x0de00000, 0x01c00000, 
+	 DEST_OPERAND | I_BIT_VARIANT}, 	/* BIC, bit 12-15 */
+	{0x0de00000, 0x00200000, 
+	 DEST_OPERAND | I_BIT_VARIANT},		/* EOR, bit 12-15 */
+	{0x0e000000, 0x0a000000, CONST_TRUE},	/* B, BL */
+	{0x0e500000, 0x08100000, DEST_REGLIST}, /* LDM(1), bit 0-15 */
+	{0x0e508000, 0x08508000, CONST_TRUE},	/* LDM(3), pc always */
+	{0x0f000000, 0x0f000000, CONST_TRUE},	/* SWI */
+	{0x0fe000f0, 0x00200090, DEST_ALT_OP}, 	/* MLA, bit 19-16 */
+	{0x0fe000f0, 0x00000090, DEST_ALT_OP}, 	/* MUL, bit 19-16 */
+	{0x0fe000f0, 0x00e00090, 
+	 DEST_OPERAND | DEST_ALT_OP}, 		/* SMLAL, bit 19-12 */
+	{0x0fe000f0, 0x00c00090,
+	 DEST_OPERAND | DEST_ALT_OP},		/* SMULL, bit 19-12 */
+	{0x0fe000f0, 0x00a00090,
+	 DEST_OPERAND | DEST_ALT_OP},		/* UMLAL bit 19-12 */
+	{0x0fe000f0, 0x00800090,
+	 DEST_OPERAND | DEST_ALT_OP},		/* UMULL bit 19-12 */
+	{0x0ff000d0, 0x01200010, CONST_TRUE},	/* BLX(2), BX */
+	{0x0ff000f0, 0x01000090, DEST_OPERAND}, /* SWP bit 12-15 */
+	{0x0ff000f0, 0x01400090, DEST_OPERAND}, /* SWPB bit 12-15 */
+	{0xfe000000, 0xfa000000, CONST_TRUE},	/* BLX(1) */
+	{0xfff000f0, 0xe1200070, CONST_TRUE}	/* BKPT */
+};
+
+#define BRANCH_INSTR_SIZE (sizeof(branch_instr)/(sizeof(struct instr_info)))
+
+int is_pc_dest(unsigned long opcode, int flag)
+{
+
+	int ret = 0;
+
+	if(flag == CONST_TRUE)
+		ret = 1;
+	else if(flag == DEST_REGLIST){
+		if(opcode & 0x8000){
+			/* pc in reglist is set */
+			ret = 1;
+		}
+	}
+	else{
+		if((flag & DEST_OPERAND) == DEST_OPERAND){
+			if((opcode & 0xf000) == 0xf000){
+				/* rd = 0xf(15) */
+				ret = 1;
+			}
+		}
+		if((flag & DEST_ALT_OP) == DEST_ALT_OP){
+			if((opcode & 0xf0000) == 0xf0000){
+				/* rd = 0xf(15) */
+				ret = 1;
+			}
+		}
+	}
+
+	return ret;
+	
+}
+
+/* If the instruction is causes a branch then returns 1, otherwise 0
+ */
+int is_branch(unsigned long opcode)
+{
+
+	int i;
+
+	for(i = 0; i < BRANCH_INSTR_SIZE; i ++){
+		if((opcode & branch_instr[i].mask) == branch_instr[i].value){
+			if((branch_instr[i].flag & I_BIT_VARIANT) != 0){
+				if((opcode & BIT_25) == 0 && 
+				   (opcode & BIT_4_7) == BIT_4_7){
+					/* not the assumed instruction */
+					continue;
+				}
+			}
+			if(is_pc_dest(opcode, branch_instr[i].flag))
+				return 1;
+			break;
+		}
+	}
+
+	return 0;
+
+}
+
+/*
+ * kdba_cp_parse_part
+ * parser the element of coprocessor name string, its format is:
+ * Cpcc<CRndd<CRmbb<Opaa>>>
+ *   cc/dd/bb/aa can be one decimal digital or 2 decimal digital.
+ *
+ * return:
+ * 	NULL: Failed
+ *	others: next point of parsing string
+ */
+char *kdba_cp_parse_part(char *str, char *prefix, unsigned int *value)
+{
+	int len1,len2,i;
+	
+	len1 = strlen (str);
+	len2 = strlen (prefix);
+	*value = 0;
+	
+	if ( len1 > len2 && strnicmp(str, prefix, len2) == 0 ) {
+		for ( i=len2; i<len2+2 && str[i]; i++ ) {
+			if ( isdigit(str[i]) ) {
+				*value *= 10;
+				*value += (str[i]-'0');
+			}
+			else {
+				break;
+			}
+		}
+		if ( i>len2 ) 
+			return str+i;
+	}
+	return NULL;
+}
+
+#define PARSER_RETURN(str)	{ 		\
+	if ( !str ) {				\
+		/* parse failed */		\
+		return -1; 			\
+	} else if ( !str[0] ) {			\
+		/* parser ended */		\
+		return 0; 			\
+	} };
+
+/*
+ *
+ * return:
+ *	0:  successfully
+ *	-1: failed
+ */
+static int kdba_parse_cpreg(char *cpname,unsigned int *cpnum, 
+		unsigned int *CRn, unsigned int *CRm, 
+		unsigned int *op2 )
+{
+	
+	*CRn = *CRm = *op2 = 0;
+	/* 
+	 * try to see if it is a general cp_reg format,
+ 	 * Cpcc<CRndd<CRmbb<Opaa>>>
+	 */
+	cpname = kdba_cp_parse_part(cpname,"CP", cpnum);
+	PARSER_RETURN(cpname);
+	cpname = kdba_cp_parse_part(cpname,"CRn", CRn);
+	PARSER_RETURN(cpname);
+	cpname = kdba_cp_parse_part(cpname,"CRm", CRm);
+	PARSER_RETURN(cpname);
+	cpname = kdba_cp_parse_part(cpname,"op", op2);
+	PARSER_RETURN(cpname);
+	/* wrong with the left string */
+	return -1;
+}
diff -uNr linux.orig/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- linux.orig/arch/arm/kernel/entry-armv.S	Mon Apr  5 15:02:43 2004
+++ linux/arch/arm/kernel/entry-armv.S	Mon Apr  5 15:07:54 2004
@@ -716,6 +716,16 @@
 		add	r5, sp, #S_SP
 		mov	r1, lr
 		stmia	r5, {r0 - r4}			@ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+#if	defined(CONFIG_KDB) && defined(CONFIG_CPU_XSCALE)
+		mrc	p15, 0, r9, c5, c0, 0		@ fsr => r9
+		tst	r9, #(1<<9)			@ debug exception?
+		beq	10f
+
+		mov	r0, sp				@ yes to call do_debug
+		adr	lr, ._dabt_svc_ret
+		b	do_debug
+10:
+#endif
 		mrs	r9, cpsr			@ Enable interrupts if they were
 		tst	r3, #I_BIT
 		biceq	r9, r9, #I_BIT			@ previously
@@ -735,6 +745,7 @@
 		bl	SYMBOL_NAME(do_DataAbort)
 		mov	r0, #I_BIT | MODE_SVC
 		msr	cpsr_c, r0
+._dabt_svc_ret:
 		ldr	r0, [sp, #S_PSR]
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
@@ -793,6 +804,15 @@
 		add	r5, sp, #S_SP
 		mov	r1, lr
 		stmia	r5, {r0 - r4}			@ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+#if	defined(CONFIG_KDB) && defined(CONFIG_CPU_XSCALE)
+		mrc	p15, 0, r9, c5, c0, 0		@ fsr => r9
+		tst	r9, #(1<<9)			@ debug exception?
+		beq	10f
+		mov	r0, sp				@ yes to call do_debug
+		adr	lr, ._pabt_svc_ret
+		b	do_debug
+10:
+#endif
 		mrs	r9, cpsr			@ Enable interrupts if they were
 		tst	r3, #I_BIT
 		biceq	r9, r9, #I_BIT			@ previously
@@ -802,6 +822,7 @@
 		bl	SYMBOL_NAME(do_PrefetchAbort)	@ call abort handler
 		mov	r0, #I_BIT | MODE_SVC
 		msr	cpsr_c, r0
+._pabt_svc_ret:
 		ldr	r0, [sp, #S_PSR]
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
diff -uNr linux.orig/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- linux.orig/arch/arm/kernel/traps.c	Mon Apr  5 15:02:21 2004
+++ linux/arch/arm/kernel/traps.c	Mon Apr  5 15:07:54 2004
@@ -134,7 +134,13 @@
 
 static void I_really_mean_dump_stack_so_dont_mess_with_me(struct task_struct *tsk, unsigned long sp)
 {
-	dump_mem("Stack: ", sp, 8192+(unsigned long)tsk);
+	dump_mem("Stack: ", sp - 16, 8192+(unsigned long)tsk);
+}
+
+void dump_stack()
+{
+	int local;
+	I_really_mean_dump_stack_so_dont_mess_with_me(current, &local);
 }
 
 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
diff -uNr linux.orig/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in
--- linux.orig/arch/arm/vmlinux-armv.lds.in	Tue Feb 26 03:37:52 2002
+++ linux/arch/arm/vmlinux-armv.lds.in	Mon Apr  5 15:07:54 2004
@@ -25,6 +25,9 @@
 		__setup_start = .;
 			*(.setup.init)
 		__setup_end = .;
+  		__kdb_initcall_start = .;
+  			*(.kdb_initcall.init)
+  		__kdb_initcall_end = .;
 		__initcall_start = .;
 			*(.initcall.init)
 		__initcall_end = .;
@@ -36,6 +39,7 @@
 		*(.text.exit)
 		*(.data.exit)
 		*(.exitcall.exit)
+		*(.kdb_exitcall.exit)
 	}
 
 	.text : {			/* Real text segment		*/
@@ -66,6 +70,10 @@
 			*(__ksymtab)
 		__stop___ksymtab = .;
 	}
+        __start___kallsyms = .;	/* All kernel symbols */
+                __kallsyms : { *(__kallsyms) }
+        __stop___kallsyms = .;
+
 
 	. = ALIGN(8192);
 
diff -uNr linux.orig/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- linux.orig/arch/i386/kernel/smpboot.c	Fri Jun 13 22:51:29 2003
+++ linux/arch/i386/kernel/smpboot.c	Mon Apr  5 15:07:55 2004
@@ -803,8 +803,7 @@
 	if (!idle)
 		panic("No idle process for CPU %d", cpu);
 
-	idle->processor = cpu;
-	idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
+	task_set_cpu_only(idle, cpu);	/* we schedule the first task manually */
 
 	map_cpu_to_boot_apicid(cpu, apicid);
 
diff -uNr linux.orig/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- linux.orig/drivers/char/keyboard.c	Mon Apr  5 15:02:21 2004
+++ linux/drivers/char/keyboard.c	Mon Apr  5 15:07:55 2004
@@ -47,6 +47,9 @@
 #include <linux/kbd_ll.h>
 #include <linux/sysrq.h>
 #include <linux/pm.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 
 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
@@ -299,6 +302,14 @@
 		del_timer(&key_autorepeat_timer);
 	}
 
+#ifdef	CONFIG_KDB
+#define E1_PAUSE 	119
+	if (!up_flag && (keycode == E1_PAUSE) && kdb_on) {
+		kdb(KDB_REASON_KEYBOARD, 0, kbd_pt_regs);
+		return;
+	}
+#endif	/* CONFIG_KDB */
+
 #ifdef CONFIG_MAGIC_SYSRQ		/* Handle the SysRq Hack */
 	if (keycode == SYSRQ_KEY) {
 		sysrq_pressed = !up_flag;
diff -uNr linux.orig/drivers/char/serial.c linux/drivers/char/serial.c
--- linux.orig/drivers/char/serial.c	Mon Apr  5 15:02:43 2004
+++ linux/drivers/char/serial.c	Mon Apr  5 15:07:55 2004
@@ -233,6 +233,31 @@
 #include <linux/sysrq.h>
 #endif
 
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#ifdef	CONFIG_SERIAL_CONSOLE
+/*
+ * kdb_serial_line records the serial line number of the first serial console.
+ * NOTE: The kernel ignores characters on the serial line unless a user space
+ * program has opened the line first.  To enter kdb before user space has opened
+ * the serial line, you can use the 'kdb=early' flag to lilo and set the
+ * appropriate breakpoints.
+ *
+ * kdb_serial_str[] is the sequence that the user must enter on the serial
+ * console to invoke kdb.  It can be a single character such as "\001"
+ * (control-A) or multiple characters such as "\eKdB".  NOTE: All except the
+ * last character are passed through to the application reading from the serial
+ * console.
+ *
+ * I tried to make the sequence a CONFIG_ option but most of CML1 cannot cope
+ * with '\' in strings, CML2 should be able to do it.  KAO.
+ */
+
+static int  kdb_serial_line = -1;
+static char kdb_serial_str[] = "\001";
+static char *kdb_serial_ptr = kdb_serial_str;
+#endif	/* CONFIG_SERIAL_CONSOLE */
+#endif	/* CONFIG_KDB */
 /*
  * All of the compatibilty code so we can compile serial.c against
  * older kernels is hidden in serial_compat.h
@@ -595,6 +620,18 @@
 				return;		// if TTY_DONT_FLIP is set
 		}
 		ch = serial_inp(info, UART_RX);
+#if	defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_KDB)
+		if ((info->line == kdb_serial_line) && kdb_on) {
+		    if (ch == *kdb_serial_ptr) {
+			if (!(*++kdb_serial_ptr)) {
+			    kdb(KDB_REASON_KEYBOARD, 0, regs);
+			    kdb_serial_ptr = kdb_serial_str;
+			    break;
+			}
+		    } else
+			kdb_serial_ptr = kdb_serial_str;
+		}
+#endif	/* CONFIG_SERIAL_CONSOLE && CONFIG_KDB */
 		*tty->flip.char_buf_ptr = ch;
 		icount->rx++;
 		
@@ -6083,6 +6120,30 @@
 	if (serial_in(info, UART_LSR) == 0xff)
 		return -1;
 
+#if	defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_KDB)
+	/*
+	 * Remember the line number of the first serial
+	 * console.  We'll make this the kdb serial console too.
+	 */
+	if (kdb_serial_line == -1) {
+		kdb_serial_line = co->index;
+		kdb_serial.io_type = info->io_type;
+		switch (info->io_type) {
+		case SERIAL_IO_MEM:
+#ifdef  SERIAL_IO_MEM32
+		case SERIAL_IO_MEM32:
+#endif
+			kdb_serial.iobase = (unsigned long)(info->iomem_base);
+			kdb_serial.ioreg_shift = info->iomem_reg_shift;
+			break;
+		default:
+			kdb_serial.iobase = state->port;
+			kdb_serial.ioreg_shift = 0;
+			break;
+		}
+	}
+#endif	/* CONFIG_SERIAL_CONSOLE && CONFIG_KDB */
+
 	return 0;
 }
 
diff -uNr linux.orig/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c
--- linux.orig/drivers/sbus/char/sab82532.c	Sat Aug  3 08:39:44 2002
+++ linux/drivers/sbus/char/sab82532.c	Mon Apr  5 15:07:55 2004
@@ -42,6 +42,28 @@
 
 #include "sunserial.h"
 
+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+/*
+ * NOTE: The kernel ignores characters on the serial line unless a user space
+ * program has opened the line first.  To enter kdb before user space has opened
+ * the serial line, you can use the 'kdb=early' flag to lilo and set the
+ * appropriate breakpoints.
+ *
+ * kdb_serial_str[] is the sequence that the user must enter on the serial
+ * console to invoke kdb.  It can be a single character such as "\001"
+ * (control-A) or multiple characters such as "\eKdB".  NOTE: All except the
+ * last character are passed through to the application reading from the serial
+ * console.
+ *
+ * I tried to make the sequence a CONFIG_ option but most of CML1 cannot cope
+ * with '\' in strings, CML2 should be able to do it.  KAO.
+ */
+
+static char kdb_serial_str[] = "\001";
+static char *kdb_serial_ptr = kdb_serial_str;
+#endif	/* CONFIG_KDB */
+
 static DECLARE_TASK_QUEUE(tq_serial);
 
 /* This is (one of many) a special gross hack to allow SU and
@@ -318,8 +340,12 @@
 }
 
 static void receive_chars(struct sab82532 *info,
-			  union sab82532_irq_status *stat)
+			  union sab82532_irq_status *stat,
+			  struct pt_regs *regs)
 {
+#if defined(CONFIG_KDB)
+	int need_kdb = 0;
+#endif
 	struct tty_struct *tty = info->tty;
 	unsigned char buf[32];
 	unsigned char status;
@@ -373,6 +399,18 @@
 			break;
 		}
 
+#if defined(CONFIG_KDB)
+		if (info->is_console && kdb_on) {
+			if (buf[i] == *kdb_serial_ptr) {
+				if (!(*++kdb_serial_ptr)) {
+					need_kdb = 1;
+					kdb_serial_ptr = kdb_serial_str;
+					break;
+				}
+			} else
+				kdb_serial_ptr = kdb_serial_str;
+		}
+#endif	/* CONFIG_KDB */
 		tty->flip.count++;
 		*tty->flip.char_buf_ptr++ = buf[i++];
 		status = buf[i++];
@@ -392,7 +430,10 @@
 		else
 			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 	}
-
+#ifdef CONFIG_KDB
+	if (need_kdb)
+		kdb(KDB_REASON_KEYBOARD, 0, regs);
+#endif
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
@@ -600,7 +641,7 @@
 
 	if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
 				SAB82532_ISR0_RFO | SAB82532_ISR0_RPF))
-		receive_chars(info, &status);
+		receive_chars(info, &status, regs);
 	if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
 	    (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
 		check_status(info, &status);
@@ -625,7 +666,7 @@
 
 	if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
 				SAB82532_ISR0_RFO | SAB82532_ISR0_RPF))
-		receive_chars(info, &status);
+		receive_chars(info, &status, regs);
 	if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
 	    (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
 		check_status(info, &status);
diff -uNr linux.orig/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- linux.orig/drivers/sbus/char/su.c	Sat Aug  3 08:39:44 2002
+++ linux/drivers/sbus/char/su.c	Mon Apr  5 15:07:55 2004
@@ -74,6 +74,30 @@
 #endif
 #include <linux/sysrq.h>
 
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+/*
+ * kdb_serial_line records the serial line number of the first serial console.
+ * NOTE: The kernel ignores characters on the serial line unless a user space
+ * program has opened the line first.  To enter kdb before user space has opened
+ * the serial line, you can use the 'kdb=early' flag to lilo and set the
+ * appropriate breakpoints.
+ *
+ * kdb_serial_str[] is the sequence that the user must enter on the serial
+ * console to invoke kdb.  It can be a single character such as "\001"
+ * (control-A) or multiple characters such as "\eKdB".  NOTE: All except the
+ * last character are passed through to the application reading from the serial
+ * console.
+ *
+ * I tried to make the sequence a CONFIG_ option but most of CML1 cannot cope
+ * with '\' in strings, CML2 should be able to do it.  KAO.
+ */
+
+static int  kdb_serial_line = -1;
+static char kdb_serial_str[] = "\001";
+static char *kdb_serial_ptr = kdb_serial_str;
+#endif	/* CONFIG_KDB */
+
 #include <asm/system.h>
 #include <asm/oplib.h>
 #include <asm/io.h>
@@ -400,6 +424,18 @@
 			saw_console_brk = 1;
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 			break;
+#ifdef	CONFIG_KDB
+		if ((info->line == kdb_serial_line) && kdb_on) {
+		    if (ch == *kdb_serial_ptr) {
+			if (!(*++kdb_serial_ptr)) {
+			    kdb(KDB_REASON_KEYBOARD, 0, regs);
+			    kdb_serial_ptr = kdb_serial_str;
+			    break;
+			}
+		    } else
+			kdb_serial_ptr = kdb_serial_str;
+		}
+#endif	/* CONFIG_KDB */
 		*tty->flip.char_buf_ptr = ch;
 		icount->rx++;
 
@@ -2972,6 +3008,16 @@
 
 	info->is_console = 1;
 
+#ifdef	CONFIG_KDB
+	/*
+	 * Remember the line number of the first serial
+	 * console.  We'll make this the kdb serial console too.
+	 */
+	if (kdb_serial_line == -1)
+		kdb_serial_line = co->index;
+	
+#endif	/* CONFIG_KDB */
+
 	return 0;
 }
 
diff -uNr linux.orig/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- linux.orig/drivers/sbus/char/sunkbd.c	Sat Aug  3 08:39:44 2002
+++ linux/drivers/sbus/char/sunkbd.c	Mon Apr  5 15:07:55 2004
@@ -44,6 +44,10 @@
 #include <asm/ebus.h>
 #endif
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif
+
 #include "sunkbd.h"
 
 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
@@ -138,6 +142,9 @@
 
 static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
 	num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
+#ifdef CONFIG_KDB
+	call_kdb,
+#endif
 	SAK, decr_console, incr_console, spawn_console, bare_num;
 
 static void_fnp spec_fn_table[] = {
@@ -145,7 +152,10 @@
 	show_state,	send_intr,	lastcons,	caps_toggle,
 	num,		hold,		scroll_forw,	scroll_back,
 	boot_it,	caps_on,	compose,	SAK,
-	decr_console,	incr_console,	spawn_console,	bare_num
+	decr_console,	incr_console,	spawn_console,	bare_num,
+#ifdef CONFIG_KDB
+	call_kdb
+#endif
 };
 
 /* maximum values each key_handler can handle */
@@ -813,6 +823,13 @@
 {
 }
 
+#ifdef CONFIG_KDB
+static void call_kdb()
+{
+	kdb(KDB_REASON_KEYBOARD, 0, pt_regs);
+}
+#endif
+
 static void do_null()
 {
 	sun_compute_shiftstate();
diff -uNr linux.orig/drivers/sbus/char/sunkeymap.c linux/drivers/sbus/char/sunkeymap.c
--- linux.orig/drivers/sbus/char/sunkeymap.c	Tue Dec 21 14:06:42 1999
+++ linux/drivers/sbus/char/sunkeymap.c	Mon Apr  5 15:07:55 2004
@@ -9,7 +9,13 @@
 u_short plain_map[NR_KEYS] = {
 	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf100,	0xf101,	0xf109,
 	0xf102,	0xf10a,	0xf103,	0xf10b,	0xf104,	0xf701,	0xf105,	0xf200,
-	0xf106,	0xf107,	0xf108,	0xf703,	0xf603,	0xf11d,	0xf200,	0xf209,
+	0xf106,	0xf107,	0xf108,	0xf703,	0xf603,
+#ifdef CONFIG_KDB
+	/* Pause (keycode 0x15) triggers kdb */ 0xf214,
+#else
+						0xf11d,
+#endif
+							0xf200,	0xf209,
 	0xf601,	0xf200,	0xf200,	0xf600,	0xf602,	0xf01b,	0xf031,	0xf032,
 	0xf033,	0xf034,	0xf035,	0xf036,	0xf037,	0xf038,	0xf039,	0xf030,
 	0xf02d,	0xf03d,	0xf060,	0xf07f,	0xf115,	0xf03d,	0xf30d,	0xf30c,
diff -uNr linux.orig/drivers/usb/hid-core.c linux/drivers/usb/hid-core.c
--- linux.orig/drivers/usb/hid-core.c	Mon Apr  5 15:02:43 2004
+++ linux/drivers/usb/hid-core.c	Mon Apr  5 15:07:55 2004
@@ -57,6 +57,26 @@
 #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>"
 #define DRIVER_DESC "USB HID support drivers"
 
+#if defined(CONFIG_KDB_USB)
+#include <linux/kdb.h>
+extern struct kdb_usb_exchange kdb_usb_infos;
+struct hid_device *hid_kbd = NULL;
+
+/* kdb_usb_hid_reset_timer
+ * This function reset the timer in the input_dev structure
+ * If you don't do that you'll be unable to exit KDB in the case 
+ * you've entered by pressing the Pause key
+ */
+void hid_reset_timer(void)
+{
+  if(hid_kbd->input.timer.list.next) {
+    (hid_kbd->input.timer.list.next)->prev = hid_kbd->input.timer.list.prev;
+    (hid_kbd->input.timer.list.prev)->next = hid_kbd->input.timer.list.next;
+    hid_kbd->input.timer.list.prev = hid_kbd->input.timer.list.next = NULL;
+  }
+}
+#endif /* CONFIG_KDB_USB */
+
 static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
 				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
 
@@ -1309,7 +1329,16 @@
 	printk(": USB HID v%x.%02x %s [%s] on usb%d:%d.%d\n",
 		hid->version >> 8, hid->version & 0xff, c, hid->name,
 		dev->bus->busnum, dev->devnum, ifnum);
-
+#if defined(CONFIG_KDB_USB)
+	/* Initialisation of the KDB structure */
+	if (!strcmp(c, "Keyboard")) {
+	        hid_kbd = hid;
+	        kdb_usb_infos.urb = &hid->urb;
+	        kdb_usb_infos.buffer = &hid->buffer[0];
+	        kdb_usb_infos.reset_timer = hid_reset_timer;
+	        kdb_usb_infos.driver = HID_ACTIVE;
+	}
+#endif
 	return hid;
 }
 
diff -uNr linux.orig/drivers/usb/host/usb-uhci.c linux/drivers/usb/host/usb-uhci.c
--- linux.orig/drivers/usb/host/usb-uhci.c	Fri Jun 13 22:51:36 2003
+++ linux/drivers/usb/host/usb-uhci.c	Mon Apr  5 15:07:55 2004
@@ -40,7 +40,10 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-
+#if defined(CONFIG_KDB_USB)
+#include <linux/kdb.h>
+extern struct kdb_usb_exchange kdb_usb_infos;
+#endif
 /* This enables more detailed sanity checks in submit_iso */
 //#define ISO_SANITY_CHECK
 
@@ -134,7 +137,6 @@
 /* used by userspace UHCI data structure dumper */
 uhci_t **uhci_devices = &devs;
 
-/*-------------------------------------------------------------------*/
 // Cleans up collected QHs, but not more than 100 in one go
 void clean_descs(uhci_t *s, int force)
 {
@@ -2917,6 +2919,112 @@
 }
 #endif
 
+/* ------------------------------------------------------------------ */
+/* KDB part */
+
+#if defined(CONFIG_KDB_USB)
+/* 
+* The part of the code of UHCI controller that
+* process the interrupt transfer
+*/
+
+void uhci_process_kdb_interrupt (uhci_t *s, struct urb *urb)
+{	
+	int i;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	struct list_head *p = urb_priv->desc_list.next;
+	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
+  
+	int actual_length;
+	int status = 0;
+  
+	for (i = 0; p != &urb_priv->desc_list; p = p->next, i++)	// Maybe we allow more than one TD later ;-)
+	{
+      		desc = list_entry (p, uhci_desc_t, desc_list);
+      
+      		if (is_td_active(desc)) {
+			// do not process active TDs
+			//dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status));
+			break;
+      		}
+      
+      		if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) {
+			// do not process one-shot TDs, no recycling
+			break;
+      		}
+      		// extract transfer parameters from TD
+      
+      		actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status));
+      		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
+      
+     	 	// see if EP is stalled
+      		if (status == -EPIPE) {
+			// set up stalled condition
+			usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+      		}
+      
+      		// if any error occurred: ignore this td, and continue
+      		if (status != 0) {
+			//uhci_show_td (desc);
+			urb->error_count++;
+			goto recycle;
+      		}
+      		else
+			urb->actual_length = actual_length;
+      
+recycle:
+      		uhci_urb_dma_sync(s, urb, urb->hcpriv);
+      
+      		if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) &&
+		    (urb->status != -ENOENT)) {
+	
+			urb->status = -EINPROGRESS;
+	
+			// Recycle INT-TD if interval!=0, else mark TD as one-shot
+			if (urb->interval) {
+	  
+	  			desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE));
+	  			if (status==0) {
+	    				desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+							    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
+	    				usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+	  			} else {
+	    				desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+							     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
+	  			}
+	  			desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
+								(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27));
+	  			mb();
+			} else {
+	  			uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
+					// correct toggle after unlink
+	  			usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+	  			clr_td_ioc(desc); // inactivate TD
+			}
+    	}
+   	}
+}
+
+/* uhci_kdb_poll
+ * This function is a minimalist version of the 
+ * controller interrupt handler
+ */
+void uhci_kdb_poll (void *__uhci, struct urb *urb)
+{
+	uhci_t *s = __uhci;
+
+	/* Reset input timer to be able to quit KDB */
+	(*kdb_usb_infos.reset_timer)();
+
+	s->unlink_urb_done=0;
+	uhci_process_kdb_interrupt (s, urb);
+
+	clean_descs(s, CLEAN_NOT_FORCED);
+	uhci_cleanup_unlink(s, CLEAN_NOT_FORCED);
+	uhci_switch_timer_int(s);
+}
+#endif
+/*-------------------------------------------------------------------*/
 _static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
 {
 	uhci_t *s;
@@ -2936,6 +3044,10 @@
 		return -1;
 
 	memset (s, 0, sizeof (uhci_t));
+#if defined(CONFIG_KDB_USB)
+	kdb_usb_infos.uhci = (void *)s;
+	kdb_usb_infos.poll_func = uhci_kdb_poll;
+#endif
 	INIT_LIST_HEAD (&s->free_desc);
 	INIT_LIST_HEAD (&s->urb_list);
 	INIT_LIST_HEAD (&s->urb_unlinked);
diff -uNr linux.orig/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- linux.orig/drivers/usb/usbkbd.c	Fri Jun 13 22:51:37 2003
+++ linux/drivers/usb/usbkbd.c	Mon Apr  5 15:07:55 2004
@@ -77,6 +77,28 @@
 	int open;
 };
 
+
+#if defined(CONFIG_KDB_USB)
+#include <linux/kdb.h>
+static struct usb_kbd *usb_kbd_ptr = NULL;
+extern struct kdb_usb_exchange kdb_usb_infos;
+
+/* usb_kbd_reset_timer
+ * This function reset the timer in the input_dev structure
+ * If you don't do that you'll be unable to exit KDB in the case 
+ * you've entered by pressing the Pause key
+ */
+
+void usb_kbd_reset_timer(void)
+{
+	if(usb_kbd_ptr->dev.timer.list.next) {
+	       (usb_kbd_ptr->dev.timer.list.next)->prev = usb_kbd_ptr->dev.timer.list.prev;
+	       (usb_kbd_ptr->dev.timer.list.prev)->next = usb_kbd_ptr->dev.timer.list.next;
+	       usb_kbd_ptr->dev.timer.list.prev = usb_kbd_ptr->dev.timer.list.next = NULL;
+	}
+}
+#endif /* CONFIG_KDB_USB */
+
 static void usb_kbd_irq(struct urb *urb)
 {
 	struct usb_kbd *kbd = urb->context;
@@ -214,6 +236,14 @@
 
 	FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
 		usb_kbd_irq, kbd, endpoint->bInterval);
+#if defined(CONFIG_KDB_USB)
+	/* Init the KDB structure */
+	usb_kbd_ptr = kbd;
+	kdb_usb_infos.urb = &kbd->irq;
+	kdb_usb_infos.buffer = &kbd->new[0];
+	kdb_usb_infos.reset_timer = usb_kbd_reset_timer;
+	kdb_usb_infos.driver = USB_KBD_ACTIVE;
+#endif /* CONFIG_KDB_USB */
 
 	kbd->dr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
 	kbd->dr.bRequest = USB_REQ_SET_REPORT;
diff -uNr linux.orig/include/asm-arm/kdb.h linux/include/asm-arm/kdb.h
--- linux.orig/include/asm-arm/kdb.h	Thu Jan  1 08:00:00 1970
+++ linux/include/asm-arm/kdb.h	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,162 @@
+#ifndef _ASM_KDB_H
+#define _ASM_KDB_H
+
+/*
+ * Kernel Debugger Architecture Dependent Global Headers
+ *
+ * Copyright (C) 1999-2002 Silicon Graphics, Inc.  All Rights Reserved
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+/*
+ * Updated for Xscale (R) architecture support 
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+	/*
+	 * KDB_ENTER() is a macro which causes entry into the kernel
+	 * debugger from any point in the kernel code stream.  If it
+	 * is intended to be used from interrupt level, it must use
+	 * a non-maskable entry method.
+	 */
+#define KDB_BREAK_BREAK 0x0000		/* BKPT 0 kdb breakpoint in kernel */
+#define KDB_BREAK_ENTER 0x0001		/* BKPT 1 for KDB_ENTER() */
+#define KDB_ENTER2(b)	do { if (kdb_on && !KDB_IS_RUNNING()) asm("\tBKPT "#b"\n"); } while (0);
+#define KDB_ENTER1(b)	KDB_ENTER2(b)
+#define KDB_ENTER()	KDB_ENTER1(KDB_BREAK_ENTER)
+
+	/*
+	 * Needed for exported symbols.
+	 */
+typedef unsigned long kdb_machreg_t;
+
+#define kdb_machreg_fmt		"0x%lx"
+#define kdb_machreg_fmt0	"0x%08lx"
+#define kdb_bfd_vma_fmt		"0x%lx"
+#define kdb_bfd_vma_fmt0	"0x%08lx"
+#define kdb_elfw_addr_fmt	"0x%x"
+#define kdb_elfw_addr_fmt0	"0x%08x"
+
+	/*
+	 * Per cpu arch specific kdb state.  Must be in range 0xff000000.
+	 */
+#define KDB_STATE_A_XSC_ICH	0x01000000	/* XScale IRQ status changed */
+#define KDB_STATE_A_XSC_IRQ	0x02000000	/* Use to save XScale I_BIT */
+
+	/*
+	 * Functions to safely read and write kernel areas.  The {to,from}_xxx
+	 * addresses are not necessarily valid, these functions must check for
+	 * validity.  If the arch already supports get and put routines with
+	 * suitable validation and/or recovery on invalid addresses then use
+	 * those routines, otherwise check it yourself.
+	 */
+
+	/*
+	 * __kdba_copy_to_user will relies on MMU to
+	 * trap invalid addresses in the from_xxx/to fields.
+	 */
+
+#include <asm/uaccess.h>
+
+unsigned long __kdba_copy_to_user(void *to, const void *from, unsigned long n);
+
+extern int kdb_getuserarea_size(void *, unsigned long, size_t);
+extern int kdb_putuserarea_size(unsigned long, void *, size_t);
+
+static inline int
+__kdba_putarea_size(unsigned long to_xxx, void *from, size_t size)
+{
+	mm_segment_t oldfs = get_fs();
+	int r;
+	char c;
+	c = *((volatile char *)from);
+	c = *((volatile char *)from + size - 1);
+      
+	if (to_xxx < PAGE_OFFSET) {
+		return kdb_putuserarea_size(to_xxx, from, size);
+	}
+
+#ifdef VPERNODE_BASE /* if present, the new CONFIG_NUMA code */
+	if (to_xxx >= VPERNODE_BASE && to_xxx < VGLOBAL_BASE) {
+		to_xxx = __imva(to_xxx);
+	}
+#endif
+	set_fs(KERNEL_DS);
+	r = __kdba_copy_to_user((void *)to_xxx, from, size);
+	set_fs(oldfs);
+	return r;
+}
+
+static inline int
+__kdba_getarea_size(void *to, unsigned long from_xxx, size_t size)
+{
+	mm_segment_t oldfs = get_fs();
+	int r;
+	*((volatile char *)to) = '\0';
+	*((volatile char *)to + size - 1) = '\0';
+
+	if (from_xxx < PAGE_OFFSET) {
+		return kdb_getuserarea_size(to, from_xxx, size);
+	}
+
+	set_fs(KERNEL_DS);
+	switch (size) {
+	case 1:
+		r = __kdba_copy_to_user(to, (void *)from_xxx, 1);
+		break;
+	case 2:
+		r = __kdba_copy_to_user(to, (void *)from_xxx, 2);
+		break;
+	case 4:
+		r = __kdba_copy_to_user(to, (void *)from_xxx, 4);
+		break;
+	case 8:
+		r = __kdba_copy_to_user(to, (void *)from_xxx, 8);
+		break;
+	default:
+		r = __kdba_copy_to_user(to, (void *)from_xxx, size);
+		break;
+	}
+	set_fs(oldfs);
+	return r;
+}
+
+#define kdba_putarea_size __kdba_putarea_size
+#define kdba_getarea_size __kdba_getarea_size
+
+static inline int
+kdba_verify_rw(unsigned long addr, size_t size)
+{
+	unsigned char data[size];
+	return(kdba_getarea_size(data, addr, size) || kdba_putarea_size(addr, data, size));
+}
+
+#endif	/* !_ASM_KDB_H */
diff -uNr linux.orig/include/asm-arm/kdbprivate.h linux/include/asm-arm/kdbprivate.h
--- linux.orig/include/asm-arm/kdbprivate.h	Thu Jan  1 08:00:00 1970
+++ linux/include/asm-arm/kdbprivate.h	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,317 @@
+#ifndef _ASM_KDBPRIVATE_H
+#define _ASM_KDBPRIVATE_H
+
+/*
+ * Kernel Debugger Architecture Dependent Private Headers
+ *
+ * Copyright (C) 1999-2002 Silicon Graphics, Inc.  All Rights Reserved
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+/*
+ * Updated for Xscale (R) architecture support 
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+/* Definition of an machine instruction.
+ * Takes care of VLIW processors like Itanium
+ */
+
+typedef struct {
+	unsigned long inst[1];
+	} kdb_machinst_t;
+
+	/*
+	 * KDB_MAXBPT describes the total number of breakpoints
+	 * supported by this architecure.
+	 */
+#define KDB_MAXBPT	16
+
+	/*
+	 * KDB_MAXHARDBPT describes the total number of hardware
+	 * breakpoint registers that exist.
+	 */
+#define KDB_NUM_IBCR	 2
+#define KDB_NUM_DBR	 2
+#define KDB_MAXHARDBPT	 (KDB_NUM_IBCR+KDB_NUM_DBR)
+
+	/*
+	 * Platform specific environment entries
+	 */
+#define KDB_PLATFORM_ENV	"IDMODE=XScale", "BYTESPERWORD=4", "IDCOUNT=16"
+
+	/*
+	 * Define the direction that the stack grows
+	 */
+#define KDB_STACK_DIRECTION	(-1)	/* Stack grows down */
+	/*
+	 * Support for XScale debug registers
+	 */
+
+typedef struct _kdbhard_bp {
+	kdb_machreg_t	bph_reg;	/* Register this breakpoint uses */
+
+	unsigned int	bph_free:1;	/* Register available for use */
+	unsigned int	bph_b_inst:1;	/* BP type, IBP or not */
+	unsigned int	bph_r_inst:1;	/* Register type, ibcr or dbr */
+	unsigned int	bph_mode:2;	/* valid only in data breakpoint. 
+	                                   0=disabled, 1=WO, 2=RW, 3=RO 
+	                                   refer to DBCON_E_Type */
+} kdbhard_bp_t;
+
+extern kdbhard_bp_t	kdb_hardbreaks[/* KDB_MAXHARDBPT */];
+				        // IBCR first, DBR 2nd
+
+#define getprsregs(regs)        ((struct switch_stack *)regs -1)
+
+extern struct switch_stack *kdb_sw[ /*NR_CPUS*/ ];
+
+/*
+ * Define certain specific instructions
+ */
+#define ARM_BREAK_INSTR           (unsigned long)((INST_AL << 28) | (0x12 << 20) | (7 << 4) | ((KDB_BREAK_BREAK >> 4) << 8) | (KDB_BREAK_BREAK&0xf))
+
+//#define KDB_HAVE_LONGJMP
+#ifdef KDB_HAVE_LONGJMP
+/*
+ * Support for setjmp/longjmp
+ */
+
+
+#define _JBLEN  10
+#define JB_r4    0
+#define JB_r5    1
+#define JB_r6    2
+#define JB_r7    3
+#define JB_r8    4
+#define JB_r9    5
+#define JB_r10   6
+#define JB_r11   7
+#define JB_SP    8
+#define JB_LR    9
+
+typedef struct __kdb_jmp_buf {
+        unsigned long   __jmp_buf[_JBLEN];
+} kdb_jmp_buf;
+
+extern int kdba_setjmp(kdb_jmp_buf *);
+extern void kdba_longjmp(kdb_jmp_buf *, int);
+
+extern kdb_jmp_buf  kdbjmpbuf[];
+#endif	/* KDB_HAVE_LONGJMP */
+
+/* Arch specific data saved for running processes */
+
+struct kdba_running_process {
+	int dummy[0];	/* Everything is in pt_regs for i386 */
+};
+
+static inline
+void kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+}
+
+static inline
+void kdba_unsave_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+}
+
+static inline unsigned int read_xsc_dcsr(void)
+{
+    unsigned int  dcsr;
+    __asm__ volatile ("mrc   p14, 0, %0, c10, c0, 0"
+                           : "=r"(dcsr));
+    return dcsr;
+}
+
+static inline void write_xsc_dcsr(unsigned int dcsr)
+{
+    __asm__ volatile ("mcr p14, 0, %0, c10, c0, 0" 
+                           : :"r"(dcsr));
+}
+
+// nr: IBCRn,  number of n
+static inline void  write_xsc_ibcr(int nr,unsigned int dat) 
+{
+    __asm__ volatile (
+        "movs   %0, %0			\n	\
+	mcreq p15, 0, %1, c14, c8, 0	\n	\
+	mcrne p15, 0, %1, c14, c9, 0"
+	: :"r"(nr),"r"(dat)                 
+	);
+}
+
+static inline unsigned int read_xsc_ibcr(int nr) 
+{
+    unsigned int  ibcr_reg;
+    __asm__ volatile (                  
+        "movs  %1, %1				\n	\
+	mrceq p15, 0, %0, c14, c8, 0		\n	\
+	mrcne p15, 0, %0, c14, c9, 0"       
+	:"=r"(ibcr_reg): "r"(nr)            
+	);
+    return ibcr_reg;
+}
+
+// nr: DBRn,  number of n
+static inline void  write_xsc_dbr(int nr,unsigned int dat) 
+{
+    __asm__ volatile (                  
+        "movs   %0, %0			\n	\
+	mcreq p15, 0, %1, c14, c0, 0	\n	\
+	mcrne p15, 0, %1, c14, c3, 0"       
+	: :"r"(nr),"r"(dat)                 
+	);
+}
+
+
+static inline unsigned int read_xsc_dbr(int nr) 
+{
+    unsigned int  dbr_reg;
+    __asm__ volatile (                  
+        "movs  %0, %0			\n	\
+	mrceq p15, 0, %1, c14, c0, 0	\n	\
+	mrcne p15, 0, %1, c14, c3, 0"       
+	:"=r"(dbr_reg): "r"(nr)             
+	);
+    return dbr_reg;
+}
+
+static inline unsigned int read_xsc_dcon(void) 
+{
+    unsigned int  dcon;
+    __asm__ volatile (
+        "mrc p15, 0, %0, c14, c4, 0"
+	:"=r"(dcon)                         
+	);
+    return dcon;
+}
+
+static inline void write_xsc_dcon(unsigned int dcon) 
+{
+    __asm__ volatile ( 
+        "mcr p15, 0, %0, c14, c4, 0"        
+	::"r"(dcon)                         
+	);
+}
+
+static inline void xsc_get_acc0(unsigned long *acc0_h,unsigned long *acc0_l)
+{
+	__asm__ volatile ("mra   %1, %0, acc0"
+		: "=r"(*acc0_h), "=r"(*acc0_l));
+	*acc0_h &= 0xff;	/* only 8bits valid */
+}
+static inline void xsc_put_acc0(unsigned long acc0_h,unsigned long acc0_l)
+{
+	__asm__ volatile ("mar   acc0, %1, %0"
+		:: "r"(acc0_h), "r"(acc0_l));
+}
+
+/*
+ * return the Big endian/Little endian bit of cp15 control register
+ * 
+ * RETURNS:
+ *	0:  	Little endian
+ *	None 0: Big endian
+ *
+ */
+static inline unsigned int arm_endian_bit(void) 
+{
+    unsigned int  control_reg;
+    __asm__ volatile (
+        "mrc p15, 0, %0, c1, c0, 0"
+	:"=r"(control_reg)                         
+	);
+    return control_reg&(1<<7);
+}
+
+
+
+// bit definition of FSR
+#define     FSR_STATUS_MASK 0xf
+#define     FSR_DOMAIN_MASK (0xf<<4)
+#define     FSR_DBG_BIT     (1<<9)
+
+
+// bit definition of XScale debug unit
+#define     DCSR_GE         (31)
+#define     DCSR_H          (30)
+#define     DCSR_TF         (23)
+#define     DCSR_TI         (22)
+#define     DCSR_TD         (20)
+#define     DCSR_TA         (19)
+#define     DCSR_TS         (18)
+#define     DCSR_TU         (17)
+#define     DCSR_TR         (16)
+#define     DCSR_SA         (5)
+#define     DCSR_MOE        (2)
+#define     DCSR_M          (1)
+#define     DCSR_E          (0)
+
+#define     DCSR_MOE_MASK   (0x7UL<<DCSR_MOE)     // 3 bits
+#define     DCSR_RSV_MASK   ((0x3fUL<<24) | (1UL<<21) | (0x3ffUL <<6))  // bits 29-24, 21, 15-6
+
+#define    MOE_RST         0
+#define    MOE_IBP         1        // Instruction Breakpoint
+#define    MOE_DBP         2        // Data Breakpoint
+#define    MOE_BKPT        3        // BKPT Instruction BP
+#define    MOE_EXT         4        // External Debug Event
+#define    MOE_VTRAP       5        // Vector Trap Occured
+#define    MOE_TRACE       6        // Trace Buffer Full Break
+#define    MOE_RSV         7        // reserved
+
+
+// bit definition of XScale debug unit DBCON
+#define     DBCON_E0        (0)
+#define     DBCON_E1        (2)
+#define     DBCON_M         (8)
+
+typedef     enum _DBCON_E_Type {
+    DBR_DISABLE=0,
+    DBR_STORE_BRK=1,
+    DBR_ACCESS_BRK=2,
+    DBR_LOAD_BRK=3
+} DBCON_E_Type;
+
+
+#define     SS_IBCRN            1       // use IBCR1 for SW single step and one after BP
+#define     IBCR_EN_MSK         1       // bit 0 of IBCRn
+struct frame_info;
+extern void kdba_get_next_fi(struct frame_info *fi);
+extern int kdba_get_fi_reg (struct frame_info *fi, int reg_num, kdb_machreg_t *reg_value);
+extern void arm_scan_prologue (struct frame_info *fi);
+extern void print_fi(struct frame_info *fi, char *str);
+extern int kdba_arm_prologue(kdb_symtab_t *symtab,struct frame_info *fi, kdb_machreg_t ss);
+extern void kdba_restore_retirq(struct pt_regs *regs, int irq_status);
+extern int kdba_disable_retirq(struct pt_regs *regs);
+extern int  is_branch(unsigned long opcode);
+extern void do_debug(struct pt_regs *regs);
+#endif	/* !_ASM_KDBPRIVATE_H */
diff -uNr linux.orig/include/linux/dis-asm.h linux/include/linux/dis-asm.h
--- linux.orig/include/linux/dis-asm.h	Thu Jan  1 08:00:00 1970
+++ linux/include/linux/dis-asm.h	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,307 @@
+/* Interface between the opcode library and its callers.
+   Written by Cygnus Support, 1993.
+
+   The opcode library (libopcodes.a) provides instruction decoders for
+   a large variety of instruction sets, callable with an identical
+   interface, for making instruction-processing programs more independent
+   of the instruction set being processed.  */
+
+/* Hacked by Scott Lurndal at SGI (02/1999) for linux kernel debugger */
+/* Upgraded to cygnus CVS Keith Owens <kaos@sgi.com> 30 Oct 2000 */
+
+#ifndef DIS_ASM_H
+#define DIS_ASM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	/*
+	 * Misc definitions
+	 */
+#ifndef PARAMS
+#define PARAMS(x)	x
+#endif
+#define PTR void *
+#define FILE int
+#if !defined(NULL)
+#define NULL 0
+#endif
+
+#define abort()		dis_abort(__LINE__)
+
+static inline void
+dis_abort(int line)
+{
+	panic("Aborting disassembler @ line %d\n", line);
+}
+
+#include <linux/slab.h>
+#include <asm/page.h>
+#define xstrdup(string) ({ char *res = kdb_strdup(string, GFP_ATOMIC); if (!res) BUG(); res; })
+#define xmalloc(size) ({ void *res = kmalloc(size, GFP_ATOMIC); if (!res) BUG(); res; })
+#define free(address) kfree(address)
+
+#include <bfd.h>
+
+typedef int (*fprintf_ftype) PARAMS((PTR, const char*, ...));
+
+enum dis_insn_type {
+  dis_noninsn,			/* Not a valid instruction */
+  dis_nonbranch,		/* Not a branch instruction */
+  dis_branch,			/* Unconditional branch */
+  dis_condbranch,		/* Conditional branch */
+  dis_jsr,			/* Jump to subroutine */
+  dis_condjsr,			/* Conditional jump to subroutine */
+  dis_dref,			/* Data reference instruction */
+  dis_dref2			/* Two data references in instruction */
+};
+
+/* This struct is passed into the instruction decoding routine, 
+   and is passed back out into each callback.  The various fields are used
+   for conveying information from your main routine into your callbacks,
+   for passing information into the instruction decoders (such as the
+   addresses of the callback functions), or for passing information
+   back from the instruction decoders to their callers.
+
+   It must be initialized before it is first passed; this can be done
+   by hand, or using one of the initialization macros below.  */
+
+typedef struct disassemble_info {
+  fprintf_ftype fprintf_func;
+  fprintf_ftype fprintf_dummy;
+  PTR stream;
+  PTR application_data;
+
+  /* Target description.  We could replace this with a pointer to the bfd,
+     but that would require one.  There currently isn't any such requirement
+     so to avoid introducing one we record these explicitly.  */
+  /* The bfd_flavour.  This can be bfd_target_unknown_flavour.  */
+  enum bfd_flavour flavour;
+  /* The bfd_arch value.  */
+  enum bfd_architecture arch;
+  /* The bfd_mach value.  */
+  unsigned long mach;
+  /* Endianness (for bi-endian cpus).  Mono-endian cpus can ignore this.  */
+  enum bfd_endian endian;
+
+  /* An array of pointers to symbols either at the location being disassembled
+     or at the start of the function being disassembled.  The array is sorted
+     so that the first symbol is intended to be the one used.  The others are
+     present for any misc. purposes.  This is not set reliably, but if it is
+     not NULL, it is correct.  */
+  asymbol **symbols;
+  /* Number of symbols in array.  */
+  int num_symbols;
+
+  /* For use by the disassembler.
+     The top 16 bits are reserved for public use (and are documented here).
+     The bottom 16 bits are for the internal use of the disassembler.  */
+  unsigned long flags;
+#define INSN_HAS_RELOC	0x80000000
+  PTR private_data;
+
+  /* Function used to get bytes to disassemble.  MEMADDR is the
+     address of the stuff to be disassembled, MYADDR is the address to
+     put the bytes in, and LENGTH is the number of bytes to read.
+     INFO is a pointer to this struct.
+     Returns an errno value or 0 for success.  */
+  int (*read_memory_func)
+    PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
+	     struct disassemble_info *info));
+
+  /* Function which should be called if we get an error that we can't
+     recover from.  STATUS is the errno value from read_memory_func and
+     MEMADDR is the address that we were trying to read.  INFO is a
+     pointer to this struct.  */
+  void (*memory_error_func)
+    PARAMS ((int status, bfd_vma memaddr, struct disassemble_info *info));
+
+  /* Function called to print ADDR.  */
+  void (*print_address_func)
+    PARAMS ((bfd_vma addr, struct disassemble_info *info));
+
+  /* Function called to determine if there is a symbol at the given ADDR.
+     If there is, the function returns 1, otherwise it returns 0.
+     This is used by ports which support an overlay manager where
+     the overlay number is held in the top part of an address.  In
+     some circumstances we want to include the overlay number in the
+     address, (normally because there is a symbol associated with
+     that address), but sometimes we want to mask out the overlay bits.  */
+  int (* symbol_at_address_func)
+    PARAMS ((bfd_vma addr, struct disassemble_info * info));
+
+  /* These are for buffer_read_memory.  */
+  bfd_byte *buffer;
+  bfd_vma buffer_vma;
+  unsigned int buffer_length;
+
+  /* This variable may be set by the instruction decoder.  It suggests
+      the number of bytes objdump should display on a single line.  If
+      the instruction decoder sets this, it should always set it to
+      the same value in order to get reasonable looking output.  */
+  int bytes_per_line;
+
+  /* the next two variables control the way objdump displays the raw data */
+  /* For example, if bytes_per_line is 8 and bytes_per_chunk is 4, the */
+  /* output will look like this:
+     00:   00000000 00000000
+     with the chunks displayed according to "display_endian". */
+  int bytes_per_chunk;
+  enum bfd_endian display_endian;
+
+  /* Number of octets per incremented target address 
+     Normally one, but some DSPs have byte sizes of 16 or 32 bits
+   */
+  unsigned int octets_per_byte;
+
+  /* Results from instruction decoders.  Not all decoders yet support
+     this information.  This info is set each time an instruction is
+     decoded, and is only valid for the last such instruction.
+
+     To determine whether this decoder supports this information, set
+     insn_info_valid to 0, decode an instruction, then check it.  */
+
+  char insn_info_valid;		/* Branch info has been set. */
+  char branch_delay_insns;	/* How many sequential insn's will run before
+				   a branch takes effect.  (0 = normal) */
+  char data_size;		/* Size of data reference in insn, in bytes */
+  enum dis_insn_type insn_type;	/* Type of instruction */
+  bfd_vma target;		/* Target address of branch or dref, if known;
+				   zero if unknown.  */
+  bfd_vma target2;		/* Second target address for dref2 */
+
+  /* Command line options specific to the target disassembler.  */
+  char * disassembler_options;
+
+} disassemble_info;
+
+
+/* Standard disassemblers.  Disassemble one instruction at the given
+   target address.  Return number of bytes processed.  */
+typedef int (*disassembler_ftype)
+     PARAMS((bfd_vma, disassemble_info *));
+
+extern int print_insn_big_mips		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_mips	PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i386_att		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i386_intel	PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_ia64		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i370		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m68hc11		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m68hc12		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m68k		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_z8001		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_z8002		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8300		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8300h		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8300s		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8500		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_alpha		PARAMS ((bfd_vma, disassemble_info*));
+extern disassembler_ftype arc_get_disassembler PARAMS ((int, int));
+extern int print_insn_big_arm		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_arm	PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_sparc		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_big_a29k		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_a29k	PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i860		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i960		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_sh		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_shl		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_hppa		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_fr30		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m32r		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m88k		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_mcore		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_mn10200		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_mn10300		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_ns32k		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_big_powerpc	PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_powerpc	PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_rs6000		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_w65		PARAMS ((bfd_vma, disassemble_info*));
+extern disassembler_ftype cris_get_disassembler PARAMS ((bfd *));
+extern int print_insn_d10v		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_d30v		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_v850		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_tic30		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_vax		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_tic54x		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_tic80		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_pj		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_avr		PARAMS ((bfd_vma, disassemble_info*));
+
+extern void print_arm_disassembler_options PARAMS ((FILE *));
+extern void parse_arm_disassembler_option  PARAMS ((char *));
+extern int  get_arm_regname_num_options    PARAMS ((void));
+extern int  set_arm_regname_option         PARAMS ((int));
+extern int  get_arm_regnames               PARAMS ((int, const char **, const char **, const char ***));
+
+/* Fetch the disassembler for a given BFD, if that support is available.  */
+extern disassembler_ftype disassembler	PARAMS ((bfd *));
+
+/* Document any target specific options available from the disassembler.  */
+extern void disassembler_usage          PARAMS ((FILE *));
+
+
+/* This block of definitions is for particular callers who read instructions
+   into a buffer before calling the instruction decoder.  */
+
+/* Here is a function which callers may wish to use for read_memory_func.
+   It gets bytes from a buffer.  */
+extern int buffer_read_memory
+  PARAMS ((bfd_vma, bfd_byte *, unsigned int, struct disassemble_info *));
+
+/* This function goes with buffer_read_memory.
+   It prints a message using info->fprintf_func and info->stream.  */
+extern void perror_memory PARAMS ((int, bfd_vma, struct disassemble_info *));
+
+
+/* Just print the address in hex.  This is included for completeness even
+   though both GDB and objdump provide their own (to print symbolic
+   addresses).  */
+extern void generic_print_address
+  PARAMS ((bfd_vma, struct disassemble_info *));
+
+/* Always true.  */
+extern int generic_symbol_at_address
+  PARAMS ((bfd_vma, struct disassemble_info *));
+
+/* Macro to initialize a disassemble_info struct.  This should be called
+   by all applications creating such a struct.  */
+#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \
+  (INFO).flavour = bfd_target_unknown_flavour, \
+  (INFO).arch = bfd_arch_unknown, \
+  (INFO).mach = 0, \
+  (INFO).endian = BFD_ENDIAN_UNKNOWN, \
+  (INFO).octets_per_byte = 1, \
+  INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC)
+
+/* Call this macro to initialize only the internal variables for the
+   disassembler.  Architecture dependent things such as byte order, or machine
+   variant are not touched by this macro.  This makes things much easier for
+   GDB which must initialize these things separately.  */
+
+#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \
+  (INFO).fprintf_func = (fprintf_ftype)(FPRINTF_FUNC), \
+  (INFO).stream = (PTR)(STREAM), \
+  (INFO).symbols = NULL, \
+  (INFO).num_symbols = 0, \
+  (INFO).buffer = NULL, \
+  (INFO).buffer_vma = 0, \
+  (INFO).buffer_length = 0, \
+  (INFO).read_memory_func = buffer_read_memory, \
+  (INFO).memory_error_func = perror_memory, \
+  (INFO).print_address_func = generic_print_address, \
+  (INFO).symbol_at_address_func = generic_symbol_at_address, \
+  (INFO).flags = 0, \
+  (INFO).bytes_per_line = 0, \
+  (INFO).bytes_per_chunk = 0, \
+  (INFO).display_endian = BFD_ENDIAN_UNKNOWN, \
+  (INFO).insn_info_valid = 0
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* ! defined (DIS_ASM_H) */
diff -uNr linux.orig/include/linux/kallsyms.h linux/include/linux/kallsyms.h
--- linux.orig/include/linux/kallsyms.h	Thu Jan  1 08:00:00 1970
+++ linux/include/linux/kallsyms.h	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,169 @@
+/* kallsyms headers
+   Copyright 2000 Keith Owens <kaos@ocs.com.au>
+
+   This file is part of the Linux modutils.  It is exported to kernel
+   space so debuggers can access the kallsyms data.
+
+   The kallsyms data contains all the non-stack symbols from a kernel
+   or a module.  The kernel symbols are held between __start___kallsyms
+   and __stop___kallsyms.  The symbols for a module are accessed via
+   the struct module chain which is based at module_list.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef MODUTILS_KALLSYMS_H
+#define MODUTILS_KALLSYMS_H 1
+
+/* Have to (re)define these ElfW entries here because external kallsyms
+ * code does not have access to modutils/include/obj.h.  This code is
+ * included from user spaces tools (modutils) and kernel, they need
+ * different includes.
+ */
+
+#ifndef ELFCLASS32
+#ifdef __KERNEL__
+#include <linux/elf.h>
+#else	/* __KERNEL__ */
+#include <elf.h>
+#endif	/* __KERNEL__ */
+#endif	/* ELFCLASS32 */
+
+#ifndef ELFCLASSM
+#define ELFCLASSM ELF_CLASS
+#endif
+
+#ifndef ElfW
+# if ELFCLASSM == ELFCLASS32
+#  define ElfW(x)  Elf32_ ## x
+#  define ELFW(x)  ELF32_ ## x
+# else
+#  define ElfW(x)  Elf64_ ## x
+#  define ELFW(x)  ELF64_ ## x
+# endif
+#endif
+
+/* Format of data in the kallsyms section.
+ * Most of the fields are small numbers but the total size and all
+ * offsets can be large so use the 32/64 bit types for these fields.
+ *
+ * Do not use sizeof() on these structures, modutils may be using extra
+ * fields.  Instead use the size fields in the header to access the
+ * other bits of data.
+ */  
+
+struct kallsyms_header {
+	int		size;		/* Size of this header */
+	ElfW(Word)	total_size;	/* Total size of kallsyms data */
+	int		sections;	/* Number of section entries */
+	ElfW(Off)	section_off;	/* Offset to first section entry */
+	int		section_size;	/* Size of one section entry */
+	int		symbols;	/* Number of symbol entries */
+	ElfW(Off)	symbol_off;	/* Offset to first symbol entry */
+	int		symbol_size;	/* Size of one symbol entry */
+	ElfW(Off)	string_off;	/* Offset to first string */
+	ElfW(Addr)	start;		/* Start address of first section */
+	ElfW(Addr)	end;		/* End address of last section */
+};
+
+struct kallsyms_section {
+	ElfW(Addr)	start;		/* Start address of section */
+	ElfW(Word)	size;		/* Size of this section */
+	ElfW(Off)	name_off;	/* Offset to section name */
+	ElfW(Word)	flags;		/* Flags from section */
+};
+
+struct kallsyms_symbol {
+	ElfW(Off)	section_off;	/* Offset to section that owns this symbol */
+	ElfW(Addr)	symbol_addr;	/* Address of symbol */
+	ElfW(Off)	name_off;	/* Offset to symbol name */
+};
+
+#define KALLSYMS_SEC_NAME "__kallsyms"
+#define KALLSYMS_IDX 2			/* obj_kallsyms creates kallsyms as section 2 */
+
+#define kallsyms_next_sec(h,s) \
+	((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size))
+#define kallsyms_next_sym(h,s) \
+	((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size))
+
+#ifdef CONFIG_KALLSYMS
+
+int kallsyms_symbol_to_address(
+	const char       *name,			/* Name to lookup */
+	unsigned long    *token,		/* Which module to start with */
+	const char      **mod_name,		/* Set to module name or "kernel" */
+	unsigned long    *mod_start,		/* Set to start address of module */
+	unsigned long    *mod_end,		/* Set to end address of module */
+	const char      **sec_name,		/* Set to section name */
+	unsigned long    *sec_start,		/* Set to start address of section */
+	unsigned long    *sec_end,		/* Set to end address of section */
+	const char      **sym_name,		/* Set to full symbol name */
+	unsigned long    *sym_start,		/* Set to start address of symbol */
+	unsigned long    *sym_end		/* Set to end address of symbol */
+	);
+
+int kallsyms_address_to_symbol(
+	unsigned long     address,		/* Address to lookup */
+	const char      **mod_name,		/* Set to module name */
+	unsigned long    *mod_start,		/* Set to start address of module */
+	unsigned long    *mod_end,		/* Set to end address of module */
+	const char      **sec_name,		/* Set to section name */
+	unsigned long    *sec_start,		/* Set to start address of section */
+	unsigned long    *sec_end,		/* Set to end address of section */
+	const char      **sym_name,		/* Set to full symbol name */
+	unsigned long    *sym_start,		/* Set to start address of symbol */
+	unsigned long    *sym_end		/* Set to end address of symbol */
+	);
+
+int kallsyms_sections(void *token,
+		      int (*callback)(void *,	/* token */
+		      	const char *,		/* module name */
+			const char *,		/* section name */
+			ElfW(Addr),		/* Section start */
+			ElfW(Addr),		/* Section end */
+			ElfW(Word)		/* Section flags */
+		      )
+		);
+
+#else
+
+static inline int kallsyms_address_to_symbol(
+	unsigned long     address,		/* Address to lookup */
+	const char      **mod_name,		/* Set to module name */
+	unsigned long    *mod_start,		/* Set to start address of module */
+	unsigned long    *mod_end,		/* Set to end address of module */
+	const char      **sec_name,		/* Set to section name */
+	unsigned long    *sec_start,		/* Set to start address of section */
+	unsigned long    *sec_end,		/* Set to end address of section */
+	const char      **sym_name,		/* Set to full symbol name */
+	unsigned long    *sym_start,		/* Set to start address of symbol */
+	unsigned long    *sym_end		/* Set to end address of symbol */
+	)
+{
+	return -ESRCH;
+}
+
+#endif
+
+int kallsyms_symbol_complete(
+	char	 *prefix_name	/* Prefix of a symbol name to lookup */
+	);
+int kallsyms_symbol_next(
+	char	 *prefix_name,	/* Prefix of a symbol name to lookup */
+	int flag			/* Indicate if search from the head */
+	);
+
+#endif /* kallsyms.h */
diff -uNr linux.orig/include/linux/kdb.h linux/include/linux/kdb.h
--- linux.orig/include/linux/kdb.h	Thu Jan  1 08:00:00 1970
+++ linux/include/linux/kdb.h	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,337 @@
+#ifndef _KDB_H
+#define _KDB_H
+
+/*
+ * Kernel Debugger Architecture Independent Global Headers
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <asm/kdb.h>
+
+#define KDB_MAJOR_VERSION	4
+#define KDB_MINOR_VERSION	3
+#define KDB_TEST_VERSION	""
+
+	/*
+	 * kdb_initial_cpu is initialized to -1, and is set to the cpu
+	 * number whenever the kernel debugger is entered.
+	 */
+extern volatile int kdb_initial_cpu;	
+#ifdef	CONFIG_KDB
+#define KDB_IS_RUNNING() (kdb_initial_cpu != -1)
+#else
+#define KDB_IS_RUNNING() (0)
+#endif	/* CONFIG_KDB */
+
+	/*
+	 * kdb_on
+	 *
+	 * 	Defines whether kdb is on or not.  Default value
+	 *	is set by CONFIG_KDB_OFF.  Boot with kdb=on/off
+	 *	or echo "[01]" > /proc/sys/kernel/kdb to change it.
+	 */
+extern int kdb_on;
+
+	/* Global 'enter the debugger' variable tested by scheduler, spinlocks
+	 * etc., to handle problems when interrupts are not working or are not
+	 * safe.
+	 */
+extern volatile int kdb_enter_debugger;
+
+#ifdef	CONFIG_SERIAL_CONSOLE
+	/*
+	 * kdb_serial.iobase is initialized to zero, and is set to the I/O
+	 * address of the serial port when the console is setup in
+	 * serial_console_setup.
+	 */
+extern struct kdb_serial {
+	int io_type;
+	unsigned long iobase;
+	unsigned long ioreg_shift;
+} kdb_serial;
+#endif
+
+	/*
+	 * kdb_diemsg
+	 *
+	 *	Contains a pointer to the last string supplied to the
+	 *	kernel 'die' panic function.
+	 */
+extern const char *kdb_diemsg;
+
+#define KDB_FLAG_EARLYKDB	(1 << 0)	/* set from boot parameter kdb=early */
+#define KDB_FLAG_CATASTROPHIC	(1 << 1)	/* A catastrophic event has occurred */
+#define KDB_FLAG_CMD_INTERRUPT	(1 << 2)	/* Previous command was interrupted */
+#define KDB_FLAG_NOIPI		(1 << 3)	/* Do not send IPIs */
+#define KDB_FLAG_ONLY_DO_DUMP	(1 << 4)	/* Only do a dump, used when kdb is off */
+
+	/*
+	 * Internal debug flags
+	 */
+#define KDB_DEBUG_FLAG_BT	0x0001		/* Stack traceback debug */
+#define KDB_DEBUG_FLAG_BP	0x0002		/* Breakpoint subsystem debug */
+#define KDB_DEBUG_FLAG_LBR	0x0004		/* Print last branch register */
+#define KDB_DEBUG_FLAG_AR	0x0008		/* Activation record, generic */
+#define KDB_DEBUG_FLAG_ARA	0x0010		/* Activation record, arch specific */
+/*      KDB_DEBUG_FLAG_CALLBACK	0x0020		WAS Event callbacks to kdb */
+#define KDB_DEBUG_FLAG_STATE	0x0040		/* State flags */
+#define KDB_DEBUG_FLAG_MASK	0xffff		/* All debug flags */
+#define KDB_DEBUG_FLAG_SHIFT	16		/* Shift factor for dbflags */
+
+extern volatile int kdb_flags;			/* Global flags, see kdb_state for per cpu state */
+
+#define KDB_FLAG(flag)		(kdb_flags & KDB_FLAG_##flag)
+#define KDB_FLAG_SET(flag)	((void)(kdb_flags |= KDB_FLAG_##flag))
+#define KDB_FLAG_CLEAR(flag)	((void)(kdb_flags &= ~KDB_FLAG_##flag))
+#define KDB_DEBUG(flag)		(kdb_flags & (KDB_DEBUG_FLAG_##flag << KDB_DEBUG_FLAG_SHIFT))
+#define KDB_DEBUG_STATE(text,value)	if (KDB_DEBUG(STATE)) kdb_print_state(text, value)
+
+	/*
+	 * Per cpu kdb state.  A cpu can be under kdb control but outside kdb,
+	 * for example when doing single step.
+	 */
+volatile extern int kdb_state[ /*NR_CPUS*/ ];
+#define KDB_STATE_KDB		0x00000001	/* Cpu is inside kdb */
+#define KDB_STATE_LEAVING	0x00000002	/* Cpu is leaving kdb */
+#define KDB_STATE_CMD		0x00000004	/* Running a kdb command */
+#define KDB_STATE_KDB_CONTROL	0x00000008	/* This cpu is under kdb control */
+#define KDB_STATE_HOLD_CPU	0x00000010	/* Hold this cpu inside kdb */
+#define KDB_STATE_DOING_SS	0x00000020	/* Doing ss command */
+#define KDB_STATE_DOING_SSB	0x00000040	/* Doing ssb command, DOING_SS is also set */
+#define KDB_STATE_SSBPT		0x00000080	/* Install breakpoint after one ss, independent of DOING_SS */
+#define KDB_STATE_REENTRY	0x00000100	/* Valid re-entry into kdb */
+#define KDB_STATE_SUPPRESS	0x00000200	/* Suppress error messages */
+#define KDB_STATE_LONGJMP	0x00000400	/* longjmp() data is available */
+#define KDB_STATE_GO_SWITCH	0x00000800	/* go is switching back to initial cpu */
+#define KDB_STATE_PRINTF_LOCK	0x00001000	/* Holds kdb_printf lock */
+#define KDB_STATE_WAIT_IPI	0x00002000	/* Waiting for kdb_ipi() NMI */
+#define KDB_STATE_RECURSE	0x00004000	/* Recursive entry to kdb */
+#define KDB_STATE_IP_ADJUSTED	0x00008000	/* Restart IP has been adjusted */
+#define KDB_STATE_GO1		0x00010000	/* go only releases one cpu */
+#define KDB_STATE_ARCH		0xff000000	/* Reserved for arch specific use */
+
+#define KDB_STATE_CPU(flag,cpu)		(kdb_state[cpu] & KDB_STATE_##flag)
+#define KDB_STATE_SET_CPU(flag,cpu)	((void)(kdb_state[cpu] |= KDB_STATE_##flag))
+#define KDB_STATE_CLEAR_CPU(flag,cpu)	((void)(kdb_state[cpu] &= ~KDB_STATE_##flag))
+
+#define KDB_STATE(flag)		KDB_STATE_CPU(flag,smp_processor_id())
+#define KDB_STATE_SET(flag)	KDB_STATE_SET_CPU(flag,smp_processor_id())
+#define KDB_STATE_CLEAR(flag)	KDB_STATE_CLEAR_CPU(flag,smp_processor_id())
+
+	/*
+	 * External entry point for the kernel debugger.  The pt_regs
+	 * at the time of entry are supplied along with the reason for
+	 * entry to the kernel debugger.
+	 */
+
+typedef enum {
+	KDB_REASON_CALL = 1,		/* Call kdb() directly - regs should be valid */
+	KDB_REASON_FAULT,		/* Kernel fault - regs valid */
+	KDB_REASON_BREAK,		/* Breakpoint inst. - regs valid */
+	KDB_REASON_DEBUG,		/* Debug Fault - regs valid */
+	KDB_REASON_OOPS,		/* Kernel Oops - regs valid */
+	KDB_REASON_SWITCH,		/* CPU switch - regs valid*/
+	KDB_REASON_ENTER,		/* KDB_ENTER() trap/fault - regs valid */
+	KDB_REASON_KEYBOARD,		/* Keyboard entry - regs valid */
+	KDB_REASON_NMI,			/* Non-maskable interrupt; regs valid */
+	KDB_REASON_WATCHDOG,		/* Watchdog interrupt; regs valid */
+	KDB_REASON_RECURSE,		/* Recursive entry to kdb; regs probably valid */
+	KDB_REASON_SILENT,		/* Silent entry/exit to kdb; regs invalid */
+	KDB_REASON_CALL_PRESET,		/* Same as KDB_REASON_CALL but kdb_process_running has been preset */
+} kdb_reason_t;
+
+typedef enum {
+	KDB_REPEAT_NONE = 0,		/* Do not repeat this command */
+	KDB_REPEAT_NO_ARGS,		/* Repeat the command without arguments */
+	KDB_REPEAT_WITH_ARGS,		/* Repeat the command including its arguments */
+} kdb_repeat_t;
+
+#ifdef	CONFIG_KDB
+extern int   kdb(kdb_reason_t, int, struct pt_regs *);
+#else
+#define kdb(reason,error_code,frame) (0)
+#endif
+
+typedef int (*kdb_func_t)(int, const char **, const char **, struct pt_regs *);
+
+	/*
+	 * Symbol table format returned by kallsyms.
+	 */
+
+typedef struct __ksymtab {
+		unsigned long value;		/* Address of symbol */
+		const char *mod_name;		/* Module containing symbol or "kernel" */
+		unsigned long mod_start;
+		unsigned long mod_end;
+		const char *sec_name;		/* Section containing symbol */
+		unsigned long sec_start;
+		unsigned long sec_end;
+		const char *sym_name;		/* Full symbol name, including any version */
+		unsigned long sym_start;
+		unsigned long sym_end;
+		} kdb_symtab_t;
+
+	/*
+	 * Exported Symbols for kernel loadable modules to use.
+	 */
+extern int           kdb_register(char *, kdb_func_t, char *, char *, short);
+extern int           kdb_register_repeat(char *, kdb_func_t, char *, char *, short, kdb_repeat_t);
+extern int           kdb_unregister(char *);
+
+extern int	     kdb_getarea_size(void *, unsigned long, size_t);
+extern int	     kdb_putarea_size(unsigned long, void *, size_t);
+
+/* Like get_user and put_user, kdb_getarea and kdb_putarea take variable
+ * names, not pointers.  The underlying *_size functions take pointers.
+ */
+#define kdb_getarea(x,addr)	kdb_getarea_size(&(x), addr, sizeof((x)))
+#define kdb_putarea(addr,x)	kdb_putarea_size(addr, &(x), sizeof((x)))
+
+extern int	     kdb_getword(unsigned long *, unsigned long, size_t);
+extern int	     kdb_putword(unsigned long, unsigned long, size_t);
+
+extern int	     kdbgetularg(const char *, unsigned long *);
+extern char         *kdbgetenv(const char *);
+extern int	     kdbgetintenv(const char *, int *);
+extern int	     kdbgetaddrarg(int, const char**, int*, unsigned long *,
+			           long *, char **, struct pt_regs *);
+extern int	     kdbgetsymval(const char *, kdb_symtab_t *);
+extern int	     kdbnearsym(unsigned long, kdb_symtab_t *);
+extern void	     kdb_printf(const char *,...)
+		     __attribute__ ((format (printf, 1, 2)));
+extern void	     kdb_init(void);
+extern void	     kdb_symbol_print(kdb_machreg_t, const kdb_symtab_t *, unsigned int);
+extern char	    *kdb_read(char *buffer, size_t bufsize);
+extern char	    *kdb_strdup(const char *str, int type);
+
+#if defined(CONFIG_SMP)
+	/*
+	 * Kernel debugger non-maskable IPI handler.
+	 */
+extern int           kdb_ipi(struct pt_regs *, void (*ack_interrupt)(void));
+extern void	     smp_kdb_stop(void);
+#else	/* CONFIG_SMP */
+#define	smp_kdb_stop()
+#endif	/* CONFIG_SMP */
+
+	/*
+	 * Interface from general kernel to enable any hardware
+	 * error reporting mechanisms.  Such as the Intel Machine
+	 * Check Architecture, for example.
+	 */
+extern void	     kdb_enablehwfault(void);
+
+	 /*
+	  * Let other code know that kdb is in control.  Routines registered
+	  * on this list are called from the initial cpu with 1 when kdb is
+	  * entered and 0 when kdb exits.
+	  *
+	  * WARNING: If a module registers itself on this list (or any notifier
+	  * list) then there is a race condition.  The module could be in the
+	  * middle of removal on one cpu when it is called via the notifier
+	  * chain on another cpu.  It is the responsibility of the module to
+	  * prevent this race.  The safest way is for the module to define a
+	  * 'can_unload' function which unregisters the module from all
+	  * notifier chains before allowing the module to be unloaded.
+	  */
+
+extern struct notifier_block *kdb_notifier_list;
+
+	 /*
+	  * Do we have a set of registers?
+	  */
+
+#define KDB_NULL_REGS(regs) \
+	(regs == (struct pt_regs *)NULL ? kdb_printf("%s: null regs - should never happen\n", __FUNCTION__), 1 : 0)
+
+	 /*
+	  * Routine for debugging the debugger state.
+	  */
+
+extern void kdb_print_state(const char *, int);
+
+#ifdef CONFIG_KDB_USB
+#include <linux/usb.h>
+#define KDB_USB_ACTIVE 	1 /* Keyboard driver is usbkbd */
+#define HID_ACTIVE 	2 /* Keyboard driver is hid    */
+
+struct kdb_usb_exchange {
+	void *uhci;			/* pointer to the UHCI structure */
+  	struct urb *urb;		/* pointer to the URB */
+	unsigned char *buffer;		/* pointer to buffer */
+	void (*poll_func)(void *, struct urb *); /* pointer to the polling function */
+	void (*reset_timer)(void);	/* pointer to the reset timer function */
+	int driver;			/* driver mode, see above KDB_USB_KBD */
+};
+extern struct kdb_usb_exchange kdb_usb_infos; /* KDB common structure */
+#endif /* CONFIG_KDB_USB */
+
+#ifdef	MODULE
+#define kdb_module_init(fn) module_init(fn)
+#define kdb_module_exit(fn) module_exit(fn)
+#else	/* !MODULE */
+extern initcall_t __kdb_initcall_start, __kdb_initcall_end;
+#define kdb_module_init(fn) \
+	static initcall_t __kdb_initcall_##fn __attribute__ ((unused,__section__ (".kdb_initcall.init"))) = fn;
+#define kdb_module_exit(fn) \
+	static exitcall_t __kdb_exitcall_##fn __attribute__ ((unused,__section__ (".kdb_exitcall.exit"))) = fn;
+#endif	/* MODULE */
+
+
+/*
+ * A backport of the 2.5 scheduler is used by many vendors of 2.4-based
+ * distributions.
+ * We can only guess its presence by the lack of the SCHED_YIELD flag.
+ * If the heuristic doesn't work, change this define by hand.
+ */
+#ifndef SCHED_YIELD
+#define __KDB_HAVE_NEW_SCHEDULER    1
+#endif
+
+static inline
+int kdb_process_cpu(const struct task_struct *p)
+{
+#ifdef __KDB_HAVE_NEW_SCHEDULER
+	return p->cpu;		/* p->cpu for O(1) scheduler */
+#else
+	return p->processor;	/* p->processor for not O(1) scheduler */
+#endif
+}
+
+extern struct task_struct *kdb_current_task;
+extern struct page * kdb_follow_page(struct mm_struct *, unsigned long, int); /* from mm/memory.c */
+
+#endif	/* !_KDB_H */
diff -uNr linux.orig/include/linux/kdbprivate.h linux/include/linux/kdbprivate.h
--- linux.orig/include/linux/kdbprivate.h	Thu Jan  1 08:00:00 1970
+++ linux/include/linux/kdbprivate.h	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,370 @@
+#ifndef _KDBPRIVATE_H
+#define _KDBPRIVATE_H
+
+/*
+ * Kernel Debugger Architecture Independent Private Headers
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/dis-asm.h>
+#include <asm/kdbprivate.h>
+
+#include "bfd.h"
+
+/*
+ * Kernel Debugger Error codes.  Must not overlap with command codes.
+ */
+
+#define KDB_NOTFOUND	(-1)
+#define KDB_ARGCOUNT	(-2)
+#define KDB_BADWIDTH	(-3)
+#define KDB_BADRADIX	(-4)
+#define KDB_NOTENV	(-5)
+#define KDB_NOENVVALUE	(-6)
+#define KDB_NOTIMP	(-7)
+#define KDB_ENVFULL	(-8)
+#define KDB_ENVBUFFULL	(-9 )
+#define KDB_TOOMANYBPT	(-10)
+#define KDB_TOOMANYDBREGS (-11)
+#define KDB_DUPBPT	(-12)
+#define KDB_BPTNOTFOUND	(-13)
+#define KDB_BADMODE	(-14)
+#define KDB_BADINT	(-15)
+#define KDB_INVADDRFMT  (-16)
+#define KDB_BADREG      (-17)
+#define KDB_BADCPUNUM   (-18)
+#define KDB_BADLENGTH	(-19)
+#define KDB_NOBP	(-20)
+#define KDB_BADADDR	(-21)
+
+/*
+ * Kernel Debugger Command codes.  Must not overlap with error codes.
+ */
+#define KDB_CMD_GO	(-1001)
+#define KDB_CMD_CPU	(-1002)
+#define KDB_CMD_SS	(-1003)
+#define KDB_CMD_SSB	(-1004)
+
+	/*
+	 * kdb_nextline
+	 *
+	 * 	Contains the current line number on the screen.  Used
+	 *	to handle the built-in pager (LINES env variable)
+	 */
+extern volatile int kdb_nextline;
+
+	/*
+	 * Breakpoint state
+	 *
+	 * 	Each active and inactive breakpoint is represented by
+	 * 	an instance of the following data structure.
+	 */
+
+typedef struct _kdb_bp {
+	bfd_vma 	bp_addr;	/* Address breakpoint is present at */
+	kdb_machinst_t	bp_inst;	/* Replaced instruction */
+
+	unsigned int	bp_free:1;	/* This entry is available */
+
+	unsigned int	bp_enabled:1;	/* Breakpoint is active in register */
+	unsigned int	bp_global:1;	/* Global to all processors */
+
+	unsigned int	bp_hardtype:1;	/* Uses hardware register */
+	unsigned int	bp_forcehw:1;	/* Force hardware register */
+	unsigned int	bp_installed:1;	/* Breakpoint is installed */
+	unsigned int	bp_delay:1;	/* Do delayed bp handling */
+	unsigned int	bp_delayed:1;	/* Delayed breakpoint */
+
+	int		bp_cpu;		/* Cpu #  (if bp_global == 0) */
+	kdbhard_bp_t	bp_template;	/* Hardware breakpoint template */
+	kdbhard_bp_t	*bp_hard;	/* Hardware breakpoint structure */
+	int		bp_adjust;	/* Adjustment to PC for real instruction */
+} kdb_bp_t;
+
+	/*
+	 * Breakpoint handling subsystem global variables
+	 */
+extern kdb_bp_t		kdb_breakpoints[/* KDB_MAXBPT */];
+
+	/*
+	 * Breakpoint architecture dependent functions.  Must be provided
+	 * in some form for all architectures.
+	 */
+extern void 		kdba_initbp(void);
+extern void		kdba_printbp(kdb_bp_t *);
+extern void		kdba_printbpreg(kdbhard_bp_t *);
+extern kdbhard_bp_t	*kdba_allocbp(kdbhard_bp_t *, int *);
+extern void		kdba_freebp(kdbhard_bp_t *);
+extern int		kdba_parsebp(int, const char**, int *, kdb_bp_t*);
+extern char 		*kdba_bptype(kdbhard_bp_t *);
+extern void		kdba_setsinglestep(struct pt_regs *);
+extern void		kdba_clearsinglestep(struct pt_regs *);
+
+	/*
+	 * Adjust instruction pointer architecture dependent function.  Must be
+	 * provided in some form for all architectures.
+	 */
+extern void		kdba_adjust_ip(kdb_reason_t, int, struct pt_regs *);
+
+	/*
+	 * KDB-only global function prototypes.
+	 */
+extern void	     kdb_id1(unsigned long);
+extern void	     kdb_id_init(void);
+
+	/*
+	 * Architecture dependent function to enable any
+	 * processor machine check exception handling modes.
+	 */
+extern void	     kdba_enable_mce(void);
+
+extern void	     kdba_enable_lbr(void);
+extern void	     kdba_disable_lbr(void);
+extern void	     kdba_print_lbr(void);
+
+	/*
+	 * Initialization functions.
+	 */
+extern void	     kdba_init(void);
+extern void	     kdb_io_init(void);
+
+	/*
+	 * Architecture specific function to read a string.
+	 */
+typedef int (*get_char_func)(void);
+extern get_char_func poll_funcs[];
+
+	/*
+	 * Data for a single activation record on stack.
+	 */
+
+typedef struct __kdb_activation_record {
+	kdb_machreg_t	start;		/* -> start of activation record */
+	kdb_machreg_t	end;		/* -> end+1 of activation record */
+	kdb_machreg_t	ret;		/* Return address to caller */
+	kdb_machreg_t	oldfp;		/* Frame pointer for caller's frame */
+	kdb_machreg_t	fp;		/* Frame pointer for callee's frame */
+	kdb_machreg_t	arg0;		/* -> First argument on stack (in previous ar) */
+	unsigned long	locals;		/* Bytes allocated for local variables */
+	unsigned long	regs;		/* Bytes allocated for saved registers */
+	unsigned long	args;		/* Bytes allocated for arguments (in previous ar) */
+	unsigned long	setup;		/* Bytes allocated for setup data */
+} kdb_ar_t;
+
+	/*
+	 * General Stack Traceback functions.
+	 */
+
+extern int	     kdb_get_next_ar(kdb_machreg_t, kdb_machreg_t,
+				     kdb_machreg_t, kdb_machreg_t,
+				     kdb_machreg_t,
+				     kdb_ar_t *, kdb_symtab_t *);
+
+	/*
+	 * Architecture specific Stack Traceback functions.
+	 */
+
+struct task_struct;
+
+extern int	     kdba_bt_address(kdb_machreg_t, int);
+extern int	     kdba_bt_process(struct task_struct *, int);
+extern int	     kdba_prologue(const kdb_symtab_t *, kdb_machreg_t,
+				   kdb_machreg_t, kdb_machreg_t, kdb_machreg_t,
+				   int, kdb_ar_t *);
+	/*
+	 * KDB Command Table
+	 */
+
+typedef struct _kdbtab {
+        char    *cmd_name;		/* Command name */
+        kdb_func_t cmd_func;		/* Function to execute command */
+        char    *cmd_usage;		/* Usage String for this command */
+        char    *cmd_help;		/* Help message for this command */
+        short    cmd_flags;		/* Parsing flags */
+        short    cmd_minlen;		/* Minimum legal # command chars required */
+	kdb_repeat_t cmd_repeat;	/* Does command auto repeat on enter? */
+} kdbtab_t;
+
+	/*
+	 * External command function declarations
+	 */
+
+extern int kdb_id(int, const char **, const char **, struct pt_regs *);
+extern int kdb_bp(int, const char **, const char **, struct pt_regs *);
+extern int kdb_bc(int, const char **, const char **, struct pt_regs *);
+extern int kdb_bt(int, const char **, const char **, struct pt_regs *);
+extern int kdb_ss(int, const char **, const char **, struct pt_regs *);
+
+	/*
+	 * External utility function declarations
+	 */
+extern char* kdb_getstr(char *, size_t, char *);
+
+	/*
+	 * Register contents manipulation
+	 */
+extern int kdba_getregcontents(const char *, struct pt_regs *, kdb_machreg_t *);
+extern int kdba_setregcontents(const char *, struct pt_regs *, kdb_machreg_t);
+extern int kdba_dumpregs(struct pt_regs *, const char *, const char *);
+extern int kdba_setpc(struct pt_regs *, kdb_machreg_t);
+extern kdb_machreg_t   kdba_getpc(struct pt_regs *);
+
+	/*
+	 * Debug register handling.
+	 */
+extern void kdba_installdbreg(kdb_bp_t*);
+extern void kdba_removedbreg(kdb_bp_t*);
+
+	/*
+	 * Breakpoint handling - External interfaces
+	 */
+extern void kdb_initbptab(void);
+extern void kdb_bp_install_global(struct pt_regs *);
+extern void kdb_bp_install_local(struct pt_regs *);
+extern void kdb_bp_remove_global(void);
+extern void kdb_bp_remove_local(void);
+
+	/*
+	 * Breakpoint handling - Internal to kdb_bp.c/kdba_bp.c
+	 */
+extern int kdba_installbp(struct pt_regs *regs, kdb_bp_t *);
+extern int kdba_removebp(kdb_bp_t *);
+
+
+typedef enum {
+	KDB_DB_BPT,	/* Breakpoint */
+	KDB_DB_SS,	/* Single-step trap */
+	KDB_DB_SSB,	/* Single step to branch */
+	KDB_DB_SSBPT,	/* Single step over breakpoint */
+	KDB_DB_NOBPT	/* Spurious breakpoint */
+} kdb_dbtrap_t;
+
+extern kdb_dbtrap_t kdba_db_trap(struct pt_regs *, int);	/* DEBUG trap/fault handler */
+extern kdb_dbtrap_t kdba_bp_trap(struct pt_regs *, int);	/* Breakpoint trap/fault hdlr */
+
+	/*
+	 * Interrupt Handling
+	 */
+typedef int kdb_intstate_t;
+
+extern void kdba_disableint(kdb_intstate_t *);
+extern void kdba_restoreint(kdb_intstate_t *);
+
+	/*
+	 * SMP and process stack manipulation routines.
+	 */
+extern int	     kdba_ipi(struct pt_regs *, void (*)(void));
+extern int	     kdba_main_loop(kdb_reason_t, kdb_reason_t, int, kdb_dbtrap_t, struct pt_regs *);
+extern int           kdb_main_loop(kdb_reason_t, kdb_reason_t, int, kdb_dbtrap_t, struct pt_regs *);
+
+	/*
+	 * General Disassembler interfaces
+	 */
+extern int kdb_dis_fprintf(PTR, const char *, ...) __attribute__ ((format (printf, 2, 3)));
+extern int kdb_dis_fprintf_dummy(PTR, const char *, ...) __attribute__ ((format (printf, 2, 3)));
+extern disassemble_info	kdb_di;
+
+	/*
+	 * Architecture Dependent Disassembler interfaces
+	 */
+extern void kdba_printaddress(kdb_machreg_t, disassemble_info *, int);
+extern int  kdba_id_printinsn(kdb_machreg_t, disassemble_info *);
+extern int  kdba_id_parsemode(const char *, disassemble_info*);
+extern void kdba_id_init(disassemble_info *);
+extern void kdba_check_pc(kdb_machreg_t *);
+
+	/*
+	 * Miscellaneous functions and data areas
+	 */
+extern char *kdb_cmds[];
+extern void kdb_syslog_data(char *syslog_data[]);
+extern unsigned long kdb_task_state_string(int argc, const char **argv, const char **envp);
+extern unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask);
+extern void kdb_ps1(struct task_struct *p);
+extern int kdb_parse(const char *cmdstr, struct pt_regs *regs);
+extern void kdb_print_nameval(const char *name, unsigned long val);
+
+	/*
+	 * Architecture Dependant Local Processor setup & cleanup interfaces
+	 */
+extern void kdba_local_arch_setup(void);
+extern void kdba_local_arch_cleanup(void);
+
+	/*
+	 * Defines for kdb_symbol_print.
+	 */
+#define KDB_SP_SPACEB	0x0001		/* Space before string */
+#define KDB_SP_SPACEA	0x0002		/* Space after string */
+#define KDB_SP_PAREN	0x0004		/* Parenthesis around string */
+#define KDB_SP_VALUE	0x0008		/* Print the value of the address */
+#define KDB_SP_SYMSIZE	0x0010		/* Print the size of the symbol */
+#define KDB_SP_NEWLINE	0x0020		/* Newline after string */
+#define KDB_SP_DEFAULT (KDB_SP_VALUE|KDB_SP_PAREN)
+
+/* Save data about running processes */
+
+struct kdb_running_process {
+	struct task_struct *p;
+	struct pt_regs *regs;
+	int seqno;				/* kdb sequence number */
+	struct kdba_running_process arch;	/* arch dependent save data */
+};
+
+extern struct kdb_running_process kdb_running_process[/* NR_CPUS */];
+extern struct task_struct *kdb_active_task[/* NR_CPUS */];
+
+extern void kdb_save_running(struct pt_regs *);
+extern void kdb_unsave_running(struct pt_regs *);
+
+/* 	Incremented each time the main kdb loop is entered on the initial cpu,
+ * 	it gives some indication of how old the saved data is.
+ */
+extern int kdb_seqno;
+
+/* Compatibility code until cpu_online() is in the standard kernel */
+#ifndef cpu_online
+#ifdef CONFIG_SMP
+#define cpu_online(cpu) test_bit(cpu, &cpu_online_map)
+#else  /* !SMP */
+#define cpu_online(cpu) ({ BUG_ON((cpu) != 0); 1; })
+#endif /* SMP */
+#endif /* cpu_online */
+
+/* kdb needs to know if a task owns the cpu.  Due to bugs in the scheduling code
+ * the initial tasks on each cpu do not decode correctly, uni-processor also has
+ * incorrect state for task_has_cpu.  Use my own function to workaround the
+ * scheduler bugs.
+ */
+
+#define kdb_task_has_cpu(p) (kdb_active_task[kdb_process_cpu(p)] == p)
+
+#endif	/* !_KDBPRIVATE_H */
diff -uNr linux.orig/include/linux/module.h linux/include/linux/module.h
--- linux.orig/include/linux/module.h	Sat Aug  3 08:39:45 2002
+++ linux/include/linux/module.h	Mon Apr  5 15:07:55 2004
@@ -412,4 +412,29 @@
 #define SET_MODULE_OWNER(some_struct) do { } while (0)
 #endif
 
+extern void print_modules(void);
+
+#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
+
+extern struct module *module_list;
+
+/*
+ * print_symbols takes a format string containing one %s.
+ * If support for resolving symbols is compiled in, the %s will
+ * be replaced by the closest symbol to the address and the entire
+ * string is printk()ed. Otherwise, nothing is printed.
+ */
+extern void print_symbol(const char *fmt, unsigned long address);
+
+#else
+
+#include <linux/errno.h>
+static inline int
+print_symbol(const char *fmt, unsigned long address)
+{
+	return -ESRCH;
+}
+
+#endif
+
 #endif /* _LINUX_MODULE_H */
diff -uNr linux.orig/include/linux/sched.h linux/include/linux/sched.h
--- linux.orig/include/linux/sched.h	Fri Jun 13 22:51:39 2003
+++ linux/include/linux/sched.h	Mon Apr  5 15:07:55 2004
@@ -567,6 +567,12 @@
 	tsk->cpus_runnable = 1UL << cpu;
 }
 
+static inline void task_set_cpu_only(struct task_struct *tsk, unsigned int cpu)
+{
+	task_set_cpu(tsk, cpu);
+	tsk->cpus_allowed = 1UL << cpu;
+}
+
 static inline void task_release_cpu(struct task_struct *tsk)
 {
 	tsk->cpus_runnable = ~0UL;
diff -uNr linux.orig/include/linux/sysctl.h linux/include/linux/sysctl.h
--- linux.orig/include/linux/sysctl.h	Mon Apr  5 15:02:44 2004
+++ linux/include/linux/sysctl.h	Mon Apr  5 15:07:55 2004
@@ -125,6 +125,7 @@
 	KERN_CORE_USES_PID=52,		/* int: use core or core.%pid */
 	KERN_TAINTED=53,	/* int: various kernel tainted flags */
 	KERN_CADPID=54,		/* int: PID of the process to notify on CAD */
+	KERN_KDB=55,		/* int: kdb on/off */
  	KERN_CORE_PATTERN=56,	/* string: pattern for core-files */
 };
 
diff -uNr linux.orig/init/main.c linux/init/main.c
--- linux.orig/init/main.c	Mon Apr  5 15:02:44 2004
+++ linux/init/main.c	Mon Apr  5 15:07:55 2004
@@ -69,6 +69,10 @@
 #include <asm/smp.h>
 #endif
 
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -251,6 +255,25 @@
                 }
                 if (next != NULL)
                         *next++ = 0;
+#ifdef	CONFIG_KDB
+		/* kdb=on, kdb=off, kdb=early */
+		if (strncmp(line, "kdb=", 4) == 0) {
+			if (strcmp(line+4, "on") == 0) {
+				kdb_on = 1;
+				continue;
+			}
+			if (strcmp(line+4, "off") == 0) {
+				kdb_on = 0;
+				continue;
+			}
+			if (strcmp(line+4, "early") == 0) {
+				kdb_on = 1;
+				kdb_flags |= KDB_FLAG_EARLYKDB;
+				continue;
+			}
+			printk("Boot flag %s not recognised, assumed to be environment variable\n", line);
+		}
+#endif	/* CONFIG_KDB */
 		if (!strncmp(line,"init=",5)) {
 			line += 5;
 			execute_command = line;
@@ -354,6 +377,7 @@
  * enable them
  */
 	lock_kernel();
+	task_set_cpu_only(current, 0);
 	printk(linux_banner);
 	setup_arch(&command_line);
 	printk("Kernel command line: %s\n", saved_command_line);
@@ -398,6 +422,13 @@
 	kmem_cache_sizes_init();
 	pgtable_cache_init();
 
+#ifdef	CONFIG_KDB
+	kdb_init();
+	if (KDB_FLAG(EARLYKDB)) {
+		KDB_ENTER();
+	}
+#endif	/* CONFIG_KDB */
+
 	/*
 	 * For architectures that have highmem, num_mappedpages represents
 	 * the amount of memory the kernel can use.  For other architectures
diff -uNr linux.orig/kdb/ChangeLog linux/kdb/ChangeLog
--- linux.orig/kdb/ChangeLog	Thu Jan  1 08:00:00 1970
+++ linux/kdb/ChangeLog	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,701 @@
+2003-06-20 Keith Owens  <kaos@sgi.com>
+
+	* More details on vm command, add vmp and pte commands.
+	  Dean Nelson, Dean Roe, SGI.
+	* YAO1SCF (Yet Another O(1) Scheduler Coexistence Fix).
+	* Changes to common code to build on sparc.  Tom Duffy.
+	* Move Tom Duffy's changes to drivers/sbus from the sparc64
+	  patch to the common patch to keep all the serial changes
+	  together.
+	* Changes to common code to build on Xscale.  Eddie Dong, Intel.
+	* Remove CROSS_COMPILE_INC.
+	* Remove obsolete boot parameter 'kdb', long since replaced by
+	  'kdb=on'.
+	* Remove obsolete kdb_eframe_t casts.
+	* Add CONFIG_KDB_CONTINUE_CATASTROPHIC.
+	* Wait a short interval for cpus to join kdb before proceeding.
+	* Automatically enable sysrq for sr command.
+	* Correct double free of kdb_printf lock, spotted by Richard Sanders.
+	* Add optional cpu parameter to btc command.
+	* kdb v4.3-2.4.20-common-1.
+
+2003-05-02 Keith Owens  <kaos@sgi.com>
+
+	* Some architectures have problems with the initial empty kallsyms
+	  section so revert to three kallsyms passes.
+	* Flush buffered input at startup and at 'more' prompt.
+	* Only print 'more' prompt when longjmp data is available.
+	* Print more data for buffers and inodes.
+	* Disable kill command when O(1) scheduler is installed, the code
+	  needs to be redone for O(1).
+	* The kernel has an undocumented assumption that enable_bh() is
+	  always called with interrupts enabled, make it so.
+	* Print trailing punctuation even for symbols that are not in kernel.
+	* Add read/write access to user pages.  Vamsi Krishna S., IBM
+	* Rename cpu_is_online to cpu_online, as in 2.5.
+	* O(1) scheduler removes init_task so kdb maintains its own list of
+	  active tasks.
+	* Delete btp 0 <cpuid> option, it needed init_tasks.
+	* Clean up USB keyboard support.  Steven Dake.
+	* Sync with XFS 2.4.20 tree.
+	* kdb v4.2-2.4.20-common-1.
+
+2003-04-04 Keith Owens  <kaos@sgi.com>
+
+	* Remove one kallsyms pass.
+	* Automatic detection of O(1) scheduler.
+	* Rename cpu_online to cpu_is_online.
+	* Workarounds for scheduler bugs.
+	* Tweak algorithm for detecting if cpu process data is available.
+	* Add 'kill' command.  Sonic Zhang, Keith Owens.
+	* kdb v4.1-2.4.20-common-1.
+
+2003-03-16 Keith Owens  <kaos@sgi.com>
+
+	* Each cpu saves its state as it enters kdb or before it enters code
+	  which cannot call kdb.
+	* Allow btp on process 0 for a specified cpu.
+	* Add btt command, backtrace given a struct task address.
+	* btc command no longer switches cpus, instead it uses the saved data.
+	* bta shows the idle task on each cpu as well as real tasks, the idle
+	  task could be handling an interrupt.
+	* ps command shows the idle task on each cpu.
+	* ps checks that the saved data for a cpu matches the process running on
+	  that cpu and warns about stale saved data or no saved data at all.
+	* Remove special cases for i386 backtrace from common code and simplify
+	  common bt code.
+	* Clean up kdb interaction with CONFIG_SERIAL_CONSOLE.
+	* Do not automatically repeat commands after the user typed 'q'.
+	* O(1) scheduler patch changes the process cpu field but does not set
+	  any indicator that O(1) is being used.  Adjust kdb_process_cpu() by
+	  hand after applying O(1).
+	* Add kdb_print_nameval() to common code.
+	* Convert tests of cpu_online_map to cpu_online() macro.
+	* module.h needs errno.h when compiling with CONFIG_MODULES=n.
+	* Correct duplicate breakpoint handling.
+	* Do not try to send IPI during a catastrophic error, send_ipi can hang
+	  and take kdb with it.
+	* kdb memmap command is i386 only, restrict it.
+	* Add large block device (LBD) support from XFS tree.  Eric Sandeen.
+	* kdb v4.0-2.4.20-common-1.
+
+2003-02-03 Keith Owens  <kaos@sgi.com>
+
+	* Register kdb commands early.
+	* Decode oops via kallsyms if it is available.
+	* Update copyright notices to 2003.
+	* Add defcmd/endefcmd to allow users to package their own macros.
+	* kdb commands that fail are ignored when prefixed with '-'.
+	* Add selection options to bta command.
+	* Add btc command (switch to each cpu and backtrace).
+	* Do real time detection of dead cpus.
+	* Clear ip adjusted flag when leaving kdb.
+	* Clean up ps command.
+	* Print ps output for each task when backtracing.
+	* Bump to version v3.0 to reduce confusion between kdb and kernel
+	  version numbers.
+	* Add kdba_local_arch_setup/kdba_local_arch_cleanup to correct
+	  keyboard freeze.  Ashish Kalra.
+	* Refuse multiple breakpoints at the same address.
+	* Add fl (file_lock) command, from XFS development tree.
+	* Correct inode_pages, from XFS development tree.
+	* Add command history and editing.  Sonic Zhang.
+	* Extend command history and editing to handle vt100 escape sequences.
+	* Allow tab completion at start of line.
+	* Touch nmi watchdog on long running bta and btc commands.
+	* Clean up ps output and standardize with bta codes.
+	* Correctly handle escaped characters in commands.
+	* Update man pages for btc and command history/editing.
+	* kdb v3.0-2.4.20-common-1.
+
+2002-11-29 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.20.
+	* Correct Documentation/kdb/kdb_sr.man.
+	* Remove leading zeroes from pids, they are decimal, not octal.
+	* kdb v2.5-2.4.20-common-1.
+
+2002-11-14 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.20-rc1.
+	* kdb v2.5-2.4.20-rc1-common-1.
+
+2002-11-14 Keith Owens  <kaos@sgi.com>
+
+	* Fix processing with O(1) scheduler.
+	* 'go' switches back to initial cpu first.
+	* 'go <address>' only allowed on initial cpu.
+	* 'go' installs the global breakpoints from the initial cpu before
+	   releasing the other cpus.
+	* If 'go' has to single step over a breakpoint then it single steps just
+	  the initial cpu, installs the global breakpoints then releases the
+	  other cpus.
+	* General clean up of handling for breakpoints and single stepping over
+	  software breakpoints.
+	* Add kdb_notifier_block so other code can tell when kdb is in control.
+	* kdb v2.5-2.4.19-common-1.
+
+2002-11-02 Keith Owens  <kaos@sgi.com>
+
+	* Correct build without CONFIG_KDB.
+	* kdb v2.4-2.4.19-common-3.
+
+2002-11-01 Keith Owens  <kaos@sgi.com>
+
+	* Minimize differences from 2.5.44.
+	* kdb v2.4-2.4.19-common-2.
+
+2002-10-31 Keith Owens  <kaos@sgi.com>
+
+	* Add defcmd/endefcmd feature.
+	* Remove kdb_eframe_t.
+	* Clear bp data before using.
+	* Sanity check if we have pt_regs.
+	* Force LINES > 1.
+	* Remove special case for KDB_REASON_PANIC, use KDB_ENTER() instead.
+	* Remove kdba_getcurrentframe().
+	* Coexist with O(1) scheduler.
+	* Add lines option to dmesg, speed up dmesg.
+	* kdb v2.4-2.4.19-common-1.
+
+2002-10-17 Keith Owens  <kaos@sgi.com>
+
+	* Add selection critera to ps and bta commands.
+	* kdb v2.3-2.4.19-common-4.
+
+2002-10-07 Keith Owens  <kaos@sgi.com>
+
+	* New man page, Documentation/kdb/kdb_sr.man.
+
+2002-10-04 Keith Owens  <kaos@sgi.com>
+
+	* Minimize differences between patches for 2.4 and 2.5 kernels.
+	* Add Configure.help for CONFIG_KDB_USB.
+	* Reduce stack usage.
+	* kdb v2.3-2.4.19-common-3.
+
+2002-08-10 Keith Owens  <kaos@sgi.com>
+
+	* Replace kdb_port with kdb_serial to support memory mapped I/O.
+	  David Mosberger.
+	* kdb v2.3-2.4.19-common-2.
+
+2002-08-07 Keith Owens <kaos@sgi.com>
+
+	* Upgrade to 2.4.19.
+	* Remove individual SGI copyrights, the general SGI copyright applies.
+	* Handle md0.  Reported by Hugh Dickins, different fix by Keith Owens.
+	* Use page_address() in kdbm_pg.c.  Hugh Dickins.
+	* Remove debugging printk from kdbm_pg.c.  Hugh Dickins.
+	* Move breakpoint address verification into arch dependent code.
+	* Dynamically resize kdb command table as required.
+	* Common code to support USB keyboard.  Sebastien Lelarge.
+	* kdb v2.3-2.4.19-common-1.
+
+2002-07-09 Keith Owens <kaos@sgi.com>
+
+	* Upgrade to 2.4.19-rc1.
+	* Add dmesg command.
+	* Clean up copyrights, Eric Sandeen.
+	* kdb v2.2-2.4.19-rc1-common-1.
+
+2002-06-14 Keith Owens <kaos@sgi.com>
+
+	* Upgrade to 2.4.19-pre10.
+	* Sync with XFS.
+	* kdb v2.1-2.4.19-pre10-common-1.
+
+2002-04-09 Keith Owens <kaos@sgi.com>
+
+	* Upgrade to 2.4.19-pre6.
+	* kdb v2.1-2.4.19-pre6-common-1.
+
+2002-03-18 Keith Owens <kaos@sgi.com>
+
+	* Syntax check mdWcN commands.
+
+2002-03-01 Keith Owens <kaos@sgi.com>
+
+	* Sync with XFS 2.4.18.
+	* kdb v2.1-2.4.18-common-2.
+
+2002-02-26 Keith Owens <kaos@sgi.com>
+
+	* Upgrade to 2.4.18.
+	* Add Paul Dorwin (IBM) magicpoint slides on using kdb as
+	  Documentation/kdb/slides.
+	* kdb v2.1-2.4.18-common-1.
+
+2002-01-23 Keith Owens <kaos@sgi.com>
+
+	* Sync with XFS pagebuf changes.
+	* kdb v2.1-2.4.17-common-2.
+
+2002-01-18 Keith Owens <kaos@sgi.com>
+
+	* Ignore single stepping during panic.
+	* Remove kdba_getword, kdba_putword.  Replace with kdb_getword,
+	  kdb_putword that rely on copy_xx_user.  The new functions return
+	  an error code, like copy_xx_user.
+	* New functions kdb_getarea, kdb_putarea for copying areas of data
+	  such as structures.  These functions also return an error code.
+	* Change all common code to use the new functions.
+	* bp command checks that it can read and write the word at the
+	  breakpoint before accepting the address.
+	* Break points are now set FIFO and cleared LIFO so overlapping
+	  entries give sensible results.
+	* Verify address before disassembling code.
+	* Common changes for sparc64.  Ethan Solomita, Tom Duffy.
+	* Remove ss <count>, never supported.
+	* Remove kallsyms entries from arch vmlinux.lds files.
+	* Specify which commands auto repeat.
+	* kdb v2.1-2.4.17-common-1.
+
+2002-01-07 Keith Owens <kaos@sgi.com>
+
+	* Remove console semaphore code, not good in interrupt.
+	* Remove fragment of ia64 patch that had crept into kdb.
+	* Release as kdb v2.0-2.4.17-common-3.
+
+2002-01-04 Keith Owens  <kaos@sgi.com>
+
+	* Sync xfs <-> kdb common code.
+
+2001-12-22 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.17.
+	* Clean up ifdef CONFIG_KDB.
+	* Add ifdef CONFIG_KDB around include kdb.h.
+	* Delete dummy kdb.h files for unsupported architectures.
+	* Delete arch i386 and ia64 specific files.  This changelog now
+	  applies to kdb common code only.
+	* Release as kdb v2.0-2.4.17-common-1.
+
+2001-12-03 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.16.
+	* Add include/asm-um/kdb.h stub to allow XFS to be tested under UML.
+	* Check if an interrupt frame on i386 came from user space.
+	* Out of scope bug fix in kdb_id.c.  Ethan Solomita.
+	* Changes to common code to support sparc64.  Ethan Solomita.
+	* Change GFP_KERNEL to GFP_ATOMIC in disasm.  Ethan Solomita.
+
+2001-11-16 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.15-pre5.
+	* Wrap () around #define expressions with unary operators.
+
+2001-11-13 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.15-pre4.
+	* kbdm_pg.c patch from Hugh Dickins.
+
+2001-11-07 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.14-ia64-011105.
+	* Change name of l1 serial I/O routine, add ia64 init command.  SGI.
+	* Sync kdbm_pg with XFS.
+
+2001-11-06 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to kernel 2.4.14.
+
+2001-11-02 Keith Owens  <kaos@sgi.com>
+
+	* Sync kdbm_pg.c with XFS.
+
+2001-10-24 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to kernel 2.4.13.
+
+2001-10-14 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* More use of TMPPREFIX in top level Makefile to speed up NFS compiles.
+
+	* Correct repeat calculations in md/mds commands.
+
+2001-10-10 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Copy bfd.h and ansidecl.h to arch/$(ARCH)/kdb, remove dependecies on
+	  user space includes.
+
+	* Update kdb v1.9 to kernel 2.4.11.
+
+2001-10-01 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Update kdb v1.9 to kernel 2.4.11-pre1 and 2.4.10-ac1.
+
+	* Correct loop in kdb_parse, reported by Tachino Nobuhiro.
+
+2001-09-25 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Update kdb v1.8 to kernel 2.4.10.
+
+	* kdbm_pg patch from Hugh Dickens.
+
+	* DProbes patch from Bharata B Rao.
+
+	* mdWcn and mmW patch from Vamsi Krishna S.
+
+	* i386 disasm layout patch from Jean-Marc Saffroy.
+
+	* Work around for 64 bit binutils, Simon Munton.
+
+	* kdb.mm doc correction by Chris Pascoe.
+
+	* Enter repeats the last command, IA64 disasm only prints one
+	  instruction.  Don Dugger.
+
+	* Allow kdb/modules to be linked into vmlinux.
+
+	* Remove obsolete code from kdb/modules/kdbm_{pg,vm}.c.
+
+	* Warn when commands are entered at more prompt.
+
+	* Add MODULE_AUTHOR, DESCRIPTION, LICENSE.
+
+	* Release as kdb v1.9.
+
+2001-02-27 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Update kdb v1.8 to kernel 2.4.2, sync kdb/modules with XFS.
+
+	* Hook into panic() call.
+
+2000-12-18 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Update kdb v1.7 to kernel 2.4.0-test13-pre3, sync kdb/modules with
+	XFS.
+
+2000-11-18 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Update to kernel 2.4.0-test11-pre7, including forward port of
+	bug fixes from WIP 2.4.0-test9 tree.
+
+	* Update to Cygnus CVS trees for disassembly code.
+
+	* Bump to kdb v1.6.
+
+2000-10-19 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Update to kernel 2.4.0-test10-pre4.
+
+2000-10-15 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* kdb/kdbmain.c (kdb_parse): Correctly handle blank input.
+
+	* kdb/kdbmain.c (kdb_local, kdb): Reason SILENT can have NULL regs.
+
+2000-10-13 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* kdb/kdbmain.c: Reduce CMD_LEN to avoid overflowing kdb_printf buffer.
+
+2000-10-11 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* kdb/kdbmain.c (kdb): Test for userspace breakpoints before driving
+	  other cpus into kdb.  Speeds up gdb and avoids SMP race.
+
+	* arch/i386/kdb/kdba_io.c (get_serial_char, get_kbd_char): Ignore
+	  unprintable characters.
+
+	* arch/i386/kdb/kdba_io.c (kdba_read): Better handling of buffer size.
+
+2000-10-04 Keith Owens  <kaos@melbourne.sgi.com>
+
+	* arch/i386/kdb/kdba_bt.c (kdba_bt_process): Verify that esp is inside
+	task_struct.  Original patch by Mike Galbraith.
+
+	* kdb/kdb_io.c (kdb_getstr): Reset output line counter, remove
+	unnecessary prompts.
+
+	* arch/i386/kdb/kdbasupport.c (kdb_getregcontents): Change " cs" to
+	"xcs", ditto ss, ds, es.  gdb2kdb does not like leading spaces.
+
+	* include/asm-xxx/kdb.h: Add dummy kdb.h for all architectures except
+	ix86.  This allows #include <linux/kdb.h> to appear in arch independent
+	code without causing compile errors.
+
+	* kdb/modules/kdbm_pg: Sync with XFS.
+
+2000-10-03  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* kdb/kdb_io.c (kdb_read): Ignore NMI while waiting for input.
+
+	* kdb/kdb_io.c, kdb/Makefile: Export kdb_read.
+
+2000-10-02  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* arch/i386/kernel/smpboot.c (do_boot_cpu): Set nmi_watchdog_source to 2
+	to avoid premature NMI oops during cpu bring up.  We have to assume that
+	a box with more than 1 cpu has a working IO-APIC.
+
+	* Documentation/kdb/{kdb.mm,kdb_md.man}: Add mdr command.
+
+	* kdb/kdbmain.c (kdb_md): Add mdr command.
+
+	* Release as kdb v1.5 against 2.4.0-test9-pre8.
+
+	* arch/i386/kdb/kdba_io.c, arch/i386/kdb/kdbasupport.c, kdb/kdbmain.c,
+	kdb/kdb_io.c, kdb/kdb_id.c: Remove zero initializers for static
+	variables.
+
+2000-09-28  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* various: Add nmi_watchdog_source, 1 local APIC, 2 IO-APIC.
+	Test nmi_watchdog_source instead of nr_ioapics so UP works on SMP hardware.
+
+	* arch/i386/kernel/io_apic.c: Rename setup_nmi to setup_nmi_io for clarity.
+
+	* kdb/kdbmain.c (kdb_parse): Only set NO_WATCHDOG if it was already set.
+
+	* kdb/kdbmain.c (kdb): Clear NO_WATCHDOG on all exit paths.
+
+	* include/linux/kdb.h: Add KDB_REASON_SILENT.
+
+	* kdb/kdbmain.c (kdb_local): Treat reason SILENT as immediate 'go'.
+
+	* kdb/kdbmain.c (kdb_init): Invoke kdb with reason SILENT to instantiate
+	any breakpoints on boot cpu.
+
+	* arch/i386/kernel/smpboot.c (smp_callin): Invoke kdb with reason SILENT
+	to instantiate any global breakpoints on this cpu.
+
+	* kdb/kdb_cmds: Remove comment that said initial commands only worked on
+	boot cpu.
+
+2000-09-27  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* arch/i386/kernel/msr.c: Move {rd,wr}msr_eio to include/asm-i386/apic.h.
+
+	* include/asm-i386/apic.h: Define NMI interfaces.
+
+	* kernel/sysctl.c (kern_table):
+	* kernel/sysctl.c (do_proc_set_nmi_watchdog):
+	Add /proc/sys/kernel/nmi_watchdog.
+
+	* arch/i386/kernel/apic.c: New routines set_nmi_counter_local,
+	setup_apic_nmi_watchdog.
+
+	* arch/i386/kernel/traps.c: New routine set_nmi_watchdog().  Call apic
+	routines to set/clear local apic timer.
+
+2000-09-26  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* include/linux/sysctl.h (enum): Add NMI_WATCHDOG.
+
+	* arch/i386/kernel/traps.c (nmi_watchdog_tick): Check nmi_watchdog is
+	still on.
+
+	* arch/i386/config.in: Add CONFIG_UP_NMI_WATCHDOG.
+
+	* Documentation/Configure.help: Add CONFIG_UP_NMI_WATCHDOG.
+
+	* Documentation/nmi_watchdog.txt: Update for UP NMI watchdog.
+
+2000-09-25  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* arch/i386/kernel/apic.c (init_apic_mappings):
+	* arch/i386/kernel/io_apic.c (IO_APIC_init_uniprocessor):
+	Merge Keir Fraser's local APIC for uniprocessors patch.
+
+2000-09-24  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Various: Declare initialization routines as __init.
+
+	* Makefile: Define and export AWK.
+
+	* kdb/Makefile: Generate gen-kdb_cmds.c from kdb/kdb_cmds.
+
+	* kdb/kdbmain.c (kdb_init): Call new routine kdb_cmds_init to execute
+	whatever the user put in kdb/kdb_cmds.
+
+	* arch/i386/kdb/kdba_bt.c (kdba_bt_stack): New parameter to
+	indicate if esp in regs is known to be valid or not.
+
+	* kdb/kdb_bp.c, arch/i386/kdb/kdba_bp.c: More trace prints for
+	breakpoint handling.
+
+	* arch/i386/kdb/kdba_bp.c (kdba_installbp): Finally found and fixed the
+	annoying breakpoint bug where breakpoints where not always installed
+	after 'go'.
+
+	* Documentation/kdb: Update man pages kdb.mm, kdb_env.man, kdb_ss.man.
+
+	* Released as kdb-v1.5-beta1-2.4.0-test8.
+
+	* Sync to 2.4.0-test9-pre6 and release as kdb-v1.5-beta1-2.4.0-test9-pre6.
+
+2000-09-23  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* arch/i386/kdb/kdbasupport.c (kdba_getregcontents): New pseudo
+	registers cesp and ceflags to help with debugging the debugger.
+
+	* kdb/kdbmain.c (kdb_local, kdb): Add KDB_REASON_RECURSE.  Add
+	environment variable RECURSE.  Add code to cope with some types of
+	recursion.
+
+	* kdb/kdbmain.c (kdb), arch/i386/kdba/kdba_bp.c: Add
+	kdba_clearsinglestep.
+
+2000-09-22  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* drivers/video/vgacon.c (write_vga): No cli() if kdb is running, avoid
+	console deadlock.
+
+	* arch/i386/kernel/irq.c (get_irqlock): Warn if kdb is running, may hang.
+
+	* include/linux/kdb.h: Define KDB_IS_RUNNING as (0) if no CONFIG_KDB.
+
+	* arch/i386/kdb/kdba_bt.c (kdba_bt_stack): Do not attempt a backtrace if
+	the code segment is not in the kernel.
+
+	* kdb/modules: Change modules from MX_OBJS to M_OBJS.  Remove EXPORT_NOSYMBOLS.
+
+2000-09-21  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* arch/i386/kernel/i386_ksyms.c: Move EXPORT_SYMBOLS for kdb to kdb/kdbmain.c.
+
+	* kdb/Makefile: Change kdb/kdbmain.o from O_OBJS to OX_OBJS.
+
+	* arch/i386/kernel/smp.c: Remove some #ifdef CONFIG_KDB.  Remove kdbprivate.h.
+
+	* include/linux/kdb.h: Add kdb_print_state.  Add KDB_STATE_WAIT_IPI.
+
+	* kdb/kdbmain.c (kdb): Only mark cpu as leaving if it is in KDB state.  Maintain
+	WAIT_IPI state so a cpu is only driven through NMI once.
+
+	* arch/i386/kernel/smp.c (smp_kdb_stop): All state fiddling moved to kdb().
+
+2000-09-20  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* include/linux/kdb.h: #define kdb() as (0) if kdb is not configured.
+
+	* arch/i386/kernel/traps.c: Remove some #ifdef CONFIG_KDB.
+
+	* include/linux/kdbprivate.h: Move per cpu state to kdb.h.
+
+	* include/linux/kdb.h: Add KDB_STATE_NO_WATCHDOG, KDB_STATE_PRINTF_LOCK.
+	Rename KDB_DEBUG_xxx to KDB_DEBUG_FLAG_xxx.  Clean up debug flag
+	definitions.
+
+	* arch/i386/kernel/traps.c (nmi_watchdog_tick): Check no watchdog.
+
+	* kdb/kdbmain.c (kdb): Set no watchdog in normal kdb code.
+
+	* kdb/kdbmain.c (kdb_parse): Allow watchdog in commands.
+
+	* kdb/kdb_io.c (kdb_printf): No watchdog during printing.  Clean up lock handling.
+
+	* kdb/kdbmain.c (kdb_set): Clean up debug flag handling.
+
+2000-09-19  Juan J. Quintela  <quintela@fi.udc.es>
+
+	* kdb/arch/i386/kdb/kdba_io.c: Allow kdb to compile without CONFIG_VT and/or
+	serial console.
+
+2000-09-19  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* include/linux/kdb.h: Define KDB_DEBUG_STATE().
+
+	* kdb/kdbmain.c (kdb): Add kdb_print_state(), calls to KDB_DEBUG_STATE().
+
+2000-09-16  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* Move to finer grained control over individual processors in kdb with
+	per cpu kdb state.  Needed to allow ss[b] to only release one processor,
+	previously ss[b] released all processors.  Also need to recover from
+	errors inside kdb commands, e.g. oops in kdbm_pg code.
+
+	* various:
+	  Move global flags KDB_FLAG_SSB, KDB_FLAG_SUPRESS, KDB_FLAG_FAULT,
+	  KDB_FLAG_SS, KDB_FLAG_SSBPT, kdb_active, to per cpu state and macros
+	  KDB_STATE(xxx).
+	  Replace kdb_flags & KDB_FLAG_xxx with KDB_FLAG(xxx).
+	  Replace kdb_flags & KDB_DEBUG_xxx with KDB_DEBUG(xxx).
+	  Replace specific tests with wrapper KDB_IS_RUNNING().
+
+	* various: Remove #ifdef CONFIG_SMP from kdb code wherever
+	possible.  Simplifies the code and makes it much more readable.
+
+	* arch/i386/kdb/kdbasupport.c (kdb_setjmp): Record if we have reliable
+	longjmp data instead of assuming it is always set.
+
+	* various: Replace smp_kdb_wait with per cpu state, HOLD_CPU.
+
+	* init/main.c : Replace #ifdef KDB_DEBUG with KDB_DEBUG(CALLBACK).
+
+	* include/linux/kdbprivate.h: Separate command return codes from error
+	codes.  Add more detailed command codes.
+
+	* arch/i386/kernel/traps.c (die): Change spin_lock_irq to
+	spin_lock_irqsave.  Why did I do this?
+
+	* kdb/kdbmain.c (kdb_parse): Set per cpu flag CMD before executing kdb
+	command.  More detailed return codes for commands that affect
+	processors.
+
+	* kdb/kdbmain.c (kdb_previous_event): New, check if any processors are
+	still executing the previous kdb event.  Removes a race window where a
+	second event could enter kdb before the first had completely ended.
+
+	* kdb/kdbmain.c (kdb): Document all the concurrency conditions and how
+	kdb handles them.  ss[b] now releases only the current cpu.  Do not set
+	breakpoints when releasing for ss[b].  Recover from errors in kdb
+	commands.  Check that we have reliable longjmp data before using it.
+
+	* various: Update return code documentation.
+
+	* kdb/kdb_bp.c (kdb_ss): Separate ss and ssb return codes.
+
+	* kdb/kdbsupport.c (kdb_ipi): Finer grained algorithm for deciding
+	whether to call send a stop signal to a cpu.
+
+	* arch/i386/kdb/kdba_bp.c (kdba_db_trap): Separate ss and ssb return
+	codes.  Reinstall delayed software breakpoints per cpu instead of
+	globally.  Changed algorithm for handling ss[b].
+
+	* arch/i386/kdb/kdba_bp.c (kdba_bp_trap): Match software breakpoints per
+	cpu instead of globally.
+
+	* include/linux/kdb.h: Bump version to kdb v1.5.
+
+2000-09-16  Keith Owens  <kaos@melbourne.sgi.com>
+
+	* kernel/sysctl.c (kern_table): add /proc/sys/kernel/kdb.
+
+	* init/main.c (parse_options): add boot flags kdb=on, kdb=off,
+	kdb=early.
+
+	* include/linux/sysctl.h (enum): add KERN_KDB.
+
+	* drivers/char/serial.c (receive_chars): check kdb_on.
+
+	* drivers/char/keyboard.c (handle_scancode): check kdb_on.
+
+	* arch/i386/kernel/traps.c (nmi_watchdog_tick): check kdb_on.
+
+	* arch/i386/config.in: add CONFIG_KDB_OFF.
+
+	* Documentation/Configure.help: add CONFIG_KDB_OFF.
+
+	* kdb/kdbmain.c: add kdb_initial_cpu, kdb_on.
+
+	* kdb/kdbmain.c (kdb): check kdb_on, set kdb_initial_cpu.
+
+	* kdb/kdbmain.c (kdb_init): add Keith Owens to kdb banner.
+
+	* kdb/kdb_io.c (kdb_printf): serialize kdb_printf output.
+
+	* kdb/kdb_bt.c (kdb_bt): check environment variable BTAPROMPT.
+
+	* kdb/kdbsupport.c (kdb_ipi): ignore NMI for kdb_initial_cpu.
+
+	* kdb/modules/kdbm_pg.c (kdbm_page): merge updates from 2.4.0-test5-xfs.
+
+	* kdb/kdb_bt.man: add btp, bta, BTAPROMPT.
+
+	* kdb/kdb.mm: add CONFIG_KDB_OFF, boot flags, btp, bta.
+
+	* include/linux/kdbprivate.h: add kdb_initial_cpu.
+
+	* include/linux/kdb.h: add kdb_on, bump version to kdb v1.4.
diff -uNr linux.orig/kdb/Makefile linux/kdb/Makefile
--- linux.orig/kdb/Makefile	Thu Jan  1 08:00:00 1970
+++ linux/kdb/Makefile	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+O_TARGET	:= kdb.o
+export-objs	:= kdbmain.o kdb_io.o
+obj-y		:= kdb_bt.o kdb_bp.o kdb_id.o kdbsupport.o gen-kdb_cmds.o kdbmain.o kdb_io.o
+
+subdir-$(CONFIG_KDB_MODULES) := modules
+obj-y += $(addsuffix /vmlinux-obj.o, $(subdir-y))
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+EXTRA_CFLAGS += -I $(TOPDIR)/arch/$(ARCH)/kdb
+
+include $(TOPDIR)/Rules.make
+
+gen-kdb_cmds.c:	kdb_cmds Makefile
+	$(AWK) 'BEGIN {print "#include <linux/init.h>"} \
+		/^ *#/{next} \
+		/^[ \t]*$$/{next} \
+		{gsub(/"/, "\\\"", $$0); \
+		  print "static __initdata char kdb_cmd" cmds++ "[] = \"" $$0 "\\n\";"} \
+		END {print "char __initdata *kdb_cmds[] = {"; for (i = 0; i < cmds; ++i) {print "  kdb_cmd" i ","}; print("  0\n};");}' \
+		kdb_cmds > gen-kdb_cmds.c
diff -uNr linux.orig/kdb/kdb_bp.c linux/kdb/kdb_bp.c
--- linux.orig/kdb/kdb_bp.c	Thu Jan  1 08:00:00 1970
+++ linux/kdb/kdb_bp.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,648 @@
+/*
+ * Kernel Debugger Architecture Independent Breakpoint Handler
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <asm/system.h>
+
+/*
+ * Table of kdb_breakpoints
+ */
+kdb_bp_t	kdb_breakpoints[KDB_MAXBPT];
+
+/*
+ * kdb_bp_install_global
+ *
+ *	Install global kdb_breakpoints prior to returning from the
+ *	kernel debugger.  This allows the kdb_breakpoints to be set
+ *	upon functions that are used internally by kdb, such as
+ *	printk().
+ *
+ * Parameters:
+ *	regs	Execution frame.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ *	This function is only called once per kdb session.
+ */
+
+void
+kdb_bp_install_global(struct pt_regs *regs)
+{
+	int i;
+
+	for(i=0; i<KDB_MAXBPT; i++) {
+		if (KDB_DEBUG(BP)) {
+			kdb_printf("kdb_bp_install_global bp %d bp_enabled %d bp_global %d\n",
+				i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global);
+		}
+		if (kdb_breakpoints[i].bp_enabled
+		 && kdb_breakpoints[i].bp_global) {
+			kdba_installbp(regs, &kdb_breakpoints[i]);
+		}
+	}
+}
+
+/*
+ * kdb_bp_install_local
+ *
+ *	Install local kdb_breakpoints prior to returning from the
+ *	kernel debugger.  This allows the kdb_breakpoints to be set
+ *	upon functions that are used internally by kdb, such as
+ *	printk().
+ *
+ * Parameters:
+ *	regs	Execution frame.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ *	This function is called once per processor.
+ */
+
+void
+kdb_bp_install_local(struct pt_regs *regs)
+{
+	int i;
+
+	for(i=0; i<KDB_MAXBPT; i++) {
+		if (KDB_DEBUG(BP)) {
+			kdb_printf("kdb_bp_install_local bp %d bp_enabled %d bp_global %d cpu %d bp_cpu %d\n",
+				i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global,
+				smp_processor_id(), kdb_breakpoints[i].bp_cpu);
+		}
+		if (kdb_breakpoints[i].bp_enabled
+		 && kdb_breakpoints[i].bp_cpu == smp_processor_id()
+		 && !kdb_breakpoints[i].bp_global){
+			kdba_installbp(regs, &kdb_breakpoints[i]);
+		}
+	}
+}
+
+/*
+ * kdb_bp_remove_global
+ *
+ * 	Remove global kdb_breakpoints upon entry to the kernel debugger.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdb_bp_remove_global(void)
+{
+	int i;
+
+	for(i=KDB_MAXBPT-1; i>=0; i--) {
+		if (KDB_DEBUG(BP)) {
+			kdb_printf("kdb_bp_remove_global bp %d bp_enabled %d bp_global %d\n",
+				i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global);
+		}
+		if (kdb_breakpoints[i].bp_enabled
+		 && kdb_breakpoints[i].bp_global) {
+			kdba_removebp(&kdb_breakpoints[i]);
+		}
+	}
+}
+
+
+/*
+ * kdb_bp_remove_local
+ *
+ * 	Remove local kdb_breakpoints upon entry to the kernel debugger.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdb_bp_remove_local(void)
+{
+	int i;
+
+	for(i=KDB_MAXBPT-1; i>=0; i--) {
+		if (KDB_DEBUG(BP)) {
+			kdb_printf("kdb_bp_remove_local bp %d bp_enabled %d bp_global %d cpu %d bp_cpu %d\n",
+				i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global,
+				smp_processor_id(), kdb_breakpoints[i].bp_cpu);
+		}
+		if (kdb_breakpoints[i].bp_enabled
+		 && kdb_breakpoints[i].bp_cpu == smp_processor_id()
+		 && !kdb_breakpoints[i].bp_global){
+			kdba_removebp(&kdb_breakpoints[i]);
+		}
+	}
+}
+
+/*
+ * kdb_printbp
+ *
+ * 	Internal function to format and print a breakpoint entry.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+static void
+kdb_printbp(kdb_bp_t *bp, int i)
+{
+	if (bp->bp_forcehw) {
+		kdb_printf("Forced ");
+	}
+
+	if (!bp->bp_template.bph_free) {
+		kdb_printf("%s ", kdba_bptype(&bp->bp_template));
+	} else {
+		kdb_printf("Instruction(i) ");
+	}
+
+	kdb_printf("BP #%d at ", i);
+	kdb_symbol_print(bp->bp_addr, NULL, KDB_SP_DEFAULT);
+
+	if (bp->bp_enabled) {
+		kdba_printbp(bp);
+		if (bp->bp_global)
+			kdb_printf(" globally");
+		else
+			kdb_printf(" on cpu %d", bp->bp_cpu);
+		if (bp->bp_adjust)
+			kdb_printf(" adjust %d", bp->bp_adjust);
+	} else {
+		kdb_printf("\n    is disabled");
+	}
+
+	kdb_printf("\n");
+}
+
+/*
+ * kdb_bp
+ *
+ * 	Handle the bp, and bpa commands.
+ *
+ *	[bp|bpa|bph] <addr-expression> [DATAR|DATAW|IO [length]]
+ *
+ * Parameters:
+ *	argc	Count of arguments in argv
+ *	argv	Space delimited command line arguments
+ *	envp	Environment value
+ *	regs	Exception frame at entry to kernel debugger
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic if failure.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ * 	bp	Set breakpoint.  Only use hardware assist if necessary.
+ *	bpa	Set breakpoint on all cpus, only use hardware regs if necessary
+ *	bph	Set breakpoint - force hardware register
+ *	bpha	Set breakpoint on all cpus, force hardware register
+ */
+
+int
+kdb_bp(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int     i, bpno;
+	kdb_bp_t *bp, *bp_check;
+	int     diag;
+	int     free;
+	kdb_machreg_t addr;
+	char   *symname = NULL;
+	long    offset = 0ul;
+	int	nextarg;
+	int	hardware;
+	int	global;
+
+	if (argc == 0) {
+		/*
+		 * Display breakpoint table
+		 */
+		for(bpno=0,bp=kdb_breakpoints; bpno<KDB_MAXBPT; bpno++, bp++) {
+			if (bp->bp_free) continue;
+
+			kdb_printbp(bp, bpno);
+		}
+
+		return 0;
+	}
+
+	global = ((strcmp(argv[0], "bpa") == 0)
+	       || (strcmp(argv[0], "bpha") == 0));
+	hardware = ((strcmp(argv[0], "bph") == 0)
+		 || (strcmp(argv[0], "bpha") == 0));
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, &symname, regs);
+	if (diag)
+		return diag;
+	if (!addr)
+		return KDB_BADINT;
+
+	/*
+	 * Allocate a new bp structure
+	 */
+	free = KDB_MAXBPT;
+	for(bpno=0,bp=kdb_breakpoints; bpno<KDB_MAXBPT; bpno++,bp++) {
+		if (bp->bp_free) {
+			break;
+		}
+	}
+
+	if (bpno == KDB_MAXBPT)
+		return KDB_TOOMANYBPT;
+
+	memset(bp, 0, sizeof(*bp));
+	bp->bp_free = 1;
+	kdba_check_pc(&addr);
+	for(i=0,bp_check=kdb_breakpoints; i<KDB_MAXBPT; i++,bp_check++) {
+		if (!bp_check->bp_free && bp_check->bp_addr == addr) {
+			kdb_printf("You already have a breakpoint at " kdb_bfd_vma_fmt0 "\n", addr);
+			return KDB_DUPBPT;
+		}
+	}
+	bp->bp_addr = addr;
+	bp->bp_free = 0;
+
+	bp->bp_forcehw = hardware;
+	if (KDB_DEBUG(BP))
+		kdb_printf("kdb_bp: forcehw is %d hardware is %d\n", bp->bp_forcehw, hardware);
+
+	/*
+	 * Handle architecture dependent parsing
+	 */
+	diag = kdba_parsebp(argc, argv, &nextarg, bp);
+	if (diag) {
+		return diag;
+	}
+
+	bp->bp_enabled = 1;
+	bp->bp_global = 1;	/* Most breakpoints are global */
+
+	if (hardware && !global) {
+		bp->bp_global = 0;
+		bp->bp_cpu = smp_processor_id();
+	}
+
+	/*
+	 * Allocate a hardware breakpoint.  If one is not available,
+ 	 * disable the breakpoint, but leave it in the breakpoint
+	 * table.  When the breakpoint is re-enabled (via 'be'), we'll
+	 * attempt to allocate a hardware register for it.
+	 */
+	if (!bp->bp_template.bph_free) {
+		bp->bp_hard = kdba_allocbp(&bp->bp_template, &diag);
+		if (diag) {
+			bp->bp_enabled = 0;
+			return diag;
+		}
+		bp->bp_hardtype = 1;
+	}
+
+	kdb_printbp(bp, bpno);
+
+	return 0;
+}
+
+/*
+ * kdb_bc
+ *
+ * 	Handles the 'bc', 'be', and 'bd' commands
+ *
+ *	[bd|bc|be] <breakpoint-number>
+ *
+ * Parameters:
+ *	argc	Count of arguments in argv
+ *	argv	Space delimited command line arguments
+ *	envp	Environment value
+ *	regs	Exception frame at entry to kernel debugger
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+#define KDBCMD_BC	0
+#define KDBCMD_BE	1
+#define KDBCMD_BD	2
+
+int
+kdb_bc(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	kdb_machreg_t 	addr;
+	kdb_bp_t	*bp = 0;
+	int lowbp = KDB_MAXBPT;
+	int highbp = 0;
+	int done = 0;
+	int i;
+	int diag;
+	int cmd;			/* KDBCMD_B? */
+
+	if (strcmp(argv[0], "be") == 0) {
+		cmd = KDBCMD_BE;
+	} else if (strcmp(argv[0], "bd") == 0) {
+		cmd = KDBCMD_BD;
+	} else
+		cmd = KDBCMD_BC;
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	if (strcmp(argv[1], "*") == 0) {
+		lowbp = 0;
+		highbp = KDB_MAXBPT;
+	} else {
+		diag = kdbgetularg(argv[1], &addr);
+		if (diag)
+			return diag;
+
+		/*
+		 * For addresses less than the maximum breakpoint number,
+		 * assume that the breakpoint number is desired.
+		 */
+		if (addr < KDB_MAXBPT) {
+			bp = &kdb_breakpoints[addr];
+			lowbp = highbp = addr;
+			highbp++;
+		} else {
+			for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+				if (bp->bp_addr == addr) {
+					lowbp = highbp = i;
+					highbp++;
+					break;
+				}
+			}
+		}
+	}
+
+	/*
+	 * Now operate on the set of breakpoints matching the input
+	 * criteria (either '*' for all, or an individual breakpoint).
+	 */
+	for(bp=&kdb_breakpoints[lowbp], i=lowbp;
+	    i < highbp;
+	    i++, bp++) {
+		if (bp->bp_free)
+			continue;
+
+		done++;
+
+		switch (cmd) {
+		case KDBCMD_BC:
+			if (bp->bp_hardtype) {
+				kdba_freebp(bp->bp_hard);
+				bp->bp_hard = 0;
+				bp->bp_hardtype = 0;
+			}
+
+			bp->bp_enabled = 0;
+			bp->bp_global = 0;
+
+			kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " cleared\n",
+				i, bp->bp_addr);
+
+			bp->bp_addr = 0;
+			bp->bp_free = 1;
+
+			break;
+		case KDBCMD_BE:
+			/*
+			 * Allocate a hardware breakpoint.  If one is not
+			 * available, don't enable the breakpoint.
+			 */
+			if (!bp->bp_template.bph_free
+			 && !bp->bp_hardtype) {
+				bp->bp_hard = kdba_allocbp(&bp->bp_template, &diag);
+				if (diag) {
+					bp->bp_enabled = 0;
+					return diag;
+				}
+				bp->bp_hardtype = 1;
+			}
+
+			bp->bp_enabled = 1;
+
+			kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " in enabled",
+				i, bp->bp_addr);
+
+			kdb_printf("\n");
+			break;
+		case KDBCMD_BD:
+			if (!bp->bp_enabled) {
+				return 0;
+			}
+
+			/*
+			 * Since this breakpoint is now disabled, we can
+			 * give up the hardware register which is allocated
+			 * to it.
+			 */
+			if (bp->bp_hardtype) {
+				kdba_freebp(bp->bp_hard);
+				bp->bp_hard = 0;
+				bp->bp_hardtype = 0;
+			}
+
+			bp->bp_enabled = 0;
+
+			kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " disabled\n",
+				i, bp->bp_addr);
+
+			break;
+		}
+		if (bp->bp_delay && (cmd == KDBCMD_BC || cmd == KDBCMD_BD)) {
+			bp->bp_delay = 0;
+			KDB_STATE_CLEAR(SSBPT);
+		}
+	}
+
+	return (!done)?KDB_BPTNOTFOUND:0;
+}
+
+/*
+ * kdb_ss
+ *
+ *	Process the 'ss' (Single Step) and 'ssb' (Single Step to Branch)
+ *	commands.
+ *
+ *	ss
+ *	ssb
+ *
+ * Parameters:
+ *	argc	Argument count
+ *	argv	Argument vector
+ *	envp	Environment vector
+ *	regs	Registers at time of entry to kernel debugger
+ * Outputs:
+ *	None.
+ * Returns:
+ *	KDB_CMD_SS[B] for success, a kdb error if failure.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ *	Set the arch specific option to trigger a debug trap after the next
+ *	instruction.
+ *
+ *	For 'ssb', set the trace flag in the debug trap handler
+ *	after printing the current insn and return directly without
+ *	invoking the kdb command processor, until a branch instruction
+ *	is encountered.
+ */
+
+int
+kdb_ss(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int ssb = 0;
+
+	ssb = (strcmp(argv[0], "ssb") == 0);
+	if (argc != 0)
+		return KDB_ARGCOUNT;
+
+	if (!regs) {
+		kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+		return KDB_BADREG;
+	}
+
+	/*
+	 * Set trace flag and go.
+	 */
+	KDB_STATE_SET(DOING_SS);
+	if (ssb)
+		KDB_STATE_SET(DOING_SSB);
+
+	kdba_setsinglestep(regs);		/* Enable single step */
+
+	if (ssb)
+		return KDB_CMD_SSB;
+	return KDB_CMD_SS;
+}
+
+/*
+ * kdb_initbptab
+ *
+ *	Initialize the breakpoint table.  Register breakpoint commands.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void __init
+kdb_initbptab(void)
+{
+	int i;
+	kdb_bp_t *bp;
+
+	/*
+	 * First time initialization.
+	 */
+	memset(&kdb_breakpoints, '\0', sizeof(kdb_breakpoints));
+
+	for (i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+		bp->bp_free = 1;
+		/*
+		 * The bph_free flag is architecturally required.  It
+		 * is set by architecture-dependent code to false (zero)
+		 * in the event a hardware breakpoint register is required
+		 * for this breakpoint.
+		 *
+		 * The rest of the template is reserved to the architecture
+		 * dependent code and _must_ not be touched by the architecture
+		 * independent code.
+		 */
+		bp->bp_template.bph_free = 1;
+	}
+
+	kdb_register_repeat("bp", kdb_bp, "[<vaddr>]", "Set/Display breakpoints", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("bl", kdb_bp, "[<vaddr>]", "Display breakpoints", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("bpa", kdb_bp, "[<vaddr>]", "Set/Display global breakpoints", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("bph", kdb_bp, "[<vaddr>]", "Set hardware breakpoint", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("bpha", kdb_bp, "[<vaddr>]", "Set global hardware breakpoint", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("bc", kdb_bc, "<bpnum>",   "Clear Breakpoint", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("be", kdb_bc, "<bpnum>",   "Enable Breakpoint", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("bd", kdb_bc, "<bpnum>",   "Disable Breakpoint", 0, KDB_REPEAT_NONE);
+
+	kdb_register_repeat("ss", kdb_ss, "", "Single Step", 1, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("ssb", kdb_ss, "", "Single step to branch/call", 0, KDB_REPEAT_NO_ARGS);
+	/*
+	 * Architecture dependent initialization.
+	 */
+	kdba_initbp();
+}
+
diff -uNr linux.orig/kdb/kdb_bt.c linux/kdb/kdb_bt.c
--- linux.orig/kdb/kdb_bt.c	Thu Jan  1 08:00:00 1970
+++ linux/kdb/kdb_bt.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,198 @@
+/*
+ * Kernel Debugger Architecture Independent Stack Traceback
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/nmi.h>
+#include <asm/system.h>
+
+
+/*
+ * kdb_bt
+ *
+ *	This function implements the 'bt' command.  Print a stack
+ *	traceback.
+ *
+ *	bt [<address-expression>]	(addr-exp is for alternate stacks)
+ *	btp <pid>			Kernel stack for <pid>
+ *	btt <address-expression>	Kernel stack for task structure at <address-expression>
+ *	bta [DRSTZU]			All processes, optionally filtered by state
+ *	btc [<cpu>]			The current process on one cpu, default is all cpus
+ *
+ * 	address expression refers to a return address on the stack.  It
+ *	is expected to be preceeded by a frame pointer.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	Backtrack works best when the code uses frame pointers.  But
+ *	even without frame pointers we should get a reasonable trace.
+ *
+ *	mds comes in handy when examining the stack to do a manual
+ *	traceback.
+ */
+
+static int
+kdb_bt1(struct task_struct *p, unsigned long mask, int argcount, int btaprompt)
+{
+	int diag;
+	char buffer[2];
+	if (kdb_getarea(buffer[0], (unsigned long)p) ||
+	    kdb_getarea(buffer[0], (unsigned long)(p+1)-1))
+		return KDB_BADADDR;
+	if (!kdb_task_state(p, mask))
+		return 0;
+	kdb_printf("Stack traceback for pid %d\n", p->pid);
+	kdb_ps1(p);
+	diag = kdba_bt_process(p, argcount);
+	if (btaprompt) {
+		kdb_getstr(buffer, sizeof(buffer), "Enter <q> to end, <cr> to continue:");
+		if (buffer[0] == 'q') {
+			kdb_printf("\n");
+			return 1;
+		}
+	}
+	touch_nmi_watchdog();
+	return 0;
+}
+
+int
+kdb_bt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int	diag;
+	int	argcount = 5;
+	int	btaprompt = 1;
+	int 	nextarg;
+	unsigned long addr;
+	long	offset;
+
+	kdbgetintenv("BTARGS", &argcount);	/* Arguments to print */
+	kdbgetintenv("BTAPROMPT", &btaprompt);	/* Prompt after each proc in bta */
+
+	if (strcmp(argv[0], "bta") == 0) {
+		struct task_struct *p;
+		unsigned long cpu;
+		unsigned long mask = kdb_task_state_string(argc, argv, envp);
+		/* Run the active tasks first */
+		for (cpu = 0; cpu < smp_num_cpus; ++cpu) {
+			p = kdb_active_task[cpu];
+			if (kdb_bt1(p, mask, argcount, btaprompt))
+				return 0;
+		}
+		/* Now the inactive tasks */
+		for_each_task(p) {
+			if (kdb_task_has_cpu(p) && kdb_active_task[kdb_process_cpu(p)] == p)
+				continue;
+			if (kdb_bt1(p, mask, argcount, btaprompt))
+				return 0;
+		}
+	} else if (strcmp(argv[0], "btp") == 0) {
+		struct task_struct *p = NULL;
+		unsigned long	   pid;
+		if (argc != 1)
+			return KDB_ARGCOUNT;
+		if ((diag = kdbgetularg((char *)argv[1], &pid)))
+			return diag;
+		for_each_task(p) {
+			if (p->pid == (pid_t)pid)
+				break;
+		}
+		if (p && p->pid == (pid_t)pid)
+			return kdb_bt1(p, ~0, argcount, 0);
+		kdb_printf("No process with pid == %ld found\n", pid);
+		return 0;
+	} else if (strcmp(argv[0], "btt") == 0) {
+		unsigned long addr;
+		if (argc != 1)
+			return KDB_ARGCOUNT;
+		if ((diag = kdbgetularg((char *)argv[1], &addr)))
+			return diag;
+		return kdb_bt1((struct task_struct *)addr, ~0, argcount, 0);
+	} else if (strcmp(argv[0], "btc") == 0) {
+		unsigned long cpu = ~0;
+		struct kdb_running_process *krp;
+		char buf[80];
+		if (argc > 1)
+			return KDB_ARGCOUNT;
+		if (argc == 1 && (diag = kdbgetularg((char *)argv[1], &cpu)))
+			return diag;
+		if (cpu != ~0) {
+			krp = kdb_running_process + cpu;
+			if (cpu >= smp_num_cpus || !krp->seqno) {
+				kdb_printf("no process for cpu %ld\n", cpu);
+				return 0;
+			}
+			sprintf(buf, "btt 0x%p\n", krp->p);
+			kdb_parse(buf, regs);
+			return 0;
+		}
+		kdb_printf("btc: cpu status: ");
+		kdb_parse("cpu\n", regs);
+		for (cpu = 0, krp = kdb_running_process; cpu < smp_num_cpus; ++cpu, ++krp) {
+			if (!krp->seqno)
+				continue;
+			sprintf(buf, "btt 0x%p\n", krp->p);
+			kdb_parse(buf, regs);
+			touch_nmi_watchdog();
+		}
+		return 0;
+	} else {
+		if (argc) {
+			nextarg = 1;
+			diag = kdbgetaddrarg(argc, argv, &nextarg, &addr,
+					     &offset, NULL, regs);
+			if (diag)
+				return diag;
+			return kdba_bt_address(addr, argcount);
+		} else {
+			return kdb_bt1(current, ~0, argcount, 0);
+		}
+	}
+
+	/* NOTREACHED */
+	return 0;
+}
diff -uNr linux.orig/kdb/kdb_cmds linux/kdb/kdb_cmds
--- linux.orig/kdb/kdb_cmds	Thu Jan  1 08:00:00 1970
+++ linux/kdb/kdb_cmds	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,6 @@
+# Initial commands for kdb, alter to suit your needs.
+# These commands are executed in kdb_init() context, no SMP, no
+# processes.  Commands that require process data (including stack or
+# registers) are not reliable this early.  set and bp commands should
+# be safe.  Global breakpoint commands affect each cpu as it is booted.
+
diff -uNr linux.orig/kdb/kdb_id.c linux/kdb/kdb_id.c
--- linux.orig/kdb/kdb_id.c	Thu Jan  1 08:00:00 1970
+++ linux/kdb/kdb_id.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,263 @@
+/*
+ * Kernel Debugger Architecture Independent Instruction Disassembly
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+disassemble_info	kdb_di;
+
+/*
+ * kdb_id
+ *
+ * 	Handle the id (instruction display) command.
+ *
+ *	id  [<addr>]
+ *
+ * Parameters:
+ *	argc	Count of arguments in argv
+ *	argv	Space delimited command line arguments
+ *	envp	Environment value
+ *	regs	Exception frame at entry to kernel debugger
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic if failure.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdb_id(int argc, const char **argv, const char **envp, struct pt_regs* regs)
+{
+	kdb_machreg_t		pc;
+	int			icount;
+	int			diag;
+	int			i;
+	char *			mode;
+	int			nextarg;
+	long			offset = 0;
+	static kdb_machreg_t 	lastpc;
+	struct disassemble_info *dip = &kdb_di;
+	char			lastbuf[50];
+	unsigned long		word;
+
+	if (argc != 1)  {
+		if (lastpc == 0) {
+			return KDB_ARGCOUNT;
+		} else {
+			sprintf(lastbuf, "0x%lx", lastpc);
+			argv[1] = lastbuf;
+			argc = 1;
+		}
+	}
+
+
+	/*
+	 * Fetch PC.  First, check to see if it is a symbol, if not,
+	 * try address.
+	 */
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &pc, &offset, NULL, regs);
+	if (diag)
+		return diag;
+	kdba_check_pc(&pc);
+	if (kdb_getarea(word, pc))
+		return(0);
+
+	/*
+	 * Number of lines to display
+	 */
+	diag = kdbgetintenv("IDCOUNT", &icount);
+	if (diag)
+		return diag;
+
+	dip->fprintf_dummy = kdb_dis_fprintf;
+
+	mode = kdbgetenv("IDMODE");
+	diag = kdba_id_parsemode(mode, dip);
+	if (diag) {
+		return diag;
+	}
+
+	for(i=0; i<icount; i++) {
+		pc += kdba_id_printinsn(pc, &kdb_di);
+		kdb_printf("\n");
+	}
+
+	lastpc = pc;
+
+	return 0;
+}
+
+/*
+ * kdb_id1
+ *
+ * 	Disassemble a single instruction at 'pc'.
+ *
+ * Parameters:
+ *	pc	Address of instruction to disassemble
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic if failure.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdb_id1(unsigned long pc)
+{
+	char   *mode;
+	int	diag;
+
+	/*
+	 * Allow the user to specify that this instruction
+	 * should be treated differently.
+	 */
+
+	kdb_di.fprintf_dummy = kdb_dis_fprintf_dummy;
+
+	mode = kdbgetenv("IDMODE");
+	diag = kdba_id_parsemode(mode, &kdb_di);
+	if (diag) {
+		kdb_printf("kdb_id: bad value in 'IDMODE' environment variable ignored\n");
+	}
+
+	(void) kdba_id_printinsn(pc, &kdb_di);
+	kdb_printf("\n");
+}
+
+/*
+ * kdb_dis_fprintf
+ *
+ *	Format and print a string.
+ *
+ * Parameters:
+ *	file	Unused paramter.
+ *	fmt	Format string
+ *	...	Optional additional parameters.
+ * Returns:
+ *	0
+ * Locking:
+ * Remarks:
+ * 	Result of format conversion cannot exceed 255 bytes.
+ */
+
+int
+kdb_dis_fprintf(PTR file, const char *fmt, ...)
+{
+	char buffer[256];
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsprintf(buffer, fmt, ap);
+	va_end(ap);
+
+	kdb_printf("%s", buffer);
+
+	return 0;
+}
+
+/*
+ * kdb_dis_fprintf_dummy
+ *
+ *	A dummy printf function for the disassembler, it does nothing.
+ *	This lets code call the disassembler to step through
+ *	instructions without actually printing anything.
+ * Inputs:
+ *	Always ignored.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Always 0.
+ * Locking:
+ *	none.
+ * Remarks:
+ *	None.
+ */
+
+int
+kdb_dis_fprintf_dummy(PTR file, const char *fmt, ...)
+{
+	return(0);
+}
+
+/*
+ * kdb_disinit
+ *
+ * 	Initialize the disassembly information structure
+ *	for the GNU disassembler.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic if failure.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void __init
+kdb_id_init(void)
+{
+	kdb_di.stream	    = NULL;
+	kdb_di.application_data = NULL;
+	kdb_di.symbols	    = NULL;
+	kdb_di.num_symbols  = 0;
+	kdb_di.flags	    = 0;
+	kdb_di.private_data	    = NULL;
+	kdb_di.buffer	    = NULL;
+	kdb_di.buffer_vma       = 0;
+	kdb_di.buffer_length    = 0;
+	kdb_di.bytes_per_line   = 0;
+	kdb_di.bytes_per_chunk  = 0;
+	kdb_di.insn_info_valid  = 0;
+	kdb_di.branch_delay_insns = 0;
+	kdb_di.data_size	    = 0;
+	kdb_di.insn_type	    = 0;
+	kdb_di.target           = 0;
+	kdb_di.target2          = 0;
+	kdb_di.fprintf_func	= kdb_dis_fprintf;
+
+	kdba_id_init(&kdb_di);
+}
diff -uNr linux.orig/kdb/kdb_io.c linux/kdb/kdb_io.c
--- linux.orig/kdb/kdb_io.c	Thu Jan  1 08:00:00 1970
+++ linux/kdb/kdb_io.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,649 @@
+/*
+ * Kernel Debugger Architecture Independent Console I/O handler
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/nmi.h>
+#include <linux/delay.h>
+
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/kallsyms.h>
+
+#ifdef CONFIG_SPARC64
+#include <asm/oplib.h>
+#else
+static struct console *kdbcons;
+#endif
+
+
+#define CMD_BUFLEN 256
+char kdb_prompt_str[CMD_BUFLEN];
+
+/*
+ * kdb_read
+ *
+ *	This function reads a string of characters, terminated by
+ *	a newline, or by reaching the end of the supplied buffer,
+ *	from the current kernel debugger console device.
+ * Parameters:
+ *	buffer	- Address of character buffer to receive input characters.
+ *	bufsize - size, in bytes, of the character buffer
+ * Returns:
+ *	Returns a pointer to the buffer containing the received
+ *	character string.  This string will be terminated by a
+ *	newline character.
+ * Locking:
+ *	No locks are required to be held upon entry to this
+ *	function.  It is not reentrant - it relies on the fact
+ *	that while kdb is running on any one processor all other
+ *	processors will be spinning at the kdb barrier.
+ * Remarks:
+ *
+ * Davidm asks, why doesn't kdb use the console abstraction;
+ * here are some reasons:
+ *      - you cannot debug the console abstraction with kdb if
+ *        kdb uses it.
+ *      - you rely on the correct functioning of the abstraction
+ *        in the presence of general system failures.
+ *      - You must acquire the console spinlock thus restricting
+ *        the usability - what if the kernel fails with the spinlock
+ *        held - one still wishes to debug such situations.
+ *      - How about debugging before the console(s) are registered?
+ *      - None of the current consoles (sercons, vt_console_driver)
+ *        have read functions defined.
+ *	- The standard pc keyboard and terminal drivers are interrupt
+ *	  driven.   We cannot enable interrupts while kdb is active,
+ *	  so the standard input functions cannot be used by kdb.
+ *
+ * An implementation could be improved by removing the need for
+ * lock acquisition - just keep a 'struct console *kdbconsole;' global
+ * variable which refers to the preferred kdb console.
+ *
+ * The bulk of this function is architecture dependent.
+ *
+ * The buffer size must be >= 2.  A buffer size of 2 means that the caller only
+ * wants a single key.
+ *
+ * An escape key could be the start of a vt100 control sequence such as \e[D
+ * (left arrow) or it could be a character in its own right.  The standard
+ * method for detecting the difference is to wait for 2 seconds to see if there
+ * are any other characters.  kdb is complicated by the lack of a timer service
+ * (interrupts are off), by multiple input sources and by the need to sometimes
+ * return after just one key.  Escape sequence processing has to be done as
+ * states in the polling loop.
+ */
+
+char *
+kdb_read(char *buffer, size_t bufsize)
+{
+	char	*cp = buffer;
+	char	*bufend = buffer+bufsize-2;	/* Reserve space for newline and null byte */
+
+	char	*lastchar;
+	char	*p_tmp;
+	char	tmp;
+	static char	tmpbuffer[CMD_BUFLEN];
+	int len = strlen(buffer);
+	int len_tmp;
+	int tab=0;
+	int count;
+	int i;
+	int diag, dtab_count;
+
+#define ESCAPE_UDELAY 1000
+#define ESCAPE_DELAY 2*1000000/ESCAPE_UDELAY	/* 2 seconds worth of udelays */
+	char escape_data[5];	/* longest vt100 escape sequence is 4 bytes */
+	char *ped = escape_data;
+	int escape_delay = 0;
+	get_char_func *f, *f_escape = NULL;
+
+	diag = kdbgetintenv("DTABCOUNT",&dtab_count);
+	if (diag)
+		dtab_count = 30;
+
+	if (len > 0 ) {
+		cp += len;
+		if (*(buffer+len-1) == '\n')
+			cp--;
+	}
+
+	lastchar = cp;
+	*cp = '\0';
+	kdb_printf("%s", buffer);
+
+	for (;;) {
+		int key;
+		for (f = &poll_funcs[0]; ; ++f) {
+			if (*f == NULL) {
+				/* Reset NMI watchdog once per poll loop */
+				touch_nmi_watchdog();
+				f = &poll_funcs[0];
+			}
+			if (escape_delay == 2) {
+				*ped = '\0';
+				ped = escape_data;
+				--escape_delay;
+			}
+			if (escape_delay == 1) {
+				key = *ped++;
+				if (!*ped)
+					--escape_delay;
+				break;
+			}
+			key = (*f)();
+			if (key == -1) {
+				if (escape_delay) {
+					udelay(ESCAPE_UDELAY);
+					--escape_delay;
+				}
+				continue;
+			}
+			if (bufsize <= 2) {
+				if (key == '\r')
+					key = '\n';
+				kdb_printf("%c", key);
+				*buffer++ = key;
+				*buffer = '\0';
+				return buffer;
+			}
+			if (escape_delay == 0 && key == '\e') {
+				escape_delay = ESCAPE_DELAY;
+				ped = escape_data;
+				f_escape = f;
+			}
+			if (escape_delay) {
+				*ped++ = key;
+				if (f_escape != f) {
+					escape_delay = 2;
+					continue;
+				}
+				if (ped - escape_data == 1) {
+					/* \e */
+					continue;
+				}
+				else if (ped - escape_data == 2) {
+					/* \e<something> */
+					if (key != '[')
+						escape_delay = 2;
+					continue;
+				} else if (ped - escape_data == 3) {
+					/* \e[<something> */
+					int mapkey = 0;
+					switch (key) {
+					case 'A': mapkey = 16; break;	/* \e[A, up arrow */
+					case 'B': mapkey = 14; break;	/* \e[B, down arrow */
+					case 'C': mapkey = 6; break;	/* \e[C, right arrow */
+					case 'D': mapkey = 2; break;	/* \e[D, left arrow */
+					case '1': /* dropthrough */
+					case '3': /* dropthrough */
+					case '4': mapkey = -1; break;	/* \e[<1,3,4>], may be home, del, end */
+					}
+					if (mapkey != -1) {
+						if (mapkey > 0) {
+							escape_data[0] = mapkey;
+							escape_data[1] = '\0';
+						}
+						escape_delay = 2;
+					}
+					continue;
+				} else if (ped - escape_data == 4) {
+					/* \e[<1,3,4><something> */
+					int mapkey = 0;
+					if (key == '~') {
+						switch (escape_data[2]) {
+						case '1': mapkey = 1; break;	/* \e[1~, home */
+						case '3': mapkey = 4; break;	/* \e[3~, del */
+						case '4': mapkey = 5; break;	/* \e[4~, end */
+						}
+					}
+					if (mapkey > 0) {
+						escape_data[0] = mapkey;
+						escape_data[1] = '\0';
+					}
+					escape_delay = 2;
+					continue;
+				}
+			}
+			break;	/* A key to process */
+		}
+
+		if (key != 9)
+			tab = 0;
+		switch (key) {
+		case 8: /* backspace */
+			if (cp > buffer) {
+				if (cp < lastchar) {
+					memcpy(tmpbuffer, cp, lastchar - cp);
+					memcpy(cp-1, tmpbuffer, lastchar - cp);
+				}
+				*(--lastchar) = '\0';
+				--cp;
+				kdb_printf("\b%s \r", cp);
+				tmp = *cp;
+				*cp = '\0';
+				kdb_printf(kdb_prompt_str);
+				kdb_printf("%s", buffer);
+				*cp = tmp;
+			}
+			break;
+		case 13: /* enter */
+			*lastchar++ = '\n';
+			*lastchar++ = '\0';
+			kdb_printf("\n");
+			return buffer;
+		case 4: /* Del */
+			if(cp < lastchar) {
+				memcpy(tmpbuffer, cp+1, lastchar - cp -1);
+				memcpy(cp, tmpbuffer, lastchar - cp -1);
+				*(--lastchar) = '\0';
+				kdb_printf("%s \r", cp);
+				tmp = *cp;
+				*cp = '\0';
+				kdb_printf(kdb_prompt_str);
+				kdb_printf("%s", buffer);
+				*cp = tmp;
+			}
+			break;
+		case 1: /* Home */
+			if(cp > buffer) {
+				kdb_printf("\r");
+				kdb_printf(kdb_prompt_str);
+				cp = buffer;
+			}
+			break;
+		case 5: /* End */
+			if(cp < lastchar) {
+				kdb_printf("%s", cp);
+				cp = lastchar;
+			}
+			break;
+		case 2: /* Left */
+			if (cp > buffer) {
+				kdb_printf("\b");
+				--cp;
+			}
+			break;
+		case 14: /* Down */
+			memset(tmpbuffer, ' ', strlen(kdb_prompt_str)+(lastchar-buffer));
+			*(tmpbuffer+strlen(kdb_prompt_str)+(lastchar-buffer)) = '\0';
+			kdb_printf("\r%s\r", tmpbuffer);
+			*lastchar = (char)key;
+			*(lastchar+1) = '\0';
+			return lastchar;
+		case 6: /* Right */
+			if (cp < lastchar) {
+				kdb_printf("%c", *cp);
+				++cp;
+			}
+			break;
+		case 16: /* Up */
+			memset(tmpbuffer, ' ', strlen(kdb_prompt_str)+(lastchar-buffer));
+			*(tmpbuffer+strlen(kdb_prompt_str)+(lastchar-buffer)) = '\0';
+			kdb_printf("\r%s\r", tmpbuffer);
+			*lastchar = (char)key;
+			*(lastchar+1) = '\0';
+			return lastchar;
+		case 9: /* Tab */
+			if (tab < 2)
+				++tab;
+			p_tmp = buffer;
+			while(*p_tmp==' ') p_tmp++;
+			if (p_tmp<=cp) {
+				memcpy(tmpbuffer, p_tmp, cp-p_tmp);
+				*(tmpbuffer + (cp-p_tmp)) = '\0';
+				p_tmp = strrchr(tmpbuffer, ' ');
+				if (p_tmp)
+					++p_tmp;
+				else
+					p_tmp = tmpbuffer;
+				len = strlen(p_tmp);
+				if (tab == 2) {
+					if((count=kallsyms_symbol_complete(p_tmp))>0) {
+						kdb_printf("\n%d symbols are found.", count);
+						if(count>dtab_count) {
+							count=dtab_count;
+							kdb_printf(" But only first %d symbols will be printed.\nYou can change the environment variable DTABCOUNT.", count);
+						}
+						kdb_printf("\n");
+						for(i=0;i<count;i++) {
+							if(kallsyms_symbol_next(p_tmp, i)<0)
+								break;
+							kdb_printf("%s ",p_tmp);
+							*(p_tmp+len)='\0';
+						}
+						if(i>=dtab_count)kdb_printf("...");
+						kdb_printf("\n");
+						kdb_printf(kdb_prompt_str);
+						kdb_printf("%s", buffer);
+					}
+				}
+				else {
+					if(kallsyms_symbol_complete(p_tmp)>0) {
+						len_tmp = strlen(p_tmp);
+						strncpy(p_tmp+len_tmp,cp, lastchar-cp+1);
+						len_tmp = strlen(p_tmp);
+						strncpy(cp, p_tmp+len, len_tmp-len+1);
+						len = len_tmp - len;
+						kdb_printf("%s", cp);
+						cp+=len;
+						lastchar+=len;
+					}
+				}
+				kdb_nextline = 1;		/* reset output line number */
+			}
+			break;
+		default:
+			if (key >= 32 &&lastchar < bufend) {
+				if (cp < lastchar) {
+					memcpy(tmpbuffer, cp, lastchar - cp);
+					memcpy(cp+1, tmpbuffer, lastchar - cp);
+				}
+				*(++lastchar) = '\0';
+				*cp = key;
+				kdb_printf("%s\r", cp);
+				++cp;
+				tmp = *cp;
+				*cp = '\0';
+				kdb_printf(kdb_prompt_str);
+				kdb_printf("%s", buffer);
+				*cp = tmp;
+			}
+			break;
+		}
+	}
+}
+
+/*
+ * kdb_getstr
+ *
+ *	Print the prompt string and read a command from the
+ *	input device.
+ *
+ * Parameters:
+ *	buffer	Address of buffer to receive command
+ *	bufsize Size of buffer in bytes
+ *	prompt	Pointer to string to use as prompt string
+ * Returns:
+ *	Pointer to command buffer.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	For SMP kernels, the processor number will be
+ *	substituted for %d, %x or %o in the prompt.
+ */
+
+char *
+kdb_getstr(char *buffer, size_t bufsize, char *prompt)
+{
+	if(prompt && kdb_prompt_str!=prompt)
+		strncpy(kdb_prompt_str, prompt, CMD_BUFLEN);
+	kdb_printf(kdb_prompt_str);
+	kdb_nextline = 1;	/* Prompt and input resets line number */
+	return kdb_read(buffer, bufsize);
+}
+
+/*
+ * kdb_input_flush
+ *
+ *	Get rid of any buffered console input.
+ *
+ * Parameters:
+ *	none
+ * Returns:
+ *	nothing
+ * Locking:
+ *	none
+ * Remarks:
+ *	Call this function whenever you want to flush input.  If there is any
+ *	outstanding input, it ignores all characters until there has been no
+ *	data for approximately half a second.
+ */
+
+#define FLUSH_UDELAY 100
+#define FLUSH_DELAY 500000/FLUSH_UDELAY	/* 0.5 seconds worth of udelays */
+
+static void
+kdb_input_flush(void)
+{
+	get_char_func *f;
+	int flush_delay = 1;
+	while (flush_delay--) {
+		touch_nmi_watchdog();
+		for (f = &poll_funcs[0]; *f; ++f) {
+			if ((*f)() != -1) {
+				flush_delay = FLUSH_DELAY;
+				break;
+			}
+		}
+		if (flush_delay)
+			udelay(FLUSH_UDELAY);
+	}
+}
+
+/*
+ * kdb_printf
+ *
+ *	Print a string to the output device(s).
+ *
+ * Parameters:
+ *	printf-like format and optional args.
+ * Returns:
+ *	0
+ * Locking:
+ *	None.
+ * Remarks:
+ *	use 'kdbcons->write()' to avoid polluting 'log_buf' with
+ *	kdb output.
+ */
+
+static char kdb_buffer[256];	/* A bit too big to go on stack */
+
+void
+kdb_printf(const char *fmt, ...)
+{
+	va_list	ap;
+	int diag;
+	int linecount;
+	int logging, saved_loglevel = 0;
+	int do_longjmp = 0;
+	int got_printf_lock = 0;
+	struct console *c = console_drivers;
+	static spinlock_t kdb_printf_lock = SPIN_LOCK_UNLOCKED;
+
+	/* Serialize kdb_printf if multiple cpus try to write at once.
+	 * But if any cpu goes recursive in kdb, just print the output,
+	 * even if it is interleaved with any other text.
+	 */
+	if (!KDB_STATE(PRINTF_LOCK)) {
+		KDB_STATE_SET(PRINTF_LOCK);
+		spin_lock(&kdb_printf_lock);
+		got_printf_lock = 1;
+	}
+
+	diag = kdbgetintenv("LINES", &linecount);
+	if (diag || linecount <= 1)
+		linecount = 22;
+
+	diag = kdbgetintenv("LOGGING", &logging);
+	if (diag)
+		logging = 0;
+
+	va_start(ap, fmt);
+	vsnprintf(kdb_buffer, sizeof(kdb_buffer), fmt, ap);
+	va_end(ap);
+
+	/*
+	 * Write to all consoles.
+	 */
+#ifdef CONFIG_SPARC64
+	if (c == NULL)
+		prom_printf("%s", kdb_buffer);
+	else
+#endif
+	while (c) {
+		c->write(c, kdb_buffer, strlen(kdb_buffer));
+		c = c->next;
+	}
+	if (logging) {
+		saved_loglevel = console_loglevel;
+		console_loglevel = 0;
+		printk("%s", kdb_buffer);
+	}
+
+	if (KDB_STATE(LONGJMP) && strchr(kdb_buffer, '\n'))
+		kdb_nextline++;
+
+	if (kdb_nextline == linecount) {
+		char buf1[16]="";
+#if defined(CONFIG_SMP)
+		char buf2[32];
+#endif
+		char *moreprompt;
+
+		/* Watch out for recursion here.  Any routine that calls
+		 * kdb_printf will come back through here.  And kdb_read
+		 * uses kdb_printf to echo on serial consoles ...
+		 */
+		kdb_nextline = 1;	/* In case of recursion */
+
+		/*
+		 * Pause until cr.
+		 */
+		moreprompt = kdbgetenv("MOREPROMPT");
+		if (moreprompt == NULL) {
+			moreprompt = "more> ";
+		}
+
+#if defined(CONFIG_SMP)
+		if (strchr(moreprompt, '%')) {
+			sprintf(buf2, moreprompt, smp_processor_id());
+			moreprompt = buf2;
+		}
+#endif
+
+		kdb_input_flush();
+		c = console_drivers;
+#ifdef CONFIG_SPARC64
+		if (c == NULL)
+			prom_printf("%s", moreprompt);
+		else
+#endif
+		while (c) {
+			c->write(c, moreprompt, strlen(moreprompt));
+			c = c->next;
+		}
+
+		if (logging)
+			printk("%s", moreprompt);
+
+		kdb_read(buf1, 2); /* '2' indicates to return immediately after getting one key. */
+		kdb_nextline = 1;	/* Really set output line 1 */
+
+		if ((buf1[0] == 'q') || (buf1[0] == 'Q')) {
+			do_longjmp = 1;
+			KDB_FLAG_SET(CMD_INTERRUPT);	/* command was interrupted */
+			kdb_printf("\n");
+		}
+		else if (buf1[0] && buf1[0] != '\n') {
+			kdb_printf("\nOnly 'q' or 'Q' are processed at more prompt, input ignored\n");
+		}
+		kdb_input_flush();
+	}
+
+	if (logging) {
+		console_loglevel = saved_loglevel;
+	}
+	if (KDB_STATE(PRINTF_LOCK) && got_printf_lock) {
+		got_printf_lock = 0;
+		spin_unlock(&kdb_printf_lock);
+		KDB_STATE_CLEAR(PRINTF_LOCK);
+	}
+	if (do_longjmp)
+#ifdef KDB_HAVE_LONGJMP
+		kdba_longjmp(&kdbjmpbuf[smp_processor_id()], 1)
+#endif	/* KDB_HAVE_LONGJMP */
+		;
+}
+
+/*
+ * kdb_io_init
+ *
+ *	Initialize kernel debugger output environment.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Select a console device.
+ */
+
+void __init
+kdb_io_init(void)
+{
+#ifndef CONFIG_SPARC64 /* we don't register serial consoles in time */
+	/*
+ 	 * Select a console.
+ 	 */
+	struct console *c = console_drivers;
+
+	while (c) {
+		if ((c->flags & CON_CONSDEV)) {
+			kdbcons = c;
+			break;
+		}
+		c = c->next;
+	}
+
+	if (kdbcons == NULL) {
+		printk("kdb: Initialization failed - no console\n");
+		while (1) {};
+	}
+	kdb_input_flush();
+#endif
+	return;
+}
+
+EXPORT_SYMBOL(kdb_read);
diff -uNr linux.orig/kdb/kdbmain.c linux/kdb/kdbmain.c
--- linux.orig/kdb/kdbmain.c	Thu Jan  1 08:00:00 1970
+++ linux/kdb/kdbmain.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,3639 @@
+/*
+ * Kernel Debugger Architecture Independent Main Code
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+/*
+ * Updated for Xscale (R) architecture support 
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#include <linux/config.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/sysrq.h>
+#include <linux/smp.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kallsyms.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/nmi.h>
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+#include <linux/dump.h>
+#endif
+
+#include <asm/system.h>
+
+#if defined(CONFIG_MODULES)
+extern struct module *module_list;
+#endif
+
+	/*
+	 * Kernel debugger state flags
+	 */
+volatile int kdb_flags;
+volatile int kdb_enter_debugger;
+
+	/*
+	 * kdb_lock protects updates to kdb_initial_cpu.  Used to
+	 * single thread processors through the kernel debugger.
+	 */
+spinlock_t kdb_lock = SPIN_LOCK_UNLOCKED;
+volatile int kdb_initial_cpu = -1;		/* cpu number that owns kdb */
+int kdb_seqno = 2;				/* how many times kdb has been entered */
+
+volatile int kdb_nextline = 1;
+static volatile int kdb_new_cpu;		/* Which cpu to switch to */
+struct task_struct *kdb_active_task[NR_CPUS];	/* Task that is active on each cpu */
+
+volatile int kdb_state[NR_CPUS];		/* Per cpu state */
+
+struct task_struct *kdb_current_task;
+
+#ifdef	CONFIG_KDB_OFF
+int kdb_on = 0;				/* Default is off */
+#else
+int kdb_on = 1;				/* Default is on */
+#endif	/* CONFIG_KDB_OFF */
+
+const char *kdb_diemsg;
+struct notifier_block *kdb_notifier_list;	/* racy for modules, see comments in kdb.h */
+static int kdb_go_count;
+#ifdef CONFIG_KDB_CONTINUE_CATASTROPHIC
+static unsigned int kdb_continue_catastrophic = CONFIG_KDB_CONTINUE_CATASTROPHIC;
+#else
+static unsigned int kdb_continue_catastrophic = 0;
+#endif
+
+#ifdef KDB_HAVE_LONGJMP
+	/*
+	 * Must have a setjmp buffer per CPU.  Switching cpus will
+	 * cause the jump buffer to be setup for the new cpu, and
+	 * subsequent switches (and pager aborts) will use the
+	 * appropriate per-processor values.
+	 */
+kdb_jmp_buf	kdbjmpbuf[NR_CPUS];
+#endif	/* KDB_HAVE_LONGJMP */
+
+	/*
+	 * kdb_commands describes the available commands.
+	 */
+static kdbtab_t *kdb_commands;
+static int kdb_max_commands;
+
+typedef struct _kdbmsg {
+	int	km_diag;	/* kdb diagnostic */
+	char	*km_msg;	/* Corresponding message text */
+} kdbmsg_t;
+
+#define KDBMSG(msgnum, text) \
+	{ KDB_##msgnum, text }
+
+static kdbmsg_t kdbmsgs[] = {
+	KDBMSG(NOTFOUND,"Command Not Found"),
+	KDBMSG(ARGCOUNT, "Improper argument count, see usage."),
+	KDBMSG(BADWIDTH, "Illegal value for BYTESPERWORD use 1, 2, 4 or 8, 8 is only allowed on 64 bit systems"),
+	KDBMSG(BADRADIX, "Illegal value for RADIX use 8, 10 or 16"),
+	KDBMSG(NOTENV, "Cannot find environment variable"),
+	KDBMSG(NOENVVALUE, "Environment variable should have value"),
+	KDBMSG(NOTIMP, "Command not implemented"),
+	KDBMSG(ENVFULL, "Environment full"),
+	KDBMSG(ENVBUFFULL, "Environment buffer full"),
+	KDBMSG(TOOMANYBPT, "Too many breakpoints defined"),
+#ifdef  CONFIG_CPU_XSCALE
+	KDBMSG(TOOMANYDBREGS, "More breakpoints than ibcr registers defined"),
+#else
+	KDBMSG(TOOMANYDBREGS, "More breakpoints than db registers defined"),
+#endif
+	KDBMSG(DUPBPT, "Duplicate breakpoint address"),
+	KDBMSG(BPTNOTFOUND, "Breakpoint not found"),
+	KDBMSG(BADMODE, "Invalid IDMODE"),
+	KDBMSG(BADINT, "Illegal numeric value"),
+	KDBMSG(INVADDRFMT, "Invalid symbolic address format"),
+	KDBMSG(BADREG, "Invalid register name"),
+	KDBMSG(BADCPUNUM, "Invalid cpu number"),
+	KDBMSG(BADLENGTH, "Invalid length field"),
+	KDBMSG(NOBP, "No Breakpoint exists"),
+	KDBMSG(BADADDR, "Invalid address"),
+};
+#undef KDBMSG
+
+static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t);
+
+
+/*
+ * Initial environment.   This is all kept static and local to
+ * this file.   We don't want to rely on the memory allocation
+ * mechanisms in the kernel, so we use a very limited allocate-only
+ * heap for new and altered environment variables.  The entire
+ * environment is limited to a fixed number of entries (add more
+ * to __env[] if required) and a fixed amount of heap (add more to
+ * KDB_ENVBUFSIZE if required).
+ */
+
+static char *__env[] = {
+#if defined(CONFIG_SMP)
+ "PROMPT=[%d]kdb> ",
+ "MOREPROMPT=[%d]more> ",
+#else
+ "PROMPT=kdb> ",
+ "MOREPROMPT=more> ",
+#endif
+ "RADIX=16",
+ "LINES=24",
+ "COLUMNS=80",
+ "MDCOUNT=8",			/* lines of md output */
+ "BTARGS=5",			/* 5 possible args in bt */
+ KDB_PLATFORM_ENV,
+ "DTABCOUNT=30",
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+ (char *)0,
+};
+
+static const int __nenv = (sizeof(__env) / sizeof(char *));
+
+/*
+ * kdbgetenv
+ *
+ *	This function will return the character string value of
+ *	an environment variable.
+ *
+ * Parameters:
+ *	match	A character string representing an environment variable.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	NULL	No environment variable matches 'match'
+ *	char*	Pointer to string value of environment variable.
+ * Locking:
+ *	No locking considerations required.
+ * Remarks:
+ */
+char *
+kdbgetenv(const char *match)
+{
+	char **ep = __env;
+	int    matchlen = strlen(match);
+	int i;
+
+	for(i=0; i<__nenv; i++) {
+		char *e = *ep++;
+
+		if (!e) continue;
+
+		if ((strncmp(match, e, matchlen) == 0)
+		 && ((e[matchlen] == '\0')
+		   ||(e[matchlen] == '='))) {
+			char *cp = strchr(e, '=');
+			return (cp)?++cp:"";
+		}
+	}
+	return (char *)0;
+}
+
+/*
+ * kdballocenv
+ *
+ *	This function is used to allocate bytes for environment entries.
+ *
+ * Parameters:
+ *	match	A character string representing a numeric value
+ * Outputs:
+ *	*value  the unsigned long represntation of the env variable 'match'
+ * Returns:
+ *	Zero on success, a kdb diagnostic on failure.
+ * Locking:
+ *	No locking considerations required.  Must be called with all
+ *	processors halted.
+ * Remarks:
+ *	We use a static environment buffer (envbuffer) to hold the values
+ *	of dynamically generated environment variables (see kdb_set).  Buffer
+ *	space once allocated is never free'd, so over time, the amount of space
+ *	(currently 512 bytes) will be exhausted if env variables are changed
+ *	frequently.
+ */
+static char *
+kdballocenv(size_t bytes)
+{
+#define	KDB_ENVBUFSIZE	512
+	static char envbuffer[KDB_ENVBUFSIZE];
+	static int  envbufsize;
+	char *ep = (char *)0;
+
+	if ((KDB_ENVBUFSIZE - envbufsize) >= bytes) {
+		ep = &envbuffer[envbufsize];
+		envbufsize += bytes;
+	}
+	return ep;
+}
+
+/*
+ * kdbgetulenv
+ *
+ *	This function will return the value of an unsigned long-valued
+ *	environment variable.
+ *
+ * Parameters:
+ *	match	A character string representing a numeric value
+ * Outputs:
+ *	*value  the unsigned long represntation of the env variable 'match'
+ * Returns:
+ *	Zero on success, a kdb diagnostic on failure.
+ * Locking:
+ *	No locking considerations required.
+ * Remarks:
+ */
+
+int
+kdbgetulenv(const char *match, unsigned long *value)
+{
+	char *ep;
+
+	ep = kdbgetenv(match);
+	if (!ep) return KDB_NOTENV;
+	if (strlen(ep) == 0) return KDB_NOENVVALUE;
+
+	*value = simple_strtoul(ep, 0, 0);
+
+	return 0;
+}
+
+/*
+ * kdbgetintenv
+ *
+ *	This function will return the value of an integer-valued
+ *	environment variable.
+ *
+ * Parameters:
+ *	match	A character string representing an integer-valued env variable
+ * Outputs:
+ *	*value  the integer representation of the environment variable 'match'
+ * Returns:
+ *	Zero on success, a kdb diagnostic on failure.
+ * Locking:
+ *	No locking considerations required.
+ * Remarks:
+ */
+
+int
+kdbgetintenv(const char *match, int *value) {
+	unsigned long val;
+	int           diag;
+
+	diag = kdbgetulenv(match, &val);
+	if (!diag) {
+		*value = (int) val;
+	}
+	return diag;
+}
+
+/*
+ * kdbgetularg
+ *
+ *	This function will convert a numeric string
+ *	into an unsigned long value.
+ *
+ * Parameters:
+ *	arg	A character string representing a numeric value
+ * Outputs:
+ *	*value  the unsigned long represntation of arg.
+ * Returns:
+ *	Zero on success, a kdb diagnostic on failure.
+ * Locking:
+ *	No locking considerations required.
+ * Remarks:
+ */
+
+int
+kdbgetularg(const char *arg, unsigned long *value)
+{
+	char *endp;
+	unsigned long val;
+
+	val = simple_strtoul(arg, &endp, 0);
+
+	if (endp == arg) {
+		/*
+		 * Try base 16, for us folks too lazy to type the
+		 * leading 0x...
+		 */
+		val = simple_strtoul(arg, &endp, 16);
+		if (endp == arg)
+			return KDB_BADINT;
+	}
+
+	*value = val;
+
+	return 0;
+}
+
+/*
+ * kdb_set
+ *
+ *	This function implements the 'set' command.  Alter an existing
+ *	environment variable or create a new one.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_set(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int i;
+	char *ep;
+	size_t varlen, vallen;
+
+	/*
+	 * we can be invoked two ways:
+	 *   set var=value    argv[1]="var", argv[2]="value"
+	 *   set var = value  argv[1]="var", argv[2]="=", argv[3]="value"
+	 * - if the latter, shift 'em down.
+	 */
+	if (argc == 3) {
+		argv[2] = argv[3];
+		argc--;
+	}
+
+	if (argc != 2)
+		return KDB_ARGCOUNT;
+
+	/*
+	 * Check for internal variables
+	 */
+	if (strcmp(argv[1], "KDBDEBUG") == 0) {
+		unsigned int debugflags;
+		char *cp;
+
+		debugflags = simple_strtoul(argv[2], &cp, 0);
+		if (cp == argv[2] || debugflags & ~KDB_DEBUG_FLAG_MASK) {
+			kdb_printf("kdb: illegal debug flags '%s'\n",
+				    argv[2]);
+			return 0;
+		}
+		kdb_flags = (kdb_flags & ~(KDB_DEBUG_FLAG_MASK << KDB_DEBUG_FLAG_SHIFT))
+			  | (debugflags << KDB_DEBUG_FLAG_SHIFT);
+
+		return 0;
+	}
+
+	/*
+	 * Tokenizer squashed the '=' sign.  argv[1] is variable
+	 * name, argv[2] = value.
+	 */
+	varlen = strlen(argv[1]);
+	vallen = strlen(argv[2]);
+	ep = kdballocenv(varlen + vallen + 2);
+	if (ep == (char *)0)
+		return KDB_ENVBUFFULL;
+
+	sprintf(ep, "%s=%s", argv[1], argv[2]);
+
+	ep[varlen+vallen+1]='\0';
+
+	for(i=0; i<__nenv; i++) {
+		if (__env[i]
+		 && ((strncmp(__env[i], argv[1], varlen)==0)
+		   && ((__env[i][varlen] == '\0')
+		    || (__env[i][varlen] == '=')))) {
+			__env[i] = ep;
+			return 0;
+		}
+	}
+
+	/*
+	 * Wasn't existing variable.  Fit into slot.
+	 */
+	for(i=0; i<__nenv-1; i++) {
+		if (__env[i] == (char *)0) {
+			__env[i] = ep;
+			return 0;
+		}
+	}
+
+	return KDB_ENVFULL;
+}
+
+/*
+ * kdbgetaddrarg
+ *
+ *	This function is responsible for parsing an
+ *	address-expression and returning the value of
+ *	the expression, symbol name, and offset to the caller.
+ *
+ *	The argument may consist of a numeric value (decimal or
+ *	hexidecimal), a symbol name, a register name (preceeded
+ *	by the percent sign), an environment variable with a numeric
+ *	value (preceeded by a dollar sign) or a simple arithmetic
+ *	expression consisting of a symbol name, +/-, and a numeric
+ *	constant value (offset).
+ *
+ * Parameters:
+ *	argc	- count of arguments in argv
+ *	argv	- argument vector
+ *	*nextarg - index to next unparsed argument in argv[]
+ *	regs	- Register state at time of KDB entry
+ * Outputs:
+ *	*value	- receives the value of the address-expression
+ *	*offset - receives the offset specified, if any
+ *	*name   - receives the symbol name, if any
+ *	*nextarg - index to next unparsed argument in argv[]
+ *
+ * Returns:
+ *	zero is returned on success, a kdb diagnostic code is
+ *      returned on error.
+ *
+ * Locking:
+ *	No locking requirements.
+ *
+ * Remarks:
+ *
+ */
+
+int
+kdbgetaddrarg(int argc, const char **argv, int *nextarg,
+	      kdb_machreg_t *value,  long *offset,
+	      char **name, struct pt_regs *regs)
+{
+	kdb_machreg_t addr;
+	long	      off = 0;
+	int	      positive;
+	int	      diag;
+	int	      found = 0;
+	char	     *symname;
+	char	      symbol = '\0';
+	char	     *cp;
+	kdb_symtab_t   symtab;
+
+	/*
+	 * Process arguments which follow the following syntax:
+	 *
+	 *  symbol | numeric-address [+/- numeric-offset]
+	 *  %register
+	 *  $environment-variable
+	 */
+
+	if (*nextarg > argc) {
+		return KDB_ARGCOUNT;
+	}
+
+	symname = (char *)argv[*nextarg];
+
+	/*
+	 * If there is no whitespace between the symbol
+	 * or address and the '+' or '-' symbols, we
+	 * remember the character and replace it with a
+	 * null so the symbol/value can be properly parsed
+	 */
+	if ((cp = strpbrk(symname, "+-")) != NULL) {
+		symbol = *cp;
+		*cp++ = '\0';
+	}
+
+	if (symname[0] == '$') {
+		diag = kdbgetulenv(&symname[1], &addr);
+		if (diag)
+			return diag;
+	} else if (symname[0] == '%') {
+		diag = kdba_getregcontents(&symname[1], regs, &addr);
+		if (diag)
+			return diag;
+	} else {
+		found = kdbgetsymval(symname, &symtab);
+		if (found) {
+			addr = symtab.sym_start;
+		} else {
+			diag = kdbgetularg(argv[*nextarg], &addr);
+			if (diag)
+				return diag;
+		}
+	}
+
+	if (!found)
+		found = kdbnearsym(addr, &symtab);
+
+	(*nextarg)++;
+
+	if (name)
+		*name = symname;
+	if (value)
+		*value = addr;
+	if (offset && name && *name)
+		*offset = addr - symtab.sym_start;
+
+	if ((*nextarg > argc)
+	 && (symbol == '\0'))
+		return 0;
+
+	/*
+	 * check for +/- and offset
+	 */
+
+	if (symbol == '\0') {
+		if ((argv[*nextarg][0] != '+')
+		 && (argv[*nextarg][0] != '-')) {
+			/*
+			 * Not our argument.  Return.
+			 */
+			return 0;
+		} else {
+			positive = (argv[*nextarg][0] == '+');
+			(*nextarg)++;
+		}
+	} else
+		positive = (symbol == '+');
+
+	/*
+	 * Now there must be an offset!
+	 */
+	if ((*nextarg > argc)
+	 && (symbol == '\0')) {
+		return KDB_INVADDRFMT;
+	}
+
+	if (!symbol) {
+		cp = (char *)argv[*nextarg];
+		(*nextarg)++;
+	}
+
+	diag = kdbgetularg(cp, &off);
+	if (diag)
+		return diag;
+
+	if (!positive)
+		off = -off;
+
+	if (offset)
+		*offset += off;
+
+	if (value)
+		*value += off;
+
+	return 0;
+}
+
+static void
+kdb_cmderror(int diag)
+{
+	int i;
+
+	if (diag >= 0) {
+		kdb_printf("no error detected\n");
+		return;
+	}
+
+	for(i=0; i<__nkdb_err; i++) {
+		if (kdbmsgs[i].km_diag == diag) {
+			kdb_printf("diag: %d: %s\n", diag, kdbmsgs[i].km_msg);
+			return;
+		}
+	}
+
+	kdb_printf("Unknown diag %d\n", -diag);
+}
+
+/*
+ * kdb_defcmd, kdb_defcmd2
+ *
+ *	This function implements the 'defcmd' command which defines one
+ *	command as a set of other commands, terminated by endefcmd.
+ *	kdb_defcmd processes the initial 'defcmd' command, kdb_defcmd2
+ *	is invoked from kdb_parse for the following commands until
+ *	'endefcmd'.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+struct defcmd_set {
+	int count;
+	int usable;
+	char *name;
+	char *usage;
+	char *help;
+	char **command;
+};
+static struct defcmd_set *defcmd_set;
+static int defcmd_set_count;
+static int defcmd_in_progress;
+
+/* Forward references */
+static int kdb_exec_defcmd(int argc, const char **argv, const char **envp, struct pt_regs *regs);
+
+static int
+kdb_defcmd2(const char *cmdstr, const char *argv0)
+{
+	struct defcmd_set *s = defcmd_set + defcmd_set_count - 1;
+	char **save_command = s->command;
+	if (strcmp(argv0, "endefcmd") == 0) {
+		defcmd_in_progress = 0;
+		if (!s->count)
+			s->usable = 0;
+		if (s->usable)
+			kdb_register(s->name, kdb_exec_defcmd, s->usage, s->help, 0);
+		return 0;
+	}
+	if (!s->usable)
+		return KDB_NOTIMP;
+	s->command = kmalloc((s->count + 1) * sizeof(*(s->command)), GFP_KERNEL);
+	if (!s->command) {
+		kdb_printf("Could not allocate new kdb_defcmd table for %s\n", cmdstr);
+		s->usable = 0;
+		return KDB_NOTIMP;
+	}
+	memcpy(s->command, save_command, s->count * sizeof(*(s->command)));
+	s->command[s->count++] = kdb_strdup(cmdstr, GFP_KERNEL);
+	kfree(save_command);
+	return 0;
+}
+
+static int
+kdb_defcmd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct defcmd_set *save_defcmd_set = defcmd_set, *s;
+	if (argc != 3)
+		return KDB_ARGCOUNT;
+	if (defcmd_in_progress) {
+		kdb_printf("kdb: nested defcmd detected, assuming missing endefcmd\n");
+		kdb_defcmd2("endefcmd", "endefcmd");
+	}
+	defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set), GFP_KERNEL);
+	if (!defcmd_set) {
+		kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]);
+		defcmd_set = save_defcmd_set;
+		return KDB_NOTIMP;
+	}
+	memcpy(defcmd_set, save_defcmd_set, defcmd_set_count * sizeof(*defcmd_set));
+	kfree(save_defcmd_set);
+	s = defcmd_set + defcmd_set_count;
+	memset(s, 0, sizeof(*s));
+	s->usable = 1;
+	s->name = kdb_strdup(argv[1], GFP_KERNEL);
+	s->usage = kdb_strdup(argv[2], GFP_KERNEL);
+	s->help = kdb_strdup(argv[3], GFP_KERNEL);
+	if (s->usage[0] == '"') {
+		strcpy(s->usage, s->usage+1);
+		s->usage[strlen(s->usage)-1] = '\0';
+	}
+	if (s->help[0] == '"') {
+		strcpy(s->help, s->help+1);
+		s->help[strlen(s->help)-1] = '\0';
+	}
+	++defcmd_set_count;
+	defcmd_in_progress = 1;
+	return 0;
+}
+
+/*
+ * kdb_exec_defcmd
+ *
+ *	Execute the set of commands associated with this defcmd name.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+static int
+kdb_exec_defcmd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int i, ret;
+	struct defcmd_set *s;
+	if (argc != 0)
+		return KDB_ARGCOUNT;
+	for (s = defcmd_set, i = 0; i < defcmd_set_count; ++i, ++s) {
+		if (strcmp(s->name, argv[0]) == 0)
+			break;
+	}
+	if (i == defcmd_set_count) {
+		kdb_printf("kdb_exec_defcmd: could not find commands for %s\n", argv[0]);
+		return KDB_NOTIMP;
+	}
+	for (i = 0; i < s->count; ++i) {
+		/* Recursive use of kdb_parse, argv is now unreliable */
+		argv = NULL;
+		kdb_printf("[%s]kdb> %s\n", s->name, s->command[i]);
+		if ((ret = kdb_parse(s->command[i], regs)))
+			return ret;
+	}
+	return 0;
+}
+
+/* Command history */
+#define KDB_CMD_HISTORY_COUNT	32
+#define CMD_BUFLEN		200	/* kdb_printf: max printline size == 256 */
+static unsigned int cmd_head=0, cmd_tail=0;
+static unsigned int cmdptr;
+static char cmd_hist[KDB_CMD_HISTORY_COUNT][CMD_BUFLEN];
+static char cmd_cur[CMD_BUFLEN];
+
+/*
+ * kdb_parse
+ *
+ *	Parse the command line, search the command table for a
+ *	matching command and invoke the command function.
+ *	This function may be called recursively, if it is, the second call
+ *	will overwrite argv and cbuf.  It is the caller's responsibility to
+ *	save their argv if they recursively call kdb_parse().
+ *
+ * Parameters:
+ *      cmdstr	The input command line to be parsed.
+ *	regs	The registers at the time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic if failure.
+ * Locking:
+ * 	None.
+ * Remarks:
+ *	Limited to 20 tokens.
+ *
+ *	Real rudimentary tokenization. Basically only whitespace
+ *	is considered a token delimeter (but special consideration
+ *	is taken of the '=' sign as used by the 'set' command).
+ *
+ *	The algorithm used to tokenize the input string relies on
+ *	there being at least one whitespace (or otherwise useless)
+ *	character between tokens as the character immediately following
+ *	the token is altered in-place to a null-byte to terminate the
+ *	token string.
+ */
+
+#define MAXARGC	20
+
+int
+kdb_parse(const char *cmdstr, struct pt_regs *regs)
+{
+	static char *argv[MAXARGC];
+	static int  argc = 0;
+	static char cbuf[CMD_BUFLEN+2];
+	const char *cp;
+	char *cpp, quoted;
+	kdbtab_t *tp;
+	int i, escaped, ignore_errors = 0;
+
+	/*
+	 * First tokenize the command string.
+	 */
+	cp = cmdstr;
+
+	if (KDB_FLAG(CMD_INTERRUPT)) {
+		/* Previous command was interrupted, newline must not repeat the command */
+		KDB_FLAG_CLEAR(CMD_INTERRUPT);
+		argc = 0;	/* no repeat */
+	}
+
+	if (*cp != '\n' && *cp != '\0') {
+		argc = 0;
+		cpp = cbuf;
+		while (*cp) {
+			/* skip whitespace */
+			while (isspace(*cp)) cp++;
+			if ((*cp == '\0') || (*cp == '\n'))
+				break;
+			if (cpp >= cbuf + CMD_BUFLEN) {
+				kdb_printf("kdb_parse: command buffer overflow, command ignored\n%s\n", cmdstr);
+				return KDB_NOTFOUND;
+			}
+			if (argc >= MAXARGC - 1) {
+				kdb_printf("kdb_parse: too many arguments, command ignored\n%s\n", cmdstr);
+				return KDB_NOTFOUND;
+			}
+			argv[argc++] = cpp;
+			escaped = 0;
+			quoted = '\0';
+			/* Copy to next unquoted and unescaped whitespace or '=' */
+			while (*cp && *cp != '\n' && (escaped || quoted || !isspace(*cp))) {
+				if (cpp >= cbuf + CMD_BUFLEN)
+					break;
+				if (escaped) {
+					escaped = 0;
+					*cpp++ = *cp++;
+					continue;
+				}
+				if (*cp == '\\') {
+					escaped = 1;
+					++cp;
+					continue;
+				}
+				if (*cp == quoted) {
+					quoted = '\0';
+				} else if (*cp == '\'' || *cp == '"') {
+					quoted = *cp;
+				}
+				if ((*cpp = *cp++) == '=' && !quoted)
+					break;
+				++cpp;
+			}
+			*cpp++ = '\0';	/* Squash a ws or '=' character */
+		}
+	}
+	if (!argc)
+		return 0;
+	if (defcmd_in_progress) {
+		int result = kdb_defcmd2(cmdstr, argv[0]);
+		if (!defcmd_in_progress) {
+			argc = 0;	/* avoid repeat on endefcmd */
+			*(argv[0]) = '\0';
+		}
+		return result;
+	}
+	if (argv[0][0] == '-' && argv[0][1] && (argv[0][1] < '0' || argv[0][1] > '9')) {
+		ignore_errors = 1;
+		++argv[0];
+	}
+
+	for(tp=kdb_commands, i=0; i < kdb_max_commands; i++,tp++) {
+		if (tp->cmd_name) {
+			/*
+			 * If this command is allowed to be abbreviated,
+			 * check to see if this is it.
+			 */
+
+			if (tp->cmd_minlen
+			 && (strlen(argv[0]) <= tp->cmd_minlen)) {
+				if (strncmp(argv[0],
+					    tp->cmd_name,
+					    tp->cmd_minlen) == 0) {
+					break;
+				}
+			}
+
+			if (strcmp(argv[0], tp->cmd_name)==0) {
+				break;
+			}
+		}
+	}
+
+	/*
+	 * If we don't find a command by this name, see if the first
+	 * few characters of this match any of the known commands.
+	 * e.g., md1c20 should match md.
+	 */
+	if (i == kdb_max_commands) {
+		for(tp=kdb_commands, i=0; i < kdb_max_commands; i++,tp++) {
+			if (tp->cmd_name) {
+				if (strncmp(argv[0],
+					    tp->cmd_name,
+					    strlen(tp->cmd_name))==0) {
+					break;
+				}
+			}
+		}
+	}
+
+	if (i < kdb_max_commands) {
+		int result;
+		KDB_STATE_SET(CMD);
+		result = (*tp->cmd_func)(argc-1,
+				       (const char**)argv,
+				       (const char**)__env,
+				       regs);
+		if (result && ignore_errors && result > KDB_CMD_GO)
+			result = 0;
+		KDB_STATE_CLEAR(CMD);
+		switch (tp->cmd_repeat) {
+		case KDB_REPEAT_NONE:
+			argc = 0;
+			if (argv[0])
+				*(argv[0]) = '\0';
+			break;
+		case KDB_REPEAT_NO_ARGS:
+			argc = 1;
+			if (argv[1])
+				*(argv[1]) = '\0';
+			break;
+		case KDB_REPEAT_WITH_ARGS:
+			break;
+		}
+		return result;
+	}
+
+	/*
+	 * If the input with which we were presented does not
+	 * map to an existing command, attempt to parse it as an
+	 * address argument and display the result.   Useful for
+	 * obtaining the address of a variable, or the nearest symbol
+	 * to an address contained in a register.
+	 */
+	{
+		kdb_machreg_t value;
+		char *name = NULL;
+		long offset;
+		int nextarg = 0;
+
+		if (kdbgetaddrarg(0, (const char **)argv, &nextarg,
+				  &value, &offset, &name, regs)) {
+			return KDB_NOTFOUND;
+		}
+
+		kdb_printf("%s = ", argv[0]);
+		kdb_symbol_print(value, NULL, KDB_SP_DEFAULT);
+		kdb_printf("\n");
+		return 0;
+	}
+}
+
+
+static int
+handle_ctrl_cmd(char *cmd)
+{
+#define CTRL_P	16
+#define CTRL_N	14
+
+	/* initial situation */
+	if (cmd_head == cmd_tail) return 0;
+
+	switch(*cmd) {
+		case CTRL_P:
+			if (cmdptr != cmd_tail)
+				cmdptr = (cmdptr-1) % KDB_CMD_HISTORY_COUNT;
+			strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN);
+			return 1;
+		case CTRL_N:
+			if (cmdptr != cmd_head)
+				cmdptr = (cmdptr+1) % KDB_CMD_HISTORY_COUNT;
+			strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN);
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * kdb_do_dump
+ *
+ *	Call the dump() function if the kernel is configured for LKCD.
+ * Inputs:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.  dump() may or may not return.
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+static void
+kdb_do_dump(struct pt_regs *regs)
+{
+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+	kdb_printf("Forcing dump (if configured)\n");
+	console_loglevel = 8;	/* to see the dump messages */
+	dump("kdb_do_dump", regs);
+#endif
+}
+
+/*
+ * kdb_reboot
+ *
+ *	This function implements the 'reboot' command.  Reboot the system
+ *	immediately.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	Shouldn't return from this function.
+ */
+
+int
+kdb_reboot(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	machine_restart(0);
+	kdb_printf("Hmm, kdb_reboot did not reboot, spinning here\n");
+	while (1) {};
+	/* NOTREACHED */
+	return 0;
+}
+
+/*
+ * kdb_local
+ *
+ *	The main code for kdb.  This routine is invoked on a specific
+ *	processor, it is not global.  The main kdb() routine ensures
+ *	that only one processor at a time is in this routine.  This
+ *	code is called with the real reason code on the first entry
+ *	to a kdb session, thereafter it is called with reason SWITCH,
+ *	even if the user goes back to the original cpu.
+ *
+ * Inputs:
+ *	reason		The reason KDB was invoked
+ *	error		The hardware-defined error code
+ *	regs		The exception frame at time of fault/breakpoint.  NULL
+ *			for reason SILENT, otherwise valid.
+ *	db_result	Result code from the break or debug point.
+ * Returns:
+ *	0	KDB was invoked for an event which it wasn't responsible
+ *	1	KDB handled the event for which it was invoked.
+ *	KDB_CMD_GO	User typed 'go'.
+ *	KDB_CMD_CPU	User switched to another cpu.
+ *	KDB_CMD_SS	Single step.
+ *	KDB_CMD_SSB	Single step until branch.
+ * Locking:
+ *	none
+ * Remarks:
+ *	none
+ */
+
+extern char kdb_prompt_str[];
+
+static int
+kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, kdb_dbtrap_t db_result)
+{
+	char		*cmdbuf;
+	int		diag;
+
+	kdb_go_count = 0;
+	if (reason != KDB_REASON_DEBUG &&
+	    reason != KDB_REASON_SILENT) {
+		kdb_printf("\nEntering kdb (current=0x%p, pid %d) ", (void *)current, current->pid);
+#if defined(CONFIG_SMP)
+		kdb_printf("on processor %d ", smp_processor_id());
+#endif
+	}
+
+	switch (reason) {
+	case KDB_REASON_DEBUG:
+	{
+		/*
+		 * If re-entering kdb after a single step
+		 * command, don't print the message.
+		 */
+		switch(db_result) {
+		case KDB_DB_BPT:
+			kdb_printf("\nEntering kdb (0x%p) ", (void *)current);
+#if defined(CONFIG_SMP)
+			kdb_printf("on processor %d ", smp_processor_id());
+#endif
+			kdb_printf("due to Debug @ " kdb_machreg_fmt "\n", kdba_getpc(regs));
+			break;
+		case KDB_DB_SSB:
+			/*
+			 * In the midst of ssb command. Just return.
+			 */
+			return KDB_CMD_SSB;	/* Continue with SSB command */
+
+			break;
+		case KDB_DB_SS:
+			break;
+		case KDB_DB_SSBPT:
+			return 1;	/* kdba_db_trap did the work */
+		default:
+			kdb_printf("kdb: Bad result from kdba_db_trap: %d\n",
+				   db_result);
+			break;
+		}
+
+	}
+		break;
+	case KDB_REASON_FAULT:
+		break;
+	case KDB_REASON_ENTER:
+		kdb_printf("due to KDB_ENTER()\n");
+		break;
+	case KDB_REASON_KEYBOARD:
+		kdb_printf("due to Keyboard Entry\n");
+		break;
+	case KDB_REASON_SWITCH:
+		kdb_printf("due to cpu switch\n");
+		if (KDB_STATE(GO_SWITCH)) {
+			KDB_STATE_CLEAR(GO_SWITCH);
+			return KDB_CMD_GO;
+		}
+		break;
+	case KDB_REASON_CALL:
+		if (!regs)
+			kdb_printf("kdb() called with no registers, restricted function");
+		kdb_printf("\n");
+		break;
+	case KDB_REASON_OOPS:
+		kdb_printf("Oops: %s\n", kdb_diemsg);
+		kdb_printf("due to oops @ " kdb_machreg_fmt "\n", kdba_getpc(regs));
+		kdba_dumpregs(regs, NULL, NULL);
+		break;
+	case KDB_REASON_NMI:
+		kdb_printf("due to NonMaskable Interrupt @ " kdb_machreg_fmt "\n",
+			  kdba_getpc(regs));
+		kdba_dumpregs(regs, NULL, NULL);
+		break;
+	case KDB_REASON_WATCHDOG:
+		kdb_printf("due to WatchDog Interrupt @ " kdb_machreg_fmt "\n",
+			  kdba_getpc(regs));
+		kdba_dumpregs(regs, NULL, NULL);
+		break;
+	case KDB_REASON_BREAK:
+		kdb_printf("due to Breakpoint @ " kdb_machreg_fmt "\n", kdba_getpc(regs));
+		/*
+		 * Determine if this breakpoint is one that we
+		 * are interested in.
+		 */
+		if (db_result != KDB_DB_BPT) {
+			kdb_printf("kdb: error return from kdba_bp_trap: %d\n", db_result);
+			return 0;	/* Not for us, dismiss it */
+		}
+		break;
+	case KDB_REASON_RECURSE:
+		kdb_printf("due to Recursion @ " kdb_machreg_fmt "\n", kdba_getpc(regs));
+		break;
+	case KDB_REASON_SILENT:
+		return KDB_CMD_GO;	/* Silent entry, silent exit */
+		break;
+	default:
+		kdb_printf("kdb: unexpected reason code: %d\n", reason);
+		return 0;	/* Not for us, dismiss it */
+	}
+
+	kdba_local_arch_setup();
+
+	kdb_current_task = current;
+
+	while (1) {
+		/*
+		 * Initialize pager context.
+		 */
+		kdb_nextline = 1;
+		KDB_STATE_CLEAR(SUPPRESS);
+#ifdef KDB_HAVE_LONGJMP
+		/*
+		 * Use kdba_setjmp/kdba_longjmp to break out of
+		 * the pager early and to attempt to recover from kdb errors.
+		 */
+		KDB_STATE_CLEAR(LONGJMP);
+		if (kdba_setjmp(&kdbjmpbuf[smp_processor_id()])) {
+			/* Command aborted (usually in pager) */
+			continue;
+		}
+		else
+			KDB_STATE_SET(LONGJMP);
+#endif	/* KDB_HAVE_LONGJMP */
+
+		cmdbuf = cmd_cur;
+		*cmdbuf = '\0';
+		*(cmd_hist[cmd_head])='\0';
+
+		if (KDB_FLAG(ONLY_DO_DUMP)) {
+			/* kdb is off but a catastrophic error requires a dump.
+			 * Take the dump and reboot.
+			 * Turn on logging so the kdb output appears in the log
+			 * buffer in the dump.
+			 */
+			const char *setargs[] = { "set", "LOGGING", "1" };
+			kdb_set(2, setargs, NULL, regs);
+			kdb_do_dump(regs);
+			kdb_reboot(0, NULL, NULL, regs);
+			/*NOTREACHED*/
+		}
+
+do_full_getstr:
+#if defined(CONFIG_SMP)
+		snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), smp_processor_id());
+#else
+		snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"));
+#endif
+		if (defcmd_in_progress)
+			strncat(kdb_prompt_str, "[defcmd]", CMD_BUFLEN);
+
+		/*
+		 * Fetch command from keyboard
+		 */
+		cmdbuf = kdb_getstr(cmdbuf, CMD_BUFLEN, kdb_prompt_str);
+		if (*cmdbuf != '\n') {
+			if (*cmdbuf < 32) {
+				if(cmdptr == cmd_head) {
+					strncpy(cmd_hist[cmd_head], cmd_cur, CMD_BUFLEN);
+					*(cmd_hist[cmd_head]+strlen(cmd_hist[cmd_head])-1) = '\0';
+				}
+				if(!handle_ctrl_cmd(cmdbuf))
+					*(cmd_cur+strlen(cmd_cur)-1) = '\0';
+				cmdbuf = cmd_cur;
+				goto do_full_getstr;
+			}
+			else
+				strncpy(cmd_hist[cmd_head], cmd_cur, CMD_BUFLEN);
+
+			cmd_head = (cmd_head+1) % KDB_CMD_HISTORY_COUNT;
+			if (cmd_head == cmd_tail) cmd_tail = (cmd_tail+1) % KDB_CMD_HISTORY_COUNT;
+
+		}
+
+		cmdptr = cmd_head;
+		diag = kdb_parse(cmdbuf, regs);
+		if (diag == KDB_NOTFOUND) {
+			kdb_printf("Unknown kdb command: '%s'\n", cmdbuf);
+			diag = 0;
+		}
+		if (diag == KDB_CMD_GO
+		 || diag == KDB_CMD_CPU
+		 || diag == KDB_CMD_SS
+		 || diag == KDB_CMD_SSB)
+			break;
+
+		if (diag)
+			kdb_cmderror(diag);
+	}
+
+	kdba_local_arch_cleanup();
+
+	return(diag);
+}
+
+
+/*
+ * kdb_print_state
+ *
+ *	Print the state data for the current processor for debugging.
+ *
+ * Inputs:
+ *	text		Identifies the debug point
+ *	value		Any integer value to be printed, e.g. reason code.
+ * Returns:
+ *	None.
+ * Locking:
+ *	none
+ * Remarks:
+ *	none
+ */
+
+void kdb_print_state(const char *text, int value)
+{
+	kdb_printf("state: %s cpu %d value %d initial %d state %x\n",
+		text, smp_processor_id(), value, kdb_initial_cpu, kdb_state[smp_processor_id()]);
+}
+
+/*
+ * kdb_previous_event
+ *
+ *	Return a count of cpus that are leaving kdb, i.e. the number
+ *	of processors that are still handling the previous kdb event.
+ *
+ * Inputs:
+ *	None.
+ * Returns:
+ *	Count of cpus in previous event.
+ * Locking:
+ *	none
+ * Remarks:
+ *	none
+ */
+
+static int
+kdb_previous_event(void)
+{
+	int i, leaving = 0;
+	for (i = 0; i < NR_CPUS; ++i) {
+		if (KDB_STATE_CPU(LEAVING, i))
+			++leaving;
+	}
+	return(leaving);
+}
+
+/*
+ * kdb_wait_for_cpus
+ *
+ * Invoked once at the start of a kdb event, from the controlling cpu.  Wait a
+ * short period for the other cpus to enter kdb state.
+ *
+ * Inputs:
+ *	none
+ * Returns:
+ *	none
+ * Locking:
+ *	none
+ * Remarks:
+ *	none
+ */
+
+int kdb_wait_for_cpus_secs = 10;		/* may be modified by ia64 MCA timeout */
+
+static void
+kdb_wait_for_cpus(void)
+{
+#ifdef	CONFIG_SMP
+	int online = 0, kdb_data = 0, prev_kdb_data = 0, i, time;
+	mdelay(100);
+	for (time = 0; time < kdb_wait_for_cpus_secs; ++time) {
+		online = 0;
+		kdb_data = 0;
+		for (i = 0; i < NR_CPUS; ++i) {
+			if (cpu_online(i)) {
+				++online;
+				if (kdb_running_process[i].seqno >= kdb_seqno - 1)
+					++kdb_data;
+			}
+		}
+		if (online == kdb_data)
+			break;
+		if (prev_kdb_data != kdb_data) {
+			kdb_nextline = 0;	/* no prompt yet */
+			kdb_printf("%d out of %d cpus in kdb, waiting for the rest\n",
+				kdb_data, online);
+			prev_kdb_data = kdb_data;
+		}
+		touch_nmi_watchdog();
+		mdelay(1000);
+	}
+	if (time) {
+		if (online == kdb_data)
+			kdb_printf("All cpus are now in kdb\n");
+		else
+			kdb_printf("%d cpu%s are not in kdb, their state is unknown\n",
+					online - kdb_data, online - kdb_data == 1 ? "" : "s");
+	}
+#endif	/* CONFIG_SMP */
+}
+
+/*
+ * kdb_main_loop
+ *
+ * The main kdb loop.  After initial setup and assignment of the controlling
+ * cpu, all cpus are in this loop.  One cpu is in control and will issue the kdb
+ * prompt, the others will spin until 'go' or cpu switch.
+ *
+ * To get a consistent view of the kernel stacks for all processes, this routine
+ * is invoked from the main kdb code via an architecture specific routine.
+ * kdba_main_loop is responsible for making the kernel stacks consistent for all
+ * processes, there should be no difference between a blocked process and a
+ * running process as far as kdb is concerned.
+ *
+ * Inputs:
+ *	reason		The reason KDB was invoked
+ *	error		The hardware-defined error code
+ *	reason2		kdb's current reason code.  Initially error but can change
+ *			acording to kdb state.
+ *	db_result	Result code from break or debug point.
+ *	regs		The exception frame at time of fault/breakpoint.  If reason
+ *			is KDB_REASON_SILENT then regs is NULL, otherwise it
+ *			should always be valid.
+ * Returns:
+ *	0	KDB was invoked for an event which it wasn't responsible
+ *	1	KDB handled the event for which it was invoked.
+ * Locking:
+ *	none
+ * Remarks:
+ *	none
+ */
+
+int
+kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
+	      kdb_dbtrap_t db_result, struct pt_regs *regs)
+{
+	int result = 1;
+	int wait_for_cpus = reason != KDB_REASON_SILENT;
+	/* Stay in kdb() until 'go', 'ss[b]' or an error */
+	while (1) {
+		/*
+		 * All processors except the one that is in control
+		 * will spin here.
+		 */
+		KDB_DEBUG_STATE("kdb_main_loop 1", reason);
+		while (KDB_STATE(HOLD_CPU)) {
+			/* state KDB is turned off by kdb_cpu to see if the
+			 * other cpus are still live, each cpu in this loop
+			 * turns it back on.
+			 */
+			if (!KDB_STATE(KDB)) {
+				KDB_STATE_SET(KDB);
+			}
+		}
+		KDB_STATE_CLEAR(SUPPRESS);
+		KDB_DEBUG_STATE("kdb_main_loop 2", reason);
+		if (KDB_STATE(LEAVING))
+			break;	/* Another cpu said 'go' */
+
+		if (wait_for_cpus) {
+			wait_for_cpus = 0;
+			kdb_wait_for_cpus();
+		}
+		/* Still using kdb, this processor is in control */
+		result = kdb_local(reason2, error, regs, db_result);
+		KDB_DEBUG_STATE("kdb_main_loop 3", result);
+
+		if (result == KDB_CMD_CPU) {
+			/* Cpu switch, hold the current cpu, release the target one. */
+			reason2 = KDB_REASON_SWITCH;
+			KDB_STATE_SET(HOLD_CPU);
+			KDB_STATE_CLEAR_CPU(HOLD_CPU, kdb_new_cpu);
+			continue;
+		}
+
+		if (result == KDB_CMD_SS) {
+			KDB_STATE_SET(DOING_SS);
+			break;
+		}
+
+		if (result == KDB_CMD_SSB) {
+			KDB_STATE_SET(DOING_SS);
+			KDB_STATE_SET(DOING_SSB);
+			break;
+		}
+
+		if (result && result != 1 && result != KDB_CMD_GO)
+			kdb_printf("\nUnexpected kdb_local return code %d\n", result);
+
+		KDB_DEBUG_STATE("kdb_main_loop 4", reason);
+		break;
+	}
+	if (KDB_STATE(DOING_SS))
+		KDB_STATE_CLEAR(SSBPT);
+	return(result);
+}
+
+/*
+ * kdb
+ *
+ *	This function is the entry point for the kernel debugger.  It
+ *	provides a command parser and associated support functions to
+ *	allow examination and control of an active kernel.
+ *
+ * 	This function may be invoked directly from any
+ *	point in the kernel by calling with reason == KDB_REASON_CALL
+ *
+ *	The breakpoint trap code should invoke this function with
+ *	one of KDB_REASON_BREAK (int 03) or KDB_REASON_DEBUG (debug register)
+ *
+ *	the die_if_kernel function should invoke this function with
+ *	KDB_REASON_OOPS.
+ *
+ *	The kernel fault handler should invoke this function with
+ *	reason == KDB_REASON_FAULT and error == trap vector #.
+ *
+ *	In single step mode, one cpu is released to run without
+ *	breakpoints.   Interrupts and NMI are reset to their original values,
+ *	the cpu is allowed to do one instruction which causes a trap
+ *	into kdb with KDB_REASON_DEBUG.
+ *
+ * Inputs:
+ *	reason		The reason KDB was invoked
+ *	error		The hardware-defined error code
+ *	regs		The exception frame at time of fault/breakpoint.  If reason
+ *			is KDB_REASON_SILENT then regs is NULL, otherwise it
+ *			should always be valid.
+ * Returns:
+ *	0	KDB was invoked for an event which it wasn't responsible
+ *	1	KDB handled the event for which it was invoked.
+ * Locking:
+ *	none
+ * Remarks:
+ *	No assumptions of system state.  This function may be invoked
+ *	with arbitrary locks held.  It will stop all other processors
+ *	in an SMP environment, disable all interrupts and does not use
+ *	the operating systems keyboard driver.
+ *
+ *	This code is reentrant but only for cpu switch.  Any other
+ *	reentrancy is an error, although kdb will attempt to recover.
+ *
+ *	At the start of a kdb session the initial processor is running
+ *	kdb() and the other processors can be doing anything.  When the
+ *	initial processor calls smp_kdb_stop() the other processors are
+ *	driven through kdb_ipi which calls kdb() with reason SWITCH.
+ *	That brings all processors into this routine, one with a "real"
+ *	reason code, the other with SWITCH.
+ *
+ *	Because the other processors are driven via smp_kdb_stop(),
+ *	they enter here from the NMI handler.  Until the other
+ *	processors exit from here and exit from kdb_ipi, they will not
+ *	take any more NMI requests.  The initial cpu will still take NMI.
+ *
+ *	Multiple race and reentrancy conditions, each with different
+ *	advoidance mechanisms.
+ *
+ *	Two cpus hit debug points at the same time.
+ *
+ *	  kdb_lock and kdb_initial_cpu ensure that only one cpu gets
+ *	  control of kdb.  The others spin on kdb_initial_cpu until
+ *	  they are driven through NMI into kdb_ipi.  When the initial
+ *	  cpu releases the others from NMI, they resume trying to get
+ *	  kdb_initial_cpu to start a new event.
+ *
+ *	A cpu is released from kdb and starts a new event before the
+ *	original event has completely ended.
+ *
+ *	  kdb_previous_event() prevents any cpu from entering
+ *	  kdb_initial_cpu state until the previous event has completely
+ *	  ended on all cpus.
+ *
+ *	An exception occurs inside kdb.
+ *
+ *	  kdb_initial_cpu detects recursive entry to kdb and attempts
+ *	  to recover.  The recovery uses longjmp() which means that
+ *	  recursive calls to kdb never return.  Beware of assumptions
+ *	  like
+ *
+ *	    ++depth;
+ *	    kdb();
+ *	    --depth;
+ *
+ *	  If the kdb call is recursive then longjmp takes over and
+ *	  --depth is never executed.
+ *
+ *	NMI handling.
+ *
+ *	  NMI handling is tricky.  The initial cpu is invoked by some kdb event,
+ *	  this event could be NMI driven but usually is not.  The other cpus are
+ *	  driven into kdb() via kdb_ipi which uses NMI so at the start the other
+ *	  cpus will not accept NMI.  Some operations such as SS release one cpu
+ *	  but hold all the others.  Releasing a cpu means it drops back to
+ *	  whatever it was doing before the kdb event, this means it drops out of
+ *	  kdb_ipi and hence out of NMI status.  But the software watchdog uses
+ *	  NMI and we do not want spurious watchdog calls into kdb.  kdba_read()
+ *	  resets the watchdog counters in its input polling loop, when a kdb
+ *	  command is running it is subject to NMI watchdog events.
+ *
+ *	  Another problem with NMI handling is the NMI used to drive the other
+ *	  cpus into kdb cannot be distinguished from the watchdog NMI.  State
+ *	  flag WAIT_IPI indicates that a cpu is waiting for NMI via kdb_ipi,
+ *	  if not set then software NMI is ignored by kdb_ipi.
+ *
+ *	Cpu switching.
+ *
+ *	  All cpus are in kdb (or they should be), all but one are
+ *	  spinning on KDB_STATE(HOLD_CPU).  Only one cpu is not in
+ *	  HOLD_CPU state, only that cpu can handle commands.
+ *
+ *	Go command entered.
+ *
+ *	  If necessary, go will switch to the initial cpu first.  If the event
+ *	  was caused by a software breakpoint (assumed to be global) that
+ *	  requires single-step to get over the breakpoint then only release the
+ *	  initial cpu, after the initial cpu has single-stepped the breakpoint
+ *	  then release the rest of the cpus.  If SSBPT is not required then
+ *	  release all the cpus at once.
+ */
+
+int
+kdb(kdb_reason_t reason, int error, struct pt_regs *regs)
+{
+	kdb_intstate_t	int_state;	/* Interrupt state */
+	kdb_reason_t	reason2 = reason;
+	int		result = 1;	/* Default is kdb handled it */
+	int		ss_event;
+	kdb_dbtrap_t 	db_result=KDB_DB_NOBPT;
+
+	switch(reason) {
+	case KDB_REASON_OOPS:
+	case KDB_REASON_NMI:
+	case KDB_REASON_WATCHDOG:
+		KDB_FLAG_SET(CATASTROPHIC);	/* kernel state is dubious now */
+		break;
+	default:
+		break;
+	}
+	if (kdb_continue_catastrophic > 2) {
+		kdb_printf("kdb_continue_catastrophic is out of range, setting to 2\n");
+		kdb_continue_catastrophic = 2;
+	}
+	if (!kdb_on && KDB_FLAG(CATASTROPHIC) && kdb_continue_catastrophic == 2) {
+		KDB_FLAG_SET(ONLY_DO_DUMP);
+	}
+	if (!kdb_on && !KDB_FLAG(ONLY_DO_DUMP))
+		return 0;
+
+	KDB_DEBUG_STATE("kdb 1", reason);
+	KDB_STATE_CLEAR(SUPPRESS);
+
+	/* Filter out userspace breakpoints first, no point in doing all
+	 * the kdb smp fiddling when it is really a gdb trap.
+	 * Save the single step status first, kdba_db_trap clears ss status.
+	 * kdba_b[dp]_trap sets SSBPT if required.
+	 */
+	ss_event = KDB_STATE(DOING_SS) || KDB_STATE(SSBPT);
+#ifdef  CONFIG_CPU_XSCALE
+	if ( KDB_STATE(A_XSC_ICH) ) {
+		/* restore changed I_BIT */
+		KDB_STATE_CLEAR(A_XSC_ICH);
+		kdba_restore_retirq(regs, KDB_STATE(A_XSC_IRQ));
+		if ( !ss_event ) {
+			kdb_printf("Stranger!!! Why IRQ bit is changed====\n");
+		}
+	}
+#endif
+	if (reason == KDB_REASON_BREAK) {
+		db_result = kdba_bp_trap(regs, error);	/* Only call this once */
+	}
+	if (reason == KDB_REASON_DEBUG) {
+		db_result = kdba_db_trap(regs, error);	/* Only call this once */
+	}
+
+	if ((reason == KDB_REASON_BREAK || reason == KDB_REASON_DEBUG)
+	 && db_result == KDB_DB_NOBPT) {
+		KDB_DEBUG_STATE("kdb 2", reason);
+		return 0;	/* Not one of mine */
+	}
+
+	/* Turn off single step if it was being used */
+	if (ss_event) {
+		kdba_clearsinglestep(regs);
+		/* Single step after a breakpoint removes the need for a delayed reinstall */
+		if (reason == KDB_REASON_BREAK || reason == KDB_REASON_DEBUG)
+			KDB_STATE_CLEAR(SSBPT);
+	}
+
+	/* kdb can validly reenter but only for certain well defined conditions */
+	if (reason == KDB_REASON_DEBUG
+	 && !KDB_STATE(HOLD_CPU)
+	 && ss_event)
+		KDB_STATE_SET(REENTRY);
+	else
+		KDB_STATE_CLEAR(REENTRY);
+
+	/* Wait for previous kdb event to completely exit before starting
+	 * a new event.
+	 */
+	while (kdb_previous_event())
+		;
+	KDB_DEBUG_STATE("kdb 3", reason);
+
+	/*
+	 * If kdb is already active, print a message and try to recover.
+	 * If recovery is not possible and recursion is allowed or
+	 * forced recursion without recovery is set then try to recurse
+	 * in kdb.  Not guaranteed to work but it makes an attempt at
+	 * debugging the debugger.
+	 */
+	if (reason != KDB_REASON_SWITCH) {
+		if (KDB_IS_RUNNING() && !KDB_STATE(REENTRY)) {
+			int recover = 1;
+			unsigned long recurse = 0;
+			kdb_printf("kdb: Debugger re-entered on cpu %d, new reason = %d\n",
+				smp_processor_id(), reason);
+			/* Should only re-enter from released cpu */
+
+			if (KDB_STATE(HOLD_CPU)) {
+				kdb_printf("     Strange, cpu %d should not be running\n", smp_processor_id());
+				recover = 0;
+			}
+			if (!KDB_STATE(CMD)) {
+				kdb_printf("     Not executing a kdb command\n");
+				recover = 0;
+			}
+			if (!KDB_STATE(LONGJMP)) {
+				kdb_printf("     No longjmp available for recovery\n");
+				recover = 0;
+			}
+			kdbgetulenv("RECURSE", &recurse);
+			if (recurse > 1) {
+				kdb_printf("     Forced recursion is set\n");
+				recover = 0;
+			}
+			if (recover) {
+				kdb_printf("     Attempting to abort command and recover\n");
+#ifdef KDB_HAVE_LONGJMP
+				kdba_longjmp(&kdbjmpbuf[smp_processor_id()], 0);
+#endif
+			}
+			if (recurse) {
+				if (KDB_STATE(RECURSE)) {
+					kdb_printf("     Already in recursive mode\n");
+				} else {
+					kdb_printf("     Attempting recursive mode\n");
+					KDB_STATE_SET(RECURSE);
+					KDB_STATE_SET(REENTRY);
+					reason2 = KDB_REASON_RECURSE;
+					recover = 1;
+				}
+			}
+			if (!recover) {
+				kdb_printf("     Cannot recover, allowing event to proceed\n");
+				return(0);
+			}
+		}
+	} else if (!KDB_IS_RUNNING()) {
+		kdb_printf("kdb: CPU switch without kdb running, I'm confused\n");
+		return(0);
+	}
+
+	/*
+	 * Disable interrupts, breakpoints etc. on this processor
+	 * during kdb command processing
+	 */
+	KDB_STATE_SET(KDB);
+	if (!ss_event) {
+		/* bh not re-enabled during single step */
+		local_bh_disable();
+	}
+	kdba_disableint(&int_state);
+	if (!KDB_STATE(KDB_CONTROL)) {
+		kdb_bp_remove_local();
+		kdba_disable_lbr();
+		KDB_STATE_SET(KDB_CONTROL);
+	}
+	else if (KDB_DEBUG(LBR))
+		kdba_print_lbr();
+
+	/*
+	 * If not entering the debugger due to CPU switch or single step
+	 * reentry, serialize access here.
+	 * The processors may race getting to this point - if,
+	 * for example, more than one processor hits a breakpoint
+	 * at the same time.   We'll serialize access to kdb here -
+	 * other processors will loop here, and the NMI from the stop
+	 * IPI will take them into kdb as switch candidates.  Once
+	 * the initial processor releases the debugger, the rest of
+	 * the processors will race for it.
+	 */
+	if (reason == KDB_REASON_SWITCH
+	 || KDB_STATE(REENTRY))
+		;	/* drop through */
+	else {
+		KDB_DEBUG_STATE("kdb 4", reason);
+		spin_lock(&kdb_lock);
+
+		while (KDB_IS_RUNNING() || kdb_previous_event()) {
+			spin_unlock(&kdb_lock);
+
+			while (KDB_IS_RUNNING() || kdb_previous_event())
+				;
+
+			spin_lock(&kdb_lock);
+		}
+		KDB_DEBUG_STATE("kdb 5", reason);
+
+		kdb_initial_cpu = smp_processor_id();
+		++kdb_seqno;
+		spin_unlock(&kdb_lock);
+		notifier_call_chain(&kdb_notifier_list, 1, NULL);
+	}
+
+	if (smp_processor_id() == kdb_initial_cpu
+	 && !KDB_STATE(REENTRY)) {
+		KDB_STATE_CLEAR(HOLD_CPU);
+		KDB_STATE_CLEAR(WAIT_IPI);
+		/*
+		 * Remove the global breakpoints.  This is only done
+		 * once from the initial processor on initial entry.
+		 */
+		kdb_bp_remove_global();
+
+		/*
+		 * If SMP, stop other processors.  The other processors
+		 * will enter kdb() with KDB_REASON_SWITCH and spin in
+		 * kdb_main_loop().
+		 */
+		KDB_DEBUG_STATE("kdb 6", reason);
+		if (smp_num_cpus > 1) {
+			int i;
+			for (i = 0; i < NR_CPUS; ++i) {
+				if (!cpu_online(i))
+					continue;
+				if (i != kdb_initial_cpu) {
+					KDB_STATE_SET_CPU(HOLD_CPU, i);
+					KDB_STATE_SET_CPU(WAIT_IPI, i);
+				}
+			}
+			KDB_DEBUG_STATE("kdb 7", reason);
+			smp_kdb_stop();
+			KDB_DEBUG_STATE("kdb 8", reason);
+		}
+	}
+
+	if (KDB_STATE(GO1)) {
+		kdb_bp_remove_global();		/* They were set for single-step purposes */
+		KDB_STATE_CLEAR(GO1);
+		reason = KDB_REASON_SILENT;	/* Now silently go */
+	}
+
+	/* Set up a consistent set of process stacks before talking to the user */
+	KDB_DEBUG_STATE("kdb 9", result);
+	result = kdba_main_loop(reason, reason2, error, db_result, regs);
+
+	KDB_DEBUG_STATE("kdb 10", result);
+	kdba_adjust_ip(reason, error, regs);
+	KDB_STATE_CLEAR(LONGJMP);
+	KDB_DEBUG_STATE("kdb 11", result);
+	/* go which requires single-step over a breakpoint must only release
+	 * one cpu.
+	 */
+	if (result == KDB_CMD_GO && KDB_STATE(SSBPT))
+		KDB_STATE_SET(GO1);
+
+	if (smp_processor_id() == kdb_initial_cpu &&
+	  !KDB_STATE(DOING_SS) &&
+	  !KDB_STATE(RECURSE)) {
+		/*
+		 * (Re)install the global breakpoints.  This is only done
+		 * once from the initial processor on go.
+		 */
+		KDB_DEBUG_STATE("kdb 12", reason);
+		kdb_bp_install_global(regs);
+		if (!KDB_STATE(GO1)) {
+			/*
+			 * Release all other cpus which will see KDB_STATE(LEAVING) is set.
+			 */
+			int i;
+			for (i = 0; i < NR_CPUS; ++i) {
+				if (KDB_STATE_CPU(KDB, i))
+					KDB_STATE_SET_CPU(LEAVING, i);
+				KDB_STATE_CLEAR_CPU(WAIT_IPI, i);
+				KDB_STATE_CLEAR_CPU(HOLD_CPU, i);
+			}
+			/* Wait until all the other processors leave kdb */
+			while (kdb_previous_event() != 1)
+				;
+			notifier_call_chain(&kdb_notifier_list, 0, NULL);
+			kdb_initial_cpu = -1;	/* release kdb control */
+			KDB_DEBUG_STATE("kdb 13", reason);
+		}
+	}
+
+	KDB_DEBUG_STATE("kdb 14", result);
+	kdba_restoreint(&int_state);
+#ifdef  CONFIG_CPU_XSCALE
+	if ( smp_processor_id() == kdb_initial_cpu &&
+	     ( KDB_STATE(SSBPT) | KDB_STATE(DOING_SS) )
+	      ) {
+		kdba_setsinglestep(regs);
+		// disable IRQ in stack frame
+		KDB_STATE_SET(A_XSC_ICH);
+		if ( kdba_disable_retirq(regs) ) {
+			KDB_STATE_SET(A_XSC_IRQ);
+		}
+		else {
+			KDB_STATE_CLEAR(A_XSC_IRQ);
+		}
+	}
+#endif
+
+	/* Only do this work if we are really leaving kdb */
+	if (!(KDB_STATE(DOING_SS) || KDB_STATE(SSBPT) || KDB_STATE(RECURSE))) {
+		KDB_DEBUG_STATE("kdb 15", result);
+		kdb_bp_install_local(regs);
+		kdba_enable_lbr();
+		local_bh_enable();
+		KDB_STATE_CLEAR(KDB_CONTROL);
+	}
+
+	KDB_DEBUG_STATE("kdb 16", result);
+	KDB_FLAG_CLEAR(CATASTROPHIC);
+	KDB_STATE_CLEAR(IP_ADJUSTED);	/* Re-adjust ip next time in */
+	KDB_STATE_CLEAR(KDB);		/* Main kdb state has been cleared */
+	KDB_STATE_CLEAR(RECURSE);
+	KDB_STATE_CLEAR(LEAVING);	/* No more kdb work after this */
+	KDB_DEBUG_STATE("kdb 17", reason);
+	return(result != 0);
+}
+
+/*
+ * kdb_mdr
+ *
+ *	This function implements the guts of the 'mdr' command.
+ *
+ *	mdr  <addr arg>,<byte count>
+ *
+ * Inputs:
+ *	addr	Start address
+ *	count	Number of bytes
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Always 0.  Any errors are detected and printed by kdb_getarea.
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+static int
+kdb_mdr(kdb_machreg_t addr, unsigned int count)
+{
+	unsigned char c;
+	while (count--) {
+		if (kdb_getarea(c, addr))
+			return(0);
+		kdb_printf("%02x", c);
+		addr++;
+	}
+	kdb_printf("\n");
+	return(0);
+}
+
+/*
+ * kdb_md
+ *
+ *	This function implements the 'md', 'md1', 'md2', 'md4', 'md8'
+ *	'mdr' and 'mds' commands.
+ *
+ *	md|mds  [<addr arg> [<line count> [<radix>]]]
+ *	mdWcN	[<addr arg> [<line count> [<radix>]]]
+ *		where W = is the width (1, 2, 4 or 8) and N is the count.
+ *		for eg., md1c20 reads 20 bytes, 1 at a time.
+ *	mdr  <addr arg>,<byte count>
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_md(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	static kdb_machreg_t last_addr;
+	static int last_radix, last_bytesperword, last_repeat;
+	int radix = 16, mdcount = 8, bytesperword = sizeof(kdb_machreg_t), repeat;
+	int nosect = 0;
+	char fmtchar, fmtstr[64];
+	kdb_machreg_t addr;
+	unsigned long word;
+	long offset = 0;
+	kdb_symtab_t symtab;
+	int symbolic = 0;
+	int valid = 0;
+
+	kdbgetintenv("MDCOUNT", &mdcount);
+	kdbgetintenv("RADIX", &radix);
+	kdbgetintenv("BYTESPERWORD", &bytesperword);
+
+	/* Assume 'md <addr>' and start with environment values */
+	repeat = mdcount * 16 / bytesperword;
+
+	if (strcmp(argv[0], "mdr") == 0) {
+		if (argc != 2)
+			return KDB_ARGCOUNT;
+		valid = 1;
+	} else if (isdigit(argv[0][2])) {
+		bytesperword = (int)(argv[0][2] - '0');
+		if (bytesperword == 0) {
+			bytesperword = last_bytesperword;
+			if (bytesperword == 0) {
+				bytesperword = 4;
+			}
+		}
+		last_bytesperword = bytesperword;
+		repeat = mdcount * 16 / bytesperword;
+		if (!argv[0][3])
+			valid = 1;
+		else if (argv[0][3] == 'c' && argv[0][4]) {
+			char *p;
+			repeat = simple_strtoul(argv[0]+4, &p, 10);
+			mdcount = ((repeat * bytesperword) + 15) / 16;
+			valid = !*p;
+		}
+		last_repeat = repeat;
+	} else if (strcmp(argv[0], "md") == 0)
+		valid = 1;
+	else if (strcmp(argv[0], "mds") == 0)
+		valid = 1;
+	if (!valid)
+		return KDB_NOTFOUND;
+
+	if (argc == 0) {
+		if (last_addr == 0)
+			return KDB_ARGCOUNT;
+		addr = last_addr;
+		radix = last_radix;
+		bytesperword = last_bytesperword;
+		repeat = last_repeat;
+		mdcount = ((repeat * bytesperword) + 15) / 16;
+	}
+
+	if (argc) {
+		kdb_machreg_t val;
+		int diag, nextarg = 1;
+		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+		if (diag)
+			return diag;
+		if (argc > nextarg+2)
+			return KDB_ARGCOUNT;
+
+		if (argc >= nextarg) {
+			diag = kdbgetularg(argv[nextarg], &val);
+			if (!diag) {
+				mdcount = (int) val;
+				repeat = mdcount * 16 / bytesperword;
+			}
+		}
+		if (argc >= nextarg+1) {
+			diag = kdbgetularg(argv[nextarg+1], &val);
+			if (!diag)
+				radix = (int) val;
+		}
+	}
+
+	if (strcmp(argv[0], "mdr") == 0) {
+		return(kdb_mdr(addr, mdcount));
+	}
+
+	switch (radix) {
+	case 10:
+		fmtchar = 'd';
+		break;
+	case 16:
+		fmtchar = 'x';
+		break;
+	case 8:
+		fmtchar = 'o';
+		break;
+	default:
+		return KDB_BADRADIX;
+	}
+
+	last_radix = radix;
+
+	if (bytesperword > sizeof(kdb_machreg_t))
+		return KDB_BADWIDTH;
+
+	switch (bytesperword) {
+	case 8:
+		sprintf(fmtstr, "%%16.16l%c ", fmtchar);
+		break;
+	case 4:
+		sprintf(fmtstr, "%%8.8l%c ", fmtchar);
+		break;
+	case 2:
+		sprintf(fmtstr, "%%4.4l%c ", fmtchar);
+		break;
+	case 1:
+		sprintf(fmtstr, "%%2.2l%c ", fmtchar);
+		break;
+	default:
+		return KDB_BADWIDTH;
+	}
+
+	last_repeat = repeat;
+	last_bytesperword = bytesperword;
+
+	if (strcmp(argv[0], "mds") == 0) {
+		symbolic = 1;
+		/* Do not save these changes as last_*, they are temporary mds
+		 * overrides.
+		 */
+		bytesperword = sizeof(kdb_machreg_t);
+		repeat = mdcount;
+		kdbgetintenv("NOSECT", &nosect);
+	}
+
+	/* Round address down modulo BYTESPERWORD */
+
+	addr &= ~(bytesperword-1);
+
+	while (repeat > 0) {
+		int	num = (symbolic?1 :(16 / bytesperword));
+		char	cbuf[32];
+		char	*c = cbuf;
+		int     i;
+
+		memset(cbuf, '\0', sizeof(cbuf));
+		kdb_printf(kdb_machreg_fmt0 " ", addr);
+
+		for(i = 0; i < num && repeat--; i++) {
+			if (kdb_getword(&word, addr, bytesperword))
+				return 0;
+
+			kdb_printf(fmtstr, word);
+			if (symbolic) {
+				kdbnearsym(word, &symtab);
+			}
+			else {
+				memset(&symtab, 0, sizeof(symtab));
+			}
+			if (symtab.sym_name) {
+				kdb_symbol_print(word, &symtab, 0);
+				if (!nosect) {
+					kdb_printf("\n");
+					kdb_printf("                       %s %s "
+						   kdb_machreg_fmt " " kdb_machreg_fmt " " kdb_machreg_fmt,
+						symtab.mod_name,
+						symtab.sec_name,
+						symtab.sec_start,
+						symtab.sym_start,
+						symtab.sym_end);
+				}
+				addr += bytesperword;
+			} else {
+#define printable_char(addr) ({char __c = '\0'; unsigned long __addr = (addr); kdb_getarea(__c, __addr); isprint(__c) ? __c : '.';})
+				switch (bytesperword) {
+				case 8:
+					*c++ = printable_char(addr++);
+					*c++ = printable_char(addr++);
+					*c++ = printable_char(addr++);
+					*c++ = printable_char(addr++);
+				case 4:
+					*c++ = printable_char(addr++);
+					*c++ = printable_char(addr++);
+				case 2:
+					*c++ = printable_char(addr++);
+				case 1:
+					*c++ = printable_char(addr++);
+					break;
+				}
+#undef printable_char
+			}
+		}
+		kdb_printf("%*s %s\n", (int)((num-i)*(2*bytesperword + 1)+1), " ", cbuf);
+	}
+	last_addr = addr;
+
+	return 0;
+}
+
+/*
+ * kdb_mm
+ *
+ *	This function implements the 'mm' command.
+ *
+ *	mm address-expression new-value
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	mm works on machine words, mmW works on bytes.
+ */
+
+int
+kdb_mm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	kdb_machreg_t addr;
+	long 	      offset = 0;
+	unsigned long contents;
+	int nextarg;
+	int width;
+
+	if (argv[0][2] && !isdigit(argv[0][2]))
+		return KDB_NOTFOUND;
+
+	if (argc < 2) {
+		return KDB_ARGCOUNT;
+	}
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+		return diag;
+
+	if (nextarg > argc)
+		return KDB_ARGCOUNT;
+
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &contents, NULL, NULL, regs)))
+		return diag;
+
+	if (nextarg != argc + 1)
+		return KDB_ARGCOUNT;
+
+	width = argv[0][2] ? (argv[0][2] - '0') : (sizeof(kdb_machreg_t));
+	if ((diag = kdb_putword(addr, contents, width)))
+		return(diag);
+
+	kdb_printf(kdb_machreg_fmt " = " kdb_machreg_fmt "\n", addr, contents);
+
+	return 0;
+}
+
+/*
+ * kdb_go
+ *
+ *	This function implements the 'go' command.
+ *
+ *	go [address-expression]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	KDB_CMD_GO for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_go(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	kdb_machreg_t addr;
+	int diag;
+	int nextarg;
+	long offset;
+
+	if (argc == 1) {
+		if (smp_processor_id() != kdb_initial_cpu) {
+			kdb_printf("go <address> must be issued from the initial cpu, do cpu %d first\n", kdb_initial_cpu);
+			return KDB_ARGCOUNT;
+		}
+		nextarg = 1;
+		diag = kdbgetaddrarg(argc, argv, &nextarg,
+				     &addr, &offset, NULL, regs);
+		if (diag)
+			return diag;
+
+		kdba_setpc(regs, addr);
+	} else if (argc)
+		return KDB_ARGCOUNT;
+
+	diag = KDB_CMD_GO;
+	if (KDB_FLAG(CATASTROPHIC)) {
+		kdb_printf("Catastrophic error detected\n");
+		kdb_printf("kdb_continue_catastrophic=%d, ",
+			kdb_continue_catastrophic);
+		if (kdb_continue_catastrophic == 0 && kdb_go_count++ == 0) {
+			kdb_printf("type go a second time if you really want to continue\n");
+			return 0;
+		}
+		if (kdb_continue_catastrophic == 2) {
+			kdb_do_dump(regs);
+			kdb_printf("forcing reboot\n");
+			kdb_reboot(0, NULL, NULL, regs);
+		}
+		kdb_printf("attempting to continue\n");
+	}
+	if (smp_processor_id() != kdb_initial_cpu) {
+		char buf[80];
+		kdb_printf("go was not issued from initial cpu, switching back to cpu %d\n", kdb_initial_cpu);
+		sprintf(buf, "cpu %d\n", kdb_initial_cpu);
+		diag = kdb_parse(buf, regs);
+		if (diag == KDB_CMD_CPU)
+			KDB_STATE_SET_CPU(GO_SWITCH, kdb_initial_cpu);
+	}
+	return diag;
+}
+
+/*
+ * kdb_rd
+ *
+ *	This function implements the 'rd' command.
+ *
+ *	rd		display all general registers.
+ *	rd  c		display all control registers.
+ *	rd  d		display all debug registers.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_rd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	/*
+	 */
+
+	if (argc == 0) {
+		return kdba_dumpregs(regs, NULL, NULL);
+	}
+
+	if (argc > 2) {
+		return KDB_ARGCOUNT;
+	}
+
+	return kdba_dumpregs(regs, argv[1], argc==2 ? argv[2]: NULL);
+}
+
+/*
+ * kdb_rm
+ *
+ *	This function implements the 'rm' (register modify)  command.
+ *
+ *	rm register-name new-contents
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	Currently doesn't allow modification of control or
+ *	debug registers, nor does it allow modification
+ *	of model-specific registers (MSR).
+ */
+
+int
+kdb_rm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	int ind = 0;
+	kdb_machreg_t contents;
+
+	if (argc != 2) {
+		return KDB_ARGCOUNT;
+	}
+
+	/*
+	 * Allow presence or absence of leading '%' symbol.
+	 */
+
+	if (argv[1][0] == '%')
+		ind = 1;
+
+	diag = kdbgetularg(argv[2], &contents);
+	if (diag)
+		return diag;
+
+	diag = kdba_setregcontents(&argv[1][ind], regs, contents);
+	if (diag)
+		return diag;
+
+	return 0;
+}
+
+#if defined(CONFIG_MAGIC_SYSRQ)
+/*
+ * kdb_sr
+ *
+ *	This function implements the 'sr' (SYSRQ key) command which
+ *	interfaces to the soi-disant MAGIC SYSRQ functionality.
+ *
+ *	sr <magic-sysrq-code>
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	None.
+ */
+int
+kdb_sr(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	extern int sysrq_enabled;
+	if (argc != 1) {
+		return KDB_ARGCOUNT;
+	}
+	if (!sysrq_enabled) {
+		kdb_printf("Auto activating sysrq\n");
+		sysrq_enabled = 1;
+	}
+
+	handle_sysrq(*argv[1], regs, 0, 0);
+
+	return 0;
+}
+#endif	/* CONFIG_MAGIC_SYSRQ */
+
+/*
+ * kdb_ef
+ *
+ *	This function implements the 'regs' (display exception frame)
+ *	command.  This command takes an address and expects to find
+ *	an exception frame at that address, formats and prints it.
+ *
+ *	regs address-expression
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	Not done yet.
+ */
+
+int
+kdb_ef(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	kdb_machreg_t   addr;
+	long		offset;
+	int nextarg;
+
+	if (argc == 1) {
+		nextarg = 1;
+		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+		if (diag)
+			return diag;
+
+		return kdba_dumpregs((struct pt_regs *)addr, NULL, NULL);
+	}
+
+	return KDB_ARGCOUNT;
+}
+
+#if defined(CONFIG_MODULES)
+extern struct module *find_module(const char *);
+extern void free_module(struct module *, int);
+
+/*
+ * kdb_lsmod
+ *
+ *	This function implements the 'lsmod' command.  Lists currently
+ *	loaded kernel modules.
+ *
+ *	Mostly taken from userland lsmod.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *
+ */
+
+int
+kdb_lsmod(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct module *mod;
+	struct module_ref *mr;
+
+	if (argc != 0)
+		return KDB_ARGCOUNT;
+
+	kdb_printf("Module                  Size  modstruct     Used by\n");
+	for (mod = module_list; mod && mod->next ;mod = mod->next) {
+		kdb_printf("%-20s%8lu  0x%p  %4ld ", mod->name, mod->size, (void *)mod,
+			(long)atomic_read(&mod->uc.usecount));
+
+		if (mod->flags & MOD_DELETED)
+			kdb_printf(" (deleted)");
+		else if (mod->flags & MOD_INITIALIZING)
+			kdb_printf(" (initializing)");
+		else if (!(mod->flags & MOD_RUNNING))
+			kdb_printf(" (uninitialized)");
+		else {
+			if (mod->flags &  MOD_AUTOCLEAN)
+				kdb_printf(" (autoclean)");
+			if (!(mod->flags & MOD_USED_ONCE))
+				kdb_printf(" (unused)");
+		}
+
+		if (mod->refs) {
+			kdb_printf(" [ ");
+
+			mr = mod->refs;
+			while (mr) {
+				kdb_printf("%s ", mr->ref->name);
+				mr = mr->next_ref;
+			}
+
+			kdb_printf("]");
+		}
+
+		kdb_printf("\n");
+	}
+
+	return 0;
+}
+
+/*
+ * kdb_rmmod
+ *
+ *	This function implements the 'rmmod' command.  Removes a given
+ *	kernel module.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	Danger: free_module() calls mod->cleanup().  If the cleanup routine
+ *	relies on interrupts then it will hang, kdb has interrupts disabled.
+ */
+
+int
+kdb_rmmod(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct module *mod;
+
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	kdb_printf("Attempting to remove module: [%s]\n", argv[1]);
+	if ((mod = find_module(argv[1])) == NULL) {
+		kdb_printf("Unable to find a module by that name\n");
+		return 0;
+	}
+
+	if (mod->refs != NULL || __MOD_IN_USE(mod)) {
+		kdb_printf("Module is in use, unable to unload\n");
+		return 0;
+	}
+
+	free_module(mod, 0);
+	kdb_printf("Module successfully unloaded\n");
+
+	return 0;
+}
+#endif	/* CONFIG_MODULES */
+
+/*
+ * kdb_env
+ *
+ *	This function implements the 'env' command.  Display the current
+ *	environment variables.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_env(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int i;
+
+	for(i=0; i<__nenv; i++) {
+		if (__env[i]) {
+			kdb_printf("%s\n", __env[i]);
+		}
+	}
+
+	if (KDB_DEBUG(MASK))
+		kdb_printf("KDBFLAGS=0x%x\n", kdb_flags);
+
+	return 0;
+}
+
+/*
+ * kdb_dmesg
+ *
+ *	This function implements the 'dmesg' command to display the contents
+ *	of the syslog buffer.
+ *
+ *	dmesg [lines]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	None.
+ */
+
+int
+kdb_dmesg(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	char *syslog_data[4], *start, *end, c;
+	int diag, logging, logsize, lines = 0;
+
+	if (argc > 1)
+		return KDB_ARGCOUNT;
+	if (argc) {
+		char *cp;
+		lines = simple_strtoul(argv[1], &cp, 0);
+		if (*cp || lines < 0)
+			lines = 0;
+	}
+
+	/* disable LOGGING if set */
+	diag = kdbgetintenv("LOGGING", &logging);
+	if (!diag && logging) {
+		const char *setargs[] = { "set", "LOGGING", "0" };
+		kdb_set(2, setargs, envp, regs);
+	}
+
+	/* syslog_data[0,1] physical start, end+1.  syslog_data[2,3] logical start, end+1. */
+	kdb_syslog_data(syslog_data);
+	if (syslog_data[2] == syslog_data[3])
+		return 0;
+	logsize = syslog_data[1] - syslog_data[0];
+	start = syslog_data[0] + (syslog_data[2] - syslog_data[0]) % logsize;
+	end = syslog_data[0] + (syslog_data[3] - syslog_data[0]) % logsize;
+#define KDB_WRAP(p) if (p < syslog_data[0]) p = syslog_data[1]-1; else if (p >= syslog_data[1]) p = syslog_data[0]
+	if (lines) {
+		char *p = end;
+		++lines;
+		do {
+			--p;
+			KDB_WRAP(p);
+			if (*p == '\n') {
+				if (--lines == 0) {
+					++p;
+					KDB_WRAP(p);
+					break;
+				}
+			}
+		} while (p != start);
+		start = p;
+	}
+	/* Do a line at a time (max 200 chars) to reduce protocol overhead */
+	c = '\0';
+	while(1) {
+		char *p;
+		int chars = 0;
+		if (!*start) {
+			while (!*start) {
+				++start;
+				KDB_WRAP(start);
+				if (start == end)
+					break;
+			}
+			if (start == end)
+				break;
+		}
+		p = start;
+		while (*start && chars < 200) {
+			c = *start;
+			++chars;
+			++start;
+			KDB_WRAP(start);
+			if (start == end || c == '\n')
+				break;
+		}
+		if (chars)
+			kdb_printf("%.*s", chars, p);
+		if (start == end)
+			break;
+	}
+	if (c != '\n')
+		kdb_printf("\n");
+
+	return 0;
+}
+
+/*
+ * kdb_cpu
+ *
+ *	This function implements the 'cpu' command.
+ *
+ *	cpu	[<cpunum>]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	KDB_CMD_CPU for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	All cpu's should be spinning in kdb().  However just in case
+ *	a cpu did not take the smp_kdb_stop NMI, check that a cpu
+ *	entered kdb() before passing control to it.
+ */
+
+int
+kdb_cpu(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	unsigned long cpunum;
+	int diag, first = 1, i;
+
+	/* ask the other cpus if they are still active */
+	for (i=0; i<NR_CPUS; i++) {
+		if (cpu_online(i))
+			KDB_STATE_CLEAR_CPU(KDB, i);
+	}
+	KDB_STATE_SET(KDB);
+	barrier();
+	/* wait for the other cpus to notice and set state KDB again,
+	 * see kdb_main_loop
+	 */
+	udelay(1000);
+
+	if (argc == 0) {
+		int i;
+
+		kdb_printf("Currently on cpu %d\n", smp_processor_id());
+		kdb_printf("Available cpus: ");
+		for (i=0; i<NR_CPUS; i++) {
+			if (cpu_online(i)) {
+				if (!first)
+					kdb_printf(", ");
+				first = 0;
+				kdb_printf("%d", i);
+				if (!KDB_STATE_CPU(KDB, i))
+					kdb_printf("*");
+			}
+		}
+		kdb_printf("\n");
+		return 0;
+	}
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	diag = kdbgetularg(argv[1], &cpunum);
+	if (diag)
+		return diag;
+
+	/*
+	 * Validate cpunum
+	 */
+	if ((cpunum > NR_CPUS)
+	 || !cpu_online(cpunum)
+	 || !KDB_STATE_CPU(KDB, cpunum))
+		return KDB_BADCPUNUM;
+
+	kdb_new_cpu = cpunum;
+
+	/*
+	 * Switch to other cpu
+	 */
+	return KDB_CMD_CPU;
+}
+
+/*
+ * kdb_ps
+ *
+ *	This function implements the 'ps' command which shows
+ *	a list of the active processes.
+ *
+ *	ps [DRSTZU]			All processes, optionally filtered by state
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+void
+kdb_ps1(struct task_struct *p)
+{
+	kdb_printf("0x%p %8d %8d  %d %4d   %c  0x%p %c%s\n",
+		   (void *)p, p->pid, p->p_pptr->pid,
+		   kdb_task_has_cpu(p), kdb_process_cpu(p),
+		   (p->state == 0) ? 'R' :
+		     (p->state < 0) ? 'U' :
+		     (p->state & TASK_UNINTERRUPTIBLE) ? 'D' :
+		     (p->state & TASK_STOPPED || p->ptrace & PT_PTRACED) ? 'T' :
+		     (p->state & TASK_ZOMBIE) ? 'Z' :
+		     (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?',
+		   (void *)(&p->thread),
+		   (p == current) ? '*': ' ',
+		   p->comm);
+	if (kdb_task_has_cpu(p)) {
+		struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+		if (!krp->seqno || !krp->p)
+			kdb_printf("  Error: no saved data for this cpu\n");
+		else {
+			if (krp->seqno < kdb_seqno - 1)
+				kdb_printf("  Warning: process state is stale\n");
+			if (krp->p != p)
+				kdb_printf("  Error: does not match running process table (0x%p)\n", krp->p);
+		}
+	}
+}
+
+int
+kdb_ps(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct task_struct *p;
+	unsigned long mask, cpu;
+
+	kdb_printf("%-*s      Pid   Parent [*] cpu State %-*s Command\n",
+		(int)(2*sizeof(void *))+2, "Task Addr",
+		(int)(2*sizeof(void *))+2, "Thread");
+	mask = kdb_task_state_string(argc, argv, envp);
+	/* Run the active tasks first */
+	for (cpu = 0; cpu < smp_num_cpus; ++cpu) {
+		p = kdb_active_task[cpu];
+		if (!kdb_task_state(p, mask))
+			continue;
+		kdb_ps1(p);
+	}
+	/* Now the real tasks */
+	for_each_task(p) {
+		if (!kdb_task_state(p, mask))
+			continue;
+		kdb_ps1(p);
+	}
+
+	return 0;
+}
+
+/*
+ * kdb_pid
+ *
+ *	This function implements the 'pid' command which switches
+ *	the currently active process.
+ *
+ *	pid [<pid>]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+
+int
+kdb_pid(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct task_struct	*p;
+	unsigned long val;
+	int diag;
+
+	if (argc > 1)
+		return KDB_ARGCOUNT;
+
+	if (argc) {
+		diag = kdbgetularg(argv[1], &val);
+		if (diag)
+			return KDB_BADINT;
+	
+		p = find_task_by_pid((pid_t)val);
+		if (!p) {
+			kdb_printf("No task with pid=%d\n", (pid_t)val);
+			return 0;
+		}
+
+		kdb_current_task = p;
+	}
+
+	kdb_printf("KDB current process is %s(pid=%d)\n", kdb_current_task->comm, 
+		   kdb_current_task->pid);
+
+	return 0;
+}
+
+/*
+ * kdb_ll
+ *
+ *	This function implements the 'll' command which follows a linked
+ *	list and executes an arbitrary command for each element.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_ll(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	kdb_machreg_t addr;
+	long 	      offset = 0;
+	kdb_machreg_t va;
+	unsigned long linkoffset;
+	int nextarg;
+
+	if (argc != 3) {
+		return KDB_ARGCOUNT;
+	}
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+	if (diag)
+		return diag;
+
+	diag = kdbgetularg(argv[2], &linkoffset);
+	if (diag)
+		return diag;
+
+	/*
+	 * Using the starting address as
+	 * the first element in the list, and assuming that
+	 * the list ends with a null pointer.
+	 */
+
+	va = addr;
+
+	while (va) {
+		char buf[80];
+
+		sprintf(buf, "%s " kdb_machreg_fmt "\n", argv[3], va);
+		diag = kdb_parse(buf, regs);
+		if (diag)
+			return diag;
+
+		addr = va + linkoffset;
+		if (kdb_getword(&va, addr, sizeof(va)))
+			return(0);
+	}
+
+	return 0;
+}
+
+/*
+ * kdb_sections_callback
+ *
+ *	Invoked from kallsyms_sections for each section.
+ *
+ * Inputs:
+ *	prevmod	Previous module name
+ *	modname	Module name
+ *	secname	Section name
+ *	secstart Start of section
+ *	secend	End of section
+ *	secflags Section flags
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Always zero
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+static int
+kdb_sections_callback(void *token, const char *modname, const char *secname,
+		      ElfW(Addr) secstart, ElfW(Addr) secend, ElfW(Word) secflags)
+{
+	const char **prevmod = (const char **)token;
+	if (*prevmod != modname) {
+		*prevmod = modname;
+		kdb_printf("\n%s", modname);
+	}
+	kdb_printf(" %s " kdb_elfw_addr_fmt0 " " kdb_elfw_addr_fmt0 " 0x%x",
+		secname, secstart, secend, secflags);
+	return(0);
+}
+
+/*
+ * kdb_sections
+ *
+ *	This function implements the 'sections' command which prints the
+ *	kernel and module sections.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_sections(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	char *prev_mod = NULL;
+	if (argc != 0) {
+		return KDB_ARGCOUNT;
+	}
+	kallsyms_sections(&prev_mod, kdb_sections_callback);
+	kdb_printf("\n");	/* End last module */
+	return(0);
+}
+
+/*
+ * kdb_help
+ *
+ *	This function implements the 'help' and '?' commands.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_help(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	kdbtab_t *kt;
+
+	kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
+	kdb_printf("----------------------------------------------------------\n");
+	for(kt=kdb_commands; kt->cmd_name; kt++) {
+		kdb_printf("%-15.15s %-20.20s %s\n", kt->cmd_name,
+			kt->cmd_usage, kt->cmd_help);
+	}
+	return 0;
+}
+
+extern int kdb_wake_up_process(struct task_struct * p);
+
+/*
+ * kdb_kill
+ *
+ *	This function implements the 'kill' commands.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+int
+kdb_kill(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+#ifdef	__KDB_HAVE_NEW_SCHEDULER
+	kdb_printf("kill command not implemented for new scheduler\n");
+	return KDB_NOTIMP;
+#else	/* !__KDB_HAVE_NEW_SCHEDULER */
+	long sig, pid;
+	char *endp;
+	struct task_struct *p, *tg;
+	int find;
+	struct siginfo info;
+
+	if (argc!=2)
+		return KDB_ARGCOUNT;
+
+	sig = simple_strtol(argv[1], &endp, 0);
+	if (*endp)
+		return KDB_BADINT;
+	if (sig >= 0 ) {
+		kdb_printf("Invalid signal parameter.<-signal>\n");
+		return 0;
+	}
+	sig=-sig;
+
+	pid = simple_strtol(argv[2], &endp, 0);
+	if (*endp)
+		return KDB_BADINT;
+	if (pid <=0 ) {
+		kdb_printf("Process ID must be large than 0.\n");
+		return 0;
+	}
+
+	/* Find the process. */
+	find = 0;
+	for_each_task(p) {
+		if(p->pid == pid) {
+			find = 1;
+			break;
+		}
+	}
+	if (!find) {
+		kdb_printf("The specified process isn't found.\n");
+		return 0;
+	}
+	/* In case the process is not a thread group leader, find the leader. */
+	if ( p->tgid != p->pid) {
+		for_each_task(tg) {
+			if(tg->pid == p->tgid) {
+				p = tg;
+				break;
+			}
+		}
+	}
+	if (!spin_trylock(&p->sigmask_lock)) {
+		kdb_printf("Can't do kill command now.\n"
+			"The sigmask lock is held somewhere else in kernel, try again later\n");
+		return 0;
+	}
+	spin_unlock(&p->sigmask_lock);
+	if (!spin_trylock(&runqueue_lock)) {
+		kdb_printf("Can't do kill command now.\n"
+			"The runqueue lock is held somewhere else in kernel, try again later\n");
+		return 0;
+	}
+	spin_unlock(&runqueue_lock);
+	info.si_signo = sig;
+	info.si_errno = 0;
+	info.si_code = SI_USER;
+	info.si_pid = pid;	/* use same capabilities as process being signalled */
+	info.si_uid = 0;	/* kdb has root authority */
+	if(send_sig_info(sig, &info, p))
+		kdb_printf("Fail to deliver Signal %ld to process %ld.\n", sig, pid);
+	else
+		kdb_printf("Signal %ld is sent to process %ld.\n", sig, pid);
+	return 0;
+#endif	/* __KDB_HAVE_NEW_SCHEDULER */
+}
+
+/*
+ * kdb_register_repeat
+ *
+ *	This function is used to register a kernel debugger command.
+ *
+ * Inputs:
+ *	cmd	Command name
+ *	func	Function to execute the command
+ *	usage	A simple usage string showing arguments
+ *	help	A simple help string describing command
+ *	repeat	Does the command auto repeat on enter?
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, one if a duplicate command.
+ * Locking:
+ *	none.
+ * Remarks:
+ *
+ */
+
+#define kdb_command_extend 50	/* arbitrary */
+int
+kdb_register_repeat(char *cmd,
+		    kdb_func_t func,
+		    char *usage,
+		    char *help,
+		    short minlen,
+		    kdb_repeat_t repeat)
+{
+	int i;
+	kdbtab_t *kp;
+
+	/*
+	 *  Brute force method to determine duplicates
+	 */
+	for (i=0, kp=kdb_commands; i<kdb_max_commands; i++, kp++) {
+		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd)==0)) {
+			kdb_printf("Duplicate kdb command registered: '%s'\n",
+				   cmd);
+			return 1;
+		}
+	}
+
+	/*
+	 * Insert command into first available location in table
+	 */
+	for (i=0, kp=kdb_commands; i<kdb_max_commands; i++, kp++) {
+		if (kp->cmd_name == NULL) {
+			break;
+		}
+	}
+
+	if (i >= kdb_max_commands) {
+		kdbtab_t *new = kmalloc((kdb_max_commands + kdb_command_extend) * sizeof(*new), GFP_KERNEL);
+		if (!new) {
+			kdb_printf("Could not allocate new kdb_command table\n");
+			return 1;
+		}
+		if (kdb_commands) {
+			memcpy(new, kdb_commands, kdb_max_commands * sizeof(*new));
+			kfree(kdb_commands);
+		}
+		memset(new + kdb_max_commands, 0, kdb_command_extend * sizeof(*new));
+		kdb_commands = new;
+		kp = kdb_commands + kdb_max_commands;
+		kdb_max_commands += kdb_command_extend;
+	}
+
+	kp->cmd_name   = cmd;
+	kp->cmd_func   = func;
+	kp->cmd_usage  = usage;
+	kp->cmd_help   = help;
+	kp->cmd_flags  = 0;
+	kp->cmd_minlen = minlen;
+	kp->cmd_repeat = repeat;
+
+	return 0;
+}
+
+/*
+ * kdb_register
+ *
+ *	Compatibility register function for commands that do not need to
+ *	specify a repeat state.  Equivalent to kdb_register_repeat with
+ *	KDB_REPEAT_NONE.
+ *
+ * Inputs:
+ *	cmd	Command name
+ *	func	Function to execute the command
+ *	usage	A simple usage string showing arguments
+ *	help	A simple help string describing command
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, one if a duplicate command.
+ * Locking:
+ *	none.
+ * Remarks:
+ *
+ */
+
+int
+kdb_register(char *cmd,
+	     kdb_func_t func,
+	     char *usage,
+	     char *help,
+	     short minlen)
+{
+	return kdb_register_repeat(cmd, func, usage, help, minlen, KDB_REPEAT_NONE);
+}
+
+/*
+ * kdb_unregister
+ *
+ *	This function is used to unregister a kernel debugger command.
+ *	It is generally called when a module which implements kdb
+ *	commands is unloaded.
+ *
+ * Inputs:
+ *	cmd	Command name
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, one command not registered.
+ * Locking:
+ *	none.
+ * Remarks:
+ *
+ */
+
+int
+kdb_unregister(char *cmd)
+{
+	int i;
+	kdbtab_t *kp;
+
+	/*
+	 *  find the command.
+	 */
+	for (i=0, kp=kdb_commands; i<kdb_max_commands; i++, kp++) {
+		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd)==0)) {
+			kp->cmd_name = NULL;
+			return 0;
+		}
+	}
+
+	/*
+	 * Couldn't find it.
+	 */
+	return 1;
+}
+
+/*
+ * kdb_inittab
+ *
+ *	This function is called by the kdb_init function to initialize
+ *	the kdb command table.   It must be called prior to any other
+ *	call to kdb_register_repeat.
+ *
+ * Inputs:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ */
+
+static void __init
+kdb_inittab(void)
+{
+	int i;
+	kdbtab_t *kp;
+	initcall_t *call;
+
+	for(i=0, kp=kdb_commands; i < kdb_max_commands; i++,kp++) {
+		kp->cmd_name = NULL;
+	}
+
+	kdb_register_repeat("md", kdb_md, "<vaddr>",   "Display Memory Contents, also mdWcN, e.g. md8c1", 1, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("mdr", kdb_md, "<vaddr> <bytes>", 	"Display Raw Memory", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("mds", kdb_md, "<vaddr>", 	"Display Memory Symbolically", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("mm", kdb_mm, "<vaddr> <contents>",   "Modify Memory Contents", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("id", kdb_id, "<vaddr>",   "Display Instructions", 1, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("go", kdb_go, "[<vaddr>]", "Continue Execution", 1, KDB_REPEAT_NONE);
+	kdb_register_repeat("rd", kdb_rd, "",		"Display Registers", 1, KDB_REPEAT_NONE);
+	kdb_register_repeat("rm", kdb_rm, "<reg> <contents>", "Modify Registers", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("ef", kdb_ef, "<vaddr>",   "Display exception frame", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("bt", kdb_bt, "[<vaddr>]", "Stack traceback", 1, KDB_REPEAT_NONE);
+	kdb_register_repeat("btp", kdb_bt, "<pid>", 	"Display stack for process <pid>", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("bta", kdb_bt, "[DRSTZU]", 	"Display stack all processes", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("btc", kdb_bt, "", 	"Backtrace current process on each cpu", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("btt", kdb_bt, "<vaddr>", 	"Backtrace process given its struct task address", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("ll", kdb_ll, "<first-element> <linkoffset> <cmd>", "Execute cmd for each element in linked list", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("env", kdb_env, "", 	"Show environment variables", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("set", kdb_set, "", 	"Set environment variables", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("help", kdb_help, "", 	"Display Help Message", 1, KDB_REPEAT_NONE);
+	kdb_register_repeat("?", kdb_help, "",         "Display Help Message", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("cpu", kdb_cpu, "<cpunum>","Switch to new cpu", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("ps", kdb_ps, "", 		"Display active task list", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("pid", kdb_pid, "<pidnum>",	"Switch to another task", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("reboot", kdb_reboot, "",  "Reboot the machine immediately", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("sections", kdb_sections, "",  "List kernel and module sections", 0, KDB_REPEAT_NONE);
+#if defined(CONFIG_MODULES)
+	kdb_register_repeat("lsmod", kdb_lsmod, "",	"List loaded kernel modules", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("rmmod", kdb_rmmod, "<modname>", "Remove a kernel module", 0, KDB_REPEAT_NONE);
+#endif
+#if defined(CONFIG_MAGIC_SYSRQ)
+	kdb_register_repeat("sr", kdb_sr, "<key>",	"Magic SysRq key", 0, KDB_REPEAT_NONE);
+#endif
+	kdb_register_repeat("dmesg", kdb_dmesg, "[lines]",	"Display syslog buffer", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>", "Send a signal to a process", 0, KDB_REPEAT_NONE);
+
+	/* Any kdb commands that are not in the base code but are required
+	 * earlier than normal initcall processing.
+	 */
+	call = &__kdb_initcall_start;
+	while (call < &__kdb_initcall_end) {
+		(*call)();
+		call++;
+	};
+}
+
+/*
+ * kdb_cmd_init
+ *
+ *	This function is called by the kdb_init function to execute any
+ *	commands defined in kdb_cmds.
+ *
+ * Inputs:
+ *	Commands in *kdb_cmds[];
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ */
+
+static void __init
+kdb_cmd_init(void)
+{
+	int i, diag;
+	for (i = 0; kdb_cmds[i]; ++i) {
+		kdb_printf("kdb_cmd[%d]%s: %s",
+				i, defcmd_in_progress ? "[defcmd]" : "", kdb_cmds[i]);
+		diag = kdb_parse(kdb_cmds[i], NULL);
+		if (diag)
+			kdb_printf("command failed, kdb diag %d\n", diag);
+	}
+	if (defcmd_in_progress) {
+		kdb_printf("Incomplete 'defcmd' set, forcing endefcmd\n");
+		kdb_parse("endefcmd", NULL);
+	}
+}
+
+/*
+ * kdb_panic
+ *
+ *	Invoked via the panic_notifier_list.
+ *
+ * Inputs:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	When this function is called from panic(), the other cpus have already
+ *	been stopped.
+ *
+ */
+
+static int
+kdb_panic(struct notifier_block *self, unsigned long command, void *ptr)
+{
+	KDB_FLAG_SET(CATASTROPHIC);	/* kernel state is dubious now */
+	KDB_ENTER();
+	return(0);
+}
+
+static struct notifier_block kdb_block = { kdb_panic, NULL, 0 };
+
+/*
+ * kdb_init
+ *
+ * 	Initialize the kernel debugger environment.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	None.
+ */
+
+void __init
+kdb_init(void)
+{
+	/*
+	 * This must be called before any calls to kdb_printf.
+	 */
+	kdb_io_init();
+
+	kdb_inittab();		/* Initialize Command Table */
+	kdb_initbptab();	/* Initialize Breakpoint Table */
+	kdb_id_init();		/* Initialize Disassembler */
+	kdba_init();		/* Architecture Dependent Initialization */
+
+	/*
+	 * Use printk() to get message in log_buf[];
+	 */
+	printk("kdb version %d.%d%s by Keith Owens, Scott Lurndal. "\
+	       "Copyright SGI, All Rights Reserved\n",
+		KDB_MAJOR_VERSION, KDB_MINOR_VERSION, KDB_TEST_VERSION);
+
+	kdb_cmd_init();		/* Preset commands from kdb_cmds */
+	kdb(KDB_REASON_SILENT, 0, 0);	/* Activate any preset breakpoints on boot cpu */
+	notifier_chain_register(&panic_notifier_list, &kdb_block);
+}
+
+EXPORT_SYMBOL(kdb_register);
+EXPORT_SYMBOL(kdb_register_repeat);
+EXPORT_SYMBOL(kdb_unregister);
+EXPORT_SYMBOL(kdb_getarea_size);
+EXPORT_SYMBOL(kdb_putarea_size);
+EXPORT_SYMBOL(kdb_getuserarea_size);
+EXPORT_SYMBOL(kdb_putuserarea_size);
+EXPORT_SYMBOL(kdb_getword);
+EXPORT_SYMBOL(kdb_putword);
+EXPORT_SYMBOL(kdbgetularg);
+EXPORT_SYMBOL(kdbgetenv);
+EXPORT_SYMBOL(kdbgetintenv);
+EXPORT_SYMBOL(kdbgetaddrarg);
+EXPORT_SYMBOL(kdb);
+EXPORT_SYMBOL(kdb_on);
+EXPORT_SYMBOL(kdb_seqno);
+EXPORT_SYMBOL(kdb_initial_cpu);
+EXPORT_SYMBOL(kdbgetsymval);
+EXPORT_SYMBOL(kdbnearsym);
+EXPORT_SYMBOL(kdb_printf);
+EXPORT_SYMBOL(kdb_symbol_print);
+EXPORT_SYMBOL(kdb_notifier_list);
+EXPORT_SYMBOL(kdb_enter_debugger);
diff -uNr linux.orig/kdb/kdbsupport.c linux/kdb/kdbsupport.c
--- linux.orig/kdb/kdbsupport.c	Thu Jan  1 08:00:00 1970
+++ linux/kdb/kdbsupport.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,860 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <stdarg.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kallsyms.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+#include <asm/uaccess.h>
+
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+/*
+ * Symbol table functions.
+ */
+
+/*
+ * kdbgetsymval
+ *
+ *	Return the address of the given symbol.
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ *      symtab  Structure to receive results
+ * Outputs:
+ * Returns:
+ *	0	Symbol not found, symtab zero filled
+ *	1	Symbol mapped to module/symbol/section, data in symtab
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdbgetsymval(const char *symname, kdb_symtab_t *symtab)
+{
+	memset(symtab, 0, sizeof(*symtab));
+	return(kallsyms_symbol_to_address(
+		symname,
+		NULL,
+		&symtab->mod_name,
+		&symtab->mod_start,
+		&symtab->mod_end,
+		&symtab->sec_name,
+		&symtab->sec_start,
+		&symtab->sec_end,
+		&symtab->sym_name,
+		&symtab->sym_start,
+		&symtab->sym_end));
+}
+
+/*
+ * kdbnearsym
+ *
+ *	Return the name of the symbol with the nearest address
+ *	less than 'addr'.
+ *
+ * Parameters:
+ * 	addr	Address to check for symbol near
+ *      symtab  Structure to receive results
+ * Outputs:
+ * Returns:
+ *	0	No sections contain this address, symtab zero filled
+ *	1	Address mapped to module/symbol/section, data in symtab
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
+{
+	int ret;
+	memset(symtab, 0, sizeof(*symtab));
+	ret = kallsyms_address_to_symbol(
+		addr,
+		&symtab->mod_name,
+		&symtab->mod_start,
+		&symtab->mod_end,
+		&symtab->sec_name,
+		&symtab->sec_start,
+		&symtab->sec_end,
+		&symtab->sym_name,
+		&symtab->sym_start,
+		&symtab->sym_end);
+	if (symtab->mod_name && *symtab->mod_name == '\0')
+		symtab->mod_name = "kernel";
+	return ret;
+}
+
+#if defined(CONFIG_SMP)
+/*
+ * kdb_ipi
+ *
+ *	This function is called from the non-maskable interrupt
+ *	handler to handle a kdb IPI instruction.
+ *
+ * Inputs:
+ *	regs	= Exception frame pointer
+ * Outputs:
+ *	None.
+ * Returns:
+ *	0	- Did not handle NMI
+ *	1	- Handled NMI
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Initially one processor is invoked in the kdb() code.  That
+ *	processor sends an ipi which drives this routine on the other
+ *	processors.  All this does is call kdb() with reason SWITCH.
+ *	This puts all processors into the kdb() routine and all the
+ *	code for breakpoints etc. is in one place.
+ *	One problem with the way the kdb NMI is sent, the NMI has no
+ *	identification that says it came from kdb.  If the cpu's kdb state is
+ *	marked as "waiting for kdb_ipi" then the NMI is treated as coming from
+ *	kdb, otherwise it is assumed to be for another reason and is ignored.
+ */
+
+int
+kdb_ipi(struct pt_regs *regs, void (*ack_interrupt)(void))
+{
+	/* Do not print before checking and clearing WAIT_IPI, IPIs are
+	 * going all the time.
+	 */
+	if (KDB_STATE(WAIT_IPI)) {
+		/*
+		 * Stopping other processors via smp_kdb_stop().
+		 */
+		if (ack_interrupt)
+			(*ack_interrupt)();	/* Acknowledge the interrupt */
+		KDB_STATE_CLEAR(WAIT_IPI);
+		KDB_DEBUG_STATE("kdb_ipi 1", 0);
+		kdb(KDB_REASON_SWITCH, 0, regs);	/* Spin in kdb() */
+		KDB_DEBUG_STATE("kdb_ipi 2", 0);
+		return 1;
+	}
+	return 0;
+}
+#endif	/* CONFIG_SMP */
+
+void
+kdb_enablehwfault(void)
+{
+	kdba_enable_mce();
+}
+
+/*
+ * kdb_get_next_ar
+ *
+ *	Get the next activation record from the stack.
+ *
+ * Inputs:
+ *	arend	Last byte +1 of the activation record.  sp for the first
+ *		frame, start of callee's activation record otherwise.
+ *	func	Start address of function.
+ *	pc	Current program counter within this function.  pc for
+ *		the first frame, caller's return address otherwise.
+ *	fp	Current frame pointer.  Register fp for the first
+ *		frame, oldfp otherwise.  0 if not known.
+ *	ss	Start of stack for the current process.
+ * Outputs:
+ *	ar	Activation record.
+ *	symtab	kallsyms symbol table data for the calling function.
+ * Returns:
+ *	1 if ar is usable, 0 if not.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Activation Record format, assuming a stack that grows down
+ *	(KDB_STACK_DIRECTION == -1).
+ *
+ *	+-----------------------------+   ^         =====================
+ *	| Return address, frame 3     |   |
+ *	+-----------------------------+   |
+ *	| Frame Pointer, frame 3      |>--'
+ *	+-----------------------------+<--.
+ *	| Locals and automatics,      |   |
+ *	| frame 2. (variable size)    |   |                 AR 2
+ *	+-----------------------------+   |
+ *	| Save registers,             |   |
+ *	| frame 2. (variable size)    |   |
+ *	+-----------------------------+   |
+ *	| Arguments to frame 1,       |   |
+ *	| (variable size)             |   |
+ *	+-----------------------------+   |         =====================
+ *	| Return address, frame 2     |   |
+ *	+-----------------------------+   |
+ *	| Frame Pointer, frame 2      |>--'
+ *	+-----------------------------+<--.
+ *	| Locals and automatics,      |   |
+ *	| frame 1. (variable size)    |   |                 AR 1
+ *	+-----------------------------+   |
+ *	| Save registers,             |   |
+ *	| frame 1. (variable size)    |   |
+ *	+-----------------------------+   |
+ *	| Arguments to frame 0,       |   |
+ *	| (variable size)             |   |
+ *	+-----------------------------+   |  -- (5) =====================
+ *	| Return address, frame 1     |   |
+ *	+-----------------------------+   |  -- (0)
+ *	| Frame Pointer, frame 1      |>--'
+ *	+-----------------------------+      -- (1), (2)
+ *	| Locals and automatics,      |
+ *	| frame 0. (variable size)    |                     AR 0
+ *	+-----------------------------+      -- (3)
+ *	| Save registers,             |
+ *	| frame 0. (variable size)    |
+ *	+-----------------------------+      -- (4) =====================
+ *
+ * The stack for the top frame can be in one of several states.
+ *  (0) Immediately on entry to the function, stack pointer (sp) is
+ *      here.
+ *  (1) If the function was compiled with frame pointers and the 'push
+ *      fp' instruction has been executed then the pointer to the
+ *      previous frame is on the stack.  However there is no guarantee
+ *      that this saved pointer is valid, the calling function might
+ *      not have frame pointers.  sp is adjusted by wordsize after
+ *      'push fp'.
+ *  (2) If the function was compiled with frame pointers and the 'copy
+ *      sp to fp' instruction has been executed then fp points here.
+ *  (3) If the function startup has 'adjust sp by 0xnn bytes' and that
+ *      instruction has been executed then sp has been adjusted by
+ *      0xnn bytes for local and automatic variables.
+ *  (4) If the function startup has one or more 'push reg' instructions
+ *      and any have been executed then sp has been adjusted by
+ *      wordsize bytes for each register saved.
+ *
+ * As the function exits it rewinds the stack, typically to (1) then (0).
+ *
+ * The stack entries for the lower frames is normally are in state (5).
+ *  (5) Arguments for the called frame are on to the stack.
+ * However lower frames can be incomplete if there is an interrupt in
+ * progress.
+ *
+ * An activation record runs from the return address for a function
+ * through to the return address for the next function or sp, whichever
+ * comes first.  For each activation record we extract :-
+ *
+ *   start    Address of the activation record.
+ *   end      Address of the last byte+1 in the activation record.
+ *   ret      Return address to caller.
+ *   oldfp    Frame pointer to previous frame, 0 if this function was
+ *            not compiled with frame pointers.
+ *   fp       Frame pointer for the current frame, 0 if this function
+ *            was not compiled with frame pointers or fp has not been
+ *            set yet.
+ *   arg0     Address of the first argument (in the previous activation
+ *            record).
+ *   locals   Bytes allocated to locals and automatics.
+ *   regs     Bytes allocated to saved registers.
+ *   args     Bytes allocated to arguments (in the previous activation
+ *            record).
+ *   setup    Bytes allocated to setup data on stack (return address,
+ *	      frame pointer).
+ *
+ * Although the kernel might be compiled with frame pointers, we still
+ * have to assume the worst and validate the frame.  Some calls from
+ * asm code to C code might not use frame pointers.  Third party binary
+ * only modules might be compiled without frame pointers, even when the
+ * rest of the kernel has frame pointers.  Some routines are always
+ * compiled with frame pointers, even if the overall kernel is not.  A
+ * routine compiled with frame pointers can be called from a routine
+ * without frame pointers, the previous "frame pointer" is saved on
+ * stack but it contains garbage.
+ *
+ * We check the object code to see if it saved a frame pointer and we
+ * validate that pointer.  Basically frame pointers are hints.
+ */
+
+#define FORCE_ARG(ar,n)	(ar)->setup = (ar)->locals = (ar)->regs = \
+			(ar)->fp = (ar)->oldfp = (ar)->ret = 0; \
+			(ar)->start = (ar)->end - KDB_STACK_DIRECTION*(n)*sizeof(unsigned long);
+
+int
+kdb_get_next_ar(kdb_machreg_t arend, kdb_machreg_t func,
+		kdb_machreg_t pc, kdb_machreg_t fp, kdb_machreg_t ss,
+		kdb_ar_t *ar, kdb_symtab_t *symtab)
+{
+	if (KDB_DEBUG(AR)) {
+		kdb_printf("kdb_get_next_ar: arend=0x%lx func=0x%lx pc=0x%lx fp=0x%lx\n",
+			arend, func, pc, fp);
+	}
+
+	memset(ar, 0, sizeof(*ar));
+	if (!kdbnearsym(pc, symtab)) {
+		symtab->sym_name = symtab->sec_name = "<unknown>";
+		symtab->mod_name = "kernel";
+		if (KDB_DEBUG(AR)) {
+			kdb_printf("kdb_get_next_ar: callee not in kernel\n");
+		}
+		pc = 0;
+	}
+
+	if (!kdba_prologue(symtab, pc, arend, fp, ss, 0, ar)) {
+		if (KDB_DEBUG(AR)) {
+			kdb_printf("kdb_get_next_ar: callee prologue failed\n");
+		}
+		return(0);
+	}
+	if (KDB_DEBUG(AR)) {
+		kdb_printf("kdb_get_next_ar: callee activation record\n");
+		kdb_printf("  start=0x%lx end=0x%lx ret=0x%lx oldfp=0x%lx fp=0x%lx\n",
+			ar->start, ar->end, ar->ret, ar->oldfp, ar->fp);
+		kdb_printf("  locals=%ld regs=%ld setup=%ld\n",
+			ar->locals, ar->regs, ar->setup);
+	}
+
+	if (ar->ret) {
+		/* Run the caller code to get arguments to callee function */
+		kdb_symtab_t	caller_symtab;
+		kdb_ar_t	caller_ar;
+		memset(&caller_ar, 0, sizeof(caller_ar));
+		if (!kdbnearsym(ar->ret, &caller_symtab)) {
+			if (KDB_DEBUG(AR)) {
+				kdb_printf("kdb_get_next_ar: caller not in kernel\n");
+			}
+		} else if (kdba_prologue(&caller_symtab, ar->ret,
+				ar->start, ar->oldfp, ss, 1, &caller_ar)) {
+				/* some caller data extracted */ ;
+		} else if (strcmp(symtab->sym_name, "do_exit") == 0) {
+			/* non-standard caller, force one argument */
+			FORCE_ARG(&caller_ar, 1);
+		} else if (KDB_DEBUG(AR)) {
+				kdb_printf("kdb_get_next_ar: caller prologue failed\n");
+		}
+		if (KDB_DEBUG(AR)) {
+			kdb_printf("kdb_get_next_ar: caller activation record\n");
+			kdb_printf("  start=0x%lx end=0x%lx ret=0x%lx"
+				   " oldfp=0x%lx fp=0x%lx\n",
+				caller_ar.start, caller_ar.end, caller_ar.ret,
+				caller_ar.oldfp, caller_ar.fp);
+			kdb_printf("  locals=%ld regs=%ld args=%ld setup=%ld\n",
+				caller_ar.locals, caller_ar.regs,
+				caller_ar.args, caller_ar.setup);
+		}
+		if (caller_ar.start) {
+			ar->args = KDB_STACK_DIRECTION*(caller_ar.end - caller_ar.start) -
+				(caller_ar.setup + caller_ar.locals + caller_ar.regs);
+			if (ar->args < 0)
+				ar->args = 0;
+			if (ar->args) {
+				ar->arg0 = ar->start -
+					KDB_STACK_DIRECTION*(ar->args - 4);
+				if (KDB_DEBUG(AR)) {
+					kdb_printf("  callee arg0=0x%lx args=%ld\n",
+						ar->arg0, ar->args);
+				}
+			}
+		}
+	}
+
+	return(1);
+}
+
+/*
+ * kdb_symbol_print
+ *
+ *	Standard method for printing a symbol name and offset.
+ * Inputs:
+ *	addr	Address to be printed.
+ *	symtab	Address of symbol data, if NULL this routine does its
+ *		own lookup.
+ *	punc	Punctuation for string, bit field.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Always 0.
+ * Locking:
+ *	none.
+ * Remarks:
+ *	The string and its punctuation is only printed if the address
+ *	is inside the kernel, except that the value is always printed
+ *	when requested.
+ */
+
+void
+kdb_symbol_print(kdb_machreg_t addr, const kdb_symtab_t *symtab_p, unsigned int punc)
+{
+	kdb_symtab_t symtab, *symtab_p2;
+	if (symtab_p) {
+		symtab_p2 = (kdb_symtab_t *)symtab_p;
+	}
+	else {
+		symtab_p2 = &symtab;
+		kdbnearsym(addr, symtab_p2);
+	}
+	if (symtab_p2->sym_name || (punc & KDB_SP_VALUE)) {
+		;	/* drop through */
+	}
+	else {
+		return;
+	}
+	if (punc & KDB_SP_SPACEB) {
+		kdb_printf(" ");
+	}
+	if (punc & KDB_SP_VALUE) {
+		kdb_printf(kdb_machreg_fmt0, addr);
+	}
+	if (symtab_p2->sym_name) {
+		if (punc & KDB_SP_VALUE) {
+			kdb_printf(" ");
+		}
+		if (punc & KDB_SP_PAREN) {
+			kdb_printf("(");
+		}
+		if (strcmp(symtab_p2->mod_name, "kernel")) {
+			kdb_printf("[%s]", symtab_p2->mod_name);
+		}
+		kdb_printf("%s", symtab_p2->sym_name);
+		if (addr != symtab_p2->sym_start) {
+			kdb_printf("+0x%lx", addr - symtab_p2->sym_start);
+		}
+		if (punc & KDB_SP_SYMSIZE) {
+			kdb_printf("/0x%lx", symtab_p2->sym_end - symtab_p2->sym_start);
+		}
+		if (punc & KDB_SP_PAREN) {
+			kdb_printf(")");
+		}
+	}
+	if (punc & KDB_SP_SPACEA) {
+		kdb_printf(" ");
+	}
+	if (punc & KDB_SP_NEWLINE) {
+		kdb_printf("\n");
+	}
+}
+
+/*
+ * kdb_strdup
+ *
+ *	kdb equivalent of strdup, for disasm code.
+ * Inputs:
+ *	str	The string to duplicate.
+ *	type	Flags to kmalloc for the new string.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Address of the new string, NULL if storage could not be allocated.
+ * Locking:
+ *	none.
+ * Remarks:
+ *	This is not in lib/string.c because it uses kmalloc which is not
+ *	available when string.o is used in boot loaders.
+ */
+
+char *kdb_strdup(const char *str, int type)
+{
+	int n = strlen(str)+1;
+	char *s = kmalloc(n, type);
+	if (!s) return NULL;
+	return strcpy(s, str);
+}
+
+/*
+ * kdb_getarea_size
+ *
+ *	Read an area of data.  The kdb equivalent of copy_from_user, with
+ *	kdb messages for invalid addresses.
+ * Inputs:
+ *	res	Pointer to the area to receive the result.
+ *	addr	Address of the area to copy.
+ *	size	Size of the area.
+ * Outputs:
+ *	none.
+ * Returns:
+ *	0 for success, < 0 for error.
+ * Locking:
+ *	none.
+ */
+
+int kdb_getarea_size(void *res, unsigned long addr, size_t size)
+{
+	int ret = kdba_getarea_size(res, addr, size);
+	if (ret) {
+		if (!KDB_STATE(SUPPRESS)) {
+			kdb_printf("kdb_getarea: Bad address 0x%lx\n", addr);
+			KDB_STATE_SET(SUPPRESS);
+		}
+		ret = KDB_BADADDR;
+	}
+	else {
+		KDB_STATE_CLEAR(SUPPRESS);
+	}
+	return(ret);
+}
+
+/*
+ * kdb_putarea_size
+ *
+ *	Write an area of data.  The kdb equivalent of copy_to_user, with
+ *	kdb messages for invalid addresses.
+ * Inputs:
+ *	addr	Address of the area to write to.
+ *	res	Pointer to the area holding the data.
+ *	size	Size of the area.
+ * Outputs:
+ *	none.
+ * Returns:
+ *	0 for success, < 0 for error.
+ * Locking:
+ *	none.
+ */
+
+int kdb_putarea_size(unsigned long addr, void *res, size_t size)
+{
+	int ret = kdba_putarea_size(addr, res, size);
+	if (ret) {
+		if (!KDB_STATE(SUPPRESS)) {
+			kdb_printf("kdb_putarea: Bad address 0x%lx\n", addr);
+			KDB_STATE_SET(SUPPRESS);
+		}
+		ret = KDB_BADADDR;
+	}
+	else {
+		KDB_STATE_CLEAR(SUPPRESS);
+	}
+	return(ret);
+}
+
+/*
+ * kdb_getword
+ *
+ * 	Read a binary value.  Unlike kdb_getarea, this treats data as numbers.
+ * Inputs:
+ *	word	Pointer to the word to receive the result.
+ *	addr	Address of the area to copy.
+ *	size	Size of the area.
+ * Outputs:
+ *	none.
+ * Returns:
+ *	0 for success, < 0 for error.
+ * Locking:
+ *	none.
+ */
+
+int kdb_getword(unsigned long *word, unsigned long addr, size_t size)
+{
+	int diag;
+	__u8  w1;
+	__u16 w2;
+	__u32 w4;
+	__u64 w8;
+	*word = 0;	/* Default value if addr or size is invalid */
+	switch (size) {
+	case 1:
+		if (!(diag = kdb_getarea(w1, addr)))
+			*word = w1;
+		break;
+	case 2:
+		if (!(diag = kdb_getarea(w2, addr)))
+			*word = w2;
+		break;
+	case 4:
+		if (!(diag = kdb_getarea(w4, addr)))
+			*word = w4;
+		break;
+	case 8:
+		if (size <= sizeof(*word)) {
+			if (!(diag = kdb_getarea(w8, addr)))
+				*word = w8;
+			break;
+		}
+		/* drop through */
+	default:
+		diag = KDB_BADWIDTH;
+		kdb_printf("kdb_getword: bad width %ld\n", (long) size);
+	}
+	return(diag);
+}
+
+/*
+ * kdb_putword
+ *
+ * 	Write a binary value.  Unlike kdb_putarea, this treats data as numbers.
+ * Inputs:
+ *	addr	Address of the area to write to..
+ *	word	The value to set.
+ *	size	Size of the area.
+ * Outputs:
+ *	none.
+ * Returns:
+ *	0 for success, < 0 for error.
+ * Locking:
+ *	none.
+ */
+
+int kdb_putword(unsigned long addr, unsigned long word, size_t size)
+{
+	int diag;
+	__u8  w1;
+	__u16 w2;
+	__u32 w4;
+	__u64 w8;
+	switch (size) {
+	case 1:
+		w1 = word;
+		diag = kdb_putarea(addr, w1);
+		break;
+	case 2:
+		w2 = word;
+		diag = kdb_putarea(addr, w2);
+		break;
+	case 4:
+		w4 = word;
+		diag = kdb_putarea(addr, w4);
+		break;
+	case 8:
+		if (size <= sizeof(word)) {
+			w8 = word;
+			diag = kdb_putarea(addr, w8);
+			break;
+		}
+		/* drop through */
+	default:
+		diag = KDB_BADWIDTH;
+		kdb_printf("kdb_putword: bad width %ld\n", (long) size);
+	}
+	return(diag);
+}
+
+/*
+ * kdb_task_state_string
+ *
+ * 	Convert a string containing any of the letters DRSTZU to a mask for
+ * 	the process state field and return the value.  If no argument is
+ * 	supplied, return ~0.
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ * Outputs:
+ *	none.
+ * Returns:
+ *	Mask for process state.
+ * Locking:
+ *	none.
+ */
+
+#define UNRUNNABLE	(1UL << (8*sizeof(unsigned long) - 1))	/* unrunnable is < 0 */
+#define RUNNING		(1UL << (8*sizeof(unsigned long) - 2))
+#define TRACED		(1UL << (8*sizeof(unsigned long) - 3))
+
+unsigned long
+kdb_task_state_string(int argc, const char **argv, const char **envp)
+{
+	long res = ~0;
+	if (argc >= 1) {
+		const char *s = argv[1];
+		res = 0;
+		while (*s) {
+			switch (*s) {
+			case 'D': res |= TASK_UNINTERRUPTIBLE; break;
+			case 'R': res |= RUNNING; break;
+			case 'S': res |= TASK_INTERRUPTIBLE; break;
+			case 'T': res |= TASK_STOPPED | TRACED; break;
+			case 'Z': res |= TASK_ZOMBIE; break;
+			case 'U': res |= UNRUNNABLE; break;
+			default:
+				  kdb_printf("kdb_task_state unknown flag '%c' ignored\n", *s);
+				  break;
+			}
+			++s;
+		}
+	}
+	return res;
+}
+
+/*
+ * kdb_task_state
+ *
+ * 	Return true if a process has the desired state given by the mask.
+ * Inputs:
+ *	p	struct task for the process
+ *	mask	mask from kdb_task_state_string to select processes
+ * Outputs:
+ *	none.
+ * Returns:
+ *	True if the process matches at least one criteria defined by the mask.
+ * Locking:
+ *	none.
+ */
+
+unsigned long
+kdb_task_state(const struct task_struct *p, unsigned long mask)
+{
+	return ((mask & p->state) ||
+		(mask & RUNNING && p->state == 0) ||
+		(mask & TRACED && p->ptrace & PT_PTRACED));
+}
+
+struct kdb_running_process kdb_running_process[NR_CPUS];
+
+/*
+ * kdb_save_running
+ *
+ * 	Save the state of a running process.  This is invoked on the current
+ * 	process on each cpu (assuming the cpu is responding).
+ * Inputs:
+ *	regs	struct pt_regs for the process
+ * Outputs:
+ *	Updates kdb_running_process[] for this cpu.
+ * Returns:
+ *	none.
+ * Locking:
+ *	none.
+ */
+
+void
+kdb_save_running(struct pt_regs *regs)
+{
+	struct kdb_running_process *krp = kdb_running_process + smp_processor_id();
+	krp->p = current;
+	krp->regs = regs;
+	krp->seqno = kdb_seqno;
+	kdba_save_running(&(krp->arch), regs);
+}
+
+/*
+ * kdb_unsave_running
+ *
+ * 	Reverse the effect of kdb_save_running.
+ * Inputs:
+ *	regs	struct pt_regs for the process
+ * Outputs:
+ *	Updates kdb_running_process[] for this cpu.
+ * Returns:
+ *	none.
+ * Locking:
+ *	none.
+ */
+
+void
+kdb_unsave_running(struct pt_regs *regs)
+{
+	struct kdb_running_process *krp = kdb_running_process + smp_processor_id();
+	kdba_unsave_running(&(krp->arch), regs);
+	krp->seqno = 0;
+}
+
+
+/*
+ * kdb_print_nameval
+ *
+ * 	Print a name and its value, converting the value to a symbol lookup
+ * 	if possible.
+ * Inputs:
+ *	name	field name to print
+ *	val	value of field
+ * Outputs:
+ *	none.
+ * Returns:
+ *	none.
+ * Locking:
+ *	none.
+ */
+
+void
+kdb_print_nameval(const char *name, unsigned long val)
+{
+	kdb_symtab_t symtab;
+	kdb_printf("  %-11.11s ", name);
+	if (kdbnearsym(val, &symtab))
+		kdb_symbol_print(val, &symtab, KDB_SP_VALUE|KDB_SP_SYMSIZE|KDB_SP_NEWLINE);
+	else
+		kdb_printf("0x%lx\n", val);
+}
+
+static struct page * kdb_get_one_user_page(struct task_struct *tsk, unsigned long start,
+		int len, int write)
+{
+	struct mm_struct *mm = tsk->mm;
+	unsigned int flags;
+	struct vm_area_struct *	vma;
+
+	/* shouldn't cross a page boundary. temporary restriction. */
+	if ((start & PAGE_MASK) != ((start+len) & PAGE_MASK)) {
+		kdb_printf("%s: crosses page boundary: addr=%08lx, len=%d\n", 
+			__FUNCTION__, start, len);
+		return NULL;
+	}
+
+	start = PAGE_ALIGN(start);
+	flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+
+	vma = find_extend_vma(mm, start);
+
+	/* may be we can allow access to VM_IO pages inside KDB? */
+	if (!vma || (vma->vm_flags & VM_IO) || !(flags & vma->vm_flags))
+		return NULL;
+
+	return kdb_follow_page(mm, start, write);
+}
+
+int kdb_getuserarea_size(void *to, unsigned long from, size_t size)
+{
+	struct page *page;
+	void * vaddr;
+
+	page = kdb_get_one_user_page(kdb_current_task, from, size, 0);
+	if (!page)
+		return size;
+
+	vaddr = kmap_atomic(page, KM_KDB);
+	memcpy(to, vaddr+ (from & (PAGE_SIZE - 1)), size);
+	kunmap_atomic(vaddr, KM_KDB);
+
+	return 0;
+}
+
+int kdb_putuserarea_size(unsigned long to, void *from, size_t size)
+{
+	struct page *page;
+	void * vaddr;
+
+	page = kdb_get_one_user_page(kdb_current_task, to, size, 1);
+	if (!page)
+		return size;
+
+	vaddr = kmap_atomic(page, KM_KDB);
+	memcpy(vaddr+ (to & (PAGE_SIZE - 1)), from, size);
+	kunmap_atomic(vaddr, KM_KDB);
+
+	return 0;
+}
diff -uNr linux.orig/kdb/modules/Makefile linux/kdb/modules/Makefile
--- linux.orig/kdb/modules/Makefile	Thu Jan  1 08:00:00 1970
+++ linux/kdb/modules/Makefile	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+O_TARGET := vmlinux-obj.o
+obj-$(CONFIG_KDB_MODULES) += kdbm_vm.o kdbm_pg.o
+CFLAGS_kdbm_vm.o	+= -I $(TOPDIR)/drivers/scsi
+
+EXTRA_CFLAGS += -I $(TOPDIR)/arch/$(ARCH)/kdb
+
+include $(TOPDIR)/Rules.make
diff -uNr linux.orig/kdb/modules/kdbm_pg.c linux/kdb/modules/kdbm_pg.c
--- linux.orig/kdb/modules/kdbm_pg.c	Thu Jan  1 08:00:00 1970
+++ linux/kdb/modules/kdbm_pg.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,662 @@
+/*
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/fs.h>
+#include <linux/iobuf.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/blkdev.h>
+#include <linux/ctype.h>
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Debug page information");
+MODULE_LICENSE("GPL");
+
+/* Standard Linux page stuff */
+
+static char	*pg_flag_vals[] = {
+	"PG_locked", "PG_error", "PG_referenced", "PG_uptodate",
+	"PG_dirty", "PG_unused_5", "PG_lru", "PG_active",
+	"PG_slab", "PG_unused_9", "PG_skip", "PG_highmem",
+	"PG_checked", "PG_arch_1", "PG_reserved", "PG_launder",
+	NULL };
+
+static char	*bh_state_vals[] = {
+	"Uptodate", "Dirty", "Lock", "Req",
+	"Mapped", "New", "Async", "Wait_IO",
+	"Launder", "JBD",
+	/*XFS*/ "Delay",
+	"Private",
+	NULL };
+
+static char *inode_flag_vals[] = {
+	"I_DIRTY_SYNC", "I_DIRTY_DATASYNC", "I_DIRTY_PAGES", "I_LOCK",
+	"I_FREEING", "I_CLEAR",
+	/*XFS*/ "I_NEW",
+	NULL };
+
+static char	*map_flags(unsigned long flags, char *mapping[])
+{
+	static	char	buffer[256];
+	int	index;
+	int	offset = 12;
+
+	buffer[0] = '\0';
+
+	for (index = 0; flags && mapping[index]; flags >>= 1, index++) {
+		if (flags & 1) {
+			if ((offset + strlen(mapping[index]) + 1) >= 80) {
+				strcat(buffer, "\n            ");
+				offset = 12;
+			} else if (offset > 12) {
+				strcat(buffer, " ");
+				offset++;
+			}
+			strcat(buffer, mapping[index]);
+			offset += strlen(mapping[index]);
+		}
+	}
+
+	return (buffer);
+}
+
+static char	*page_flags(unsigned long flags)
+{
+	return(map_flags(flags, pg_flag_vals));
+}
+
+static int
+kdbm_buffers(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	struct buffer_head	bh;
+	unsigned long addr;
+	long	offset=0;
+	int nextarg;
+	int diag;
+	
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+	    (diag = kdb_getarea(bh, addr)))
+		return(diag);
+
+	kdb_printf("buffer_head at 0x%lx\n", addr);
+	kdb_printf("  next 0x%p bno %llu rsec %llu size %d dev 0x%x rdev 0x%x\n",
+		bh.b_next, (unsigned long long)bh.b_blocknr,
+		(unsigned long long)bh.b_rsector, bh.b_size,
+		bh.b_dev, bh.b_rdev);
+	kdb_printf("  count %d state 0x%lx [%s] b_list %d\n",
+		bh.b_count.counter, bh.b_state,
+		map_flags(bh.b_state, bh_state_vals), bh.b_list);
+	kdb_printf("  ftime %ld (%ld) b_next_free 0x%p b_prev_free 0x%p\n",
+		bh.b_flushtime, bh.b_flushtime - jiffies,
+		bh.b_next_free, bh.b_prev_free);
+	kdb_printf("  b_reqnext 0x%p b_data 0x%p\n",
+		bh.b_reqnext, bh.b_data);
+	kdb_printf("  b_inode_buffers.prev 0x%p b_inode_buffers.next 0x%p\n",
+		bh.b_inode_buffers.prev, bh.b_inode_buffers.next);
+	kdb_printf("  b_page 0x%p b_this_page 0x%p b_private 0x%p\n",
+		bh.b_page, bh.b_this_page, bh.b_private);
+	kdb_printf("  b_end_io ");
+	/*if (bh.b_end_io)
+		kdb_symbol_print(kdba_funcptr_value(bh.b_end_io), NULL, KDB_SP_VALUE);
+	else
+		kdb_printf("(NULL)");*/
+	kdb_printf("\n");
+
+	return 0;
+}
+
+static int
+kdbm_page(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	struct page	page;
+	unsigned long addr;
+	long	offset=0;
+	int nextarg;
+	int diag;
+	
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+	if (diag)
+		return diag;
+
+	if (addr < PAGE_OFFSET)
+		addr = (unsigned long) &mem_map[addr];
+
+	if ((diag = kdb_getarea(page, addr)))
+		return(diag);
+
+	kdb_printf("struct page at 0x%lx\n", addr);
+	kdb_printf("  next 0x%p prev 0x%p addr space 0x%p index %lu (offset 0x%x)\n",
+		   page.list.next, page.list.prev, page.mapping, page.index,
+		   (int)(page.index << PAGE_CACHE_SHIFT));
+	kdb_printf("  count %d flags %s\n",
+		   page.count.counter, page_flags(page.flags));
+	kdb_printf("  virtual 0x%p\n", page_address((struct page *)addr));
+	if (page.buffers)
+		kdb_printf("  buffers 0x%p\n", page.buffers);
+
+	return 0;
+}
+
+unsigned long
+print_request(unsigned long addr)
+{
+	struct request	rq;
+
+	if (kdb_getarea(rq, addr))
+		return(0);
+
+	kdb_printf("struct request at 0x%lx\n", addr);
+	kdb_printf("  rq_dev 0x%x cmd %d errors %d sector %llu nr_sectors %lu waiting 0x%p\n",
+			rq.rq_dev, rq.cmd, rq.errors,
+			(unsigned long long)rq.sector, rq.nr_sectors,
+			rq.waiting);
+
+	kdb_printf("  hsect %llu hnrsect %lu nrseg %u nrhwseg %u currnrsect %lu seq %d\n",
+			(unsigned long long)rq.hard_sector, rq.hard_nr_sectors,
+			rq.nr_segments, rq.nr_hw_segments,
+			rq.current_nr_sectors, rq.elevator_sequence);
+	kdb_printf("  ");
+	kdb_printf("bh 0x%p bhtail 0x%p req_q 0x%p\n\n",
+			rq.bh, rq.bhtail, rq.q);
+
+	return (unsigned long) rq.queue.next;
+}
+
+static int
+kdbm_request(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	long	offset=0;
+	unsigned long addr;
+	int nextarg;
+	int diag;
+	
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+	if (diag)
+		return diag;
+
+	print_request(addr);
+	return 0;
+}
+
+
+static int
+kdbm_rqueue(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	struct request_queue	rq;
+	unsigned long addr, head_addr, next;
+	long	offset=0;
+	int nextarg;
+	int i, diag;
+	
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+	    (diag = kdb_getarea(rq, addr)))
+		return(diag);
+
+	kdb_printf("struct request_queue at 0x%lx [%s]\n", addr,
+			rq.plugged ? "plugged" : "running");
+	kdb_printf(" read free %d list [0x%p, 0x%p]\n",
+			rq.rq[READ].count,
+			rq.rq[READ].free.prev,
+			rq.rq[READ].free.next);
+	kdb_printf(" write free %d list [0x%p, 0x%p]\n",
+			rq.rq[WRITE].count,
+			rq.rq[WRITE].free.prev,
+			rq.rq[WRITE].free.next);
+
+	i = 0;
+	next = (unsigned long)rq.queue_head.next;
+	head_addr = addr + offsetof(struct request_queue, queue_head);
+	kdb_printf(" request queue: %s\n", next == head_addr ?
+		"empty" : "");
+	while (next != head_addr) {
+		i++;
+		next = print_request(next);
+	}
+
+	if (i)
+		kdb_printf("%d requests found\n", i);
+
+	return 0;
+}
+
+
+static void
+do_buffer(unsigned long addr)
+{
+	struct buffer_head	bh;
+	
+	if (kdb_getarea(bh, addr))
+		return;
+
+	kdb_printf("bh 0x%lx bno %8llu [%s]\n", addr,
+		 (unsigned long long)bh.b_blocknr,
+		 map_flags(bh.b_state, bh_state_vals));
+}
+
+static int
+kdbm_inode_pages(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	struct inode *inode = NULL;
+	struct address_space *ap = NULL;
+	unsigned long addr, addr1 = 0;
+	long offset=0;
+	int nextarg;
+	int diag;
+	int which=0;
+
+	struct list_head *head, *curr;
+	
+	if (argc < 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+	if (diag)
+		goto out;
+
+	if (argc == 2) {
+		nextarg = 2;
+		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr1,
+					&offset, NULL, regs);
+		if (diag)
+			goto out;
+		kdb_printf("Looking for page index 0x%lx ... \n", addr1);
+	}
+
+	if (!(inode = kmalloc(sizeof(*inode), GFP_ATOMIC))) {
+		kdb_printf("kdbm_inode_pages: cannot kmalloc inode\n");
+		goto out;
+	}
+	if (!(ap = kmalloc(sizeof(*ap), GFP_ATOMIC))) {
+		kdb_printf("kdbm_inode_pages: cannot kmalloc ap\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea(*inode, addr)))
+		goto out;
+	if (!inode->i_mapping) {
+		kdb_printf("inode has no mapping\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea(*ap, (unsigned long) inode->i_mapping)))
+		goto out;
+	
+ again:
+	if (which == 0){
+	  which=1;
+	  head = &inode->i_mapping->clean_pages;
+	  kdb_printf("CLEAN  page_struct   index  cnt  flags\n");
+	} else if (which == 1) {
+	  which=2;
+	  head = &inode->i_mapping->dirty_pages;
+	  kdb_printf("DIRTY  page_struct   index  cnt  flags\n");
+	} else if (which == 2) {
+	  which=3;
+	  head = &inode->i_mapping->locked_pages;
+	  kdb_printf("LOCKED page_struct   index  cnt  flags\n");
+	} else {
+	  goto out;
+	}
+	
+	curr = head->next;
+	while (curr != head) {
+		struct page 	 page;
+		struct list_head curr_struct;
+
+		addr = (unsigned long) list_entry(curr, struct page, list);
+		if ((diag = kdb_getarea(page, addr)))
+			goto out;
+
+		if (!addr1 || page.index == addr1 ||
+			(addr1 == -1 && (page.flags & ( 1 << PG_locked))))
+		{
+			kdb_printf("    0x%lx    %6lu    %5d    0x%lx ",
+				addr, page.index, page.count.counter,
+				page.flags);
+			if (page.buffers)
+				do_buffer((unsigned long) page.buffers);
+			else
+				kdb_printf("bh [NULL]\n");
+		}
+
+		if ((diag = kdb_getarea(curr_struct, (unsigned long) curr)))
+			goto out;
+
+		curr = curr_struct.next;
+	}
+	goto again;
+ out:
+	if (inode)
+		kfree(inode);
+	if (ap)
+		kfree(ap);
+	return diag;
+}
+
+static int
+kdbm_inode(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	struct inode *inode = NULL;
+	unsigned long addr;
+	unsigned char *iaddr;
+	long	offset=0;
+	int nextarg;
+	int diag;
+	
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+		goto out;
+	if (!(inode = kmalloc(sizeof(*inode), GFP_ATOMIC))) {
+		kdb_printf("kdbm_inode: cannot kmalloc inode\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea(*inode, addr)))
+		goto out;
+
+	kdb_printf("struct inode at  0x%lx\n", addr);
+
+	kdb_printf(" i_ino = %lu i_count = %u i_dev = 0x%x i_size %Ld\n",
+					inode->i_ino, atomic_read(&inode->i_count),
+					inode->i_dev, inode->i_size);
+
+	kdb_printf(" i_mode = 0%o  i_nlink = %d  i_rdev = 0x%x\n",
+					inode->i_mode, inode->i_nlink,
+					inode->i_rdev);
+
+	kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n",
+		list_entry(inode->i_hash.next, struct inode, i_hash),
+		list_entry(inode->i_hash.prev, struct inode, i_hash));
+
+	kdb_printf(" i_list.nxt = 0x%p i_list.prv = 0x%p\n",
+		list_entry(inode->i_list.next, struct inode, i_list),
+		list_entry(inode->i_list.prev, struct inode, i_list));
+
+	kdb_printf(" i_dentry.nxt = 0x%p i_dentry.prv = 0x%p\n",
+		list_entry(inode->i_dentry.next, struct dentry, d_alias),
+		list_entry(inode->i_dentry.prev, struct dentry, d_alias));
+
+	kdb_printf(" i_dirty_buffers.nxt = 0x%p i_dirty_buffers.prv = 0x%p\n",
+		list_entry(inode->i_dirty_buffers.next,
+				struct buffer_head, b_inode_buffers),
+		list_entry(inode->i_dirty_buffers.prev,
+				struct buffer_head, b_inode_buffers));
+
+	kdb_printf(" i_dirty_data_buffers.nxt = 0x%p i_dirty_data_buffers.prv = 0x%p\n",
+		list_entry(inode->i_dirty_data_buffers.next,
+				struct buffer_head, b_inode_buffers),
+		list_entry(inode->i_dirty_data_buffers.prev,
+				struct buffer_head, b_inode_buffers));
+
+	kdb_printf(" i_sb = 0x%p i_op = 0x%p i_data = 0x%lx nrpages = %lu\n",
+					inode->i_sb, inode->i_op,
+					addr + offsetof(struct inode, i_data),
+					inode->i_data.nrpages);
+	kdb_printf(" i_fop= 0x%p i_flock = 0x%p i_mapping = 0x%p\n",
+			   inode->i_fop, inode->i_flock, inode->i_mapping);
+	
+	kdb_printf(" i_flags 0x%x i_state 0x%lx [%s]",
+			   inode->i_flags, inode->i_state,
+			   map_flags(inode->i_state, inode_flag_vals));
+
+	iaddr  = (char *)addr;
+	iaddr += offsetof(struct inode, u);
+
+	kdb_printf("  fs specific info @ 0x%p\n", iaddr);
+out:
+	if (inode)
+		kfree(inode);
+	return diag;
+}
+
+static int
+kdbm_sb(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	struct super_block *sb = NULL;
+	unsigned long addr;
+	long	offset=0;
+	int nextarg;
+	int diag;
+	
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+		goto out;
+	if (!(sb = kmalloc(sizeof(*sb), GFP_ATOMIC))) {
+		kdb_printf("kdbm_sb: cannot kmalloc sb\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea(*sb, addr)))
+		goto out;
+
+	kdb_printf("struct super_block at  0x%lx\n", addr);
+	kdb_printf(" s_dev 0x%x blocksize 0x%lx\n", sb->s_dev, sb->s_blocksize);
+	kdb_printf(" s_flags 0x%lx s_root 0x%p\n", sb->s_flags, sb->s_root);
+	kdb_printf(" s_dirt %d s_dirty.next 0x%p s_dirty.prev 0x%p\n",
+		sb->s_dirt, sb->s_dirty.next, sb->s_dirty.prev);
+	kdb_printf(" s_locked_inodes.next 0x%p s_locked_inodes.prev 0x%p\n",
+		sb->s_locked_inodes.next, sb->s_locked_inodes.prev);
+out:
+	if (sb)
+		kfree(sb);
+	return diag;
+}
+
+
+static int
+kdbm_kiobuf(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	struct kiobuf *kiobuf = NULL;
+	struct page page;
+	struct page **page_array = NULL;
+	unsigned long addr;
+	long offset=0;
+	int nextarg;
+	int diag;
+	int i, s;
+	
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+		goto out;
+	if (!(kiobuf = kmalloc(sizeof(*kiobuf), GFP_ATOMIC))) {
+		kdb_printf("kdbm_kiobuf: cannot kmalloc kiobuf\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea(*kiobuf, addr)))
+		goto out;
+
+	kdb_printf("kiobuf at 0x%lx\n", addr);
+	kdb_printf("  nr_pages %d array_len %d offset 0x%x length 0x%x\n",
+		   kiobuf->nr_pages, kiobuf->array_len,
+		   kiobuf->offset, kiobuf->length);
+	kdb_printf("  errno %d\n", kiobuf->errno);
+	kdb_printf("    page_struct   page_addr     cnt  flags\n");
+	s = kiobuf->nr_pages*sizeof(*page_array);
+	if (!(page_array = kmalloc(s, GFP_ATOMIC))) {
+		kdb_printf("kdbm_kiobuf: cannot kmalloc page_array\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea_size(page_array, (unsigned long)kiobuf->maplist, s)))
+		goto out;
+	kiobuf->maplist = page_array;
+	for (i = 0; i < kiobuf->nr_pages; i++) {
+		if ((diag = kdb_getarea(page, (unsigned long) kiobuf->maplist[i])))
+			goto out;
+		kdb_printf("    0x%p",  kiobuf->maplist[i]);
+		kdb_printf("    0x%p", page_address(kiobuf->maplist[i]));
+		kdb_printf("    %d    0x%lx\n", page.count.counter, page.flags);
+	}
+out:
+	if (kiobuf)
+		kfree(kiobuf);
+	if (page_array)
+		kfree(page_array);
+	return diag;
+}
+
+#ifdef	CONFIG_X86
+/* According to Steve Lord, this code is ix86 specific.  Patches to extend it to
+ * other architectures will be greatefully accepted.
+ */
+static int
+kdbm_memmap(int argc, const char **argv, const char **envp,
+        struct pt_regs *regs)
+{
+	struct page	page;
+	int		i, page_count;
+	int		slab_count = 0;
+	int		dirty_count = 0;
+	int		locked_count = 0;
+	int		page_counts[9];
+	int		buffered_count = 0;
+#ifdef buffer_delay
+	int		delay_count = 0;
+#endif
+	int		diag;
+	unsigned long addr;
+
+	addr = (unsigned long)mem_map;
+	page_count = max_mapnr;
+	memset(page_counts, 0, sizeof(page_counts));
+
+	for (i = 0; i < page_count; i++) {
+		if ((diag = kdb_getarea(page, addr)))
+			return(diag);
+		addr += sizeof(page);
+
+		if (PageSlab(&page))
+			slab_count++;
+		if (PageDirty(&page))
+			dirty_count++;
+		if (PageLocked(&page))
+			locked_count++;
+		if (page.count.counter < 8)
+			page_counts[page.count.counter]++;
+		else
+			page_counts[8]++;
+		if (page.buffers) {
+			buffered_count++;
+#ifdef buffer_delay
+			if (buffer_delay(page.buffers))
+				delay_count++;
+#endif
+		}
+
+	}
+
+	kdb_printf("  Total pages:      %6d\n", page_count);
+	kdb_printf("  Slab pages:       %6d\n", slab_count);
+	kdb_printf("  Dirty pages:      %6d\n", dirty_count);
+	kdb_printf("  Locked pages:     %6d\n", locked_count);
+	kdb_printf("  Buffer pages:     %6d\n", buffered_count);
+#ifdef buffer_delay
+	kdb_printf("  Delalloc pages:   %6d\n", delay_count);
+#endif
+	for (i = 0; i < 8; i++) {
+		kdb_printf("  %d page count:     %6d\n",
+			i, page_counts[i]);
+	}
+	kdb_printf("  high page count:  %6d\n", page_counts[8]);
+	return 0;
+}
+#endif	/* CONFIG_X86 */
+
+static int __init kdbm_pg_init(void)
+{
+	kdb_register("kiobuf", kdbm_kiobuf, "<vaddr>", "Display kiobuf", 0);
+	kdb_register("page", kdbm_page, "<vaddr>", "Display page", 0);
+	kdb_register("inode", kdbm_inode, "<vaddr>", "Display inode", 0);
+	kdb_register("sb", kdbm_sb, "<vaddr>", "Display super_block", 0);
+	kdb_register("bh", kdbm_buffers, "<buffer head address>", "Display buffer", 0);
+	kdb_register("inode_pages", kdbm_inode_pages, "<inode *>", "Display pages in an inode", 0);
+	kdb_register("req", kdbm_request, "<vaddr>", "dump request struct", 0);
+	kdb_register("rqueue", kdbm_rqueue, "<vaddr>", "dump request queue", 0);
+#ifdef	CONFIG_X86
+	kdb_register("memmap", kdbm_memmap, "", "page table summary", 0);
+#endif
+
+	return 0;
+}
+
+
+static void __exit kdbm_pg_exit(void)
+{
+	kdb_unregister("kiobuf");
+	kdb_unregister("page");
+	kdb_unregister("inode");
+	kdb_unregister("sb");
+	kdb_unregister("bh");
+	kdb_unregister("inode_pages");
+	kdb_unregister("req");
+	kdb_unregister("rqueue");
+#ifdef	CONFIG_X86
+	kdb_unregister("memmap");
+#endif
+}
+
+module_init(kdbm_pg_init)
+module_exit(kdbm_pg_exit)
diff -uNr linux.orig/kdb/modules/kdbm_vm.c linux/kdb/modules/kdbm_vm.c
--- linux.orig/kdb/modules/kdbm_vm.c	Thu Jan  1 08:00:00 1970
+++ linux/kdb/modules/kdbm_vm.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,698 @@
+/*
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/blkdev.h>
+#include <linux/types.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <scsi.h>
+#include <hosts.h>
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Debug VM information");
+MODULE_LICENSE("GPL");
+
+struct __vmflags {
+	unsigned long mask;
+	char *name;
+} vmflags[] = {
+	{ VM_READ, "READ" },
+	{ VM_WRITE, "WRITE" },
+	{ VM_EXEC, "EXEC" },
+	{ VM_SHARED, "SHARED" },
+	{ VM_MAYREAD, "MAYREAD" },
+	{ VM_MAYWRITE, "MAYWRITE" },
+	{ VM_MAYEXEC, "MAYEXEC" },
+	{ VM_MAYSHARE, "MAYSHARE" },
+	{ VM_GROWSDOWN, "GROWSDOWN" },
+	{ VM_GROWSUP, "GROWSUP" },
+	{ VM_SHM, "SHM" },
+	{ VM_DENYWRITE, "DENYWRITE" },
+	{ VM_EXECUTABLE, "EXECUTABLE" },
+	{ VM_LOCKED, "LOCKED" },
+	{ VM_IO , "IO " },
+	{ 0, "" }
+};
+
+static int
+kdbm_print_vm(struct vm_area_struct *vp, unsigned long addr, int verbose_flg)
+{
+	struct __vmflags *tp;
+
+	kdb_printf("struct vm_area_struct at 0x%lx for %d bytes\n",
+		   addr, (int) sizeof (struct vm_area_struct));
+
+	kdb_printf("vm_start = 0x%p   vm_end = 0x%p\n", (void *) vp->vm_start,
+		   (void *) vp->vm_end);
+	kdb_printf("vm_page_prot = 0x%lx\n", pgprot_val(vp->vm_page_prot));
+
+	kdb_printf("vm_flags: ");
+	for (tp = vmflags; tp->mask; tp++) {
+		if (vp->vm_flags & tp->mask) {
+			kdb_printf(" %s", tp->name);
+		}
+	}
+	kdb_printf("\n");
+
+	if (!verbose_flg)
+		return 0;
+
+	kdb_printf("vm_mm = 0x%p\n", (void *) vp->vm_mm);
+	kdb_printf("vm_next = 0x%p\n", (void *) vp->vm_next);
+	kdb_printf("vm_next_share = 0x%p\n", (void *) vp->vm_next_share);
+	kdb_printf("vm_pprev_share = 0x%p\n", (void *) vp->vm_pprev_share);
+	kdb_printf("vm_ops = 0x%p\n", (void *) vp->vm_ops);
+	if (vp->vm_ops != NULL) {
+		kdb_printf("vm_ops->open = 0x%p\n", vp->vm_ops->open);
+		kdb_printf("vm_ops->close = 0x%p\n", vp->vm_ops->close);
+		kdb_printf("vm_ops->nopage = 0x%p\n", vp->vm_ops->nopage);
+#ifdef HAVE_VMOP_MPROTECT
+		kdb_printf("vm_ops->mprotect = 0x%p\n", vp->vm_ops->mprotect);
+#endif
+	}
+	kdb_printf("vm_pgoff = 0x%lx\n", vp->vm_pgoff);
+	kdb_printf("vm_file = 0x%p\n", (void *) vp->vm_file);
+	kdb_printf("vm_private_data = 0x%p\n", vp->vm_private_data);
+
+	return 0;
+}
+
+static int
+kdbm_print_vmp(struct vm_area_struct *vp, int verbose_flg)
+{
+	struct __vmflags *tp;
+
+	if (verbose_flg) {
+		kdb_printf("0x%lx:  ", (unsigned long) vp);
+	}
+
+	kdb_printf("0x%p  0x%p ", (void *) vp->vm_start, (void *) vp->vm_end);
+
+	for (tp = vmflags; tp->mask; tp++) {
+		if (vp->vm_flags & tp->mask) {
+			kdb_printf(" %s", tp->name);
+		}
+	}
+	kdb_printf("\n");
+
+	return 0;
+}
+
+/*
+ * kdbm_vm
+ *
+ *     This function implements the 'vm' command.  Print a vm_area_struct.
+ *
+ *     vm [-v] <address>               Print vm_area_struct at <address>
+ *     vmp [-v] <pid>                  Print all vm_area_structs for <pid>
+ */
+
+static int
+kdbm_vm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	unsigned long addr;
+	long offset = 0;
+	int nextarg;
+	int diag;
+	int verbose_flg = 0;
+
+	if (argc == 2) {
+		if (strcmp(argv[1], "-v") != 0) {
+			return KDB_ARGCOUNT;
+		}
+		verbose_flg = 1;
+	} else if (argc != 1) {
+		return KDB_ARGCOUNT;
+	}
+
+	if (strcmp(argv[0], "vmp") == 0) {
+		struct task_struct *tp;
+		struct vm_area_struct *vp;
+		pid_t pid;
+
+		if ((diag = kdbgetularg(argv[argc], (unsigned long *) &pid)))
+			return diag;
+
+		for_each_task(tp) {
+			if (tp->pid == pid) {
+				if (tp->mm != NULL) {
+					if (verbose_flg)
+						kdb_printf
+						    ("vm_area_struct       ");
+					kdb_printf
+					    ("vm_start            vm_end              vm_flags\n");
+					vp = tp->mm->mmap;
+					while (vp != NULL) {
+						kdbm_print_vmp(vp, verbose_flg);
+						vp = vp->vm_next;
+					}
+				}
+				return 0;
+			}
+		}
+
+		kdb_printf("No process with pid == %d found\n", pid);
+
+	} else {
+		struct vm_area_struct v;
+
+		nextarg = argc;
+		if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset,
+					  NULL, regs))
+		    || (diag = kdb_getarea(v, addr)))
+			return (diag);
+
+		kdbm_print_vm(&v, addr, verbose_flg);
+	}
+
+	return 0;
+}
+
+static int
+kdbm_print_pte(pte_t * pte)
+{
+	kdb_printf("0x%lx (", (unsigned long) pte_val(*pte));
+
+	if (pte_present(*pte)) {
+		if (pte_exec(*pte))
+			kdb_printf("X");
+		if (pte_write(*pte))
+			kdb_printf("W");
+		if (pte_read(*pte))
+			kdb_printf("R");
+		if (pte_young(*pte))
+			kdb_printf("A");
+		if (pte_dirty(*pte))
+			kdb_printf("D");
+
+	} else {
+		kdb_printf("OFFSET=0x%lx ", SWP_OFFSET(pte_to_swp_entry(*pte)));
+		kdb_printf("TYPE=0x%lx", SWP_TYPE(pte_to_swp_entry(*pte)));
+	}
+
+	kdb_printf(")");
+
+	/* final newline is output by caller of kdbm_print_pte() */
+
+	return 0;
+}
+
+/*
+ * kdbm_pte
+ *
+ *     This function implements the 'pte' command.  Print all pte_t structures
+ *     that map to the given virtual address range for the given process.
+ *
+ *     pte <pid> <address> [<nbytes>]   Print all pte_t structures for virtual
+ *                                      <address> in address space of <pid>
+ */
+
+static int
+kdbm_pte(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	unsigned long addr;
+	unsigned long nbytes = 1;
+	long npgs;
+	int diag;
+	int found;
+	pid_t pid;
+	struct task_struct *tp;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (argc < 2 || argc > 3) {
+		return KDB_ARGCOUNT;
+	}
+
+	if ((diag = kdbgetularg(argv[1], (unsigned long *) &pid))) {
+		return diag;
+	}
+
+	found = 0;
+	for_each_task(tp) {
+		if (tp->pid == pid) {
+			if (tp->mm != NULL) {
+				found = 1;
+				break;
+			}
+			kdb_printf("task structure's mm field is NULL\n");
+			return 0;
+		}
+	}
+
+	if (!found) {
+		kdb_printf("No process with pid == %d found\n", pid);
+		return 0;
+	}
+
+	if ((diag = kdbgetularg(argv[2], &addr))) {
+		return diag;
+	}
+
+	if (argc == 3) {
+		if ((diag = kdbgetularg(argv[3], &nbytes))) {
+			return diag;
+		}
+	}
+
+	kdb_printf("vaddr              pte\n");
+
+	npgs = ((((addr & ~PAGE_MASK) + nbytes) + ~PAGE_MASK) >> PAGE_SHIFT);
+	while (npgs-- > 0) {
+
+		kdb_printf("0x%p ", (void *) (addr & PAGE_MASK));
+
+		pgd = pgd_offset(tp->mm, addr);
+		if (pgd_present(*pgd)) {
+			pmd = pmd_offset(pgd, addr);
+			if (pmd_present(*pmd)) {
+				pte = pte_offset(pmd, addr);
+				if (pte_present(*pte)) {
+					kdbm_print_pte(pte);
+				}
+			}
+		}
+
+		kdb_printf("\n");
+		addr += PAGE_SIZE;
+	}
+
+	return 0;
+}
+
+static int
+kdbm_fp(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct file   f;
+	struct inode *i = NULL;
+	struct dentry d;
+	int	      nextarg;
+	unsigned long addr;
+	long	      offset;
+	int	      diag;
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+	    (diag = kdb_getarea(f, addr)) ||
+	    (diag = kdb_getarea(d, (unsigned long)f.f_dentry)))
+		goto out;
+	if (!(i = kmalloc(sizeof(*i), GFP_ATOMIC))) {
+		kdb_printf("kdbm_fp: cannot kmalloc inode\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea(i, (unsigned long)d.d_inode)))
+		goto out;
+	
+	kdb_printf("name.name 0x%p  name.len  %d\n",
+		    d.d_name.name, d.d_name.len);
+
+	kdb_printf("File Pointer at 0x%lx\n", addr);
+
+	kdb_printf(" f_list.nxt = 0x%p f_list.prv = 0x%p\n",
+					f.f_list.next, f.f_list.prev);
+
+	kdb_printf(" f_dentry = 0x%p f_op = 0x%p\n",
+					f.f_dentry, f.f_op);
+
+	kdb_printf(" f_count = %d f_flags = 0x%x f_mode = 0x%x\n",
+					f.f_count.counter, f.f_flags, f.f_mode);
+
+	kdb_printf(" f_pos = %Ld f_reada = %ld f_ramax = %ld\n",
+					f.f_pos, f.f_reada, f.f_ramax);
+
+	kdb_printf(" f_raend = %ld f_ralen = %ld f_rawin = %ld\n\n",
+					f.f_raend, f.f_ralen, f.f_rawin);
+
+
+	kdb_printf("\nDirectory Entry at 0x%p\n", f.f_dentry);
+	kdb_printf(" d_name.len = %d d_name.name = 0x%p>\n",
+					d.d_name.len, d.d_name.name);
+
+	kdb_printf(" d_count = %d d_flags = 0x%x d_inode = 0x%p\n",
+					atomic_read(&d.d_count), d.d_flags, d.d_inode);
+
+	kdb_printf(" d_hash.nxt = 0x%p d_hash.prv = 0x%p\n",
+					d.d_hash.next, d.d_hash.prev);
+
+	kdb_printf(" d_lru.nxt = 0x%p d_lru.prv = 0x%p\n",
+					d.d_lru.next, d.d_lru.prev);
+
+	kdb_printf(" d_child.nxt = 0x%p d_child.prv = 0x%p\n",
+					d.d_child.next, d.d_child.prev);
+
+	kdb_printf(" d_subdirs.nxt = 0x%p d_subdirs.prv = 0x%p\n",
+					d.d_subdirs.next, d.d_subdirs.prev);
+
+	kdb_printf(" d_alias.nxt = 0x%p d_alias.prv = 0x%p\n",
+					d.d_alias.next, d.d_alias.prev);
+
+	kdb_printf(" d_op = 0x%p d_sb = 0x%p\n\n",
+					d.d_op, d.d_sb);
+
+
+	kdb_printf("\nInode Entry at 0x%p\n", d.d_inode);
+
+	kdb_printf(" i_mode = 0%o  i_nlink = %d  i_rdev = 0x%x\n",
+					i->i_mode, i->i_nlink, i->i_rdev);
+
+	kdb_printf(" i_ino = %ld i_count = %d i_dev = 0x%x\n",
+					i->i_ino, atomic_read(&i->i_count), i->i_dev);
+
+	kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n",
+					i->i_hash.next, i->i_hash.prev);
+
+	kdb_printf(" i_list.nxt = 0x%p i_list.prv = 0x%p\n",
+					i->i_list.next, i->i_list.prev);
+
+	kdb_printf(" i_dentry.nxt = 0x%p i_dentry.prv = 0x%p\n",
+					i->i_dentry.next, i->i_dentry.prev);
+
+out:
+	if (i)
+		kfree(i);
+	return diag;
+}
+
+static int
+kdbm_fl(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct file_lock  fl;
+	int               nextarg;
+	unsigned long     addr;
+	long              offset;
+	int               diag;
+
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+		(diag = kdb_getarea(fl, addr)))
+			return diag;
+
+	kdb_printf("File_lock at 0x%lx\n", addr);
+
+	kdb_printf(" fl_next = 0x%p fl_link.nxt = 0x%p fl_link.prv = 0x%p\n",
+			fl.fl_next, fl.fl_link.next, fl.fl_link.prev);
+	kdb_printf(" fl_block.nxt = 0x%p fl_block.prv = 0x%p\n",
+			fl.fl_block.next, fl.fl_block.prev);
+	kdb_printf(" fl_owner = 0x%p fl_pid = %d fl_wait = 0x%p\n",
+			fl.fl_owner, fl.fl_pid, &fl.fl_wait);
+	kdb_printf(" fl_file = 0x%p fl_flags = 0x%x\n",
+			fl.fl_file, fl.fl_flags);
+	kdb_printf(" fl_type = %d fl_start = 0x%llx fl_end = 0x%llx\n",
+			fl.fl_type, fl.fl_start, fl.fl_end);
+
+	kdb_printf(" fl_notify = 0x%p fl_insert = 0x%p fl_remove = 0x%p\n",
+			fl.fl_notify, fl.fl_insert, fl.fl_remove);
+
+/*
+	kdb_printf(" fl_fasync = 0x%p fl_break 0x%lx\n",
+			fl.fl_fasync, fl.fl_break_time);
+*/
+
+	return 0;
+}
+
+
+static int
+kdbm_dentry(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct dentry d;
+	int	      nextarg;
+	unsigned long addr;
+	long	      offset;
+	int	      diag;
+	char          buf[256];
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+	    (diag = kdb_getarea(d, addr)))
+		return diag;
+	
+	
+	kdb_printf("Dentry at 0x%lx\n", addr);
+
+	if ((d.d_name.len > sizeof(buf)) || (diag = kdb_getarea_size(buf, (unsigned long)(d.d_name.name), d.d_name.len)))
+		kdb_printf(" d_name.len = %d d_name.name = 0x%p\n",
+					d.d_name.len, d.d_name.name);
+	else
+		kdb_printf(" d_name.len = %d d_name.name = 0x%p <%.*s>\n",
+					d.d_name.len, d.d_name.name,
+					(int)(d.d_name.len), d.d_name.name);
+	
+	kdb_printf(" d_count = %d d_flags = 0x%x d_inode = 0x%p\n",
+					atomic_read(&d.d_count), d.d_flags, d.d_inode);
+
+	kdb_printf(" d_parent = 0x%p\n", d.d_parent);
+
+	kdb_printf(" d_hash.nxt = 0x%p d_hash.prv = 0x%p\n",
+					d.d_hash.next, d.d_hash.prev);
+
+	kdb_printf(" d_lru.nxt = 0x%p d_lru.prv = 0x%p\n",
+					d.d_lru.next, d.d_lru.prev);
+
+	kdb_printf(" d_child.nxt = 0x%p d_child.prv = 0x%p\n",
+					d.d_child.next, d.d_child.prev);
+
+	kdb_printf(" d_subdirs.nxt = 0x%p d_subdirs.prv = 0x%p\n",
+					d.d_subdirs.next, d.d_subdirs.prev);
+
+	kdb_printf(" d_alias.nxt = 0x%p d_alias.prv = 0x%p\n",
+					d.d_alias.next, d.d_alias.prev);
+
+	kdb_printf(" d_op = 0x%p d_sb = 0x%p\n\n",
+					d.d_op, d.d_sb);
+
+	return 0;
+}
+
+static int
+kdbm_sh(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	int nextarg;
+	unsigned long addr;
+	long	      offset =0L;
+	struct Scsi_Host sh;
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+	    (diag = kdb_getarea(sh, addr)))
+		return diag;
+
+	kdb_printf("Scsi_Host at 0x%lx\n", addr);
+	kdb_printf("next = 0x%p   host_queue = 0x%p\n",
+		   sh.next, sh.host_queue);
+	kdb_printf("ehandler = 0x%p eh_wait = 0x%p  en_notify = 0x%p eh_action = 0x%p\n",
+		   sh.ehandler, sh.eh_wait, sh.eh_notify, sh.eh_action);
+	kdb_printf("eh_active = 0x%d host_wait = 0x%p hostt = 0x%p host_busy = %d\n",
+		   sh.eh_active, &sh.host_wait, sh.hostt, sh.host_active.counter);
+	kdb_printf("host_failed = %d  extra_bytes = %d  host_no = %d resetting = %d\n",
+		   sh.host_failed, sh.extra_bytes, sh.host_no, sh.resetting);
+	kdb_printf("max id/lun/channel = [%d/%d/%d]  this_id = %d\n",
+		   sh.max_id, sh.max_lun, sh.max_channel, sh.this_id);
+	kdb_printf("can_queue = %d cmd_per_lun = %d  sg_tablesize = %d u_isa_dma = %d\n",
+		   sh.can_queue, sh.cmd_per_lun, sh.sg_tablesize, sh.unchecked_isa_dma);
+	kdb_printf("host_blocked = %d  reverse_ordering = %d \n",
+		   sh.host_blocked, sh.reverse_ordering);
+
+	return 0;
+}
+
+static int
+kdbm_sd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	int nextarg;
+	unsigned long addr;
+	long offset =0L;
+	struct scsi_device *sd = NULL;
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+		goto out;
+	if (!(sd = kmalloc(sizeof(*sd), GFP_ATOMIC))) {
+		kdb_printf("kdbm_sd: cannot kmalloc sd\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea(*sd, addr)))
+		goto out;
+
+	kdb_printf("scsi_device at 0x%lx\n", addr);
+	kdb_printf("next = 0x%p   prev = 0x%p  host = 0x%p\n",
+		   sd->next, sd->prev, sd->host);
+	kdb_printf("device_busy = %d   device_queue 0x%p\n",
+		   sd->device_busy, sd->device_queue);
+	kdb_printf("id/lun/chan = [%d/%d/%d]  single_lun = %d  device_blocked = %d\n",
+		   sd->id, sd->lun, sd->channel, sd->single_lun, sd->device_blocked);
+	kdb_printf("queue_depth = %d current_tag = %d  scsi_level = %d\n",
+		   sd->queue_depth, sd->current_tag, sd->scsi_level);
+	kdb_printf("%8.8s %16.16s %4.4s\n", sd->vendor, sd->model, sd->rev);
+out:
+	if (sd)
+		kfree(sd);
+	return diag;
+}
+
+static char *
+str_rq_status(int rq_status)
+{
+	switch (rq_status) {
+	case RQ_INACTIVE:
+		return "RQ_INACTIVE";
+	case RQ_ACTIVE:
+		return "RQ_ACTIVE";
+	case RQ_SCSI_BUSY:
+		return "RQ_SCSI_BUSY";
+	case RQ_SCSI_DONE:
+		return "RQ_SCSI_DONE";
+	case RQ_SCSI_DISCONNECTING:
+		return "RQ_SCSI_DISCONNECTING";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+static int
+kdbm_sc(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	int nextarg;
+	unsigned long addr;
+	long offset =0L;
+	struct scsi_cmnd *sc = NULL;
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+		goto out;
+	if (!(sc = kmalloc(sizeof(*sc), GFP_ATOMIC))) {
+		kdb_printf("kdbm_sc: cannot kmalloc sc\n");
+		goto out;
+	}
+	if ((diag = kdb_getarea(*sc, addr)))
+		goto out;
+
+	kdb_printf("scsi_cmnd at 0x%lx\n", addr);
+	kdb_printf("host = 0x%p  state = %d  owner = %d  device = 0x%p\nb",
+		    sc->host, sc->state, sc->owner, sc->device);
+	kdb_printf("next = 0x%p  reset_chain = 0x%p  eh_state = %d done = 0x%p\n",
+		   sc->next, sc->reset_chain, sc->eh_state, sc->done);
+	kdb_printf("serial_number = %ld  serial_num_at_to = %ld retries = %d timeout = %d\n",
+		   sc->serial_number, sc->serial_number_at_timeout, sc->retries, sc->timeout);
+	kdb_printf("id/lun/cmnd = [%d/%d/%d]  cmd_len = %d  old_cmd_len = %d\n",
+		   sc->target, sc->lun, sc->channel, sc->cmd_len, sc->old_cmd_len);
+	kdb_printf("cmnd = [%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x]\n",
+		   sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], sc->cmnd[4],
+		   sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], sc->cmnd[8], sc->cmnd[9],
+		   sc->cmnd[10], sc->cmnd[11]);
+	kdb_printf("data_cmnd = [%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x]\n",
+		   sc->data_cmnd[0], sc->data_cmnd[1], sc->data_cmnd[2], sc->data_cmnd[3], sc->data_cmnd[4],
+		   sc->data_cmnd[5], sc->data_cmnd[6], sc->data_cmnd[7], sc->data_cmnd[8], sc->data_cmnd[9],
+		   sc->data_cmnd[10], sc->data_cmnd[11]);
+	kdb_printf("request_buffer = 0x%p  bh_next = 0x%p  request_bufflen = %d\n",
+		   sc->request_buffer, sc->bh_next, sc->request_bufflen);
+	kdb_printf("use_sg = %d  old_use_sg = %d sglist_len = %d abore_reason = %d\n",
+		   sc->use_sg, sc->old_use_sg, sc->sglist_len, sc->abort_reason);
+	kdb_printf("bufflen = %d  buffer = 0x%p  underflow = %d transfersize = %d\n",
+		   sc->bufflen, sc->buffer, sc->underflow, sc->transfersize);
+	kdb_printf("tag = %d pid = %ld\n",
+		   sc->tag, sc->pid);
+	kdb_printf("request struct\n");
+	kdb_printf("rq_status = %s  rq_dev = [%d/%d]  errors = %d  cmd = %d\n",
+		   str_rq_status(sc->request.rq_status),
+		   MAJOR(sc->request.rq_dev),
+		   MINOR(sc->request.rq_dev), sc->request.cmd,
+		   sc->request.errors);
+	kdb_printf("sector = %llu  nr_sectors = %lu  current_nr_sectors = %lu\n",
+		   (unsigned long long)sc->request.sector,
+		   sc->request.nr_sectors, sc->request.current_nr_sectors);
+	kdb_printf("buffer = 0x%p bh = 0x%p bhtail = 0x%p\n",
+		   sc->request.buffer, sc->request.bh, sc->request.bhtail);
+
+out:
+	if (sc)
+		kfree(sc);
+	return diag;
+}
+
+static int __init kdbm_vm_init(void)
+{
+	kdb_register("vm", kdbm_vm, "[-v] <vaddr>", "Display vm_area_struct", 0);
+	kdb_register("vmp", kdbm_vm, "[-v] <pid>", "Display all vm_area_struct for <pid>", 0);
+	kdb_register("pte", kdbm_pte, "<pid> <vaddr> [<nbytes>]", "Display pte_t", 0);
+	kdb_register("dentry", kdbm_dentry, "<dentry>", "Display interesting dentry stuff", 0);
+	kdb_register("filp", kdbm_fp, "<filp>", "Display interesting filp stuff", 0);
+	kdb_register("fl", kdbm_fl, "<fl>", "Display interesting file_lock stuff", 0);
+	kdb_register("sh", kdbm_sh, "<vaddr>", "Show scsi_host", 0);
+	kdb_register("sd", kdbm_sd, "<vaddr>", "Show scsi_device", 0);
+	kdb_register("sc", kdbm_sc, "<vaddr>", "Show scsi_cmnd", 0);
+	
+	return 0;
+}
+
+static void __exit kdbm_vm_exit(void)
+{
+	kdb_unregister("vm");
+	kdb_unregister("vmp");
+	kdb_unregister("pte");
+	kdb_unregister("dentry");
+	kdb_unregister("filp");
+	kdb_unregister("fl");
+	kdb_unregister("sh");
+	kdb_unregister("sd");
+	kdb_unregister("sc");
+}
+
+module_init(kdbm_vm_init)
+module_exit(kdbm_vm_exit)
diff -uNr linux.orig/kernel/Makefile linux/kernel/Makefile
--- linux.orig/kernel/Makefile	Mon Apr  5 15:02:23 2004
+++ linux/kernel/Makefile	Mon Apr  5 15:07:55 2004
@@ -22,6 +22,7 @@
 obj-$(CONFIG_MODULES) += ksyms.o
 obj-$(CONFIG_PM) += pm.o
 obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+obj-$(CONFIG_KALLSYMS) += kallsyms.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -uNr linux.orig/kernel/kallsyms.c linux/kernel/kallsyms.c
--- linux.orig/kernel/kallsyms.c	Thu Jan  1 08:00:00 1970
+++ linux/kernel/kallsyms.c	Mon Apr  5 15:07:55 2004
@@ -0,0 +1,418 @@
+/* An example of using kallsyms data in a kernel debugger.
+
+   Copyright 2000 Keith Owens <kaos@ocs.com.au> April 2000
+
+   This file is part of the Linux modutils.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+
+/*
+   This code uses the list of all kernel and module symbols to :-
+
+   * Find any non-stack symbol in a kernel or module.  Symbols do
+     not have to be exported for debugging.
+
+   * Convert an address to the module (or kernel) that owns it, the
+     section it is in and the nearest symbol.  This finds all non-stack
+     symbols, not just exported ones.
+
+   You need modutils >= 2.3.11 and a kernel with the kallsyms patch
+   which was compiled with CONFIG_KALLSYMS.
+ */
+
+#include <linux/elf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kallsyms.h>
+#include <linux/kdb.h>
+
+/* These external symbols are only set on kernels compiled with
+ * CONFIG_KALLSYMS.
+ */
+
+extern const char __start___kallsyms[];
+extern const char __stop___kallsyms[];
+
+static struct module **kallsyms_module_list;
+
+static void kallsyms_get_module_list(void)
+{
+	const struct kallsyms_header	*ka_hdr;
+	const struct kallsyms_section	*ka_sec;
+	const struct kallsyms_symbol	*ka_sym;
+	const char			*ka_str;
+	int i;
+	const char *p;
+
+	if (__start___kallsyms >= __stop___kallsyms)
+		return;
+	ka_hdr = (struct kallsyms_header *)__start___kallsyms;
+	ka_sec = (struct kallsyms_section *)
+		((char *)(ka_hdr) + ka_hdr->section_off);
+	ka_sym = (struct kallsyms_symbol *)
+		((char *)(ka_hdr) + ka_hdr->symbol_off);
+	ka_str = 
+		((char *)(ka_hdr) + ka_hdr->string_off);
+
+	for (i = 0; i < ka_hdr->symbols; kallsyms_next_sym(ka_hdr, ka_sym), ++i) {
+		p = ka_str + ka_sym->name_off;
+		if (strcmp(p, "module_list") == 0) {
+			if (ka_sym->symbol_addr)
+				kallsyms_module_list = (struct module **)(ka_sym->symbol_addr);
+			break;
+		}
+	}
+}
+
+static inline void kallsyms_do_first_time(void)
+{
+	static int first_time = 1;
+	if (first_time)
+		kallsyms_get_module_list();
+	first_time = 0;
+}
+
+/* A symbol can appear in more than one module.  A token is used to
+ * restart the scan at the next module, set the token to 0 for the
+ * first scan of each symbol.
+ */
+
+int kallsyms_symbol_to_address(
+	const char	 *name,		/* Name to lookup */
+	unsigned long 	 *token,	/* Which module to start at */
+	const char	**mod_name,	/* Set to module name */
+	unsigned long 	 *mod_start,	/* Set to start address of module */
+	unsigned long 	 *mod_end,	/* Set to end address of module */
+	const char	**sec_name,	/* Set to section name */
+	unsigned long 	 *sec_start,	/* Set to start address of section */
+	unsigned long 	 *sec_end,	/* Set to end address of section */
+	const char	**sym_name,	/* Set to full symbol name */
+	unsigned long 	 *sym_start,	/* Set to start address of symbol */
+	unsigned long 	 *sym_end	/* Set to end address of symbol */
+	)
+{
+	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+	const struct kallsyms_section	*ka_sec;
+	const struct kallsyms_symbol	*ka_sym = NULL;
+	const char			*ka_str = NULL;
+	const struct module *m;
+	int i = 0, l;
+	const char *p, *pt_R;
+	char *p2;
+
+	kallsyms_do_first_time();
+	if (!kallsyms_module_list)
+		return(0);
+
+	/* Restart? */
+	m = *kallsyms_module_list;
+	if (token && *token) {
+		for (; m; m = m->next)
+			if ((unsigned long)m == *token)
+				break;
+		if (m)
+			m = m->next;
+	}
+
+	for (; m; m = m->next) {
+		if (!mod_member_present(m, kallsyms_start) || 
+		    !mod_member_present(m, kallsyms_end) ||
+		    m->kallsyms_start >= m->kallsyms_end)
+			continue;
+		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+		ka_sym = (struct kallsyms_symbol *)
+			((char *)(ka_hdr) + ka_hdr->symbol_off);
+		ka_str = 
+			((char *)(ka_hdr) + ka_hdr->string_off);
+		for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
+			p = ka_str + ka_sym->name_off;
+			if (strcmp(p, name) == 0)
+				break;
+			/* Unversioned requests match versioned names */
+			if (!(pt_R = strstr(p, "_R")))
+				continue;
+			l = strlen(pt_R);
+			if (l < 10)
+				continue;	/* Not _R.*xxxxxxxx */
+			(void)simple_strtoul(pt_R+l-8, &p2, 16);
+			if (*p2)
+				continue;	/* Not _R.*xxxxxxxx */
+			if (strncmp(p, name, pt_R-p) == 0)
+				break;	/* Match with version */
+		}
+		if (i < ka_hdr->symbols)
+			break;
+	}
+
+	if (token)
+		*token = (unsigned long)m;
+	if (!m)
+		return(0);	/* not found */
+
+	ka_sec = (const struct kallsyms_section *)
+		((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off);
+	*mod_name = *(m->name) ? m->name : "kernel";
+	*mod_start = ka_hdr->start;
+	*mod_end = ka_hdr->end;
+	*sec_name = ka_sec->name_off + ka_str;
+	*sec_start = ka_sec->start;
+	*sec_end = ka_sec->start + ka_sec->size;
+	*sym_name = ka_sym->name_off + ka_str;
+	*sym_start = ka_sym->symbol_addr;
+	if (i < ka_hdr->symbols-1) {
+		const struct kallsyms_symbol *ka_symn = ka_sym;
+		kallsyms_next_sym(ka_hdr, ka_symn);
+		*sym_end = ka_symn->symbol_addr;
+	}
+	else
+		*sym_end = *sec_end;
+	return(1);
+}
+
+int kallsyms_address_to_symbol(
+	unsigned long	  address,	/* Address to lookup */
+	const char	**mod_name,	/* Set to module name */
+	unsigned long 	 *mod_start,	/* Set to start address of module */
+	unsigned long 	 *mod_end,	/* Set to end address of module */
+	const char	**sec_name,	/* Set to section name */
+	unsigned long 	 *sec_start,	/* Set to start address of section */
+	unsigned long 	 *sec_end,	/* Set to end address of section */
+	const char	**sym_name,	/* Set to full symbol name */
+	unsigned long 	 *sym_start,	/* Set to start address of symbol */
+	unsigned long 	 *sym_end	/* Set to end address of symbol */
+	)
+{
+	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+	const struct kallsyms_section	*ka_sec = NULL;
+	const struct kallsyms_symbol	*ka_sym;
+	const char			*ka_str;
+	const struct module *m;
+	int i;
+	unsigned long end;
+
+	kallsyms_do_first_time();
+	if (!kallsyms_module_list)
+		return(0);
+
+	for (m = *kallsyms_module_list; m; m = m->next) {
+		if (!mod_member_present(m, kallsyms_start) || 
+		    !mod_member_present(m, kallsyms_end) ||
+		    m->kallsyms_start >= m->kallsyms_end)
+			continue;
+		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+		ka_sec = (const struct kallsyms_section *)
+			((char *)ka_hdr + ka_hdr->section_off);
+		/* Is the address in any section in this module? */
+		for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
+			if (ka_sec->start <= address &&
+			    (ka_sec->start + ka_sec->size) > address)
+				break;
+		}
+		if (i < ka_hdr->sections)
+			break;	/* Found a matching section */
+	}
+
+	if (!m)
+		return(0);	/* not found */
+
+	ka_sym = (struct kallsyms_symbol *)
+		((char *)(ka_hdr) + ka_hdr->symbol_off);
+	ka_str = 
+		((char *)(ka_hdr) + ka_hdr->string_off);
+	*mod_name = *(m->name) ? m->name : "kernel";
+	*mod_start = ka_hdr->start;
+	*mod_end = ka_hdr->end;
+	*sec_name = ka_sec->name_off + ka_str;
+	*sec_start = ka_sec->start;
+	*sec_end = ka_sec->start + ka_sec->size;
+	*sym_name = *sec_name;		/* In case we find no matching symbol */
+	*sym_start = *sec_start;
+	*sym_end = *sec_end;
+
+	for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
+		if (ka_sym->symbol_addr > address)
+			continue;
+		if (i < ka_hdr->symbols-1) {
+			const struct kallsyms_symbol *ka_symn = ka_sym;
+			kallsyms_next_sym(ka_hdr, ka_symn);
+			end = ka_symn->symbol_addr;
+		}
+		else
+			end = *sec_end;
+		if (end <= address)
+			continue;
+		if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off
+		    != (char *)ka_sec)
+			continue;	/* wrong section */
+		*sym_name = ka_str + ka_sym->name_off;
+		*sym_start = ka_sym->symbol_addr;
+		*sym_end = end;
+		break;
+	}
+	return(1);
+}
+
+/* List all sections in all modules.  The callback routine is invoked with
+ * token, module name, section name, section start, section end, section flags.
+ */
+int kallsyms_sections(void *token,
+		      int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word)))
+{
+	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+	const struct kallsyms_section	*ka_sec = NULL;
+	const char			*ka_str;
+	const struct module *m;
+	int i;
+
+	kallsyms_do_first_time();
+	if (!kallsyms_module_list)
+		return(0);
+
+	for (m = *kallsyms_module_list; m; m = m->next) {
+		if (!mod_member_present(m, kallsyms_start) || 
+		    !mod_member_present(m, kallsyms_end) ||
+		    m->kallsyms_start >= m->kallsyms_end)
+			continue;
+		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+		ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off);
+		ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
+		for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
+			if (callback(
+				token,
+				*(m->name) ? m->name : "kernel",
+				ka_sec->name_off + ka_str,
+				ka_sec->start,
+				ka_sec->start + ka_sec->size,
+				ka_sec->flags))
+				return(0);
+		}
+	}
+	return(1);
+}
+
+
+/* paramter prefix_name is a buffer provided by the caller, it must ends with '\0'. */
+/* return the extra string together with the given prefix of a symbol name. */
+/* return 0 means no prefix string is found. */
+/* return >0 means prefix string is found. */
+int kallsyms_symbol_complete(
+	char	 *prefix_name	/* Prefix of a symbol name to lookup */
+	)
+{
+	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+	const struct kallsyms_symbol	*ka_sym = NULL;
+	const char			*ka_str = NULL;
+	const struct module *m;
+	int i = 0;
+	int prefix_len=strlen(prefix_name);
+	int cur_pos=0, last_pos=0;
+	int find=0;
+	int number=0;
+	const char *p;
+
+	kallsyms_do_first_time();
+	if (!kallsyms_module_list)
+		return(0);
+
+	for (m = *kallsyms_module_list; m; m = m->next) {
+		if (!mod_member_present(m, kallsyms_start) ||
+		    !mod_member_present(m, kallsyms_end) ||
+		    m->kallsyms_start >= m->kallsyms_end)
+			continue;
+		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+		ka_sym = (struct kallsyms_symbol *)
+			((char *)(ka_hdr) + ka_hdr->symbol_off);
+		ka_str =
+			((char *)(ka_hdr) + ka_hdr->string_off);
+		for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
+			p = ka_str + ka_sym->name_off;
+			if (strncmp(p, prefix_name,prefix_len) == 0) {
+				++number;
+				if (find == 0) {
+					last_pos = strlen(p);
+					strncpy(prefix_name, p, last_pos+1);
+					find = 1;
+				}
+				else {
+					for (cur_pos = prefix_len ; cur_pos < last_pos; cur_pos++) {
+						if (*(p + cur_pos) == '\0'
+							|| *(p + cur_pos) != prefix_name[cur_pos]) {
+							last_pos = cur_pos;
+							prefix_name[cur_pos] = '\0';
+							break;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return number;
+}
+
+/* paramter prefix_name is a buffer provided by the caller, it must ends with '\0'. */
+/* parameter flag = 0 means search from the head, flag = 1 means continue search. */
+/* return a symbol string which matches the given prefix. */
+/* return 0 means no prefix string is found. */
+/* return >0 means prefix string is found. */
+int kallsyms_symbol_next(
+	char	 *prefix_name,	/* Prefix of a symbol name to lookup */
+	int flag			/* Indicate if search from the head */
+	)
+{
+	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+	const char			*ka_str = NULL;
+	static const struct kallsyms_symbol	*ka_sym;
+	static const struct module *m;
+	static int i;
+	int prefix_len=strlen(prefix_name);
+	const char *p;
+
+	kallsyms_do_first_time();
+	if (!kallsyms_module_list)
+		return(0);
+
+	if(!flag) {
+		m = *kallsyms_module_list;
+	}
+
+	for (; m; m = m->next) {
+		if (!mod_member_present(m, kallsyms_start) ||
+		    !mod_member_present(m, kallsyms_end) ||
+		    m->kallsyms_start >= m->kallsyms_end)
+			continue;
+		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+		if(!flag) {
+			ka_sym = (struct kallsyms_symbol *)
+				((char *)(ka_hdr) + ka_hdr->symbol_off);
+			i = 0;
+		}
+		ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
+
+		for (; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
+			p = ka_str + ka_sym->name_off;
+			if (strncmp(p, prefix_name,prefix_len) == 0) {
+				strncpy(prefix_name, p, strlen(p)+1);
+				++i;
+				kallsyms_next_sym(ka_hdr, ka_sym);
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
diff -uNr linux.orig/kernel/ksyms.c linux/kernel/ksyms.c
--- linux.orig/kernel/ksyms.c	Mon Apr  5 15:02:23 2004
+++ linux/kernel/ksyms.c	Mon Apr  5 15:07:55 2004
@@ -56,6 +56,9 @@
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
+#ifdef CONFIG_KALLSYMS
+#include <linux/kallsyms.h>
+#endif
 
 extern void set_device_ro(kdev_t dev,int flag);
 
@@ -82,6 +85,15 @@
 EXPORT_SYMBOL(inter_module_put);
 EXPORT_SYMBOL(try_inc_mod_count);
 
+#ifdef CONFIG_KALLSYMS
+extern const char __start___kallsyms[];
+extern const char __stop___kallsyms[];
+EXPORT_SYMBOL(__start___kallsyms);
+EXPORT_SYMBOL(__stop___kallsyms);
+EXPORT_SYMBOL(kallsyms_symbol_to_address);
+EXPORT_SYMBOL(kallsyms_address_to_symbol);
+#endif
+
 /* process memory management */
 EXPORT_SYMBOL(do_mmap_pgoff);
 EXPORT_SYMBOL(do_munmap);
@@ -588,3 +600,8 @@
 
 /* debug */
 EXPORT_SYMBOL(dump_stack);
+#if defined(CONFIG_KDB_USB)
+#include <linux/kdb.h>
+EXPORT_SYMBOL(kdb_usb_infos);
+#endif
+
diff -uNr linux.orig/kernel/module.c linux/kernel/module.c
--- linux.orig/kernel/module.c	Fri Jun 13 22:51:39 2003
+++ linux/kernel/module.c	Mon Apr  5 15:07:55 2004
@@ -3,6 +3,7 @@
 #include <linux/module.h>
 #include <asm/module.h>
 #include <asm/uaccess.h>
+#include <linux/kallsyms.h>
 #include <linux/vmalloc.h>
 #include <linux/smp_lock.h>
 #include <asm/pgalloc.h>
@@ -1235,6 +1236,30 @@
 	show:	s_show
 };
 
+#define MODLIST_SIZE 4096
+
+/*
+ * this function isn't smp safe but that's not really a problem; it's
+ * called from oops context only and any locking could actually prevent
+ * the oops from going out; the line that is generated is informational
+ * only and should NEVER prevent the real oops from going out. 
+ */
+void print_modules(void)
+{
+	static char modlist[MODLIST_SIZE];
+	struct module *this_mod;
+	int pos = 0;
+
+	this_mod = module_list;
+	while (this_mod) {
+		if (this_mod->name)
+			pos += snprintf(modlist+pos, MODLIST_SIZE-pos-1, 
+					"%s ", this_mod->name);
+		this_mod = this_mod->next;
+	}
+	printk("%s\n",modlist);
+}
+
 #else		/* CONFIG_MODULES */
 
 /* Dummy syscalls for people who don't want modules */
@@ -1280,4 +1305,81 @@
 	return 1;
 }
 
+void print_modules(void)
+{
+}
+
 #endif	/* CONFIG_MODULES */
+
+
+#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
+
+#define MAX_SYMBOL_SIZE 512
+
+static void
+address_to_exported_symbol(unsigned long address, const char **mod_name, 
+			   const char **sym_name, unsigned long *sym_start,
+			   unsigned long *sym_end)
+{
+	struct module *this_mod;
+	int i;
+
+	for (this_mod = module_list; this_mod; this_mod = this_mod->next) {
+		/* walk the symbol list of this module. Only symbols
+		   who's address is smaller than the searched for address
+		   are relevant; and only if it's better than the best so far */
+		for (i = 0; i < this_mod->nsyms; i++)
+			if ((this_mod->syms[i].value <= address) &&
+			    (*sym_start < this_mod->syms[i].value)) {
+				*sym_start = this_mod->syms[i].value;
+				*sym_name  = this_mod->syms[i].name;
+				*mod_name  = this_mod->name;
+				if (i + 1 < this_mod->nsyms)
+					*sym_end = this_mod->syms[i+1].value;
+				else
+					*sym_end = (unsigned long) this_mod + this_mod->size;
+			}
+	}
+}
+
+void
+print_symbol(const char *fmt, unsigned long address)
+{
+	/* static to not take up stackspace; if we race here too bad */
+	static char buffer[MAX_SYMBOL_SIZE];
+
+	const char *mod_name = NULL, *sec_name = NULL, *sym_name = NULL;
+	unsigned long mod_start, mod_end, sec_start, sec_end,
+		sym_start, sym_end;
+	char *tag = "";
+	
+	memset(buffer, 0, MAX_SYMBOL_SIZE);
+
+	sym_start = 0;
+	if (!kallsyms_address_to_symbol(address, &mod_name, &mod_start, &mod_end, &sec_name, &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) {
+		tag = "E ";
+		address_to_exported_symbol(address, &mod_name, &sym_name, &sym_start, &sym_end);
+	}
+
+	if (sym_start) {
+		if (*mod_name)
+		    snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x [%s]",
+			 tag, sym_name,
+			 (unsigned int)(address - sym_start),
+			 (unsigned int)(sym_end - sym_start),
+			 mod_name);
+		else
+		    snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x",
+			 tag, sym_name,
+			 (unsigned int)(address - sym_start),
+			 (unsigned int)(sym_end - sym_start));
+		printk(fmt, buffer);
+	}
+#if 0
+ else {
+		printk(fmt, "[unresolved]");
+	}
+#endif
+}
+
+#endif
diff -uNr linux.orig/kernel/printk.c linux/kernel/printk.c
--- linux.orig/kernel/printk.c	Fri Jun 13 22:51:39 2003
+++ linux/kernel/printk.c	Mon Apr  5 15:07:55 2004
@@ -292,6 +292,20 @@
 	return error;
 }
 
+#ifdef	CONFIG_KDB
+/* kdb dmesg command needs access to the syslog buffer.  do_syslog() uses locks
+ * so it cannot be used during debugging.  Just tell kdb where the start and
+ * end of the physical and logical logs are.  This is equivalent to do_syslog(3).
+ */
+void kdb_syslog_data(char *syslog_data[4])
+{
+	syslog_data[0] = log_buf;
+	syslog_data[1] = log_buf + sizeof(log_buf);
+	syslog_data[2] = log_buf + log_end - (logged_chars < LOG_BUF_LEN ? logged_chars : LOG_BUF_LEN);
+	syslog_data[3] = log_buf + log_end;
+}
+#endif
+
 asmlinkage long sys_syslog(int type, char * buf, int len)
 {
 	if ((type != 3) && !capable(CAP_SYS_ADMIN))
diff -uNr linux.orig/kernel/sched.c linux/kernel/sched.c
--- linux.orig/kernel/sched.c	Fri Jun 13 22:51:39 2003
+++ linux/kernel/sched.c	Mon Apr  5 15:07:55 2004
@@ -525,6 +525,7 @@
 		goto out_unlock;
 	}
 #else
+	task_release_cpu(prev);
 	prev->policy &= ~SCHED_YIELD;
 #endif /* CONFIG_SMP */
 }
@@ -658,6 +659,12 @@
 
 #endif /* CONFIG_SMP */
 
+#ifdef	CONFIG_KDB
+	{
+		extern struct task_struct *kdb_active_task[];
+		kdb_active_task[smp_processor_id()] = next;
+	}
+#endif
 	kstat.context_swtch++;
 	/*
 	 * there are 3 processes which are affected by a context switch:
diff -uNr linux.orig/kernel/sysctl.c linux/kernel/sysctl.c
--- linux.orig/kernel/sysctl.c	Fri Jun 13 22:51:39 2003
+++ linux/kernel/sysctl.c	Mon Apr  5 15:07:55 2004
@@ -30,6 +30,9 @@
 #include <linux/init.h>
 #include <linux/sysrq.h>
 #include <linux/highuid.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 
 #include <asm/uaccess.h>
 
@@ -259,6 +262,10 @@
 	{KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug",
 	 &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec},
 #endif
+#ifdef	CONFIG_KDB
+	{KERN_KDB, "kdb", &kdb_on, sizeof(int),
+	 0644, NULL, &proc_dointvec},
+#endif	/* CONFIG_KDB */
 	{0}
 };
 
diff -uNr linux.orig/mm/memory.c linux/mm/memory.c
--- linux.orig/mm/memory.c	Mon Apr  5 15:02:37 2004
+++ linux/mm/memory.c	Mon Apr  5 15:07:55 2004
@@ -1552,3 +1552,15 @@
 	}
 	return page;
 }
+
+#ifdef CONFIG_KDB
+struct page * kdb_follow_page(struct mm_struct *mm, unsigned long address, int write) 
+{
+	struct page *page = follow_page(mm, address, write);
+
+	if (!page)
+		return get_page_map(page);
+
+	return page;
+}
+#endif
