[BACK]Return to kdb-v4.4-2.6.15-common-1 CVS log [TXT][DIR] Up to [Development] / linux-2.6-xfs / split-patches

File: [Development] / linux-2.6-xfs / split-patches / Attic / kdb-v4.4-2.6.15-common-1 (download)

Revision 1.1, Tue Jan 10 14:23:00 2006 UTC (11 years, 9 months ago) by nathans.longdrop.melbourne.sgi.com
Branch: MAIN

Merge up to 2.6.15
Merge of 2.6.x-xfs-melb:linux:24948a by kenmcd.

%patch
Index: 2.6.x-xfs/Documentation/kdb/kdb.mm
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb.mm	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb.mm	2006-01-10 17:22:51.342606734 +1100
@@ -0,0 +1,487 @@
+.TH KDB 8 "September 21, 2005"
+.hy 0
+.SH NAME
+Built-in Kernel Debugger for Linux - v4.4
+.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 no longer supported.
+.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 control sequence \fB<esc>KDB\fP 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 console driver is still usable.
+.P
+\fBNote:\fR\ When the serial console sequence consists of multiple
+characters such as <esc>KDB then all but the last character are passed
+through to the application that is reading from the serial console.
+After exiting from kdb, you should use backspace to delete the rest of
+the control sequence.
+.P
+You can boot with kdb activated but without the ability to enter kdb
+via any keyboard sequence.
+In this mode, kdb will only be entered after a system failure.
+Booting with kdb=on-nokey will activate kdb but ignore keyboard
+sequences that would normally drop you into kdb.
+kdb=on-nokey is mainly useful when you are using a PC keyboard and your
+application needs to use the Pause key.
+You can also activate this mode by
+.nf
+  echo "2" > /proc/sys/kernel/kdb
+.fi
+.P
+If the console is sitting on the login prompt when you enter kdb, then
+the login command may switch into upper case mode.
+This is not a kdb bug, it is a "feature" of login - if the userid is
+all upper case then login assumes that you using a TeleType (circa
+1960) which does not have lower case characters.
+Wait 60 seconds for login to timeout and it will switch back to lower
+case mode.
+.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
+If you are using a USB keyboard then kdb commands cannot be entered
+until the kernel has initialised the USB subsystem and recognised the
+keyboard.
+Using kdb=early with a USB keyboard will not work, the USB subsystem is
+initialised too late.
+.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.
+A line whose first non-space character is '#' is printed and ignored.
+.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
+handlers	Control the display of IA64 MCA/INIT handlers
+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.
+mdp	Display memory based on a physical address
+mdr	Display raw memory contents
+mds	Display memory contents symbolically
+mm	Modify memory contents, words
+mmW	Modify memory contents, bytes
+per_cpu	Display per_cpu variables
+pid	Change the default process context
+ps	Display process status
+reboot	Reboot the machine
+rd	Display register contents
+rm	Modify register contents
+rq	Display runqueue for one cpu
+rqa	Display runqueue for all cpus
+set	Add/change environment variable
+sr	Invoke SysReq commands
+ss	Single step a cpu
+ssb	Single step a cpu until a branch instruction
+stackdepth	Print the stack depth for selected processes
+summary	Summarize the system
+.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.
+\&'+' after a cpu number indicates a cpu for which kdb has some data, but
+that cpu is no longer responding to kdb, so you cannot switch to it.
+This could be a cpu that has failed after entering kdb, or the cpu may
+have saved its state for debugging then entered the prom, this is
+normal for an IA64 MCA event.
+\&'I' after a cpu number means that the cpu was idle before it entered
+kdb, it is unlikely to contain any useful data.
+\&'F' after a cpu number means that the cpu is offline.
+There is currenly no way to distinguish between cpus that used to be
+online but are now offline and cpus that were never online, the kernel
+does not maintain the information required to separate those two cases.
+.I cpu
+followed by a number will switch to that cpu, you cannot switch to
+a cpu marked '*', '+' or 'F'.
+This command is only available if the kernel was configured for SMP.
+.TP 8
+dmesg [lines] [adjust]
+Displays the system messages from the kernel buffer.
+If kdb logging is on, it is disabled by dmesg and is left as disabled.
+With no parameters or a zero value for 'lines', dmesg dumps the entire
+kernel buffer.
+If lines is specified and is positive, dmesg dumps the last 'lines'
+from the buffer.
+If lines is specified and is negative, dmesg dumps the first 'lines'
+from the buffer.
+If adjust is specified, adjust the starting point for the lines that
+are printed.
+When 'lines' is positive, move the starting point back by 'adjust'
+lines, when 'lines' is negative, move the starting point forward by
+\&'adjust' lines.
+.I dmesg -100
+will dump 100 lines, from the start of the buffer.
+.I dmesg 100
+will dump 100 lines, starting 100 lines from the end of the buffer,
+.I dmesg 100 100
+will dump 100 lines, starting 200 lines from the end of the buffer.
+.I dmesg -100 100
+will dump 100 lines, starting 100 lines from the start of the buffer.
+.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
+.P
+When used with no parameters, defcmd prints all the defined commands.
+.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
+handlers
+Control the display of IA64 MCA/INIT handlers.
+The IA64 MCA/INIT handlers run on separate tasks.
+During an MCA/INIT event, the active tasks are typically the handlers,
+rather than the original tasks, which is not very useful for debugging.
+By default, KDB hides the MCA/INIT handlers so commands such as ps and
+btc will display the original task.
+You can change this behaviour by using
+.I handlers show
+to display the MCA/INIT handlers instead of the original tasks or use
+.I handlers hide
+(the default) to hide the MCA/INIT handlers and display the original
+tasks.
+.I handlers status
+will list the address of the handler task and the original task for
+each cpu.
+\fBNote:\fR\ If the original task was running in user space or it
+failed any of the MCA/INIT verification tests then there is no original
+task to display.
+In this case, the handler will be displayed even if
+.I handlers hide
+is set and
+.I handlers status
+will not show an original task.
+.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
+per_cpu <variable_name> [<length>] [<cpu>]
+Display the values of a per_cpu variable, the variable_name is
+specified without the \fIper_cpu__\fR prefix.
+Length is the length of the variable, 1-8, if omitted or 0 it defaults
+to the size of the machine's register.
+To display the variable on a specific cpu, the third parameter is the
+cpu number.
+When the third parameter is omitted, the variable's value is printed
+from all cpus, except that zero values are suppressed.
+For each cpu, per_cpu prints the cpu number, the address of the
+variable and its value.
+.TP 8
+pid <number>
+Change the current process context, with no parameters it displays the
+current process.
+The current process is used to display registers, both kernel and user
+space.
+It is also used when dumping user pages.
+.TP 8
+reboot
+Reboot the system, with no attempt to do a clean close down.
+.TP 8
+rq <cpu>
+Display the runqueues for the specified cpu.
+.TP 8
+rqa
+Display the runqueues for all cpus.
+.TP 8
+stackdepth <percentage>
+Print the stack usage for processes using more than the specified
+percentage of their stack.
+If percentage is not supplied, it defaults to 60.
+This command is only implemented on i386 and ia64 architectures,
+patches for other architectures will be gratefully accepted.
+.TP 8
+summary
+Print a summary of the system, including the time (no timezone is
+applied), uname information and various critical system counters.
+.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,ps,rd,sr,ss}.man
Index: 2.6.x-xfs/Documentation/kdb/kdb_bp.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_bp.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_bp.man	2006-01-10 17:22:51.343583161 +1100
@@ -0,0 +1,197 @@
+.TH BD 1 "July 12, 2004"
+.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.
+A breakpoint-number of \fI*\fR will disable all break points.
+.P
+The
+.B be
+command will re-enable a disabled breakpoint.
+A breakpoint-number of \fI*\fR will enable all break points.
+.P
+The
+.B bc
+command will clear a breakpoint from the breakpoint table.
+A breakpoint-number of \fI*\fR will clear all break points.
+.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
Index: 2.6.x-xfs/Documentation/kdb/kdb_bt.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_bt.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_bt.man	2006-01-10 17:22:51.345536017 +1100
@@ -0,0 +1,223 @@
+.TH BT 1 "September 21, 2005"
+.SH NAME
+bt \- Stack Traceback command
+.SH SYNOPSIS
+bt [ <stack-frame-address> ]
+.LP
+btp <pid>
+.LP
+btt <struct-task-address>
+.LP
+bta [ DRSTZUIMA ]
+.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).
+\fBbtp\fP sets the current process for any following register display or update
+commands.
+.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.
+\fBbtt\fP sets the current process for any following register display or update
+commands.
+.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 useful processes.
+If a parameter is specified, it is a single string consisting of the
+letters D, R, S, T, Z, U, I, M and A in any order.
+See the kdb \fBps\fR man page for more details.
+\fBbta\fP does not change the current process.
+.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.
+\fBbtc\fP with no arguments does not change the current process.
+\fBbtc\fP with a cpu number sets the current process for any following register
+display or update commands.
+.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 (not available on 2.6 kernels).
+.IP * 3
+The start address of the section (not available on 2.6 kernels).
+.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
+Unfortunately the 2.6 kernel does not provide the information required
+to locate the start of the section, which makes it very difficult to
+perform a reliable objdump on a module.
+.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.
+On IA64 hardware, there is no difference between input and local registers, the
+first \fBBTARGS\fP registers are printed, up to the total limit of input plus
+local registers.
+Use a large value for \fBBTARGS\fP if you want to see the local registers on
+IA64.
+.PP
+If the \fBBTSP\fP environment variable is non-zero then each backtrace frame
+may print an extra line giving information about the stack pointers, this is
+architecture specific.
+.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.
+The default is NOSECT=1 so section data is suppressed; use set\ NOSECT=0
+to see section information.
+.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.
+.PP
+\fBbt\fR with no parameters uses the \fBPS\fR environment variable, see
+the kdb \fBps\fR man page.
+.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
Index: 2.6.x-xfs/Documentation/kdb/kdb_env.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_env.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_env.man	2006-01-10 17:22:51.345536017 +1100
@@ -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.
Index: 2.6.x-xfs/Documentation/kdb/kdb_ll.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_ll.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_ll.man	2006-01-10 17:22:51.346512444 +1100
@@ -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>
Index: 2.6.x-xfs/Documentation/kdb/kdb_md.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_md.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_md.man	2006-01-10 17:22:51.347488872 +1100
@@ -0,0 +1,136 @@
+.TH MD 1 "August 4, 2004"
+.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
+mdp \fIphysical-address-expression\fP,\fIbytes\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 mdp
+command displays the contents of physical memory, starting at the
+specified physical address for the specified number of bytes.
+The address is preceded by 'phys'.
+.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
+NOSECT
+If the \fBNOSECT\fP environment variable is non-zero then the
+section information is suppressed.
+The default is NOSECT=1 so section data is suppressed; use set\ NOSECT=0
+to see section information.
+.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.
Index: 2.6.x-xfs/Documentation/kdb/kdb_ps.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_ps.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_ps.man	2006-01-10 17:22:51.347488872 +1100
@@ -0,0 +1,96 @@
+.TH PS 1 "September 14, 2004"
+.SH NAME
+ps \- Display processes
+.SH SYNOPSIS
+ps [ DRSTCZEUIMA ]
+.SH DESCRIPTION
+The
+.B ps
+command displays the 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.
+.P
+Without any parameters, \fBps\fP displays all the interesting
+processes, excluding idle tasks and sleeping system daemons.
+If a parameter is specified, it is a single string consisting of the
+letters D, R, S, T, C, Z, E, U, I and M, 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.
+The states are\ :-
+.P
+.DS
+.TS
+box, center;
+l | l
+l | l.
+D	Uninterruptible sleep
+R	Running
+S	Interruptible sleep
+T	Stopped
+C	Traced
+Z	Zombie
+E	Dead
+U	Unrunnable
+I	Idle task
+M	Sleeping system daemon
+A	All
+.TE
+.DE
+.P
+For state R (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.
+.P
+The idle task is run on each cpu when there is no work for that cpu to do.
+Unless the idle task is servicing an interrupt, there is no point in
+printing the idle task.
+An idle task that is not servicing a interrupt is marked as state I,
+while servicing an interrupt it is in state R.
+By default, idle tasks are not printed, use \fBps\ I\fR to print them.
+If the idle tasks are not being printed, the start of the \fBps\R
+output contains a list of which cpus are idle.
+.P
+Each cpu has one or more system daemons to handle per cpu work such as
+soft irqs.
+A system daemon (idenified by a NULL mm pointer) that is sleeping is
+marked as state M.
+These processes rarely have any useful data and generate a lot of
+output on large machines, so sleeping system daemons are not printed by
+default.
+Use \fBps\ M\fR to print them.
+.P
+At the start of the \fBps\fR output is a line giving the cpu status,
+see the kdb \fBcpu\fR command.
+.SH LIMITATIONS
+None.
+.SH ENVIRONMENT
+.TP 8
+PS
+This environment variable (default=DRSTCZEU) is used when \fBps\fR
+is issued with no parameters.
+
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.TP 8
+\fBps\fR
+displays the useful tasks, suppressing idle tasks and sleeping
+system daemons.
+
+.TP 8
+\fBps\ RD\fR
+displays only tasks that are running or are in an uninterruptible
+sleep.
+
+.TP 8
+\fBps\ DRSTCZEUIM\fR
+displays all tasks.
+
+.TP 8
+\fBps\ A\fR
+displays all tasks.
+This is easier than remembering DRSTCZEUIM.
+
Index: 2.6.x-xfs/Documentation/kdb/kdb_rd.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_rd.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_rd.man	2006-01-10 17:22:51.348465300 +1100
@@ -0,0 +1,170 @@
+.TH RD 1 "September 20, 2005"
+.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.
+If the bt* or pid commands have been used to change the current process then
+.B rd
+and
+.B rm
+may not be able to display any registers.
+'n' argument is only used for XScale platform to identify the desired
+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
+On IA64, the parameter to
+.B rd
+can be d (debug registers), u (user registers at most recent entry to kernel),
+i (interrupt registers), %isr (current interrupt status), s (stacked
+registers), k (kernel registers).  You can also specify these individual
+registers -
+psr,
+ifs,
+ip,
+unat,
+pfs,
+rsc,
+rnat,
+bsps,
+pr,
+ldrs,
+ccv,
+fpsr,
+b0,
+b6,
+b7,
+r1,
+r2,
+r3,
+r8,
+r9,
+r10,
+r11,
+r12,
+r13,
+r14,
+r15,
+r16,
+r17,
+r18,
+r19,
+r20,
+r21,
+r22,
+r23,
+r24,
+r25,
+r26,
+r27,
+r28,
+r29,
+r30,
+r31.
+.B rm
+can change any of the individual registers or the stacked registers.
+.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 from kdb's current task.
+
+.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.
Index: 2.6.x-xfs/Documentation/kdb/kdb_sr.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_sr.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_sr.man	2006-01-10 17:22:51.349441727 +1100
@@ -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.
Index: 2.6.x-xfs/Documentation/kdb/kdb_ss.man
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/kdb_ss.man	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/kdb_ss.man	2006-01-10 17:22:51.350418155 +1100
@@ -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>
+
Index: 2.6.x-xfs/Documentation/kdb/slides
===================================================================
--- 2.6.x-xfs.orig/Documentation/kdb/slides	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/Documentation/kdb/slides	2006-01-10 17:22:51.354323866 +1100
@@ -0,0 +1,1382 @@
+#! /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
+		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
Index: 2.6.x-xfs/Makefile
===================================================================
--- 2.6.x-xfs.orig/Makefile	2006-01-10 17:07:47.300392035 +1100
+++ 2.6.x-xfs/Makefile	2006-01-10 17:22:51.355300294 +1100
@@ -585,6 +585,7 @@
 
 ifeq ($(KBUILD_EXTMOD),)
 core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+core-$(CONFIG_KDB) += kdb/
 
 vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
 		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
Index: 2.6.x-xfs/drivers/char/keyboard.c
===================================================================
--- 2.6.x-xfs.orig/drivers/char/keyboard.c	2006-01-10 17:07:47.342378429 +1100
+++ 2.6.x-xfs/drivers/char/keyboard.c	2006-01-10 17:22:51.356276721 +1100
@@ -39,6 +39,9 @@
 #include <linux/vt_kern.h>
 #include <linux/sysrq.h>
 #include <linux/input.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 
 static void kbd_disconnect(struct input_handle *handle);
 extern void ctrl_alt_del(void);
@@ -1062,6 +1065,13 @@
 			if (keycode < BTN_MISC)
 				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
 
+#ifdef	CONFIG_KDB
+	if (down && !rep && keycode == KEY_PAUSE && kdb_on == 1) {
+		kdb(KDB_REASON_KEYBOARD, 0, regs);
+		return;
+	}
+#endif	/* CONFIG_KDB */
+
 #ifdef CONFIG_MAGIC_SYSRQ	       /* Handle the SysRq Hack */
 	if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
 		sysrq_down = down;
Index: 2.6.x-xfs/drivers/serial/8250.c
===================================================================
--- 2.6.x-xfs.orig/drivers/serial/8250.c	2005-12-05 09:56:15.577329392 +1100
+++ 2.6.x-xfs/drivers/serial/8250.c	2006-01-10 17:22:51.358229577 +1100
@@ -46,6 +46,19 @@
 #include <asm/irq.h>
 
 #include "8250.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.
+ */
+
+static int  kdb_serial_line = -1;
+static const char *kdb_serial_ptr = kdb_serial_str;
+#endif	/* CONFIG_KDB */
 
 /*
  * Configuration:
@@ -1154,6 +1167,18 @@
 			 */
 		}
 		ch = serial_inp(up, UART_RX);
+#ifdef	CONFIG_KDB
+		if ((up->port.line == kdb_serial_line) && kdb_on == 1) {
+		    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 */
 		flag = TTY_NORMAL;
 		up->port.icount.rx++;
 
@@ -2268,6 +2293,30 @@
 	if (!port->iobase && !port->membase)
 		return -ENODEV;
 
+#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;
+		kdb_serial.io_type = port->iotype;
+		switch (port->iotype) {
+		case SERIAL_IO_MEM:
+#ifdef  SERIAL_IO_MEM32
+		case SERIAL_IO_MEM32:
+#endif
+			kdb_serial.iobase = (unsigned long)(port->membase);
+			kdb_serial.ioreg_shift = port->regshift;
+			break;
+		default:
+			kdb_serial.iobase = port->iobase;
+			kdb_serial.ioreg_shift = 0;
+			break;
+		}
+	}
+#endif	/* CONFIG_KDB */
+
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 
Index: 2.6.x-xfs/drivers/serial/sn_console.c
===================================================================
--- 2.6.x-xfs.orig/drivers/serial/sn_console.c	2005-10-28 15:24:24.378002436 +1000
+++ 2.6.x-xfs/drivers/serial/sn_console.c	2006-01-10 17:22:51.359206004 +1100
@@ -49,6 +49,22 @@
 #include <linux/delay.h> /* for mdelay */
 #include <linux/miscdevice.h>
 #include <linux/serial_core.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/serial_reg.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.
+ */
+
+static int  kdb_serial_line = -1;
+static char *kdb_serial_ptr = (char *)kdb_serial_str;
+#endif /* CONFIG_KDB */
+
 
 #include <asm/io.h>
 #include <asm/sn/simulator.h>
@@ -488,6 +504,26 @@
 			       "obtaining data from the console (0x%0x)\n", ch);
 			break;
 		}
+#ifdef CONFIG_KDB
+	if (kdb_on == 1) {
+		if (ch == *kdb_serial_ptr) {
+			if (!(*++kdb_serial_ptr)) {
+				spin_unlock_irqrestore(&port->sc_port.lock, flags);
+				if (!regs) {
+					KDB_STATE_SET(KEYBOARD);
+					KDB_ENTER();   /* to get some registers */
+				} else
+					kdb(KDB_REASON_KEYBOARD, 0, regs);
+				kdb_serial_ptr = (char *)kdb_serial_str;
+				spin_lock_irqsave(&port->sc_port.lock, flags);
+				break;
+			}
+		}
+		else
+			kdb_serial_ptr = (char *)kdb_serial_str;
+	}
+#endif /* CONFIG_KDB */
+
 #ifdef CONFIG_MAGIC_SYSRQ
                 if (sysrq_requested) {
                         unsigned long sysrq_timeout = sysrq_requested + HZ*5;
@@ -1047,6 +1083,15 @@
  */
 static int __init sn_sal_console_setup(struct console *co, char *options)
 {
+#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;
 }
 
@@ -1122,3 +1167,31 @@
 }
 
 console_initcall(sn_sal_serial_console_init);
+
+#ifdef	CONFIG_KDB
+int
+l1_control_in_polled(int offset)
+{
+	int sal_call_status = 0, input;
+	int ret = 0;
+	if (offset == UART_LSR) {
+		ret = (UART_LSR_THRE | UART_LSR_TEMT);	/* can send anytime */
+		sal_call_status = ia64_sn_console_check(&input);
+		if (!sal_call_status && input) {
+			/* input pending */
+			ret |= UART_LSR_DR;
+		}
+	}
+	return ret;
+}
+
+int
+l1_serial_in_polled(void)
+{
+	int ch;
+	if (!ia64_sn_console_getc(&ch))
+		return ch;
+	else
+		return 0;
+}
+#endif /* CONFIG_KDB */
Index: 2.6.x-xfs/drivers/serial/8250_early.c
===================================================================
--- 2.6.x-xfs.orig/drivers/serial/8250_early.c	2005-12-05 09:56:15.587093669 +1100
+++ 2.6.x-xfs/drivers/serial/8250_early.c	2006-01-10 17:22:51.360182432 +1100
@@ -35,6 +35,13 @@
 #include <asm/io.h>
 #include <asm/serial.h>
 
+
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+
+static int  kdb_serial_line = -1;
+#endif	/* CONFIG_KDB */
+
 struct early_uart_device {
 	struct uart_port port;
 	char options[16];		/* e.g., 115200n8 */
@@ -191,6 +198,31 @@
 	if ((err = parse_options(device, options)) < 0)
 		return err;
 
+
+#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 = console->index;
+		kdb_serial.io_type = device->port.iotype;
+		switch (device->port.iotype) {
+		case SERIAL_IO_MEM:
+#ifdef  SERIAL_IO_MEM32
+		case SERIAL_IO_MEM32:
+#endif
+			kdb_serial.iobase = (unsigned long)(device->port.membase);
+			kdb_serial.ioreg_shift = device->port.regshift;
+			break;
+		default:
+			kdb_serial.iobase = device->port.iobase;
+			kdb_serial.ioreg_shift = 0;
+			break;
+		}
+	}
+#endif	/* CONFIG_KDB */
+
 	init_port(device);
 	return 0;
 }
Index: 2.6.x-xfs/drivers/usb/host/ohci-hcd.c
===================================================================
--- 2.6.x-xfs.orig/drivers/usb/host/ohci-hcd.c	2005-12-05 09:56:16.212983798 +1100
+++ 2.6.x-xfs/drivers/usb/host/ohci-hcd.c	2006-01-10 17:22:51.361158860 +1100
@@ -17,6 +17,7 @@
  *
  * History:
  * 
+ * 2005/06/23 CONFIG_KDB_USB support. (ayoung@sgi.com)
  * 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer)
  * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
  * 2003/02/24 show registers in sysfs (Kevin Brosius)
@@ -879,6 +880,53 @@
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef	CONFIG_KDB_USB
+
+static void
+ohci_kdb_poll (void * __ohci, struct urb *urb)
+{
+	struct ohci_hcd *ohci;
+	struct ohci_regs * regs;
+
+	/*
+	 * NOTE - we use the ohci_hcd from the urb rather than the
+	 * __ohci parameter (which is NULL anyway). This ensures
+	 * that we will process the proper controller for the urb.
+	 */
+
+	if (!urb) /* can happen if no keyboard attached */
+		return;
+
+	ohci = (struct ohci_hcd *) hcd_to_ohci(urb->dev->bus->hcpriv);
+	regs = ohci->regs;
+
+	/* if the urb is not currently in progress resubmit it */
+	if (urb->status != -EINPROGRESS) {
+
+		if (usb_submit_urb (urb, SLAB_ATOMIC))
+			return;
+
+		/* make sure the HC registers are set correctly */
+		writel (OHCI_INTR_WDH, &regs->intrenable);
+		writel (OHCI_INTR_WDH, &regs->intrstatus);
+		writel (OHCI_INTR_MIE, &regs->intrenable);
+
+		// flush those pci writes
+		(void) readl (&ohci->regs->control);
+	}
+
+	if (ohci->hcca->done_head) {
+		dl_done_list_kdb (ohci, urb);
+		writel (OHCI_INTR_WDH, &regs->intrstatus);
+		// flush the pci write
+		(void) readl (&ohci->regs->control);
+	}
+}
+
+#endif /* CONFIG_KDB_USB */
+
+/*-------------------------------------------------------------------------*/
+
 #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
 
 MODULE_AUTHOR (DRIVER_AUTHOR);
Index: 2.6.x-xfs/drivers/usb/host/ohci-pci.c
===================================================================
--- 2.6.x-xfs.orig/drivers/usb/host/ohci-pci.c	2005-12-05 09:56:16.226653785 +1100
+++ 2.6.x-xfs/drivers/usb/host/ohci-pci.c	2006-01-10 17:22:51.362135288 +1100
@@ -18,6 +18,10 @@
 #error "This file is PCI bus glue.  CONFIG_PCI must be defined."
 #endif
 
+#ifdef	CONFIG_KDB_USB
+#include <linux/kdb.h>
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int
@@ -98,6 +102,11 @@
 		ohci_stop (hcd);
 		return ret;
 	}
+
+#ifdef	CONFIG_KDB_USB
+	kdb_usb_infos.poll_func = ohci_kdb_poll;
+	kdb_usb_infos.uhci = NULL; /* not used */
+#endif
 	return 0;
 }
 
Index: 2.6.x-xfs/drivers/usb/host/ohci-q.c
===================================================================
--- 2.6.x-xfs.orig/drivers/usb/host/ohci-q.c	2005-06-20 16:55:32.315687217 +1000
+++ 2.6.x-xfs/drivers/usb/host/ohci-q.c	2006-01-10 17:22:51.362135288 +1100
@@ -1114,3 +1114,65 @@
     		td = td_next;
   	}  
 }
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_KDB_USB
+static void
+dl_done_list_kdb (struct ohci_hcd *ohci, struct urb *kdburb)
+{
+	struct td	*td = dl_reverse_done_list (ohci);
+
+  	while (td) {
+		struct td	*td_next = td->next_dl_td;
+		struct urb	*urb = td->urb;
+		urb_priv_t	*urb_priv = urb->hcpriv;
+		struct ed	*ed = td->ed;
+
+		if (urb != kdburb) {
+			td = td_next;
+			continue;
+		}
+
+		/* update URB's length and status from TD */
+   		td_done (ohci, urb, td);
+  		urb_priv->td_cnt++;
+
+		/* If all this urb's TDs are done, just resubmit it */
+  		if (urb_priv->td_cnt == urb_priv->length) {
+			urb->actual_length = 0;
+			urb->status = -EINPROGRESS;
+			td_submit_urb (ohci, urb);
+		}
+
+		/* clean schedule:  unlink EDs that are no longer busy */
+		if (list_empty (&ed->td_list)) {
+			if (ed->state == ED_OPER)
+				start_ed_unlink (ohci, ed);
+
+		/* ... reenabling halted EDs only after fault cleanup */
+		} else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE))
+					== cpu_to_hc32 (ohci, ED_SKIP)) {
+			td = list_entry (ed->td_list.next, struct td, td_list);
+ 			if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
+				ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP);
+				/* ... hc may need waking-up */
+				switch (ed->type) {
+				case PIPE_CONTROL:
+					ohci_writel (ohci, OHCI_CLF,
+						&ohci->regs->cmdstatus);
+					break;
+				case PIPE_BULK:
+					ohci_writel (ohci, OHCI_BLF,
+						&ohci->regs->cmdstatus);
+					break;
+				}
+			}
+		}
+
+    		td = td_next;
+  	}
+}
+
+#endif /* CONFIG_KDB_USB */
Index: 2.6.x-xfs/drivers/usb/input/hid-core.c
===================================================================
--- 2.6.x-xfs.orig/drivers/usb/input/hid-core.c	2005-12-20 16:44:01.561345850 +1100
+++ 2.6.x-xfs/drivers/usb/input/hid-core.c	2006-01-10 17:22:51.364088143 +1100
@@ -44,6 +44,10 @@
 #define DRIVER_DESC "USB HID core driver"
 #define DRIVER_LICENSE "GPL"
 
+#ifdef	CONFIG_KDB_USB
+#include <linux/kdb.h>
+#endif
+
 static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
 				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
 /*
@@ -1824,6 +1828,12 @@
 	if (!hid)
 		return;
 
+#ifdef CONFIG_KDB_USB
+	/* Unlink the KDB USB struct */
+	if (hid->urbin == kdb_usb_infos.urb)
+		memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos));
+#endif
+
 	usb_set_intfdata(intf, NULL);
 	usb_kill_urb(hid->urbin);
 	usb_kill_urb(hid->urbout);
@@ -1896,6 +1906,15 @@
 	printk(": USB HID v%x.%02x %s [%s] on %s\n",
 		hid->version >> 8, hid->version & 0xff, c, hid->name, path);
 
+#ifdef	CONFIG_KDB_USB
+	/* Initialization of the KDB structure */
+	if (!strcmp(c, "Keyboard")) {
+		kdb_usb_infos.urb = hid->urbin;
+		kdb_usb_infos.buffer = hid->inbuf;
+		kdb_usb_infos.reset_timer = NULL;
+	}
+#endif
+
 	return 0;
 }
 
Index: 2.6.x-xfs/drivers/usb/input/usbkbd.c
===================================================================
--- 2.6.x-xfs.orig/drivers/usb/input/usbkbd.c	2005-12-05 09:56:16.395575770 +1100
+++ 2.6.x-xfs/drivers/usb/input/usbkbd.c	2006-01-10 17:22:51.365064571 +1100
@@ -82,6 +82,10 @@
 	dma_addr_t leds_dma;
 };
 
+#ifdef	CONFIG_KDB_USB
+#include <linux/kdb.h>
+#endif
+
 static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_kbd *kbd = urb->context;
@@ -297,6 +301,13 @@
 	usb_fill_int_urb(kbd->irq, dev, pipe,
 			 kbd->new, (maxp > 8 ? 8 : maxp),
 			 usb_kbd_irq, kbd, endpoint->bInterval);
+
+#ifdef	CONFIG_KDB_USB
+	/* Init the KDB structure */
+	kdb_usb_infos.urb = kbd->irq;
+	kdb_usb_infos.buffer = kbd->new;
+	kdb_usb_infos.reset_timer = NULL;
+#endif
 	kbd->irq->transfer_dma = kbd->new_dma;
 	kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -329,6 +340,11 @@
 	struct usb_kbd *kbd = usb_get_intfdata (intf);
 
 	usb_set_intfdata(intf, NULL);
+#ifdef CONFIG_KDB_USB
+       /* Unlink the KDB USB struct */
+       if (kbd && kbd->irq == kdb_usb_infos.urb)
+               memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos));
+#endif /* CONFIG_KDB_USB */
 	if (kbd) {
 		usb_kill_urb(kbd->irq);
 		input_unregister_device(kbd->dev);
Index: 2.6.x-xfs/fs/proc/proc_misc.c
===================================================================
--- 2.6.x-xfs.orig/fs/proc/proc_misc.c	2005-12-05 09:56:19.583612075 +1100
+++ 2.6.x-xfs/fs/proc/proc_misc.c	2006-01-10 17:22:51.366040998 +1100
@@ -206,6 +206,106 @@
 #undef K
 }
 
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+/* Like meminfo_read_proc() but without the locks and using kdb_printf() */
+void
+kdb_meminfo_read_proc(void)
+{
+	struct sysinfo i;
+	struct page_state ps;
+	unsigned long inactive;
+	unsigned long active;
+	unsigned long free;
+	unsigned long committed;
+	unsigned long allowed;
+	struct vmalloc_info vmi;
+
+	get_page_state(&ps);
+	get_zone_counts(&active, &inactive, &free);
+
+/*
+ * display in kilobytes.
+ */
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+	si_meminfo(&i);
+	kdb_si_swapinfo(&i);
+	committed = atomic_read(&vm_committed_space);
+	allowed = ((totalram_pages - hugetlb_total_pages())
+		* sysctl_overcommit_ratio / 100) + total_swap_pages;
+
+	get_vmalloc_info(&vmi);
+
+	kdb_printf(
+		"MemTotal:     %8lu kB\n"
+		"MemFree:      %8lu kB\n"
+		"Buffers:      %8lu kB\n",
+		K(i.totalram),
+		K(i.freeram),
+		K(i.bufferram)
+		);
+	kdb_printf(
+		"Cached:       %8lu kB\n"
+		"SwapCached:   %8lu kB\n"
+		"Active:       %8lu kB\n",
+		K(get_page_cache_size()-total_swapcache_pages-i.bufferram),
+		K(total_swapcache_pages),
+		K(active)
+		);
+	kdb_printf(
+		"Inactive:     %8lu kB\n"
+		"HighTotal:    %8lu kB\n"
+		"HighFree:     %8lu kB\n",
+		K(inactive),
+		K(i.totalhigh),
+		K(i.freehigh)
+		);
+	kdb_printf(
+		"LowTotal:     %8lu kB\n"
+		"LowFree:      %8lu kB\n"
+		"SwapTotal:    %8lu kB\n",
+		K(i.totalram-i.totalhigh),
+		K(i.freeram-i.freehigh),
+		K(i.totalswap)
+		);
+	kdb_printf(
+		"SwapFree:     %8lu kB\n"
+		"Dirty:        %8lu kB\n"
+		"Writeback:    %8lu kB\n",
+		K(i.freeswap),
+		K(ps.nr_dirty),
+		K(ps.nr_writeback)
+		);
+	kdb_printf(
+		"Mapped:       %8lu kB\n"
+		"Slab:         %8lu kB\n"
+		"CommitLimit:  %8lu kB\n",
+		K(ps.nr_mapped),
+		K(ps.nr_slab),
+		K(allowed)
+		);
+	kdb_printf(
+		"Committed_AS: %8lu kB\n"
+		"PageTables:   %8lu kB\n"
+		"VmallocTotal: %8lu kB\n",
+		K(committed),
+		K(ps.nr_page_table_pages),
+		VMALLOC_TOTAL >> 10
+		);
+	kdb_printf(
+		"VmallocUsed:  %8lu kB\n"
+		"VmallocChunk: %8lu kB\n",
+		vmi.used >> 10,
+		vmi.largest_chunk >> 10
+		);
+
+#ifdef	CONFIG_HUGETLBFS
+	kdb_hugetlb_report_meminfo();
+#endif
+}
+#endif	/* CONFIG_KDB */
+
 extern struct seq_operations fragmentation_op;
 static int fragmentation_open(struct inode *inode, struct file *file)
 {
Index: 2.6.x-xfs/fs/proc/mmu.c
===================================================================
--- 2.6.x-xfs.orig/fs/proc/mmu.c	2005-06-20 16:55:33.291273654 +1000
+++ 2.6.x-xfs/fs/proc/mmu.c	2006-01-10 17:22:51.366040998 +1100
@@ -31,6 +31,10 @@
 #include <asm/div64.h>
 #include "internal.h"
 
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif
+
 void get_vmalloc_info(struct vmalloc_info *vmi)
 {
 	struct vm_struct *vma;
@@ -47,6 +51,9 @@
 
 		prev_end = VMALLOC_START;
 
+#ifdef	CONFIG_KDB
+		if (!KDB_IS_RUNNING())
+#endif
 		read_lock(&vmlist_lock);
 
 		for (vma = vmlist; vma; vma = vma->next) {
@@ -72,6 +79,9 @@
 		if (VMALLOC_END - prev_end > vmi->largest_chunk)
 			vmi->largest_chunk = VMALLOC_END - prev_end;
 
+#ifdef	CONFIG_KDB
+		if (!KDB_IS_RUNNING())
+#endif
 		read_unlock(&vmlist_lock);
 	}
 }
Index: 2.6.x-xfs/include/linux/console.h
===================================================================
--- 2.6.x-xfs.orig/include/linux/console.h	2005-06-20 16:55:33.932875545 +1000
+++ 2.6.x-xfs/include/linux/console.h	2006-01-10 17:22:51.367017426 +1100
@@ -119,7 +119,12 @@
 
 /* Some debug stub to catch some of the obvious races in the VT code */
 #if 1
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#define WARN_CONSOLE_UNLOCKED()	WARN_ON(!is_console_locked() && !oops_in_progress && !atomic_read(&kdb_event))
+#else	/* !CONFIG_KDB */
 #define WARN_CONSOLE_UNLOCKED()	WARN_ON(!is_console_locked() && !oops_in_progress)
+#endif	/* CONFIG_KDB */
 #else
 #define WARN_CONSOLE_UNLOCKED()
 #endif
Index: 2.6.x-xfs/include/linux/dis-asm.h
===================================================================
--- 2.6.x-xfs.orig/include/linux/dis-asm.h	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/include/linux/dis-asm.h	2006-01-10 17:22:51.367993854 +1100
@@ -0,0 +1,316 @@
+/* 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; })
+#if 0	/* CONFIG_KDB */
+#define xmalloc(size) ({ void *res = kmalloc(size, GFP_ATOMIC); if (!res) BUG(); res; })
+#define free(address) kfree(address)
+#else
+#define xmalloc(size) ({ void *res = debug_kmalloc(size, GFP_ATOMIC); if (!res) BUG(); res; })
+#define free(address) debug_kfree(address)
+#endif
+
+#if 0	/* CONFIG_KDB */
+#include <bfd.h>
+#else
+#include <asm/bfd.h>
+#endif
+
+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) */
Index: 2.6.x-xfs/include/linux/kdb.h
===================================================================
--- 2.6.x-xfs.orig/include/linux/kdb.h	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/include/linux/kdb.h	2006-01-10 17:22:51.368970281 +1100
@@ -0,0 +1,190 @@
+#ifndef _KDB_H
+#define _KDB_H
+
+/*
+ * Kernel Debugger Architecture Independent Global Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <asm/atomic.h>
+
+/* These are really private, but they must be defined before including
+ * asm-$(ARCH)/kdb.h, so make them public and put them here.
+ */
+extern int kdb_getuserarea_size(void *, unsigned long, size_t);
+extern int kdb_putuserarea_size(unsigned long, void *, size_t);
+
+#include <asm/kdb.h>
+
+#define KDB_MAJOR_VERSION	4
+#define KDB_MINOR_VERSION	4
+#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 */
+extern atomic_t kdb_event;
+
+/*
+ * kdb_on
+ *
+ * 	Defines whether kdb is on or not.  Default value
+ *	is set by CONFIG_KDB_OFF.  Boot with kdb=on/off/on-nokey
+ *	or echo "[012]" > /proc/sys/kernel/kdb to change it.
+ */
+extern int kdb_on;
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_SGI_L1_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 */
+#define KDB_FLAG_NO_CONSOLE	(1 << 5)	/* No console is available, kdb is disabled */
+#define KDB_FLAG_RECOVERY	(1 << 6)	/* kdb is being entered for an error which has been recovered */
+
+extern volatile int kdb_flags;			/* Global flags, see kdb_state for per cpu state */
+
+extern void kdb_save_flags(void);
+extern void kdb_restore_flags(void);
+
+#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))
+
+/*
+ * 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_ENTER_SLAVE,		/* KDB_ENTER_SLAVE() 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;
+
+#ifdef	CONFIG_KDB
+extern asmlinkage int kdb(kdb_reason_t, int, struct pt_regs *);
+#else
+#define kdb(reason,error_code,frame) (0)
+#endif
+
+/* Mainly used by kdb code, but this function is sometimes used
+ * by hacked debug code so make it generally available, not private.
+ */
+extern void kdb_printf(const char *,...)
+	    __attribute__ ((format (printf, 1, 2)));
+typedef void (*kdb_printf_t)(const char *, ...)
+	     __attribute__ ((format (printf, 1, 2)));
+extern void kdb_init(void);
+
+#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 one of the KDB_EVENT codes below.
+ *
+ * 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;
+
+#define KDB_EVENT_EXITING	0
+#define KDB_EVENT_ENTERED	1
+#define KDB_EVENT_REBOOTING	2
+#define KDB_EVENT_DUMPING	3
+
+#ifdef CONFIG_KDB_USB
+#include <linux/usb.h>
+
+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 */
+};
+extern struct kdb_usb_exchange kdb_usb_infos; /* KDB common structure */
+#endif /* CONFIG_KDB_USB */
+
+static inline
+int kdb_process_cpu(const struct task_struct *p)
+{
+	unsigned int cpu = p->thread_info->cpu;
+	if (cpu > NR_CPUS)
+		cpu = 0;
+	return cpu;
+}
+
+extern const char kdb_serial_str[];
+
+#endif	/* !_KDB_H */
Index: 2.6.x-xfs/include/linux/kdbprivate.h
===================================================================
--- 2.6.x-xfs.orig/include/linux/kdbprivate.h	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/include/linux/kdbprivate.h	2006-01-10 17:22:51.370923137 +1100
@@ -0,0 +1,502 @@
+#ifndef _KDBPRIVATE_H
+#define _KDBPRIVATE_H
+
+/*
+ * Kernel Debugger Architecture Independent Private Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+#include <linux/dis-asm.h>
+#include <asm/kdbprivate.h>
+#include <asm/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)
+
+	/*
+	 * 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 */
+
+#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)
+
+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;
+
+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;
+extern int kallsyms_symbol_next(char *prefix_name, int flag);
+extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
+
+	/*
+	 * 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_getphysword(unsigned long *word,
+			unsigned long addr, size_t size);
+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 char *kdb_read(char *buffer, size_t bufsize);
+extern char *kdb_strdup(const char *str, int type);
+extern void kdb_symbol_print(kdb_machreg_t, const kdb_symtab_t *, unsigned int);
+
+	 /*
+	  * 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);
+
+	/*
+	 * 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_KEYBOARD	0x00020000	/* kdb entered via keyboard on this 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())
+
+	/*
+	 * 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 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.
+	 */
+
+#if	defined(__i386__) || defined(__x86_64__)
+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 *);
+#endif
+
+	/*
+	 * Architecture specific Stack Traceback functions.
+	 */
+
+struct task_struct;
+
+extern int kdba_bt_address(kdb_machreg_t, int);
+extern int kdba_bt_process(const 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_bt(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 unsigned long 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 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(const char *);
+extern char kdb_task_state_char (const struct task_struct *);
+extern unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask);
+extern void kdb_ps_suppressed(void);
+extern void kdb_ps1(const 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);
+extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info, int seqno);
+#ifdef CONFIG_SWAP
+extern void kdb_si_swapinfo(struct sysinfo *);
+#else
+#include <linux/swap.h>
+#define kdb_si_swapinfo(x) si_swapinfo(x)
+#endif
+extern void kdb_meminfo_read_proc(void);
+#ifdef	CONFIG_HUGETLB_PAGE
+extern void kdb_hugetlb_report_meminfo(void);
+#endif	/* CONFIG_HUGETLB_PAGE */
+extern const char *kdb_walk_kallsyms(loff_t *pos);
+
+	/*
+	 * 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 */
+	int irq_depth;				/* irq count */
+	struct kdba_running_process arch;	/* arch dependent save data */
+};
+
+extern struct kdb_running_process kdb_running_process[/* NR_CPUS */];
+
+extern void kdb_save_running(struct pt_regs *);
+extern void kdb_unsave_running(struct pt_regs *);
+extern struct task_struct *kdb_curr_task(int);
+
+/* 	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;
+
+#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_used__ __attribute__ ((__section__ (".kdb_initcall.init"))) = fn;
+#define kdb_module_exit(fn) \
+	static exitcall_t __kdb_exitcall_##fn __attribute_used__ __attribute__ ((__section__ (".kdb_exitcall.exit"))) = fn;
+#endif	/* MODULE */
+
+#define kdb_task_has_cpu(p) (task_curr(p))
+extern void kdb_runqueue(unsigned long cpu, kdb_printf_t xxx_printf);
+
+/* Simplify coexistence with NPTL */
+#define	kdb_do_each_thread(g, p) do_each_thread(g, p)
+#define	kdb_while_each_thread(g, p) while_each_thread(g, p)
+
+#define GFP_KDB (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
+
+extern void *debug_kmalloc(size_t size, int flags);
+extern void debug_kfree(const void *);
+
+extern void kdb_initsupport(void);
+
+extern void kdba_set_current_task(const struct task_struct *);
+extern const struct task_struct *kdb_current_task;
+extern struct pt_regs *kdb_current_regs;
+
+/* 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.
+ */
+
+extern int kdba_putarea_size(unsigned long to_xxx, void *from, size_t size);
+extern int kdba_getarea_size(void *to, unsigned long from_xxx, size_t size);
+extern int kdba_verify_rw(unsigned long addr, size_t size);
+
+#endif	/* !_KDBPRIVATE_H */
Index: 2.6.x-xfs/include/linux/sysctl.h
===================================================================
--- 2.6.x-xfs.orig/include/linux/sysctl.h	2005-12-20 16:44:01.602355806 +1100
+++ 2.6.x-xfs/include/linux/sysctl.h	2006-01-10 17:22:51.371899564 +1100
@@ -146,6 +146,7 @@
 	KERN_RANDOMIZE=68, /* int: randomize virtual address space */
 	KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */
 	KERN_SPIN_RETRY=70,	/* int: number of spinlock retries */
+	KERN_KDB=71,		/* int: kdb on/off */
 };
 
 
Index: 2.6.x-xfs/init/main.c
===================================================================
--- 2.6.x-xfs.orig/init/main.c	2005-12-05 09:56:22.988415319 +1100
+++ 2.6.x-xfs/init/main.c	2006-01-10 17:22:51.372875992 +1100
@@ -68,6 +68,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.
@@ -160,6 +164,26 @@
 
 extern struct obs_kernel_param __setup_start[], __setup_end[];
 
+#ifdef	CONFIG_KDB
+static int __init kdb_setup(char *str)
+{
+	if (strcmp(str, "on") == 0) {
+		kdb_on = 1;
+	} else if (strcmp(str, "on-nokey") == 0) {
+		kdb_on = 2;
+	} else if (strcmp(str, "off") == 0) {
+		kdb_on = 0;
+	} else if (strcmp(str, "early") == 0) {
+		kdb_on = 1;
+		kdb_flags |= KDB_FLAG_EARLYKDB;
+	} else
+		printk("kdb flag %s not recognised\n", str);
+	return 0;
+}
+
+__setup("kdb=", kdb_setup);
+#endif	/* CONFIG_KDB */
+
 static int __init obsolete_checksetup(char *line)
 {
 	struct obs_kernel_param *p;
@@ -520,6 +544,14 @@
 	pgtable_cache_init();
 	prio_tree_init();
 	anon_vma_init();
+
+#ifdef	CONFIG_KDB
+	kdb_init();
+	if (KDB_FLAG(EARLYKDB)) {
+		KDB_ENTER();
+	}
+#endif	/* CONFIG_KDB */
+
 #ifdef CONFIG_X86
 	if (efi_enabled)
 		efi_enter_virtual_mode();
Index: 2.6.x-xfs/kdb/ChangeLog
===================================================================
--- 2.6.x-xfs.orig/kdb/ChangeLog	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/ChangeLog	2006-01-10 17:22:51.376781703 +1100
@@ -0,0 +1,1284 @@
+2006-01-04 Keith Owens  <kaos@sgi.com>
+
+	* Print all buffers on a page in inode pages and update formatting to be
+	  legible, too.  David Chinner, SGI.
+	* Update page flags in kdbm_pg.
+	* Remove inline from *.c files.
+	* kdb v4.4-2.6.15-common-1.
+
+2005-12-25 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.15-rc7-common-1.
+
+2005-12-20 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.15-rc6-common-1.
+
+2005-12-10 Keith Owens  <kaos@sgi.com>
+
+	* Update mapping of flags to strings in kdbm_pg.c and kdbm_vm.c.
+	* kdb v4.4-2.6.15-rc5-common-3.
+
+2005-12-06 Keith Owens  <kaos@sgi.com>
+
+	* Add RECOVERY flag to global KDB flags.
+	* Add kdb_{save,restore}_flags.
+	* kdb v4.4-2.6.15-rc5-common-2.
+
+2005-12-05 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.15-rc5-common-1.
+
+2005-12-02 Keith Owens  <kaos@sgi.com>
+
+	* kdbm_vm.c: offsets of page macros should be unsigned long.  Reported
+	  by Dean Nelson, SGI.
+	* kdb v4.4-2.6.15-rc4-common-1.
+
+2005-11-30 Keith Owens  <kaos@sgi.com>
+
+	* New follow_page() API.
+	* kdb v4.4-2.6.15-rc3-common-1.
+
+2005-11-21 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.15-rc2-common-1.
+
+2005-11-15 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.15-rc1-common-1.
+
+2005-11-15 Keith Owens  <kaos@sgi.com>
+
+	* Allow kdb_printf() to be used outside kdb, in preemptible context.
+	* Build with CONFIG_SWAP=n.  Reported by Leo Yuriev.
+	* kdb v4.4-2.6.14-common-2.
+
+2005-10-28 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.14-common-1.
+
+2005-10-21 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.14-rc5-common-1.
+
+2005-10-11 Keith Owens  <kaos@sgi.com>
+
+	* Handle removal of USB keyboard.  Aaron Young, SGI.
+	* kdb v4.4-2.6.14-rc4-common-1.
+
+2005-10-05 Keith Owens  <kaos@sgi.com>
+
+	* Extend kdb_notifier_list() codes to include dumping.
+	* Use emergency_restart() for reboot, it can be called from interrupt
+	  context, unlike machine_restart().
+	* kdb v4.4-2.6.14-rc3-common-1.
+
+2005-09-21 Keith Owens  <kaos@sgi.com>
+
+	* Support kdb_current_task in register display and modify commands.
+	* Document what changes kdb's notion of the current task.
+	* Update rd documentation for IA64.
+	* Move some definictions to kdbprivate.h and remove some unused symbol
+	  exports.
+	* kdb v4.4-2.6.14-rc2-common-1.
+
+2005-09-20 Keith Owens  <kaos@sgi.com>
+
+	* Document IA64 handlers command.
+	* Add more fields to the task command.
+	* Cope with MCA/INIT handlers in the ps command.
+	* Namespace cleanup, delete unused exports, make some functions static.
+	* Add a kdb_notifier_list callback when kdb is about to reboot the
+	  system.
+	* kdb v4.4-2.6.14-rc1-common-1.
+
+2005-08-29 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.13-common-1.
+
+2005-08-24 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.13-rc7-common-1.
+
+2005-08-08 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.13-rc6-common-1.
+
+2005-08-02 Keith Owens  <kaos@sgi.com>
+
+	* Print more fields from filp, dentry.
+	* Add kdb=on-nokey to suppress kdb entry from the keyboard.
+	* kdb v4.4-2.6.13-rc5-common-1.
+
+2005-07-30 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.13-rc4-common-1.
+
+2005-07-26 Keith Owens  <kaos@sgi.com>
+
+	* Fix compile problem with CONFIG_USB_KBD.
+	* kdb v4.4-2.6.13-rc3-common-3.
+
+2005-07-22 Keith Owens  <kaos@sgi.com>
+
+	* The asmlinkage kdb() patch was lost during packaging.  Reinstate it.
+	* kdb v4.4-2.6.13-rc3-common-2.
+
+2005-07-19 Keith Owens  <kaos@sgi.com>
+
+	* Add support for USB keyboard (OHCI only).  Aaron Young, SGI.
+	* kdb v4.4-2.6.13-rc3-common-1.
+
+2005-07-08 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.13-rc2-common-1.
+
+2005-07-01 Keith Owens  <kaos@sgi.com>
+
+	* Make kdb() asmlinkage to avoid problems with CONFIG_REGPARM.
+	* Change some uses of smp_processor_id() to be preempt safe.
+	* Use DEFINE_SPINLOCK().
+	* kdb v4.4-2.6.13-rc1-common-1.
+
+2005-06-18 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.12-common-1.
+
+2005-06-08 Keith Owens  <kaos@sgi.com>
+
+	* Correct early exit from bd *.
+	* kdb v4.4-2.6.12-rc6-common-1.
+
+2005-05-25 Keith Owens  <kaos@sgi.com>
+
+	* Delete Documentation/kdb/dump.txt.  lkcd now has reasonable
+	  integration with kdb.
+	* kdb v4.4-2.6.12-rc5-common-1.
+
+2005-05-08 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.12-rc4-common-1.
+
+2005-04-21 Keith Owens  <kaos@sgi.com>
+
+	* Add rpte command (find the pte for a physical page).
+	* kdb v4.4-2.6.12-rc3-common-1.
+
+2005-04-06 Keith Owens  <kaos@sgi.com>
+
+	* Add rq and rqa commands.  John Hawkes, SGI.
+	* kdb v4.4-2.6.12-rc2-common-1.
+
+2005-03-29 Keith Owens  <kaos@sgi.com>
+
+	* Use register_sysctl_table() instead of patching kernel/sysctl.c.
+	* Non-ASCII characters are not printable.
+	* kdb v4.4-2.6.12-rc1-common-1.
+
+2005-03-15 Keith Owens  <kaos@sgi.com>
+
+	* More coexistence patches for lkcd.  Jason Uhlenkott, SGI.
+	* kdb v4.4-2.6.11-common-3.
+
+2005-03-08 Keith Owens  <kaos@sgi.com>
+
+	* Coexistence patches for lkcd.  Jason Uhlenkott, SGI.
+	* kdb v4.4-2.6.11-common-2.
+
+2005-03-03 Keith Owens  <kaos@sgi.com>
+
+	* Add kdb to drivers/serial/8250_early.c.  Francois Wellenreiter, Bull.
+	* kdb v4.4-2.6.11-common-1.
+
+2005-02-14 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.11-rc4-common-1.
+
+2005-02-08 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.11-rc3-bk4-common-1.
+
+2005-02-03 Keith Owens  <kaos@sgi.com>
+
+	* Print more superblock fields.  Nathan Scott, SGI.
+	* Remove kallsyms correction for modules, Linus took it.
+	* kdb v4.4-2.6.11-rc3-common-1.
+
+2005-01-27 Keith Owens  <kaos@sgi.com>
+
+	* Add bio command.  Nathan Scott, SGI.
+	* kdb v4.4-2.6.11-rc2-common-1.
+
+2005-01-20 Keith Owens  <kaos@sgi.com>
+
+	* Include kallsyms correction for modules until Linus takes it.
+	* kdb v4.4-2.6.11-rc1-bk7-common-1.
+
+2005-01-12 Keith Owens  <kaos@sgi.com>
+
+	* kallsyms now supports all symbols properly, remove kdb patch.
+	* Add last ditch allocator for debugging.
+	* Update kdb_meminfo_read_proc() for vmalloc changes.
+	* Update kdbm_vm.c for 4 level page tables.
+	* kdb v4.4-2.6.11-rc1-common-1.
+
+2004-12-25 Keith Owens  <kaos@sgi.com>
+
+	* Add kobject command.
+	* Ignore low addresses and large offsets in kdbnearsym().
+	* Console updates for sn2 simulator.
+	* kdb v4.4-2.6.10-common-1.
+
+2004-12-07 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.10-rc3-common-1.
+
+2004-11-23 Keith Owens  <kaos@sgi.com>
+
+	* Remove warning message from kdb_get_one_user_page(), it was too noisy.
+	* kdb v4.4-2.6.10-rc2-common-1.
+
+2004-11-02 Keith Owens  <kaos@sgi.com>
+
+	* Build with kdb patch applied but CONFIG_KDB=n.
+	* kdb v4.4-2.6.10-rc1-common-2.
+
+2004-10-29 Keith Owens  <kaos@sgi.com>
+
+	* Handle new compression scheme for kallsyms.
+	* Handle move of DEAD and ZOMBIE for task->state to task->exit_state.
+	* Tweak the concept of a valid kernel address to get all symbols,
+	  including the symbols in the ia64 gate page.
+	* kdb v4.4-2.6.10-rc1-common-1.
+
+2004-10-21 Keith Owens  <kaos@sgi.com>
+
+	* Handle variable size for the kernel log buffer.
+	* kdb v4.4-2.6.9-common-2.
+
+2004-10-19 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.9-common-1.
+
+2004-10-12 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.9-rc4-common-1.
+
+2004-10-01 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.9-rc3-common-1.
+
+2004-09-30 Keith Owens  <kaos@sgi.com>
+
+	* Add stackdepth command to Documentation/kdb/kdb.mm.  stackdepth is
+	  only supported on i386 and ia64 at the moment.
+	* Skip kdbm_pg memmap build on x86_64.  Scott Lurndal, 3leafnetworks.
+	* Export kdb_serial_str for modular I/O.  Bryan Cardillo, UPenn.
+	* Reinstate tab completion for symbols.
+	* kdb v4.4-2.6.9-rc2-common-2.
+
+2004-09-14 Keith Owens  <kaos@sgi.com>
+
+	* Add task states C (traCed) and E (dEad).
+	* kdb v4.4-2.6.9-rc2-common-1.
+
+2004-08-27 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.9-rc1-common-1.
+
+2004-08-14 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.8-common-1.
+
+2004-08-12 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.8-rc4-common-1.
+
+2004-08-05 Keith Owens  <kaos@sgi.com>
+
+	* Mark kdb_initcall as __attribute_used__ for newer gcc.
+	* kdb v4.4-2.6.8-rc3-common-2.
+
+2004-08-04 Keith Owens  <kaos@sgi.com>
+
+	* Add mdp (memory display physical) comnmand.
+	  Ananth N Mavinakayanahalli, IBM.
+	* kdb v4.4-2.6.8-rc3-common-1.
+
+2004-07-18 Keith Owens  <kaos@sgi.com>
+
+	* Patch for new sn_console.  Erik Jacobson. SGI.
+	* kdb v4.4-2.6.8-rc2-common-1.
+
+2004-07-12 Keith Owens  <kaos@sgi.com>
+
+	* Convert kdbm_task to standard cpumask_t.
+	* Document '*' (all breakpoints) option on bd/be/bc commands.
+	* kdb v4.4-2.6.8-rc1-common-1.
+
+2004-06-30 Keith Owens  <kaos@sgi.com>
+
+	* Common changes to help the x86-64 port.
+	* kdb v4.4-2.6.7-common-3.
+
+2004-06-20 Keith Owens  <kaos@sgi.com>
+
+	* Move kdb includes in mm/swapfile.c to reduce conflicts with other
+	  SGI patches.
+	* kdb v4.4-2.6.7-common-2.
+
+2004-06-16 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.7-common-1.
+
+2004-06-09 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.7-rc3-common-1.
+
+2004-06-09 Keith Owens  <kaos@sgi.com>
+
+	* Namespace clean up.  Mark code/variables as static when it is only
+	  used in one file, delete dead code/variables.
+	* Saved interrupt state requires long, not int.
+	* kdb v4.4-2.6.7-rc2-common-3.
+
+2004-06-08 Keith Owens  <kaos@sgi.com>
+
+	* Whitespace clean up, no code changes.
+	* kdb v4.4-2.6.7-rc2-common-2.
+
+2004-06-07 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.4-2.6.7-rc2-common-1.
+
+2004-06-06 Keith Owens  <kaos@sgi.com>
+
+	* Avoid recursion problems in kdb_init().
+	* Add standard archkdb commands.
+	* Add per_cpu command.
+	* Move kdb_{get,put}userarea_size definitions to linux/kdb.h.
+	* kdb v4.4-2.6.6-common-2.
+
+2004-05-23 Keith Owens  <kaos@sgi.com>
+
+	* Shrink the output from the cpu command.
+	* Add cpu state 'I', the cpu is idle.
+	* Add cpu state '+', some kdb data is available but the cpu is not
+	  responding.
+	* Do not print tasks in state I or M by default in ps and bta commands.
+	* Add states I (idle task) and M (sleeping system daemon) to ps and
+	  bta commands.
+	* Delete unused variables.
+	* Move private kdb fields from kdb.h to kdbprivate.h.
+	* Print 'for keyboard entry' for the special cases when KDB_ENTER() is
+	  used to get registers.
+	* Move bfd.h and ansidecl.h from arch/$(ARCH)/kdb to include/asm-$(ARCH)
+	  and remove -I arch/$(ARCH)/kdb.
+	* dmesg command now prints from either the start or end of dmesg, or at
+	  an arbitrary point in the middle of the kernel log buffer.
+	* Sensible string dump for multi byte md commands.
+	* 'page' command handles ia64 correctly.
+	* Show some activity when waiting for cpus to enter kdb.
+	* Change the KDB entry code to <esc>KDB.
+	* Allow comment commands, starting with '#'.
+	* Commands defined using defcmd from kdb_cmds are not printed as they
+	  are entered, use defcmd with no parameters to print all the defined
+	  commands.
+	* Add summary command.
+	* Update copyright notices.
+	* Zero suppression on md command.
+	* Make set NOSECT=1 the default.
+	* PPC64 uses OF-stdout instead of console.  Ananth N Mavinakayanahalli.
+	* kdb v4.4-2.6.6-common-1.
+
+2004-05-10 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.6.6-common-1.
+
+2004-05-06 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.6.6-rc3-common-1.
+
+2004-05-06 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.6.6-rc2-common-1.
+
+2004-04-30 Keith Owens  <kaos@sgi.com>
+
+	* Rewrite inode_pages command for new radix code in struct page.
+	* kdb v4.3-2.6.6-rc1-common-1.
+
+2004-04-11 Keith Owens  <kaos@sgi.com>
+
+	* Unlock sn_sal_lock before entering kdb from sn_serial.
+	* kdb v4.3-2.6.5-common-2.
+
+2004-04-05 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.6.5-common-1.
+
+2004-03-22 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.6.5-rc2-common-1.
+
+2004-03-12 Keith Owens  <kaos@sgi.com>
+
+	* More work to avoid spurious messages from WARN_CONSOLE_UNLOCKED().
+	* bh command bug fixes.  Nathan Scott.
+	* kdb v4.3-2.6.4-common-1.
+
+2004-03-06 Keith Owens  <kaos@sgi.com>
+
+	* Set KDB_IS_RUNNING() during kdb_init to avoid spurious messages from
+	  WARN_CONSOLE_UNLOCKED().
+	* Correct loss of symbol names in kdbnearsym.
+	* kdb v4.3-2.6.4-rc2-common-1.
+
+2004-02-29 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.6.4-rc1-common-1.
+
+2004-02-21 Keith Owens  <kaos@sgi.com>
+
+	* Correct build of kdb_cmds when using a separate object directory and
+	  make it quiet.  j-nomura (NEC), Keith Owens.
+	* kdb v4.3-2.6.3-common-2.
+
+2004-02-18 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.6.3-common-1.
+
+2004-02-17 Keith Owens  <kaos@sgi.com>
+
+	* Remove WAR for incorrect console registration patch.
+	* kdb v4.3-2.6.3-rc4-common-1.
+
+2004-02-17 Keith Owens  <kaos@sgi.com>
+
+	* Convert longjmp buffers from static to dynamic allocation, for large
+	  cpu counts.
+	* Tweak kdbm_task for SMP/UP.
+	* Reconcile with kdb-v4.3 2.4.25-rc1-common-1.
+	* Simplify coexistence with NPTL patches.
+	* Support kill command on new scheduler.
+	* Do not refetch data when printing a value as characters.
+	* Document the pid command.
+	* Work around 2.6 kallsyms 'feature'.
+	* Upgrade to 2.6.3-rc3.
+	* WAR for incorrect console registration patch.
+	* kdb v4.3-2.6.3-rc3-common-1.
+
+2003-12-03 Keith Owens  <kaos@sgi.com>
+
+	* Reconcile 2.6-test versions from Xavier Bru (Bull), Greg Banks (SGI),
+	  Jim Houston (Concurrent Computer Corp).
+	* Reconcile with kdb v4.3-2.4.23-common-2.
+	* Clean up CONFIG_KDB changes to {scripts,kernel}/kallsyms.c.
+	* Correct handling of kdb command line arguments.
+	* Make hooks into module code less intrusive.
+	* Delete kdb_active_task, not required with O(1) scheduler.
+	* Port kdbm_task.c from 2.4.
+	* Disable debug check in exit.c::next_thread() when kdb is running.
+	* Remove "only bh_disable when interrupts are set".  BH must be disabled
+	  in kdb to prevent deadlock on breakpoints in interrupt handlers.
+	* Add kdb to drivers/char/sn_serial.c.
+	* kdb v4.3-2.6.0-test11-common-1.
+
+2003-11-11 Xavier Bru   <xavier.bru@bull.net>
+	* Merge to 2.6.0-test9
+2003-10-17 Xavier Bru   <xavier.bru@bull.net>
+	* fix NUll ptr in kdb_ps at early prompt.
+2003-10-14 Xavier Bru   <xavier.bru@bull.net>
+	* fix NUll ptr in kdb_ps when cpu not present.
+2003-10-06 Xavier Bru   <xavier.bru@bull.net>
+	* Merge to 2.6.0-test5
+	* fix compile error with CONFIG_MODULES not set.
+
+2003-09-08 Xavier Bru   <xavier.bru@bull.net>
+	* Merge to 2.6.0-test4
+
+2003-07-10 Xavier Bru   <xavier.bru@bull.net>
+
+	* Merge kdb v4.3 to 2.5.72 ia64
+	* don't call local_bh_enable() with interrupts masked.
+
+2003-04-07 Xavier Bru   <xavier.bru@bull.net>
+
+	* Merge kdb v4.1 to 2.5.64 ia64
+	* new kernel parameters support
+	* new module format
+	* new kallsyms support
+
+2003-12-02 Keith Owens  <kaos@sgi.com>
+
+	* Use correct page alignment in kdb_get_one_user_page().
+	  Prasanna S Panchamukhi, IBM.
+	* Split pte command into pte -m and pte -p.  Dean Roe, SGI.
+	* kdb v4.3-2.4.23-common-2.
+
+2003-12-01 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.23-common-1.
+
+2003-11-11 Keith Owens  <kaos@sgi.com>
+
+	* Make KDB for USB keyboards build.  Peter T. Breuer.
+	* Do not use USB keyboard if it has not been probed.
+	* kdb v4.3-2.4.23-rc1-common-1.
+
+2003-10-10 Keith Owens  <kaos@sgi.com>
+
+	* Sync with XFS 2.4.22 tree.
+	* kdb v4.3-2.4.22-common-2.
+
+2003-08-29 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.22-common-1.
+
+2003-07-27 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.22-pre8-common-8.
+
+2003-07-20 Keith Owens  <kaos@sgi.com>
+
+	* Make kdb_serial_str a common constant, the same for all consoles.
+	* Support SGI L1 console.
+	* kdb v4.3-2.4.21-common-8.
+
+2003-07-14 Keith Owens  <kaos@sgi.com>
+
+	* Correct ll command.
+	* kdb v4.3-2.4.21-common-7.
+
+2003-07-08 Keith Owens  <kaos@sgi.com>
+
+	* Export more kdb symbols.  Vamsi Krishna S., IBM.
+	* kdb v4.3-2.4.21-common-6.
+
+2003-07-07 Keith Owens  <kaos@sgi.com>
+
+	* Tweak 'waiting for cpus' message.
+	* kdb v4.3-2.4.21-common-5.
+
+2003-07-07 Keith Owens  <kaos@sgi.com>
+
+	* 2.4.21-ia64-030702 patches common code that affects kdb.  Workaround
+	  this nuisance.
+	* kdb v4.3-2.4.21-common-4.
+
+2003-06-24 Keith Owens  <kaos@sgi.com>
+
+	* Add task and sigset commands.  Mark Goodwin, SGI.
+	* kdb v4.3-2.4.21-common-3.
+
+2003-06-23 Keith Owens  <kaos@sgi.com>
+
+	* Sync with XFS 2.4.21 tree.
+	* kdb v4.3-2.4.21-common-2.
+
+2003-06-20 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.21-common-1.
+
+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.
Index: 2.6.x-xfs/kdb/Makefile
===================================================================
--- 2.6.x-xfs.orig/kdb/Makefile	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/Makefile	2006-01-10 17:22:51.377758131 +1100
@@ -0,0 +1,28 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+#
+
+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 /built-in.o, $(subdir-y))
+
+clean-files := gen-kdb_cmds.c
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+quiet_cmd_gen-kdb = GENKDB  $@
+      cmd_gen-kdb = $(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};");}' \
+		$(filter-out %/Makefile,$^) > $@
+
+$(obj)/gen-kdb_cmds.c:	$(src)/kdb_cmds $(wildcard $(TOPDIR)/arch/$(ARCH)/kdb/kdb_cmds) $(src)/Makefile
+	$(call cmd,gen-kdb)
Index: 2.6.x-xfs/kdb/kdb_bp.c
===================================================================
--- 2.6.x-xfs.orig/kdb/kdb_bp.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/kdb_bp.c	2006-01-10 17:22:51.378734558 +1100
@@ -0,0 +1,623 @@
+/*
+ * Kernel Debugger Architecture Independent Breakpoint Handler
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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
+ */
+
+static 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>
+ *	[bd|bc|be] *
+ *
+ * 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
+
+static 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 " enabled",
+				i, bp->bp_addr);
+
+			kdb_printf("\n");
+			break;
+		case KDBCMD_BD:
+			if (!bp->bp_enabled)
+				break;
+
+			/*
+			 * 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.
+ */
+
+static 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();
+}
Index: 2.6.x-xfs/kdb/kdb_bt.c
===================================================================
--- 2.6.x-xfs.orig/kdb/kdb_bt.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/kdb_bt.c	2006-01-10 17:22:51.379710986 +1100
@@ -0,0 +1,182 @@
+/*
+ * Kernel Debugger Architecture Independent Stack Traceback
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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 [DRSTCZEUIMA]		All useful 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(const struct task_struct *p, unsigned long mask, int argcount, int btaprompt)
+{
+	int diag;
+	char buffer[2];
+	/* FIXME: use kdb_verify_area */
+	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 *g, *p;
+		unsigned long cpu;
+		unsigned long mask = kdb_task_state_string(argc ? argv[1] : NULL);
+		if (argc == 0)
+			kdb_ps_suppressed();
+		/* Run the active tasks first */
+		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+			if (!cpu_online(cpu))
+				continue;
+			p = kdb_curr_task(cpu);
+			if (kdb_bt1(p, mask, argcount, btaprompt))
+				return 0;
+		}
+		/* Now the inactive tasks */
+		kdb_do_each_thread(g, p) {
+			if (task_curr(p))
+				continue;
+			if (kdb_bt1(p, mask, argcount, btaprompt))
+				return 0;
+		} kdb_while_each_thread(g, p);
+	} else if (strcmp(argv[0], "btp") == 0) {
+		struct task_struct *p;
+		unsigned long pid;
+		if (argc != 1)
+			return KDB_ARGCOUNT;
+		if ((diag = kdbgetularg((char *)argv[1], &pid)))
+			return diag;
+		if ((p = find_task_by_pid(pid))) {
+			kdba_set_current_task(p);
+			return kdb_bt1(p, ~0UL, 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;
+		kdba_set_current_task((struct task_struct *)addr);
+		return kdb_bt1((struct task_struct *)addr, ~0UL, argcount, 0);
+	} else if (strcmp(argv[0], "btc") == 0) {
+		unsigned long cpu = ~0;
+		struct kdb_running_process *krp;
+		const struct task_struct *save_current_task = kdb_current_task;
+		char buf[80];
+		if (argc > 1)
+			return KDB_ARGCOUNT;
+		if (argc == 1 && (diag = kdbgetularg((char *)argv[1], &cpu)))
+			return diag;
+		/* Recursive use of kdb_parse, do not use argv after this point */
+		argv = NULL;
+		if (cpu != ~0) {
+			krp = kdb_running_process + cpu;
+			if (cpu >= NR_CPUS || !krp->seqno || !cpu_online(cpu)) {
+				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 < NR_CPUS; ++cpu, ++krp) {
+			if (!cpu_online(cpu) || !krp->seqno)
+				continue;
+			sprintf(buf, "btt 0x%p\n", krp->p);
+			kdb_parse(buf, regs);
+			touch_nmi_watchdog();
+		}
+		kdba_set_current_task(save_current_task);
+		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(kdb_current_task, ~0UL, argcount, 0);
+		}
+	}
+
+	/* NOTREACHED */
+	return 0;
+}
Index: 2.6.x-xfs/kdb/kdb_cmds
===================================================================
--- 2.6.x-xfs.orig/kdb/kdb_cmds	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/kdb_cmds	2006-01-10 17:22:51.380687414 +1100
@@ -0,0 +1,29 @@
+# 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.
+
+# Standard debugging information for first level support, just type archkdb
+# or archkdbcpu or archkdbshort at the kdb prompt.
+
+defcmd archkdb "" "First line arch debugging"
+  set BTSYMARG 1
+  set BTARGS 5
+  -archkdbcommon
+  -bta
+endefcmd
+
+defcmd archkdbcpu "" "archkdb with only tasks on cpus"
+  set BTSYMARG 1
+  set BTARGS 5
+  -archkdbcommon
+  -btc
+endefcmd
+
+defcmd archkdbshort "" "archkdb with less detailed backtrace"
+  set BTSYMARG 0
+  set BTARGS 0
+  -archkdbcommon
+  -bta
+endefcmd
Index: 2.6.x-xfs/kdb/kdb_id.c
===================================================================
--- 2.6.x-xfs.orig/kdb/kdb_id.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/kdb_id.c	2006-01-10 17:22:51.380687414 +1100
@@ -0,0 +1,239 @@
+/*
+ * Kernel Debugger Architecture Independent Instruction Disassembly
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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);
+}
Index: 2.6.x-xfs/kdb/kdb_io.c
===================================================================
--- 2.6.x-xfs.orig/kdb/kdb_io.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/kdb_io.c	2006-01-10 17:22:51.382640269 +1100
@@ -0,0 +1,649 @@
+/*
+ * Kernel Debugger Architecture Independent Console I/O handler
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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
+
+#ifdef CONFIG_PPC64
+#include <asm/udbg.h>
+#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);
+				count = kallsyms_symbol_complete(p_tmp, sizeof(tmpbuffer) - (p_tmp - tmpbuffer));
+				if (tab == 2) {
+					if (count > 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 (count > 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 DEFINE_SPINLOCK(kdb_printf_lock);
+
+	preempt_disable();
+	/* 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;
+		atomic_inc(&kdb_event);
+	}
+
+	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
+
+#ifdef CONFIG_PPC64
+	if (udbg_write)
+		udbg_write(kdb_buffer, strlen(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, get_cpu());
+			put_cpu();
+			moreprompt = buf2;
+		}
+#endif
+
+		kdb_input_flush();
+		c = console_drivers;
+#ifdef CONFIG_SPARC64
+		if (c == NULL)
+			prom_printf("%s", moreprompt);
+		else
+#endif
+
+#ifdef CONFIG_PPC64
+		if (udbg_write)
+			udbg_write(moreprompt, strlen(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);
+		atomic_dec(&kdb_event);
+	}
+	preempt_enable();
+	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(KERN_ERR "kdb: Initialization failed - no console.  kdb is disabled.\n");
+		KDB_FLAG_SET(NO_CONSOLE);
+		kdb_on = 0;
+	}
+	kdb_input_flush();
+#endif
+	return;
+}
+
+EXPORT_SYMBOL(kdb_read);
Index: 2.6.x-xfs/kdb/kdbmain.c
===================================================================
--- 2.6.x-xfs.orig/kdb/kdbmain.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/kdbmain.c	2006-01-10 17:22:51.393380974 +1100
@@ -0,0 +1,4005 @@
+/*
+ * Kernel Debugger Architecture Independent Main Code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ */
+
+/*
+ * 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/utsname.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/mm.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>
+#include <linux/ptrace.h>
+#include <linux/sysctl.h>
+#if defined(CONFIG_CRASH_DUMP) || defined(CONFIG_CRASH_DUMP_MODULE)
+#include <linux/dump.h>
+#endif
+
+#include <asm/system.h>
+
+/*
+ * Kernel debugger state flags
+ */
+volatile int kdb_flags;
+atomic_t kdb_event;
+
+/*
+ * kdb_lock protects updates to kdb_initial_cpu.  Used to
+ * single thread processors through the kernel debugger.
+ */
+static DEFINE_SPINLOCK(kdb_lock);
+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 */
+
+volatile int kdb_state[NR_CPUS];		/* Per cpu state */
+
+const struct task_struct *kdb_current_task;
+struct pt_regs *kdb_current_regs;
+
+#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;
+#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",
+ "NOSECT=1",
+ (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 *));
+
+/*
+ * kdb_serial_str is the sequence that the user must enter on a 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 would have been able to do it but we lost CML2.
+ * KAO.
+ */
+const char kdb_serial_str[] = "\eKDB";
+EXPORT_SYMBOL(kdb_serial_str);
+
+struct task_struct *
+kdb_curr_task(int cpu)
+{
+	struct task_struct *p = curr_task(cpu);
+#ifdef	_TIF_MCA_INIT
+	struct kdb_running_process *krp = kdb_running_process + cpu;
+	if ((p->thread_info->flags & _TIF_MCA_INIT) && krp->p)
+		p = krp->p;
+#endif
+	return p;
+}
+
+/*
+ * 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 NULL;
+}
+
+/*
+ * 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:
+ */
+
+static 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:
+ */
+
+static 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], kdb_current_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_KDB);
+	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_KDB);
+	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 (defcmd_in_progress) {
+		kdb_printf("kdb: nested defcmd detected, assuming missing endefcmd\n");
+		kdb_defcmd2("endefcmd", "endefcmd");
+	}
+	if (argc == 0) {
+		int i;
+		for (s = defcmd_set; s < defcmd_set + defcmd_set_count; ++s) {
+			kdb_printf("defcmd %s \"%s\" \"%s\"\n", s->name, s->usage, s->help);
+			for (i = 0; i < s->count; ++i)
+				kdb_printf("%s", s->command[i]);
+			kdb_printf("endefcmd\n");
+		}
+		return 0;
+	}
+	if (argc != 3)
+		return KDB_ARGCOUNT;
+	defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set), GFP_KDB);
+	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_KDB);
+	s->usage = kdb_strdup(argv[2], GFP_KDB);
+	s->help = kdb_strdup(argv[3], GFP_KDB);
+	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, do not use argv after this point */
+		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') || (*cp == '#' && !defcmd_in_progress))
+				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_CRASH_DUMP) || defined(CONFIG_CRASH_DUMP_MODULE)
+	notifier_call_chain(&kdb_notifier_list, KDB_EVENT_DUMPING, NULL);
+	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.
+ */
+
+static int
+kdb_reboot(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	notifier_call_chain(&kdb_notifier_list, KDB_EVENT_REBOOTING, NULL);
+	emergency_restart();
+	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;
+	struct task_struct *kdb_current = kdb_curr_task(smp_processor_id());
+
+	/* If kdb has been entered for an event which has been/will be
+	 * recovered then silently return.  We have to get this far into kdb in
+	 * order to synchronize all the cpus, typically only one cpu (monarch)
+	 * knows that the event is recoverable but the other cpus (slaves) may
+	 * also be driven into kdb before that decision is made by the monarch.
+	 *
+	 * To pause in kdb even for recoverable events, 'set RECOVERY_PAUSE 1'
+	 */
+	if (reason == KDB_REASON_ENTER
+	    && KDB_FLAG(RECOVERY)
+	    && !KDB_FLAG(CATASTROPHIC)) {
+		int recovery_pause = 0;
+		kdbgetintenv("RECOVERY_PAUSE", &recovery_pause);
+		if (recovery_pause == 0)
+			reason = KDB_REASON_SILENT;
+		else
+			kdb_printf("%s: Recoverable error detected but"
+				   " RECOVERY_PAUSE is set, staying in KDB\n",
+				   __FUNCTION__);
+	}
+
+	kdb_go_count = 0;
+	if (reason != KDB_REASON_DEBUG &&
+	    reason != KDB_REASON_SILENT) {
+		kdb_printf("\nEntering kdb (current=0x%p, pid %d) ", kdb_current, kdb_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) ", kdb_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:
+		if (KDB_STATE(KEYBOARD))
+			kdb_printf("due to Keyboard Entry\n");
+		else
+			kdb_printf("due to KDB_ENTER()\n");
+		break;
+	case KDB_REASON_KEYBOARD:
+		KDB_STATE_SET(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();
+
+	kdba_set_current_task(kdb_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 (kdbjmpbuf) {
+			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, timeout in %d second(s)\n",
+				kdb_data, online, kdb_wait_for_cpus_secs - time);
+			prev_kdb_data = kdb_data;
+		}
+		touch_nmi_watchdog();
+		mdelay(1000);
+		if (time % 4 == 0)
+			kdb_printf(".");
+	}
+	if (time) {
+		int wait = online - kdb_data;
+		if (wait == 0)
+			kdb_printf("All cpus are now in kdb\n");
+		else
+			kdb_printf("%d cpu%s not in kdb, %s state is unknown\n",
+					wait,
+					wait == 1 ? " is" : "s are",
+					wait == 1 ? "its" : "their");
+	}
+#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.
+ */
+
+asmlinkage 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 = 0;	/* Default is kdb did not handle it */
+	int ss_event;
+	kdb_dbtrap_t db_result=KDB_DB_NOBPT;
+	preempt_disable();
+	atomic_inc(&kdb_event);
+
+	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))
+		goto out;
+
+	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);
+		goto out;	/* 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");
+				/*temp*/
+				while (KDB_IS_RUNNING())
+					cpu_relax();
+				goto out;
+			}
+		}
+	} else if (!KDB_IS_RUNNING()) {
+		kdb_printf("kdb: CPU switch without kdb running, I'm confused\n");
+		goto out;
+	}
+
+	/*
+	 * 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.
+	 *
+	 * The above describes the normal state of affairs, where two or more
+	 * cpus that are entering kdb at the "same" time are assumed to be for
+	 * separate events.  However some processes such as ia64 MCA/INIT will
+	 * drive all the cpus into error processing at the same time.  For that
+	 * case, all of the cpus entering kdb at the "same" time are really a
+	 * single event.
+	 *
+	 * That case is handled by the use of KDB_ENTER by one cpu (the
+	 * monarch) and KDB_ENTER_SLAVE on the other cpus (the slaves).
+	 * KDB_ENTER_SLAVE maps to KDB_REASON_ENTER_SLAVE.  The slave events
+	 * will be treated as if they had just responded to the kdb IPI, i.e.
+	 * as if they were KDB_REASON_SWITCH.
+	 *
+	 * Because of races across multiple cpus, ENTER_SLAVE can occur before
+	 * the main ENTER.   Hold up ENTER_SLAVE here until the main ENTER
+	 * arrives.
+	 */
+
+	if (reason == KDB_REASON_ENTER_SLAVE) {
+		spin_lock(&kdb_lock);
+		while (!KDB_IS_RUNNING()) {
+			spin_unlock(&kdb_lock);
+			while (!KDB_IS_RUNNING())
+				cpu_relax();
+			spin_lock(&kdb_lock);
+		}
+		reason = KDB_REASON_SWITCH;
+		spin_unlock(&kdb_lock);
+	}
+
+	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())
+				cpu_relax();
+			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, KDB_EVENT_ENTERED, 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 (NR_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(reason2, 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, KDB_EVENT_EXITING, 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(KEYBOARD);
+	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);
+out:
+	atomic_dec(&kdb_event);
+	preempt_enable();
+	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:
+ */
+
+static void
+kdb_md_line(const char *fmtstr, kdb_machreg_t addr,
+	    int symbolic, int nosect, int bytesperword,
+	    int num, int repeat, int phys)
+{
+	/* print just one line of data */
+	kdb_symtab_t symtab;
+	char cbuf[32];
+	char *c = cbuf;
+	int i;
+	unsigned long word;
+
+	memset(cbuf, '\0', sizeof(cbuf));
+	if (phys)
+		kdb_printf("phys " kdb_machreg_fmt0 " ", addr);
+	else
+		kdb_printf(kdb_machreg_fmt0 " ", addr);
+
+	for (i = 0; i < num && repeat--; i++) {
+		if (phys) {
+			if (kdb_getphysword(&word, addr, bytesperword))
+				break;
+		} else if (kdb_getword(&word, addr, bytesperword))
+			break;
+		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 {
+			union {
+				u64 word;
+				unsigned char c[8];
+			} wc;
+			unsigned char *cp;
+#ifdef	__BIG_ENDIAN
+			cp = wc.c + 8 - bytesperword;
+#else
+			cp = wc.c;
+#endif
+			wc.word = word;
+#define printable_char(c) ({unsigned char __c = c; isascii(__c) && isprint(__c) ? __c : '.';})
+			switch (bytesperword) {
+			case 8:
+				*c++ = printable_char(*cp++);
+				*c++ = printable_char(*cp++);
+				*c++ = printable_char(*cp++);
+				*c++ = printable_char(*cp++);
+				addr += 4;
+			case 4:
+				*c++ = printable_char(*cp++);
+				*c++ = printable_char(*cp++);
+				addr += 2;
+			case 2:
+				*c++ = printable_char(*cp++);
+				addr++;
+			case 1:
+				*c++ = printable_char(*cp++);
+				addr++;
+				break;
+			}
+#undef printable_char
+		}
+	}
+	kdb_printf("%*s %s\n", (int)((num-i)*(2*bytesperword + 1)+1), " ", cbuf);
+}
+
+static 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;
+	int symbolic = 0;
+	int valid = 0;
+	int phys = 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;
+	else if (strcmp(argv[0], "mdp") == 0) {
+		phys = 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) {
+		unsigned long a;
+		int n, z, num = (symbolic ? 1 : (16 / bytesperword));
+
+		for (a = addr, z = 0; z < repeat; a += bytesperword, ++z) {
+			if (phys) {
+				if (kdb_getphysword(&word, a, bytesperword)
+						|| word)
+					break;
+			} else if (kdb_getword(&word, a, bytesperword) || word)
+				break;
+		}
+		n = min(num, repeat);
+		kdb_md_line(fmtstr, addr, symbolic, nosect, bytesperword, num, repeat, phys);
+		addr += bytesperword * n;
+		repeat -= n;
+		z = (z + num - 1) / num;
+		if (z > 2) {
+			int s = num * (z-2);
+			kdb_printf(kdb_machreg_fmt0 "-" kdb_machreg_fmt0 " zero suppressed\n",
+				addr, addr + bytesperword * s - 1);
+			addr += bytesperword * s;
+			repeat -= s;
+		}
+	}
+	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.
+ */
+
+static 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:
+ */
+
+static 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);
+		/* Recursive use of kdb_parse, do not use argv after this point */
+		argv = NULL;
+		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:
+ */
+
+static int
+kdb_rd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	if (argc == 0) {
+		return kdba_dumpregs(kdb_current_regs, NULL, NULL);
+	}
+
+	if (argc > 2) {
+		return KDB_ARGCOUNT;
+	}
+
+	return kdba_dumpregs(kdb_current_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).
+ */
+
+static 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], kdb_current_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.
+ */
+static 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);
+
+	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.
+ */
+
+static 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 list_head *kdb_modules;
+extern void free_module(struct module *);
+
+/* modules using other modules */
+struct module_use
+{
+	struct list_head list;
+	struct module *module_which_uses;
+};
+
+/*
+ * 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:
+ *
+ */
+
+static int
+kdb_lsmod(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct module *mod;
+
+	if (argc != 0)
+		return KDB_ARGCOUNT;
+
+	kdb_printf("Module                  Size  modstruct     Used by\n");
+	list_for_each_entry(mod, kdb_modules, list) {
+
+		kdb_printf("%-20s%8lu  0x%p ", mod->name,
+			   mod->core_size, (void *)mod);
+#ifdef CONFIG_MODULE_UNLOAD
+		kdb_printf("%4d ", module_refcount(mod));
+#endif
+		if (mod->state == MODULE_STATE_GOING)
+			kdb_printf(" (Unloading)");
+		else if (mod->state == MODULE_STATE_COMING)
+			kdb_printf(" (Loading)");
+		else
+			kdb_printf(" (Live)");
+
+#ifdef CONFIG_MODULE_UNLOAD
+		{
+			struct module_use *use;
+			kdb_printf(" [ ");
+			list_for_each_entry(use, &mod->modules_which_use_me, list)
+				kdb_printf("%s ", use->module_which_uses->name);
+			kdb_printf("]\n");
+		}
+#endif
+	}
+
+	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:
+ */
+
+static 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] [adjust]
+ *
+ * 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.
+ */
+
+static int
+kdb_dmesg(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	char *syslog_data[4], *start, *end, c = '\0', *p;
+	int diag, logging, logsize, lines = 0, adjust = 0, n;
+
+	if (argc > 2)
+		return KDB_ARGCOUNT;
+	if (argc) {
+		char *cp;
+		lines = simple_strtol(argv[1], &cp, 0);
+		if (*cp)
+			lines = 0;
+		if (argc > 1) {
+			adjust = simple_strtoul(argv[2], &cp, 0);
+			if (*cp || adjust < 0)
+				adjust = 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[2];
+	end = syslog_data[3];
+#define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0])
+	for (n = 0, p = start; p < end; ++p) {
+		if ((c = *KDB_WRAP(p)) == '\n')
+			++n;
+	}
+	if (c != '\n')
+		++n;
+	if (lines < 0) {
+		if (adjust >= n)
+			kdb_printf("buffer only contains %d lines, nothing printed\n", n);
+		else if (adjust - lines >= n)
+			kdb_printf("buffer only contains %d lines, last %d lines printed\n",
+				n, n - adjust);
+		if (adjust) {
+			for (; start < end && adjust; ++start) {
+				if (*KDB_WRAP(start) == '\n')
+					--adjust;
+			}
+			if (start < end)
+				++start;
+		}
+		for (p = start; p < end && lines; ++p) {
+			if (*KDB_WRAP(p) == '\n')
+				++lines;
+		}
+		end = p;
+	} else if (lines > 0) {
+		int skip = n - (adjust + lines);
+		if (adjust >= n) {
+			kdb_printf("buffer only contains %d lines, nothing printed\n", n);
+			skip = n;
+		} else if (skip < 0) {
+			lines += skip;
+			skip = 0;
+			kdb_printf("buffer only contains %d lines, first %d lines printed\n",
+				n, lines);
+		}
+		for (; start < end && skip; ++start) {
+			if (*KDB_WRAP(start) == '\n')
+				--skip;
+		}
+		for (p = start; p < end && lines; ++p) {
+			if (*KDB_WRAP(p) == '\n')
+				--lines;
+		}
+		end = p;
+	}
+	/* Do a line at a time (max 200 chars) to reduce protocol overhead */
+	c = '\n';
+	while (start != end) {
+		char buf[201], *p = buf;
+		while (start < end && (c = *KDB_WRAP(start)) && (p - buf) < sizeof(buf)-1) {
+			++start;
+			*p++ = c;
+			if (c == '\n')
+				break;
+		}
+		*p = '\0';
+		kdb_printf("%s", buf);
+	}
+	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.
+ */
+
+static void
+kdb_cpu_status(void)
+{
+	int i, start_cpu, first_print = 1;
+	char state, prev_state = '?';
+
+	kdb_printf("Currently on cpu %d\n", smp_processor_id());
+	kdb_printf("Available cpus: ");
+	for (start_cpu = -1, i = 0; i < NR_CPUS; i++) {
+		if (!cpu_online(i))
+			state = 'F';	/* cpu is offline */
+		else {
+			struct kdb_running_process *krp = kdb_running_process+i;
+			if (KDB_STATE_CPU(KDB, i)) {
+				state = ' ';	/* cpu is responding to kdb */
+				if (kdb_task_state_char(krp->p) == 'I')
+					state = 'I';	/* running the idle task */
+			} else if (krp->seqno && krp->p && krp->seqno >= kdb_seqno - 1)
+				state = '+';	/* some kdb data, but not responding */
+			else
+				state = '*';	/* no kdb data */
+		}
+		if (state != prev_state) {
+			if (prev_state != '?') {
+				if (!first_print)
+					kdb_printf(", ");
+				first_print = 0;
+				kdb_printf("%d", start_cpu);
+				if (start_cpu < i-1)
+					kdb_printf("-%d", i-1);
+				if (prev_state != ' ')
+					kdb_printf("(%c)", prev_state);
+			}
+			prev_state = state;
+			start_cpu = i;
+		}
+	}
+	/* print the trailing cpus, ignoring them if they are all offline */
+	if (prev_state != 'F') {
+		if (!first_print)
+			kdb_printf(", ");
+		kdb_printf("%d", start_cpu);
+		if (start_cpu < i-1)
+			kdb_printf("-%d", i-1);
+		if (prev_state != ' ')
+			kdb_printf("(%c)", prev_state);
+	}
+	kdb_printf("\n");
+}
+
+static int
+kdb_cpu(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	unsigned long cpunum;
+	int diag, 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) {
+		kdb_cpu_status();
+		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;
+}
+
+/* The user may not realize that ps/bta with no parameters does not print idle
+ * or sleeping system daemon processes, so tell them how many were suppressed.
+ */
+void
+kdb_ps_suppressed(void)
+{
+	int idle = 0, daemon = 0;
+	unsigned long mask_I = kdb_task_state_string("I"),
+		      mask_M = kdb_task_state_string("M");
+	unsigned long cpu;
+	const struct task_struct *p, *g;
+	for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_online(cpu))
+			continue;
+		p = kdb_curr_task(cpu);
+		if (kdb_task_state(p, mask_I))
+			++idle;
+	}
+	kdb_do_each_thread(g, p) {
+		if (kdb_task_state(p, mask_M))
+			++daemon;
+	} kdb_while_each_thread(g, p);
+	if (idle || daemon) {
+		if (idle)
+			kdb_printf("%d idle process%s (state I)%s",
+				   idle, idle == 1 ? "" : "es",
+				   daemon ? " and " : "");
+		if (daemon)
+			kdb_printf("%d sleeping system daemon (state M) process%s",
+				   daemon, daemon == 1 ? "" : "es");
+		kdb_printf(" suppressed\n");
+	}
+}
+
+/*
+ * kdb_ps
+ *
+ *	This function implements the 'ps' command which shows
+ *	a list of the active processes.
+ *
+ *	ps [DRSTCZEUIMA]		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(const struct task_struct *p)
+{
+	struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+	kdb_printf("0x%p %8d %8d  %d %4d   %c  0x%p %c%s\n",
+		   (void *)p, p->pid, p->parent->pid,
+		   kdb_task_has_cpu(p), kdb_process_cpu(p),
+		   kdb_task_state_char(p),
+		   (void *)(&p->thread),
+		   p == kdb_curr_task(smp_processor_id()) ? '*': ' ',
+		   p->comm);
+	if (kdb_task_has_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);
+		}
+	}
+}
+
+static int
+kdb_ps(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct task_struct *g, *p;
+	unsigned long mask, cpu;
+
+	if (argc == 0)
+		kdb_ps_suppressed();
+	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[1] : NULL);
+	/* Run the active tasks first */
+	for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_online(cpu))
+			continue;
+		p = kdb_curr_task(cpu);
+		if (kdb_task_state(p, mask))
+			kdb_ps1(p);
+	}
+	kdb_printf("\n");
+	/* Now the real tasks */
+	kdb_do_each_thread(g, p) {
+		if (kdb_task_state(p, mask))
+			kdb_ps1(p);
+	} kdb_while_each_thread(g, 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:
+ */
+
+
+static 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;
+		}
+
+		kdba_set_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:
+ */
+
+static 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;
+	const char *command;
+
+	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;
+	if (!(command = kdb_strdup(argv[3], GFP_KDB))) {
+		kdb_printf("%s: cannot duplicate command\n", __FUNCTION__);
+		return 0;
+	}
+	/* Recursive use of kdb_parse, do not use argv after this point */
+	argv = NULL;
+
+	while (va) {
+		char buf[80];
+
+		sprintf(buf, "%s " kdb_machreg_fmt "\n", command, va);
+		diag = kdb_parse(buf, regs);
+		if (diag)
+			return diag;
+
+		addr = va + linkoffset;
+		if (kdb_getword(&va, addr, sizeof(va)))
+			return 0;
+	}
+	kfree(command);
+
+	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:
+ */
+
+static 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:
+ */
+
+static int
+kdb_kill(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	long sig, pid;
+	char *endp;
+	struct task_struct *p;
+	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. */
+	if (!(p = find_task_by_pid(pid))) {
+		kdb_printf("The specified process isn't found.\n");
+		return 0;
+	}
+	p = p->group_leader;
+	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 */
+	kdb_send_sig_info(p, &info, kdb_seqno);
+	return 0;
+}
+
+struct kdb_tm {
+	int tm_sec;	/* seconds */
+	int tm_min;	/* minutes */
+	int tm_hour;	/* hours */
+	int tm_mday;	/* day of the month */
+	int tm_mon;	/* month */
+	int tm_year;	/* year */
+};
+
+static void
+kdb_gmtime(struct timespec *tv, struct kdb_tm *tm)
+{
+	/* This will work from 1970-2099, 2100 is not a leap year */
+	static int mon_day[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+	memset(tm, 0, sizeof(*tm));
+	tm->tm_sec  = tv->tv_sec % (24 * 60 * 60);
+	tm->tm_mday = tv->tv_sec / (24 * 60 * 60) + (2 * 365 + 1); /* shift base from 1970 to 1968 */
+	tm->tm_min =  tm->tm_sec / 60 % 60;
+	tm->tm_hour = tm->tm_sec / 60 / 60;
+	tm->tm_sec =  tm->tm_sec % 60;
+	tm->tm_year = 68 + 4*(tm->tm_mday / (4*365+1));
+	tm->tm_mday %= (4*365+1);
+	mon_day[1] = 29;
+	while (tm->tm_mday >= mon_day[tm->tm_mon]) {
+		tm->tm_mday -= mon_day[tm->tm_mon];
+		if (++tm->tm_mon == 12) {
+			tm->tm_mon = 0;
+			++tm->tm_year;
+			mon_day[1] = 28;
+		}
+	}
+	++tm->tm_mday;
+}
+
+/*
+ * Most of this code has been lifted from kernel/timer.c::sys_sysinfo().
+ * I cannot call that code directly from kdb, it has an unconditional
+ * cli()/sti() and calls routines that take locks which can stop the debugger.
+ */
+
+static void
+kdb_sysinfo(struct sysinfo *val)
+{
+	struct timespec uptime;
+	do_posix_clock_monotonic_gettime(&uptime);
+	memset(val, 0, sizeof(*val));
+	val->uptime = uptime.tv_sec;
+	val->loads[0] = avenrun[0];
+	val->loads[1] = avenrun[1];
+	val->loads[2] = avenrun[2];
+	val->procs = nr_threads-1;
+	si_meminfo(val);
+	kdb_si_swapinfo(val);
+
+	return;
+}
+
+/*
+ * kdb_summary
+ *
+ *	This function implements the 'summary' command.
+ *
+ * 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_summary(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	extern struct timespec xtime;
+	extern struct timezone sys_tz;
+	struct kdb_tm tm;
+	struct sysinfo val;
+
+	if (argc)
+		return KDB_ARGCOUNT;
+
+	kdb_printf("sysname    %s\n", system_utsname.sysname);
+	kdb_printf("release    %s\n", system_utsname.release);
+	kdb_printf("version    %s\n", system_utsname.version);
+	kdb_printf("machine    %s\n", system_utsname.machine);
+	kdb_printf("nodename   %s\n", system_utsname.nodename);
+	kdb_printf("domainname %s\n", system_utsname.domainname);
+
+	kdb_gmtime(&xtime, &tm);
+	kdb_printf("date       %04d-%02d-%02d %02d:%02d:%02d tz_minuteswest %d\n",
+		1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
+		tm.tm_hour, tm.tm_min, tm.tm_sec,
+		sys_tz.tz_minuteswest);
+
+	kdb_sysinfo(&val);
+	kdb_printf("uptime     ");
+	if (val.uptime > (24*60*60)) {
+		int days = val.uptime / (24*60*60);
+		val.uptime %= (24*60*60);
+		kdb_printf("%d day%s ", days, days == 1 ? "" : "s");
+	}
+	kdb_printf("%02ld:%02ld\n", val.uptime/(60*60), (val.uptime/60)%60);
+
+	/* lifted from fs/proc/proc_misc.c::loadavg_read_proc() */
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+	kdb_printf("load avg   %ld.%02ld %ld.%02ld %ld.%02ld\n",
+		LOAD_INT(val.loads[0]), LOAD_FRAC(val.loads[0]),
+		LOAD_INT(val.loads[1]), LOAD_FRAC(val.loads[1]),
+		LOAD_INT(val.loads[2]), LOAD_FRAC(val.loads[2]));
+	kdb_printf("\n");
+#undef LOAD_INT
+#undef LOAD_FRAC
+
+	kdb_meminfo_read_proc();	/* in fs/proc/proc_misc.c */
+
+	return 0;
+}
+
+/*
+ * kdb_per_cpu
+ *
+ *	This function implements the 'per_cpu' command.
+ *
+ * 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_per_cpu(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	char buf[256], fmtstr[64];
+	kdb_symtab_t symtab;
+	cpumask_t suppress = CPU_MASK_NONE;
+	int cpu, diag;
+	unsigned long addr, val, bytesperword = 0, whichcpu = ~0UL;
+
+	if (argc < 1 || argc > 3)
+		return KDB_ARGCOUNT;
+
+	snprintf(buf, sizeof(buf), "per_cpu__%s", argv[1]);
+	if (!kdbgetsymval(buf, &symtab)) {
+		kdb_printf("%s is not a per_cpu variable\n", argv[1]);
+		return KDB_BADADDR;
+	}
+	if (argc >=2 && (diag = kdbgetularg(argv[2], &bytesperword)))
+		return diag;
+	if (!bytesperword)
+		bytesperword = sizeof(kdb_machreg_t);
+	else if (bytesperword > sizeof(kdb_machreg_t))
+		return KDB_BADWIDTH;
+	sprintf(fmtstr, "%%0%dlx ", (int)(2*bytesperword));
+	if (argc >= 3) {
+		if ((diag = kdbgetularg(argv[3], &whichcpu)))
+			return diag;
+		if (!cpu_online(whichcpu)) {
+			kdb_printf("cpu %ld is not online\n", whichcpu);
+			return KDB_BADCPUNUM;
+		}
+	}
+
+	/* Most architectures use __per_cpu_offset[cpu], some use
+	 * __per_cpu_offset(cpu), smp has no __per_cpu_offset.
+	 */
+#ifdef	__per_cpu_offset
+#define KDB_PCU(cpu) __per_cpu_offset(cpu)
+#else
+#ifdef	CONFIG_SMP
+#define KDB_PCU(cpu) __per_cpu_offset[cpu]
+#else
+#define KDB_PCU(cpu) 0
+#endif
+#endif
+
+	for_each_online_cpu(cpu) {
+		if (whichcpu != ~0UL && whichcpu != cpu)
+			continue;
+		addr = symtab.sym_start + KDB_PCU(cpu);
+		if ((diag = kdb_getword(&val, addr, bytesperword))) {
+			kdb_printf("%5d " kdb_bfd_vma_fmt0 " - unable to read, diag=%d\n",
+				cpu, addr, diag);
+			continue;
+		}
+#ifdef	CONFIG_SMP
+		if (!val) {
+			cpu_set(cpu, suppress);
+			continue;
+		}
+#endif	/* CONFIG_SMP */
+		kdb_printf("%5d ", cpu);
+		kdb_md_line(fmtstr, addr,
+			bytesperword == sizeof(kdb_machreg_t),
+			1, bytesperword, 1, 1, 0);
+	}
+	if (cpus_weight(suppress) == 0)
+		return 0;
+	kdb_printf("Zero suppressed cpu(s):");
+	for (cpu = first_cpu(suppress); cpu < NR_CPUS; cpu = next_cpu(cpu, suppress)) {
+		kdb_printf(" %d", cpu);
+		if (cpu == NR_CPUS-1 || next_cpu(cpu, suppress) != cpu + 1)
+			continue;
+		while (cpu < NR_CPUS && next_cpu(cpu, suppress) == cpu + 1)
+			++cpu;
+		kdb_printf("-%d", cpu);
+	}
+	kdb_printf("\n");
+
+#undef KDB_PCU
+
+	return 0;
+}
+
+
+/*
+ * 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_KDB);
+		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("mdp", kdb_md, "<paddr> <bytes>", 	"Display Physical 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, "[DRSTCZEUIMA]", 	"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);
+#if defined(CONFIG_MODULES)
+	kdb_register_repeat("lsmod", kdb_lsmod, "",	"List loaded kernel modules", 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);
+	kdb_register_repeat("summary", kdb_summary, "", "Summarize the system", 4, KDB_REPEAT_NONE);
+	kdb_register_repeat("per_cpu", kdb_per_cpu, "", "Display per_cpu variables", 3, 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) {
+		if (!defcmd_in_progress)
+			kdb_printf("kdb_cmd[%d]: %s", i, 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 };
+
+#ifdef	CONFIG_SYSCTL
+static int proc_do_kdb(ctl_table *table, int write, struct file *filp,
+		       void *buffer, size_t *lenp, loff_t *ppos)
+{
+	if (KDB_FLAG(NO_CONSOLE) && write) {
+		printk(KERN_ERR "kdb has no working console and has switched itself off\n");
+		return -EINVAL;
+	}
+	return proc_dointvec(table, write, filp, buffer, lenp, ppos);
+}
+
+static ctl_table kdb_kern_table[] = {
+	{
+		.ctl_name	= KERN_KDB,
+		.procname	= "kdb",
+		.data		= &kdb_on,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_do_kdb,
+	},
+	{}
+};
+
+static ctl_table kdb_root_table[] = {
+	{
+		.ctl_name	= CTL_KERN,
+		.procname	= "kernel",
+		.mode		= 0555,
+		.child		= kdb_kern_table,
+	},
+	{}
+};
+#endif	/* CONFIG_SYSCTL */
+
+/*
+ * kdb_init
+ *
+ * 	Initialize the kernel debugger environment.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	None.
+ */
+
+void __init
+kdb_init(void)
+{
+	kdb_initial_cpu = smp_processor_id();
+	/*
+	 * 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 */
+	kdb_initsupport();	/* Initialize support routines */
+	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_initial_cpu = -1;	/* Avoid recursion problems */
+	kdb(KDB_REASON_SILENT, 0, 0);	/* Activate any preset breakpoints on boot cpu */
+	kdb_initial_cpu = smp_processor_id();
+	notifier_chain_register(&panic_notifier_list, &kdb_block);
+
+#ifdef KDB_HAVE_LONGJMP
+	kdbjmpbuf = vmalloc(NR_CPUS * sizeof(*kdbjmpbuf));
+	if (!kdbjmpbuf)
+		printk(KERN_ERR "Cannot allocate kdbjmpbuf, no kdb recovery will be possible\n");
+#endif	/* KDB_HAVE_LONGJMP */
+
+	kdb_initial_cpu = -1;
+}
+
+#ifdef	CONFIG_SYSCTL
+static int __init
+kdb_late_init(void)
+{
+	register_sysctl_table(kdb_root_table, 0);
+	return 0;
+}
+
+__initcall(kdb_late_init);
+#endif
+
+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(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(kdbnearsym);
+EXPORT_SYMBOL(kdb_printf);
+EXPORT_SYMBOL(kdb_symbol_print);
+EXPORT_SYMBOL(kdb_notifier_list);
+EXPORT_SYMBOL(kdb_running_process);
Index: 2.6.x-xfs/kdb/kdbsupport.c
===================================================================
--- 2.6.x-xfs.orig/kdb/kdbsupport.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/kdbsupport.c	2006-01-10 17:22:51.397286685 +1100
@@ -0,0 +1,1285 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * 03/02/13    added new 2.5 kallsyms <xavier.bru@bull.net>
+ */
+
+#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/ptrace.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/hardirq.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+#ifdef CONFIG_MODULES
+extern struct list_head *kdb_modules;
+#endif
+
+/*
+ * 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)
+{
+	if (KDB_DEBUG(AR))
+		kdb_printf("kdbgetsymval: symname=%s, symtab=%p\n", symname, symtab);
+	memset(symtab, 0, sizeof(*symtab));
+
+	if ((symtab->sym_start = kallsyms_lookup_name(symname))) {
+		if (KDB_DEBUG(AR))
+			kdb_printf("kdbgetsymval: returns 1, symtab->sym_start=0x%lx\n", symtab->sym_start);
+		return 1;
+	}
+	if (KDB_DEBUG(AR))
+		kdb_printf("kdbgetsymval: returns 0\n");
+	return 0;
+}
+
+/*
+ * 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:
+ *	2.6 kallsyms has a "feature" where it unpacks the name into a string.
+ *	If that string is reused before the caller expects it then the caller
+ *	sees its string change without warning.  To avoid cluttering up the
+ *	main kdb code with lots of kdb_strdup, tests and kfree calls, kdbnearsym
+ *	maintains an LRU list of the last few unique strings.  The list is sized
+ *	large enough to hold active strings, no kdb caller of kdbnearsym makes
+ *	more than ~20 later calls before using a saved value.
+ */
+
+int
+kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
+{
+	int ret = 0;
+	unsigned long symbolsize;
+	unsigned long offset;
+	static char *knt[100];	/* kdb name table, arbitrary size */
+#define knt1_size 128		/* must be >= kallsyms table size */
+	char *knt1 = NULL;
+
+	if (KDB_DEBUG(AR))
+		kdb_printf("kdbnearsym: addr=0x%lx, symtab=%p\n", addr, symtab);
+	memset(symtab, 0, sizeof(*symtab));
+
+	if (addr < 4096)
+		goto out;
+	knt1 = debug_kmalloc(knt1_size, GFP_ATOMIC);
+	if (!knt1) {
+		kdb_printf("kdbnearsym: addr=0x%lx cannot kmalloc knt1\n", addr);
+		goto out;
+	}
+	symtab->sym_name = kallsyms_lookup(addr, &symbolsize , &offset, (char **)(&symtab->mod_name), knt1);
+	if (offset > 8*1024*1024) {
+		symtab->sym_name = NULL;
+		addr = offset = symbolsize = 0;
+	}
+	symtab->sym_start = addr - offset;
+	symtab->sym_end = symtab->sym_start + symbolsize;
+	ret = symtab->sym_name != NULL && *(symtab->sym_name) != '\0';
+
+	if (ret) {
+		int i;
+		/* Another 2.6 kallsyms "feature".  Sometimes the sym_name is
+		 * set but the buffer passed into kallsyms_lookup is not used,
+		 * so it contains garbage.  The caller has to work out which
+		 * buffer needs to be saved.
+		 *
+		 * What was Rusty smoking when he wrote that code?
+		 */
+		if (symtab->sym_name != knt1) {
+			strncpy(knt1, symtab->sym_name, knt1_size);
+			knt1[knt1_size-1] = '\0';
+		}
+		for (i = 0; i < ARRAY_SIZE(knt); ++i) {
+			if (knt[i] && strcmp(knt[i], knt1) == 0)
+				break;
+		}
+		if (i >= ARRAY_SIZE(knt)) {
+			debug_kfree(knt[0]);
+			memcpy(knt, knt+1, sizeof(knt[0])*(ARRAY_SIZE(knt)-1));
+		} else {
+			debug_kfree(knt1);
+			knt1 = knt[i];
+			memcpy(knt+i, knt+i+1, sizeof(knt[0])*(ARRAY_SIZE(knt)-i-1));
+		}
+		i = ARRAY_SIZE(knt) - 1;
+		knt[i] = knt1;
+		symtab->sym_name = knt[i];
+		knt1 = NULL;
+	}
+
+	if (symtab->mod_name == NULL)
+		symtab->mod_name = "kernel";
+	if (KDB_DEBUG(AR))
+		kdb_printf("kdbnearsym: returns %d symtab->sym_start=0x%lx, symtab->mod_name=%p, symtab->sym_name=%p (%s)\n", ret, symtab->sym_start, symtab->mod_name, symtab->sym_name, symtab->sym_name);
+
+out:
+	debug_kfree(knt1);
+	return ret;
+}
+
+/*
+ * kallsyms_symbol_complete
+ *
+ * Parameters:
+ *	prefix_name	prefix of a symbol name to lookup
+ *	max_len		maximum length that can be returned
+ * Returns:
+ *	Number of symbols which match the given prefix.
+ * Notes:
+ *	prefix_name is changed to contain the longest unique prefix that
+ *	starts with this prefix (tab completion).
+ */
+
+static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1];
+
+int kallsyms_symbol_complete(char *prefix_name, int max_len)
+{
+	loff_t pos = 0;
+	int prefix_len = strlen(prefix_name), prev_len = 0;
+	int i, number = 0;
+	const char *name;
+
+	while ((name = kdb_walk_kallsyms(&pos))) {
+		if (strncmp(name, prefix_name, prefix_len) == 0) {
+			strcpy(ks_namebuf, name);
+			/* Work out the longest name that matches the prefix */
+			if (++number == 1) {
+				prev_len = min_t(int, max_len-1, strlen(ks_namebuf));
+				memcpy(ks_namebuf_prev, ks_namebuf, prev_len);
+				ks_namebuf_prev[prev_len] = '\0';
+			} else for (i = 0; i < prev_len; ++i) {
+				if (ks_namebuf[i] != ks_namebuf_prev[i]) {
+					prev_len = i;
+					ks_namebuf_prev[i] = '\0';
+					break;
+				}
+			}
+		}
+	}
+ 	if (prev_len > prefix_len)
+		memcpy(prefix_name, ks_namebuf_prev, prev_len+1);
+	return number;
+}
+
+/*
+ * kallsyms_symbol_next
+ *
+ * Parameters:
+ *	prefix_name	prefix of a symbol name to lookup
+ *	flag	0 means search from the head, 1 means continue search.
+ * Returns:
+ *	1 if a symbol matches the given prefix.
+ *	0 if no string found
+ */
+
+int kallsyms_symbol_next(char *prefix_name, int flag)
+{
+	int prefix_len = strlen(prefix_name);
+	static loff_t pos;
+	const char *name;
+
+	if (!flag)
+		pos = 0;
+
+	while ((name = kdb_walk_kallsyms(&pos))) {
+		if (strncmp(name, prefix_name, prefix_len) == 0) {
+			strncpy(prefix_name, name, strlen(name)+1);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+#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 */
+
+#if	defined(__i386__) || defined(__x86_64__)
+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 - sizeof (ar->args));
+				if (KDB_DEBUG(AR)) {
+					kdb_printf("  callee arg0=0x%lx args=%ld\n",
+						ar->arg0, ar->args);
+				}
+			}
+		}
+	}
+
+	return(1);
+}
+#endif	/* defined(__i386__) || defined(__x86_64__) */
+
+/*
+ * 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_getphys
+ *
+ * Read data from a physical address. Validate the address is in range,
+ * use kmap_atomic() to get data
+ *
+ * Similar to kdb_getarea() - but for phys addresses
+ *
+ * Inputs:
+ * 	res	Pointer to the word to receive the result
+ * 	addr	Physical address of the area to copy
+ * 	size	Size of the area
+ * Outputs:
+ * 	none.
+ * Returns:
+ *	0 for success, < 0 for error.
+ * Locking:
+ * 	none.
+ */
+static int kdb_getphys(void *res, unsigned long addr, size_t size)
+{
+	unsigned long pfn;
+	void *vaddr;
+	struct page *page;
+
+	pfn = (addr >> PAGE_SHIFT);
+	if (!pfn_valid(pfn))
+		return 1;
+	page = pfn_to_page(pfn);
+	vaddr = kmap_atomic(page, KM_KDB);
+	memcpy(res, vaddr + (addr & (PAGE_SIZE -1)), size);
+	kunmap_atomic(vaddr, KM_KDB);
+
+	return 0;
+}
+
+/*
+ * kdb_getphysword
+ *
+ * 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_getphysword(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_getphys(&w1, addr, sizeof(w1))))
+			*word = w1;
+		break;
+	case 2:
+		if (!(diag = kdb_getphys(&w2, addr, sizeof(w2))))
+			*word = w2;
+		break;
+	case 4:
+		if (!(diag = kdb_getphys(&w4, addr, sizeof(w4))))
+			*word = w4;
+		break;
+	case 8:
+		if (size <= sizeof(*word)) {
+			if (!(diag = kdb_getphys(&w8, addr, sizeof(w8))))
+				*word = w8;
+			break;
+		}
+		/* drop through */
+	default:
+		diag = KDB_BADWIDTH;
+		kdb_printf("kdb_getphysword: bad width %ld\n", (long) size);
+	}
+	return(diag);
+}
+
+/*
+ * 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 DRSTCZEUIMA to a mask
+ *	for the process state field and return the value.  If no argument is
+ *	supplied, return the mask that corresponds to environment variable PS,
+ *	DRSTCZEU by default.
+ * Inputs:
+ *	s	String to convert
+ * Outputs:
+ *	none.
+ * Returns:
+ *	Mask for process state.
+ * Locking:
+ *	none.
+ * Notes:
+ *	The mask folds data from several sources into a single long value, so
+ *	be carefull not to overlap the bits.  TASK_* bits are in the LSB,
+ *	special cases like UNRUNNABLE are in the MSB.  As of 2.6.10-rc1 there
+ *	is no overlap between TASK_* and EXIT_* but that may not always be
+ *	true, so EXIT_* bits are shifted left 16 bits before being stored in
+ *	the mask.
+ */
+
+#define UNRUNNABLE	(1UL << (8*sizeof(unsigned long) - 1))	/* unrunnable is < 0 */
+#define RUNNING		(1UL << (8*sizeof(unsigned long) - 2))
+#define IDLE		(1UL << (8*sizeof(unsigned long) - 3))
+#define DAEMON		(1UL << (8*sizeof(unsigned long) - 4))
+
+unsigned long
+kdb_task_state_string(const char *s)
+{
+	long res = 0;
+	if (!s && !(s = kdbgetenv("PS"))) {
+		s = "DRSTCZEU";	/* default value for ps */
+	}
+	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; break;
+		case 'C': res |= TASK_TRACED; break;
+		case 'Z': res |= EXIT_ZOMBIE << 16; break;
+		case 'E': res |= EXIT_DEAD << 16; break;
+		case 'U': res |= UNRUNNABLE; break;
+		case 'I': res |= IDLE; break;
+		case 'M': res |= DAEMON; break;
+		case 'A': res = ~0UL; break;
+		default:
+			  kdb_printf("%s: unknown flag '%c' ignored\n", __FUNCTION__, *s);
+			  break;
+		}
+		++s;
+	}
+	return res;
+}
+
+/*
+ * kdb_task_state_char
+ *
+ *	Return the character that represents the task state.
+ * Inputs:
+ *	p	struct task for the process
+ * Outputs:
+ *	none.
+ * Returns:
+ *	One character to represent the task state.
+ * Locking:
+ *	none.
+ */
+
+char
+kdb_task_state_char (const struct task_struct *p)
+{
+	int cpu = kdb_process_cpu(p);
+	struct kdb_running_process *krp = kdb_running_process + cpu;
+	char state = (p->state == 0) ? 'R' :
+		     (p->state < 0) ? 'U' :
+		     (p->state & TASK_UNINTERRUPTIBLE) ? 'D' :
+		     (p->state & TASK_STOPPED) ? 'T' :
+		     (p->state & TASK_TRACED) ? 'C' :
+		     (p->exit_state & EXIT_ZOMBIE) ? 'Z' :
+		     (p->exit_state & EXIT_DEAD) ? 'E' :
+		     (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
+	if (p->pid == 0) {
+		/* Idle task.  Is it really idle, apart from the kdb interrupt? */
+		if (!kdb_task_has_cpu(p) || krp->irq_depth == 1) {
+			/* There is a corner case when the idle task takes an
+			 * interrupt and dies in the interrupt code.  It has an
+			 * interrupt count of 1 but that did not come from kdb.
+			 * This corner case can only occur on the initial cpu,
+			 * all the others were entered via the kdb IPI.
+			 */
+			if (cpu != kdb_initial_cpu || KDB_STATE_CPU(KEYBOARD, cpu))
+				state = 'I';	/* idle task */
+		}
+	}
+	else if (!p->mm && state == 'S') {
+		state = 'M';	/* sleeping system daemon */
+	}
+	return state;
+}
+
+/*
+ * 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)
+{
+	char state[] = { kdb_task_state_char(p), '\0' };
+	return (mask & kdb_task_state_string(state)) != 0;
+}
+
+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;
+	krp->irq_depth = hardirq_count() >> HARDIRQ_SHIFT;
+	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(const 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. */
+	if ((start & PAGE_MASK) != ((start+len) & PAGE_MASK))
+		return NULL;
+
+	/* we need to align start address to the current page boundy, PAGE_ALIGN
+	 * aligns to next page boundry.
+	 * FIXME: What about hugetlb?
+	 */
+	start = start & PAGE_MASK;
+	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 follow_page(vma, start, write ? FOLL_WRITE : 0);
+}
+
+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;
+}
+
+/* Last ditch allocator for debugging, so we can still debug even when the
+ * GFP_ATOMIC pool has been exhausted.  The algorithms are tuned for space
+ * usage, not for speed.  One smallish memory pool, the free chain is always in
+ * ascending address order to allow coalescing, allocations are done in brute
+ * force best fit.
+ */
+
+struct debug_alloc_header {
+	u32 next;	/* offset of next header from start of pool */
+	u32 size;
+};
+#define dah_align 8
+
+static u64 debug_alloc_pool_aligned[64*1024/dah_align];	/* 64K pool */
+static char *debug_alloc_pool = (char *)debug_alloc_pool_aligned;
+static u32 dah_first;
+
+/* Locking is awkward.  The debug code is called from all contexts, including
+ * non maskable interrupts.  A normal spinlock is not safe in NMI context.  Try
+ * to get the debug allocator lock, if it cannot be obtained after a second
+ * then give up.  If the lock could not be previously obtained on this cpu then
+ * only try once.
+ */
+static DEFINE_SPINLOCK(dap_lock);
+static
+int get_dap_lock(void)
+{
+	static int dap_locked = -1;
+	int count;
+	if (dap_locked == smp_processor_id())
+		count = 1;
+	else
+		count = 1000;
+	while (1) {
+		if (spin_trylock(&dap_lock)) {
+			dap_locked = -1;
+			return 1;
+		}
+		if (!count--)
+			break;
+		udelay(1000);
+	}
+	dap_locked = smp_processor_id();
+	return 0;
+}
+
+void *debug_kmalloc(size_t size, int flags)
+{
+	unsigned int rem, h_offset;
+	struct debug_alloc_header *best, *bestprev, *prev, *h;
+	void *p = NULL;
+	if ((p = kmalloc(size, flags)))
+		return p;
+	if (!get_dap_lock())
+		return NULL;
+	h = (struct debug_alloc_header *)(debug_alloc_pool + dah_first);
+	prev = best = bestprev = NULL;
+	while (1) {
+		if (h->size >= size && (!best || h->size < best->size)) {
+			best = h;
+			bestprev = prev;
+		}
+		if (!h->next)
+			break;
+		prev = h;
+		h = (struct debug_alloc_header *)(debug_alloc_pool + h->next);
+	}
+	if (!best)
+		goto out;
+	rem = (best->size - size) & -dah_align;
+	/* The pool must always contain at least one header */
+	if (best->next == 0 && bestprev == NULL && rem < sizeof(*h))
+		goto out;
+	if (rem >= sizeof(*h)) {
+		best->size = (size + dah_align - 1) & -dah_align;
+		h_offset = (char *)best - debug_alloc_pool + sizeof(*best) + best->size;
+		h = (struct debug_alloc_header *)(debug_alloc_pool + h_offset);
+		h->size = rem - sizeof(*h);
+		h->next = best->next;
+	} else
+		h_offset = best->next;
+	if (bestprev)
+		bestprev->next = h_offset;
+	else
+		dah_first = h_offset;
+	p = best+1;
+out:
+	spin_unlock(&dap_lock);
+	return p;
+}
+
+void debug_kfree(const void *p)
+{
+	struct debug_alloc_header *h;
+	unsigned int h_offset;
+	if (!p)
+		return;
+	if ((char *)p < debug_alloc_pool ||
+	    (char *)p >= debug_alloc_pool + sizeof(debug_alloc_pool_aligned)) {
+		kfree(p);
+		return;
+	}
+	if (!get_dap_lock())
+		return;		/* memory leak, cannot be helped */
+	h = (struct debug_alloc_header *)p - 1;
+	h_offset = (char *)h - debug_alloc_pool;
+	if (h_offset < dah_first) {
+		h->next = dah_first;
+		dah_first = h_offset;
+	} else {
+		struct debug_alloc_header *prev;
+		prev = (struct debug_alloc_header *)(debug_alloc_pool + dah_first);
+		while (1) {
+			if (!prev->next || prev->next > h_offset)
+				break;
+			prev = (struct debug_alloc_header *)(debug_alloc_pool + prev->next);
+		}
+		if (sizeof(*prev) + prev->size == h_offset) {
+			prev->size += sizeof(*h) + h->size;
+			h = prev;
+			h_offset = (char *)h - debug_alloc_pool;
+		} else {
+			h->next = prev->next;
+			prev->next = h_offset;
+		}
+	}
+	if (h_offset + sizeof(*h) + h->size == h->next) {
+		struct debug_alloc_header *next;
+		next = (struct debug_alloc_header *)(debug_alloc_pool + h->next);
+		h->size += sizeof(*next) + next->size;
+		h->next = next->next;
+	}
+	spin_unlock(&dap_lock);
+}
+
+void kdb_initsupport()
+{
+	struct debug_alloc_header *h;
+	h = (struct debug_alloc_header *)debug_alloc_pool;
+	h->next = 0;
+	h->size = sizeof(debug_alloc_pool_aligned) - sizeof(*h);
+	dah_first = 0;
+}
+
+/* Maintain a small stack of kdb_flags to allow recursion without disturbing
+ * the global kdb state.
+ */
+
+static int kdb_flags_stack[4], kdb_flags_index;
+
+void
+kdb_save_flags(void)
+{
+	BUG_ON(kdb_flags_index >= ARRAY_SIZE(kdb_flags_stack));
+	kdb_flags_stack[kdb_flags_index++] = kdb_flags;
+}
+
+void
+kdb_restore_flags(void)
+{
+	BUG_ON(kdb_flags_index <= 0);
+	kdb_flags = kdb_flags_stack[--kdb_flags_index];
+}
Index: 2.6.x-xfs/kdb/modules/Makefile
===================================================================
--- 2.6.x-xfs.orig/kdb/modules/Makefile	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/modules/Makefile	2006-01-10 17:22:51.398263112 +1100
@@ -0,0 +1,15 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+#
+
+obj-$(CONFIG_KDB_MODULES) += kdbm_pg.o kdbm_task.o kdbm_vm.o kdbm_sched.o
+ifdef CONFIG_X86
+ifndef CONFIG_X86_64
+obj-$(CONFIG_KDB_MODULES) += kdbm_x86.o
+endif
+endif
+CFLAGS_kdbm_vm.o	+= -I $(TOPDIR)/drivers/scsi
Index: 2.6.x-xfs/kdb/modules/kdbm_pg.c
===================================================================
--- 2.6.x-xfs.orig/kdb/modules/kdbm_pg.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/modules/kdbm_pg.c	2006-01-10 17:22:51.400215968 +1100
@@ -0,0 +1,653 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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/bio.h>
+#include <linux/buffer_head.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 */
+
+#ifndef CONFIG_DISCONTIGMEM
+/* From include/linux/page_flags.h */
+static char *pg_flag_vals[] = {
+	"PG_locked", "PG_error", "PG_referenced", "PG_uptodate",
+	"PG_dirty", "PG_lru", "PG_active", "PG_slab",
+	"PG_checked", "PG_arch_1", "PG_reserved", "PG_private",
+	"PG_writeback", "PG_nosave", "PG_compound", "PG_swapcache",
+	"PG_mappedtodisk", "PG_reclaim", "PG_nosave_free", "PG_uncached",
+	NULL };
+#endif
+
+/* From include/linux/buffer_head.h */
+static char *bh_state_vals[] = {
+	"Uptodate", "Dirty", "Lock", "Req",
+	"Uptodate_Lock", "Mapped", "New", "Async_read",
+	"Async_write", "Delay", "Boundary", "Write_EIO",
+	"Ordered", "Eopnotsupp", "Private",
+	NULL };
+
+/* From include/linux/bio.h */
+static char *bio_flag_vals[] = {
+	"Uptodate", "RW_block", "EOF", "Seg_valid",
+	"Cloned", "Bounced", "User_mapped", "Eopnotsupp",
+	NULL };
+
+/* From include/linux/fs.h */
+static char *inode_flag_vals[] = {
+	"I_DIRTY_SYNC", "I_DIRTY_DATASYNC", "I_DIRTY_PAGES", "I_LOCK",
+	"I_FREEING", "I_CLEAR", "I_NEW", "I_WILL_FREE",
+	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 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("  bno %llu size %d dev 0x%x\n",
+		(unsigned long long)bh.b_blocknr,
+		bh.b_size,
+		bh.b_bdev ? bh.b_bdev->bd_dev : 0);
+	kdb_printf("  count %d state 0x%lx [%s]\n",
+		bh.b_count.counter, bh.b_state,
+		map_flags(bh.b_state, bh_state_vals));
+	kdb_printf("  b_data 0x%p\n",
+		bh.b_data);
+	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
+print_biovec(struct bio_vec *vec, int vcount)
+{
+	struct bio_vec bvec;
+	unsigned long addr;
+	int diag;
+	int i;
+
+	if (vcount < 1 || vcount > BIO_MAX_PAGES) {
+		kdb_printf("  [skipped iovecs, vcnt is %d]\n", vcount);
+		return 0;
+	}
+
+	addr = (unsigned long)vec;
+	for (i = 0; i < vcount; i++) {
+		if ((diag = kdb_getarea(bvec, addr)))
+			return(diag);
+		addr += sizeof(bvec);
+		kdb_printf("  [%d] page 0x%p length=%u offset=%u\n",
+			i, bvec.bv_page, bvec.bv_len, bvec.bv_offset);
+	}
+	return 0;
+}
+
+static int
+kdbm_bio(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	struct bio bio;
+	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(bio, addr)))
+		return(diag);
+
+	kdb_printf("bio at 0x%lx\n", addr);
+	kdb_printf("  bno %llu  next 0x%p  dev 0x%x\n",
+		(unsigned long long)bio.bi_sector,
+		bio.bi_next, bio.bi_bdev ? bio.bi_bdev->bd_dev : 0);
+	kdb_printf("  vcnt %u vec 0x%p  rw 0x%lx flags 0x%lx [%s]\n",
+		bio.bi_vcnt, bio.bi_io_vec, bio.bi_rw, bio.bi_flags,
+		map_flags(bio.bi_flags, bio_flag_vals));
+	print_biovec(bio.bi_io_vec, bio.bi_vcnt);
+	kdb_printf("  count %d  private 0x%p\n",
+		atomic_read(&bio.bi_cnt), bio.bi_private);
+	kdb_printf("  bi_end_io ");
+	if (bio.bi_end_io)
+		kdb_symbol_print(kdba_funcptr_value(bio.bi_end_io), NULL, KDB_SP_VALUE);
+	else
+		kdb_printf("(NULL)");
+	kdb_printf("\n");
+
+	return 0;
+}
+
+#ifndef CONFIG_DISCONTIGMEM
+static char *page_flags(unsigned long flags)
+{
+	return(map_flags(flags, pg_flag_vals));
+}
+
+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;
+
+#ifdef	__ia64__
+	if (rgn_index(addr) == 0)
+		addr = (unsigned long) &mem_map[addr];	/* assume region 0 is a page index, not an address */
+#else
+	if (addr < PAGE_OFFSET)
+		addr = (unsigned long) &mem_map[addr];
+#endif
+
+	if ((diag = kdb_getarea(page, addr)))
+		return(diag);
+
+	kdb_printf("struct page at 0x%lx\n", addr);
+	kdb_printf("  addr space 0x%p index %lu (offset 0x%llx)\n",
+		   page.mapping, page.index,
+		   (unsigned long long)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_has_buffers(&page))
+		kdb_printf("  buffers 0x%p\n", page_buffers(&page));
+	else
+		kdb_printf("  private 0x%lx\n", page.u.private);
+
+	return 0;
+}
+#endif /* CONFIG_DISCONTIGMEM */
+
+static 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("  errors %d sector %llu nr_sectors %lu waiting 0x%p\n",
+			rq.errors,
+			(unsigned long long)rq.sector, rq.nr_sectors,
+			rq.waiting);
+
+	kdb_printf("  hsect %llu hnrsect %lu nrseg %u nrhwseg %u currnrsect %u\n",
+			(unsigned long long)rq.hard_sector, rq.hard_nr_sectors,
+			rq.nr_phys_segments, rq.nr_hw_segments,
+			rq.current_nr_sectors);
+
+	return (unsigned long) rq.queuelist.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\n", addr);
+	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("\tbh 0x%lx bno %8llu [%s]\n", addr,
+		 (unsigned long long)bh.b_blocknr,
+		 map_flags(bh.b_state, bh_state_vals));
+}
+
+static void
+kdbm_show_page(struct page *page, int first)
+{
+	if (first)
+		kdb_printf("page_struct       index   cnt zone nid flags\n");
+	kdb_printf("%p%s %6lu %5d %3ld %3ld 0x%lx",
+		page_address(page), sizeof(void *) == 4 ? "        " : "",
+		page->index, atomic_read(&(page->_count)),
+		page_zonenum(page), page_to_nid(page),
+		page->flags & (~0UL >> ZONES_SHIFT));
+#define kdb_page_flags(page, type) if (Page ## type(page)) kdb_printf(" " #type);
+	kdb_page_flags(page, Locked);
+	kdb_page_flags(page, Error);
+	kdb_page_flags(page, Referenced);
+	kdb_page_flags(page, Uptodate);
+	kdb_page_flags(page, Dirty);
+	kdb_page_flags(page, LRU);
+	kdb_page_flags(page, Active);
+	kdb_page_flags(page, Slab);
+	kdb_page_flags(page, Checked);
+	if (page->flags & (1UL << PG_arch_1))
+		kdb_printf(" arch_1");
+	kdb_page_flags(page, Reserved);
+	kdb_page_flags(page, Private);
+	kdb_page_flags(page, Writeback);
+	kdb_page_flags(page, Nosave);
+	kdb_page_flags(page, Compound);
+	kdb_page_flags(page, SwapCache);
+	kdb_page_flags(page, MappedToDisk);
+	kdb_page_flags(page, Reclaim);
+	kdb_page_flags(page, NosaveFree);
+	kdb_page_flags(page, Uncached);
+
+	/* PageHighMem is not a flag any more, but treat it as one */
+	kdb_page_flags(page, HighMem);
+
+	if (page_has_buffers(page)) {
+		struct buffer_head *head, *bh;
+		kdb_printf("\n");
+		head = bh = page_buffers(page);
+		do {
+			do_buffer((unsigned long) bh);
+		} while ((bh = bh->b_this_page) != head);
+	} else if (page->u.private) {
+		kdb_printf(" private= 0x%lx", page->u.private);
+	}
+	kdb_printf("\n");
+#undef kdb_page_flags
+}
+
+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;
+	pgoff_t next = 0;
+	struct page *page;
+	int first;
+
+	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);
+		next = 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;
+
+	/* Run the pages in the radix tree, printing the state of each page */
+	first = 1;
+	while (radix_tree_gang_lookup(&ap->page_tree, (void **)&page, next, 1)) {
+		kdbm_show_page(page, first);
+		if (addr1)
+			break;
+		first = 0;
+		next = page->index + 1;
+	}
+
+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_size %Ld\n",
+					inode->i_ino, atomic_read(&inode->i_count),
+					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.pprev = 0x%p\n",
+		inode->i_hash.next,
+		inode->i_hash.pprev);
+
+	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_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_frozen %d s_id [%s]\n", sb->s_frozen, sb->s_id);
+out:
+	if (sb)
+		kfree(sb);
+	return diag;
+}
+
+
+
+#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+/* 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_has_buffers(&page)) {
+			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 && !CONFIG_X86_64 */
+
+static int __init kdbm_pg_init(void)
+{
+#ifndef CONFIG_DISCONTIGMEM
+	kdb_register("page", kdbm_page, "<vaddr>", "Display page", 0);
+#endif
+	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("bio", kdbm_bio, "<bio address>", "Display bio", 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);
+#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+	kdb_register("memmap", kdbm_memmap, "", "page table summary", 0);
+#endif
+
+	return 0;
+}
+
+
+static void __exit kdbm_pg_exit(void)
+{
+#ifndef CONFIG_DISCONTIGMEM
+	kdb_unregister("page");
+#endif
+	kdb_unregister("inode");
+	kdb_unregister("sb");
+	kdb_unregister("bh");
+	kdb_unregister("bio");
+	kdb_unregister("inode_pages");
+	kdb_unregister("req");
+	kdb_unregister("rqueue");
+#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+	kdb_unregister("memmap");
+#endif
+}
+
+module_init(kdbm_pg_init)
+module_exit(kdbm_pg_exit)
Index: 2.6.x-xfs/kdb/modules/kdbm_task.c
===================================================================
--- 2.6.x-xfs.orig/kdb/modules/kdbm_task.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/modules/kdbm_task.c	2006-01-10 17:22:51.400215968 +1100
@@ -0,0 +1,179 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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 <linux/sched.h>
+#include <asm/signal.h>
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Debug struct task and sigset information");
+MODULE_LICENSE("GPL");
+
+static char *
+kdb_cpus_allowed_string(struct task_struct *tp)
+{
+	static char maskbuf[(NR_CPUS + 31) / 32 * 9 + 1];
+	if (cpus_full(tp->cpus_allowed))
+		strcpy(maskbuf, "ALL");
+	else if (cpus_empty(tp->cpus_allowed))
+		strcpy(maskbuf, "NONE");
+	else if (cpus_weight(tp->cpus_allowed) == 1)
+		snprintf(maskbuf, sizeof(maskbuf), "ONLY(%d)", first_cpu(tp->cpus_allowed));
+	else
+		cpumask_scnprintf(maskbuf, sizeof(maskbuf), tp->cpus_allowed);
+	return maskbuf;
+}
+
+static int
+kdbm_task(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	unsigned long addr;
+	long offset=0;
+	int nextarg;
+	int e = 0;
+	struct task_struct *tp = NULL, *tp1;
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	if ((e = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) != 0)
+		return(e);
+
+	if (!(tp = kmalloc(sizeof(*tp), GFP_ATOMIC))) {
+	    kdb_printf("%s: cannot kmalloc tp\n", __FUNCTION__);
+	    goto out;
+	}
+	if ((e = kdb_getarea(*tp, addr))) {
+	    kdb_printf("%s: invalid task address\n", __FUNCTION__);
+	    goto out;
+	}
+
+	tp1 = (struct task_struct *)addr;
+	kdb_printf(
+	    "struct task at 0x%lx, pid=%d flags=0x%lx state=%ld comm=\"%s\"\n",
+	    addr, tp->pid, tp->flags, tp->state, tp->comm);
+
+	kdb_printf("  cpu=%d policy=%lu ", kdb_process_cpu(tp), tp->policy);
+	kdb_printf(
+	    "prio=%d static_prio=%d cpus_allowed=%s",
+	    tp->prio, tp->static_prio, kdb_cpus_allowed_string(tp));
+	kdb_printf(" &thread=0x%p\n", &tp1->thread);
+
+	kdb_printf("  need_resched=%d ",
+		test_tsk_thread_flag(tp, TIF_NEED_RESCHED));
+	kdb_printf(
+	    "timestamp=%llu time_slice=%u",
+	    tp->timestamp, tp->time_slice);
+	kdb_printf(" lock_depth=%d\n", tp->lock_depth);
+
+	kdb_printf(
+	    "  fs=0x%p files=0x%p mm=0x%p\n",
+	    tp->fs, tp->files, tp->mm);
+
+	kdb_printf(
+	    "  uid=%d euid=%d suid=%d fsuid=%d gid=%d egid=%d sgid=%d fsgid=%d\n",
+	    tp->uid, tp->euid, tp->suid, tp->fsuid, tp->gid, tp->egid, tp->sgid, tp->fsgid);
+
+	kdb_printf(
+	    "  user=0x%p\n",
+	    tp->user);
+
+	if (tp->sysvsem.undo_list)
+		kdb_printf(
+		    "  sysvsem.sem_undo refcnt %d proc_list=0x%p\n",
+		    atomic_read(&tp->sysvsem.undo_list->refcnt),
+		    tp->sysvsem.undo_list->proc_list);
+
+	kdb_printf(
+	    "  signal=0x%p &blocked=0x%p &pending=0x%p\n",
+	    tp->signal, &tp1->blocked, &tp1->pending);
+
+	kdb_printf(
+	    "  utime=%ld stime=%ld cutime=%ld cstime=%ld\n",
+	    tp->utime, tp->stime,
+	    tp->signal ? tp->signal->cutime : 0L,
+	    tp->signal ? tp->signal->cstime : 0L);
+
+	kdb_printf("  thread_info=0x%p\n", tp->thread_info);
+	kdb_printf("  ti flags=0x%lx\n", (unsigned long)tp->thread_info->flags);
+
+out:
+	if (tp)
+	    kfree(tp);
+	return e;
+}
+
+static int
+kdbm_sigset(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	sigset_t *sp = NULL;
+	unsigned long addr;
+	long offset=0;
+	int nextarg;
+	int e = 0;
+	int i;
+	char fmt[32];
+
+	if (argc != 1)
+		return KDB_ARGCOUNT;
+
+#ifndef _NSIG_WORDS
+	kdb_printf("unavailable on this platform, _NSIG_WORDS not defined.\n");
+#else
+	nextarg = 1;
+	if ((e = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) != 0)
+		return(e);
+
+	if (!(sp = kmalloc(sizeof(*sp), GFP_ATOMIC))) {
+	    kdb_printf("%s: cannot kmalloc sp\n", __FUNCTION__);
+	    goto out;
+	}
+	if ((e = kdb_getarea(*sp, addr))) {
+	    kdb_printf("%s: invalid sigset address\n", __FUNCTION__);
+	    goto out;
+	}
+
+	sprintf(fmt, "[%%d]=0x%%0%dlx ", (int)sizeof(sp->sig[0])*2);
+	kdb_printf("sigset at 0x%p : ", sp);
+	for (i=_NSIG_WORDS-1; i >= 0; i--) {
+	    if (i == 0 || sp->sig[i]) {
+		kdb_printf(fmt, i, sp->sig[i]);
+	    }
+	}
+	kdb_printf("\n");
+#endif /* _NSIG_WORDS */
+
+out:
+	if (sp)
+	    kfree(sp);
+	return e;
+}
+
+static int __init kdbm_task_init(void)
+{
+	kdb_register("task", kdbm_task, "<vaddr>", "Display task_struct", 0);
+	kdb_register("sigset", kdbm_sigset, "<vaddr>", "Display sigset_t", 0);
+
+	return 0;
+}
+
+static void __exit kdbm_task_exit(void)
+{
+	kdb_unregister("task");
+	kdb_unregister("sigset");
+}
+
+kdb_module_init(kdbm_task_init)
+kdb_module_exit(kdbm_task_exit)
Index: 2.6.x-xfs/kdb/modules/kdbm_vm.c
===================================================================
--- 2.6.x-xfs.orig/kdb/modules/kdbm_vm.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/modules/kdbm_vm.c	2006-01-10 17:22:51.403145251 +1100
@@ -0,0 +1,839 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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 <linux/swap.h>
+#include <linux/swapops.h>
+
+#include <scsi.h>
+#include <scsi/scsi_host.h>
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Debug VM information");
+MODULE_LICENSE("GPL");
+
+struct __vmflags {
+	unsigned long mask;
+	char *name;
+};
+
+static struct __vmflags 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_PFNMAP, "PFNMAP" },
+	{ VM_DENYWRITE, "DENYWRITE" },
+	{ VM_EXECUTABLE, "EXECUTABLE" },
+	{ VM_LOCKED, "LOCKED" },
+	{ VM_IO , "IO " },
+	{ VM_SEQ_READ , "SEQ_READ " },
+	{ VM_RAND_READ , "RAND_READ " },
+	{ VM_DONTCOPY , "DONTCOPY " },
+	{ VM_DONTEXPAND , "DONTEXPAND " },
+	{ VM_RESERVED , "RESERVED " },
+	{ VM_ACCOUNT , "ACCOUNT " },
+	{ VM_HUGETLB , "HUGETLB " },
+	{ VM_NONLINEAR , "NONLINEAR " },
+	{ VM_MAPPED_COPY , "MAPPED_COPY " },
+	{ VM_INSERTPAGE , "INSERTPAGE " },
+	{ 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("shared.vm_set.list.next = 0x%p\n", (void *) vp->shared.vm_set.list.next);
+	kdb_printf("shared.vm_set.list.prev = 0x%p\n", (void *) vp->shared.vm_set.list.prev);
+	kdb_printf("shared.vm_set.parent = 0x%p\n", (void *) vp->shared.vm_set.parent);
+	kdb_printf("shared.vm_set.head = 0x%p\n", (void *) vp->shared.vm_set.head);
+	kdb_printf("anon_vma_node.next = 0x%p\n", (void *) vp->anon_vma_node.next);
+	kdb_printf("anon_vma_node.prev = 0x%p\n", (void *) vp->anon_vma_node.prev);
+	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 *g, *tp;
+		struct vm_area_struct *vp;
+		pid_t pid;
+
+		if ((diag = kdbgetularg(argv[argc], (unsigned long *) &pid)))
+			return diag;
+
+		kdb_do_each_thread(g, 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_while_each_thread(g, tp);
+
+		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%ulx", 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 (<address> through <address>
+ *     plus <nbytes>) for the given process. The default value for nbytes is
+ *     one.
+ *
+ *     pte -m <mm> <address> [<nbytes>]    Print all pte_t structures for
+ *					   virtual <address> in address space
+ *					   of <mm> which is a pointer to a
+ *					   mm_struct
+ *     pte -p <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;
+	long offset = 0;
+	int nextarg;
+	unsigned long nbytes = 1;
+	long npgs;
+	int diag;
+	int found;
+	pid_t pid;
+	struct task_struct *tp;
+	struct mm_struct *mm, copy_of_mm;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (argc < 3 || argc > 4) {
+		return KDB_ARGCOUNT;
+	}
+
+	 if (strcmp(argv[1], "-p") == 0) {
+		if ((diag = kdbgetularg(argv[2], (unsigned long *) &pid))) {
+			return diag;
+		}
+
+		found = 0;
+		for_each_process(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;
+		}
+		mm = tp->mm;
+	} else if (strcmp(argv[1], "-m") == 0) {
+
+
+		nextarg = 2;
+		if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset,
+					  NULL, regs))
+		    || (diag = kdb_getarea(copy_of_mm, addr)))
+			return (diag);
+		mm = &copy_of_mm;
+	} else {
+		return KDB_ARGCOUNT;
+	}
+
+	if ((diag = kdbgetularg(argv[3], &addr))) {
+		return diag;
+	}
+
+	if (argc == 4) {
+		if ((diag = kdbgetularg(argv[4], &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(mm, addr);
+		if (pgd_present(*pgd)) {
+			pud = pud_offset(pgd, addr);
+			if (pud_present(*pud)) {
+				pmd = pmd_offset(pud, addr);
+				if (pmd_present(*pmd)) {
+					pte = pte_offset_map(pmd, addr);
+					if (pte_present(*pte)) {
+						kdbm_print_pte(pte);
+					}
+				}
+			}
+		}
+
+		kdb_printf("\n");
+		addr += PAGE_SIZE;
+	}
+
+	return 0;
+}
+
+/*
+ * kdbm_rpte
+ *
+ *     This function implements the 'rpte' command.  Print all pte_t structures
+ *     that contain the given physical page range (<pfn> through <pfn>
+ *     plus <npages>) for the given process. The default value for npages is
+ *     one.
+ *
+ *     rpte -m <mm> <pfn> [<npages>]	   Print all pte_t structures for
+ *					   physical page <pfn> in address space
+ *					   of <mm> which is a pointer to a
+ *					   mm_struct
+ *     rpte -p <pid> <pfn> [<npages>]	   Print all pte_t structures for
+ *					   physical page <pfn> in address space
+ *					   of <pid>
+ */
+
+static int
+kdbm_rpte(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	unsigned long addr;
+	unsigned long pfn;
+	long offset = 0;
+	int nextarg;
+	unsigned long npages = 1;
+	int diag;
+	int found;
+	pid_t pid;
+	struct task_struct *tp;
+	struct mm_struct *mm, copy_of_mm;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned long g, u, m, t;
+
+	if (argc < 3 || argc > 4) {
+		return KDB_ARGCOUNT;
+	}
+
+	 if (strcmp(argv[1], "-p") == 0) {
+		if ((diag = kdbgetularg(argv[2], (unsigned long *) &pid))) {
+			return diag;
+		}
+
+		found = 0;
+		for_each_process(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;
+		}
+		mm = tp->mm;
+	} else if (strcmp(argv[1], "-m") == 0) {
+
+
+		nextarg = 2;
+		if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset,
+					  NULL, regs))
+		    || (diag = kdb_getarea(copy_of_mm, addr)))
+			return (diag);
+		mm = &copy_of_mm;
+	} else {
+		return KDB_ARGCOUNT;
+	}
+
+	if ((diag = kdbgetularg(argv[3], &pfn))) {
+		return diag;
+	}
+
+	if (argc == 4) {
+		if ((diag = kdbgetularg(argv[4], &npages))) {
+			return diag;
+		}
+	}
+
+	/* spaces after vaddr depends on sizeof(unsigned long) */
+	kdb_printf("pfn              vaddr%*s pte\n",
+		   (int)(2*sizeof(unsigned long) + 2 - 5), " ");
+
+	for (g = 0, pgd = pgd_offset(mm, 0UL); g < PTRS_PER_PGD; ++g, ++pgd) {
+		if (pgd_none(*pgd) || pgd_bad(*pgd))
+			continue;
+		for (u = 0, pud = pud_offset(pgd, 0UL); u < PTRS_PER_PUD; ++u, ++pud) {
+			if (pud_none(*pud) || pud_bad(*pud))
+				continue;
+			for (m = 0, pmd = pmd_offset(pud, 0UL); m < PTRS_PER_PMD; ++m, ++pmd) {
+				if (pmd_none(*pmd) || pmd_bad(*pmd))
+					continue;
+				for (t = 0, pte = pte_offset_map(pmd, 0UL); t < PTRS_PER_PTE; ++t, ++pte) {
+					if (pte_none(*pte))
+						continue;
+					if (pte_pfn(*pte) < pfn || pte_pfn(*pte) >= (pfn + npages))
+						continue;
+					addr = g << PGDIR_SHIFT;
+#ifdef __ia64__
+					/* IA64 plays tricks with the pgd mapping to save space.
+					 * This reverses pgd_index().
+					 */
+					{
+						unsigned long region = g >> (PAGE_SHIFT - 6);
+						unsigned long l1index = g - (region << (PAGE_SHIFT - 6));
+						addr = (region << 61) + (l1index << PGDIR_SHIFT);
+					}
+#endif
+					addr += (m << PMD_SHIFT) + (t << PAGE_SHIFT);
+					kdb_printf("0x%-14lx " kdb_bfd_vma_fmt0 " ",
+						   pte_pfn(*pte), addr);
+					kdbm_print_pte(pte);
+					kdb_printf("\n");
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int
+kdbm_print_dentry(unsigned long daddr)
+{
+	struct dentry d;
+	int diag;
+	char buf[256];
+
+	kdb_printf("Dentry at 0x%lx\n", daddr);
+	if ((diag = kdb_getarea(d, (unsigned long)daddr)))
+		return diag;
+
+	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.pprev);
+
+	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 d_fsdata = 0x%p\n",
+					d.d_op, d.d_sb, d.d_fsdata);
+
+	kdb_printf(" d_iname = %s\n",
+					d.d_iname);
+
+	if (d.d_inode) {
+		struct inode i;
+		kdb_printf("\nInode Entry at 0x%p\n", d.d_inode);
+		if ((diag = kdb_getarea(i, (unsigned long)d.d_inode)))
+			return diag;
+		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\n",
+						i.i_ino, atomic_read(&i.i_count));
+
+		kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n",
+						i.i_hash.next, i.i_hash.pprev);
+
+		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);
+
+	}
+	kdb_printf("\n");
+	return 0;
+}
+
+static int
+kdbm_filp(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct file   f;
+	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)))
+		return diag;
+
+	kdb_printf("File Pointer at 0x%lx\n", addr);
+
+	kdb_printf(" fu_list.nxt = 0x%p fu_list.prv = 0x%p\n",
+					f.f_u.fu_list.next, f.f_u.fu_list.prev);
+
+	kdb_printf(" f_dentry = 0x%p f_vfsmnt = 0x%p f_op = 0x%p\n",
+					f.f_dentry, f.f_vfsmnt, 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 security = 0x%p\n",
+					f.f_pos, f.f_security);
+
+	kdb_printf(" private_data = 0x%p f_mapping = 0x%p\n\n",
+					f.private_data, f.f_mapping);
+
+	return kdbm_print_dentry((unsigned long)f.f_dentry);
+}
+
+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(" file_lock_operations\n");
+	kdb_printf("   fl_insert = 0x%p fl_remove = 0x%p fl_copy_lock = 0x%p fl_release_private = 0x%p\n",
+			fl.fl_ops->fl_insert, fl.fl_ops->fl_remove,
+			fl.fl_ops->fl_copy_lock, fl.fl_ops->fl_release_private);
+
+	kdb_printf(" lock_manager_operations\n");
+	kdb_printf("   fl_compare_owner = 0x%p fl_notify = 0x%p\n",
+			fl.fl_lmops->fl_compare_owner, fl.fl_lmops->fl_notify);
+
+	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)
+{
+	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)))
+		return diag;
+
+	return kdbm_print_dentry(addr);
+}
+
+static int
+kdbm_kobject(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct kobject k;
+	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(k, addr)))
+		return diag;
+
+
+	kdb_printf("kobject at 0x%lx\n", addr);
+
+	if (k.k_name) {
+		char c;
+		kdb_printf(" k_name 0x%p", k.k_name);
+		if (kdb_getarea(c, (unsigned long)k.k_name) == 0)
+			kdb_printf(" '%s'", k.k_name);
+		kdb_printf("\n");
+	}
+
+	if (k.k_name != ((struct kobject *)addr)->name)
+		kdb_printf(" name '%." __stringify(KOBJ_NAME_LEN) "s'\n", k.k_name);
+
+	kdb_printf(" kref.refcount %d'\n", atomic_read(&k.kref.refcount));
+
+	kdb_printf(" entry.next = 0x%p entry.prev = 0x%p\n",
+					k.entry.next, k.entry.prev);
+
+	kdb_printf(" parent = 0x%p kset = 0x%p ktype = 0x%p dentry = 0x%p\n",
+					k.parent, k.kset, k.ktype, k.dentry);
+
+	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("host_queue = 0x%p\n", sh.__devices.next);
+	kdb_printf("ehandler = 0x%p eh_action = 0x%p\n",
+		   sh.ehandler, sh.eh_action);
+	kdb_printf("host_wait = 0x%p hostt = 0x%p\n",
+		   &sh.host_wait, sh.hostt);
+	kdb_printf("host_failed = %d  host_no = %d resetting = %d\n",
+		   sh.host_failed, 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->siblings.next, sd->siblings.prev, sd->host);
+	kdb_printf("device_busy = %d   current_cmnd 0x%p\n",
+		   sd->device_busy, sd->current_cmnd);
+	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 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("device = 0x%p  next = 0x%p  done = 0x%p\n",
+		   sc->device, sc->list.next, sc->done);
+	kdb_printf("serial_number = %ld  retries = %d\n",
+		   sc->serial_number, sc->retries);
+	kdb_printf("cmd_len = %d  old_cmd_len = %d\n",
+		   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  request_bufflen = %d\n",
+		   sc->request_buffer, sc->request_bufflen);
+	kdb_printf("use_sg = %d  old_use_sg = %d sglist_len = %d\n",
+		   sc->use_sg, sc->old_use_sg, sc->sglist_len);
+	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);
+
+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, "( -m <mm> | -p <pid> ) <vaddr> [<nbytes>]", "Display pte_t for mm_struct or pid", 0);
+	kdb_register("rpte", kdbm_rpte, "( -m <mm> | -p <pid> ) <pfn> [<npages>]", "Find pte_t containing pfn for mm_struct or pid", 0);
+	kdb_register("dentry", kdbm_dentry, "<dentry>", "Display interesting dentry stuff", 0);
+	kdb_register("kobject", kdbm_kobject, "<kobject>", "Display interesting kobject stuff", 0);
+	kdb_register("filp", kdbm_filp, "<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("rpte");
+	kdb_unregister("dentry");
+	kdb_unregister("kobject");
+	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)
Index: 2.6.x-xfs/kdb/modules/kdbm_sched.c
===================================================================
--- 2.6.x-xfs.orig/kdb/modules/kdbm_sched.c	2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/modules/kdbm_sched.c	2006-01-10 17:22:51.403145251 +1100
@@ -0,0 +1,58 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Debug scheduler information");
+MODULE_LICENSE("GPL");
+
+static int
+kdbm_runqueues(int argc, const char **argv, const char **envp,
+	struct pt_regs *regs)
+{
+	unsigned long cpu;
+	int ret = 0;
+
+	if (argc == 1) {
+		ret = kdbgetularg((char *)argv[1], &cpu);
+		if (!ret) {
+			if (!cpu_online(cpu)) {
+				kdb_printf("Invalid cpu number\n");
+			} else
+				kdb_runqueue(cpu, kdb_printf);
+		}
+	} else if (argc == 0) {
+		for_each_online_cpu(cpu)
+			kdb_runqueue(cpu, kdb_printf);
+	} else {
+		/* More than one arg */
+		kdb_printf("Specify one cpu number\n");
+	}
+	return ret;
+}
+
+static int __init kdbm_sched_init(void)
+{
+	kdb_register("rq",  kdbm_runqueues, "<cpunum>", "Display runqueue for <cpunum>", 0);
+	kdb_register("rqa", kdbm_runqueues, "", "Display all runqueues", 0);
+	return 0;
+}
+
+static void __exit kdbm_sched_exit(void)
+{
+	kdb_unregister("rq");
+	kdb_unregister("rqa");
+}
+
+module_init(kdbm_sched_init)
+module_exit(kdbm_sched_exit)
Index: 2.6.x-xfs/kernel/exit.c
===================================================================
--- 2.6.x-xfs.orig/kernel/exit.c	2005-12-05 09:56:23.000132451 +1100
+++ 2.6.x-xfs/kernel/exit.c	2006-01-10 17:22:51.404121678 +1100
@@ -5,6 +5,9 @@
  */
 
 #include <linux/config.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
Index: 2.6.x-xfs/kernel/module.c
===================================================================
--- 2.6.x-xfs.orig/kernel/module.c	2005-12-05 09:56:23.008920300 +1100
+++ 2.6.x-xfs/kernel/module.c	2006-01-10 17:22:51.406074534 +1100
@@ -2021,6 +2021,13 @@
 	return NULL;
 }
 
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+struct list_head *kdb_modules = &modules;	/* kdb needs the list of modules */
+#else	/* !CONFIG_KDB */
+#define	KDB_IS_RUNNING() 0
+#endif	/* CONFIG_KDB */
+
 struct module *module_get_kallsym(unsigned int symnum,
 				  unsigned long *value,
 				  char *type,
@@ -2028,7 +2035,8 @@
 {
 	struct module *mod;
 
-	down(&module_mutex);
+	if (!KDB_IS_RUNNING())
+		down(&module_mutex);
 	list_for_each_entry(mod, &modules, list) {
 		if (symnum < mod->num_symtab) {
 			*value = mod->symtab[symnum].st_value;
@@ -2036,12 +2044,14 @@
 			strncpy(namebuf,
 				mod->strtab + mod->symtab[symnum].st_name,
 				127);
-			up(&module_mutex);
+			if (!KDB_IS_RUNNING())
+				up(&module_mutex);
 			return mod;
 		}
 		symnum -= mod->num_symtab;
 	}
-	up(&module_mutex);
+	if (!KDB_IS_RUNNING())
+		up(&module_mutex);
 	return NULL;
 }
 
Index: 2.6.x-xfs/kernel/printk.c
===================================================================
--- 2.6.x-xfs.orig/kernel/printk.c	2005-12-05 09:56:23.019661004 +1100
+++ 2.6.x-xfs/kernel/printk.c	2006-01-10 17:22:51.407050962 +1100
@@ -356,6 +356,20 @@
 	return do_syslog(type, buf, len);
 }
 
+#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 + log_buf_len;
+	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	/* CONFIG_KDB */
+
 /*
  * Call the console drivers on a range of log_buf
  */
Index: 2.6.x-xfs/kernel/sched.c
===================================================================
--- 2.6.x-xfs.orig/kernel/sched.c	2005-12-05 09:56:23.025519570 +1100
+++ 2.6.x-xfs/kernel/sched.c	2006-01-10 17:22:51.409980245 +1100
@@ -5702,7 +5702,7 @@
 
 #endif /* CONFIG_MAGIC_SYSRQ */
 
-#ifdef CONFIG_IA64
+#if	defined(CONFIG_IA64) || defined(CONFIG_KDB)
 /*
  * These functions are only useful for the IA64 MCA handling.
  *
@@ -5745,3 +5745,80 @@
 }
 
 #endif
+
+#ifdef	CONFIG_KDB
+
+#include <linux/kdb.h>
+
+static void
+kdb_prio(char *name, prio_array_t *array, kdb_printf_t xxx_printf)
+{
+	int pri;
+
+	xxx_printf("  %s nr_active:%d  bitmap: 0x%lx 0x%lx 0x%lx\n",
+		name, array->nr_active,
+		array->bitmap[0], array->bitmap[1], array->bitmap[2]);
+
+	pri = sched_find_first_bit(array->bitmap);
+	if (pri != MAX_PRIO) {
+		xxx_printf("   bitmap priorities:");
+		while (pri != MAX_PRIO) {
+			xxx_printf(" %d", pri);
+			pri++;
+			pri = find_next_bit(array->bitmap, MAX_PRIO, pri);
+		}
+		xxx_printf("\n");
+	}
+
+	for (pri = 0; pri < MAX_PRIO; pri++) {
+		int printed_hdr = 0;
+		struct list_head *head, *curr;
+
+		head = array->queue + pri;
+		curr = head->next;
+		while(curr != head) {
+			task_t *task;
+			if (!printed_hdr) {
+				xxx_printf("   queue at priority=%d\n", pri);
+				printed_hdr = 1;
+			}
+			task = list_entry(curr, task_t, run_list);
+			xxx_printf("    0x%p %d %s  time_slice:%d\n",
+				   task, task->pid, task->comm,
+				   task->time_slice);
+			curr = curr->next;
+		}
+	}
+}
+
+/* This code must be in sched.c because struct runqueue is only defined in this
+ * source.  To allow most of kdb to be modular, this code cannot call any kdb
+ * functions directly, any external functions that it needs must be passed in
+ * as parameters.
+ */
+
+void
+kdb_runqueue(unsigned long cpu, kdb_printf_t xxx_printf)
+{
+	struct runqueue *rq;
+
+	rq = cpu_rq(cpu);
+
+	xxx_printf("CPU%ld lock:%s curr:0x%p(%d)(%s)",
+		   cpu, (spin_is_locked(&rq->lock))?"LOCKED":"free",
+		   rq->curr, rq->curr->pid, rq->curr->comm);
+	if (rq->curr == rq->idle)
+		xxx_printf(" is idle");
+	xxx_printf("\n ");
+#ifdef CONFIG_SMP
+	xxx_printf(" cpu_load:%lu %lu %lu",
+			rq->cpu_load[0], rq->cpu_load[1], rq->cpu_load[2]);
+#endif
+	xxx_printf(" nr_running:%lu nr_switches:%llu\n",
+		   rq->nr_running, rq->nr_switches);
+	kdb_prio("active", rq->active, xxx_printf);
+	kdb_prio("expired", rq->expired, xxx_printf);
+}
+EXPORT_SYMBOL(kdb_runqueue);
+
+#endif	/* CONFIG_KDB */
Index: 2.6.x-xfs/kernel/signal.c
===================================================================
--- 2.6.x-xfs.orig/kernel/signal.c	2005-12-05 09:56:23.027472426 +1100
+++ 2.6.x-xfs/kernel/signal.c	2006-01-10 17:22:51.410956672 +1100
@@ -2631,3 +2631,52 @@
 				  __alignof__(struct sigqueue),
 				  SLAB_PANIC, NULL, NULL);
 }
+
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+/*
+ * kdb_send_sig_info
+ *
+ *	Allows kdb to send signals without exposing signal internals.
+ *
+ * Inputs:
+ *	t	task
+ *	siginfo	signal information
+ *	seqno	current kdb sequence number (avoid including kdbprivate.h)
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	Checks if the required locks are available before calling the main
+ *	signal code, to avoid kdb deadlocks.
+ * Remarks:
+ */
+void
+kdb_send_sig_info(struct task_struct *t, struct siginfo *info, int seqno)
+{
+	static struct task_struct *kdb_prev_t;
+	static int kdb_prev_seqno;
+	int sig, new_t;
+	if (!spin_trylock(&t->sighand->siglock)) {
+		kdb_printf("Can't do kill command now.\n"
+			"The sigmask lock is held somewhere else in kernel, try again later\n");
+		return;
+	}
+	spin_unlock(&t->sighand->siglock);
+	new_t = kdb_prev_t != t || kdb_prev_seqno != seqno;
+	kdb_prev_t = t;
+	kdb_prev_seqno = seqno;
+	if (t->state != TASK_RUNNING && new_t) {
+		kdb_printf("Process is not RUNNING, sending a signal from kdb risks deadlock\n"
+			   "on the run queue locks.  The signal has _not_ been sent.\n"
+			   "Reissue the kill command if you want to risk the deadlock.\n");
+		return;
+	}
+	sig = info->si_signo;
+	if (send_sig_info(sig, info, t))
+		kdb_printf("Fail to deliver Signal %d to process %d.\n", sig, t->pid);
+	else
+		kdb_printf("Signal %d is sent to process %d.\n", sig, t->pid);
+}
+#endif	/* CONFIG_KDB */
Index: 2.6.x-xfs/kernel/kallsyms.c
===================================================================
--- 2.6.x-xfs.orig/kernel/kallsyms.c	2005-12-05 09:56:23.004038162 +1100
+++ 2.6.x-xfs/kernel/kallsyms.c	2006-01-10 17:22:51.411933100 +1100
@@ -419,3 +419,25 @@
 __initcall(kallsyms_init);
 
 EXPORT_SYMBOL(__print_symbol);
+
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+const char *kdb_walk_kallsyms(loff_t *pos)
+{
+	static struct kallsym_iter kdb_walk_kallsyms_iter;
+	if (*pos == 0) {
+		memset(&kdb_walk_kallsyms_iter, 0, sizeof(kdb_walk_kallsyms_iter));
+		reset_iter(&kdb_walk_kallsyms_iter, 0);
+	}
+	while (1) {
+		if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
+			return NULL;
+		++*pos;
+		/* Some debugging symbols have no name.  Ignore them. */
+		if (kdb_walk_kallsyms_iter.name[0])
+			return kdb_walk_kallsyms_iter.name;
+	}
+}
+#endif	/* CONFIG_KDB */
Index: 2.6.x-xfs/mm/hugetlb.c
===================================================================
--- 2.6.x-xfs.orig/mm/hugetlb.c	2005-12-05 09:56:23.057741683 +1100
+++ 2.6.x-xfs/mm/hugetlb.c	2006-01-10 17:22:51.411933100 +1100
@@ -233,6 +233,23 @@
 		nid, free_huge_pages_node[nid]);
 }
 
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+/* Like hugetlb_report_meminfo() but using kdb_printf() */
+void
+kdb_hugetlb_report_meminfo(void)
+{
+	kdb_printf(
+		"HugePages_Total: %5lu\n"
+		"HugePages_Free:  %5lu\n"
+		"Hugepagesize:    %5lu kB\n",
+		nr_huge_pages,
+		free_huge_pages,
+		HPAGE_SIZE/1024);
+}
+#endif	/* CONFIG_KDB */
+
 int is_hugepage_mem_enough(size_t size)
 {
 	return (size + ~HPAGE_MASK)/HPAGE_SIZE <= free_huge_pages;
Index: 2.6.x-xfs/mm/swapfile.c
===================================================================
--- 2.6.x-xfs.orig/mm/swapfile.c	2005-12-05 09:56:23.089963796 +1100
+++ 2.6.x-xfs/mm/swapfile.c	2006-01-10 17:22:51.413885955 +1100
@@ -14,6 +14,10 @@
 #include <linux/swap.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#endif	/* CONFIG_KDB */
 #include <linux/namei.h>
 #include <linux/shm.h>
 #include <linux/blkdev.h>
@@ -1598,6 +1602,24 @@
 	spin_unlock(&swap_lock);
 }
 
+#ifdef	CONFIG_KDB
+/* Like si_swapinfo() but without the locks */
+void kdb_si_swapinfo(struct sysinfo *val)
+{
+	unsigned int i;
+	unsigned long nr_to_be_unused = 0;
+
+	for (i = 0; i < nr_swapfiles; i++) {
+		if (!(swap_info[i].flags & SWP_USED) ||
+		     (swap_info[i].flags & SWP_WRITEOK))
+			continue;
+		nr_to_be_unused += swap_info[i].inuse_pages;
+	}
+	val->freeswap = nr_swap_pages + nr_to_be_unused;
+	val->totalswap = total_swap_pages + nr_to_be_unused;
+}
+#endif	/* CONFIG_KDB */
+
 /*
  * Verify that a swap entry is valid and increment its swap map count.
  *

%diffstat
 Documentation/kdb/kdb.mm      |  487 +++++
 Documentation/kdb/kdb_bp.man  |  197 ++
 Documentation/kdb/kdb_bt.man  |  223 ++
 Documentation/kdb/kdb_env.man |   46 
 Documentation/kdb/kdb_ll.man  |  134 +
 Documentation/kdb/kdb_md.man  |  136 +
 Documentation/kdb/kdb_ps.man  |   96 +
 Documentation/kdb/kdb_rd.man  |  170 +
 Documentation/kdb/kdb_sr.man  |   68 
 Documentation/kdb/kdb_ss.man  |  109 +
 Documentation/kdb/slides      | 1382 ++++++++++++++
 Makefile                      |    1 
 drivers/char/keyboard.c       |   10 
 drivers/serial/8250.c         |   49 
 drivers/serial/8250_early.c   |   32 
 drivers/serial/sn_console.c   |   73 
 drivers/usb/host/ohci-hcd.c   |   48 
 drivers/usb/host/ohci-pci.c   |    9 
 drivers/usb/host/ohci-q.c     |   62 
 drivers/usb/input/hid-core.c  |   19 
 drivers/usb/input/usbkbd.c    |   16 
 fs/proc/mmu.c                 |   10 
 fs/proc/proc_misc.c           |  100 +
 include/linux/console.h       |    5 
 include/linux/dis-asm.h       |  316 +++
 include/linux/kdb.h           |  190 +
 include/linux/kdbprivate.h    |  502 +++++
 include/linux/sysctl.h        |    1 
 init/main.c                   |   32 
 kdb/ChangeLog                 | 1284 +++++++++++++
 kdb/Makefile                  |   28 
 kdb/kdb_bp.c                  |  623 ++++++
 kdb/kdb_bt.c                  |  182 +
 kdb/kdb_cmds                  |   29 
 kdb/kdb_id.c                  |  239 ++
 kdb/kdb_io.c                  |  649 ++++++
 kdb/kdbmain.c                 | 4005 ++++++++++++++++++++++++++++++++++++++++++
 kdb/kdbsupport.c              | 1285 +++++++++++++
 kdb/modules/Makefile          |   15 
 kdb/modules/kdbm_pg.c         |  653 ++++++
 kdb/modules/kdbm_sched.c      |   58 
 kdb/modules/kdbm_task.c       |  179 +
 kdb/modules/kdbm_vm.c         |  839 ++++++++
 kernel/exit.c                 |    3 
 kernel/kallsyms.c             |   22 
 kernel/module.c               |   16 
 kernel/printk.c               |   14 
 kernel/sched.c                |   79 
 kernel/signal.c               |   49 
 mm/hugetlb.c                  |   17 
 mm/swapfile.c                 |   22 
 51 files changed, 14809 insertions(+), 4 deletions(-)