--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/Configure.help.~1~	Wed Oct 25 18:57:50 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/Configure.help	Wed Oct 25 19:09:54 2000
@@ -11407,6 +11407,19 @@
   keys are documented in Documentation/sysrq.txt. Don't say Y unless
   you really know what this hack does.
 
+Kernel Debugging support
+CONFIG_KDB
+  This option provides a built-in kernel debugger.  The built-in 
+  kernel debugger contains commands which allow memory to be examined,
+  instructions to be disassembled and breakpoints to be set.
+
+Kernel Debugging backtrace framepointer support
+CONFIG_KDB_FRAMEPTR
+  This option causes the system to use the frame pointer as a 
+  real frame pointer rather than as a general purpose register.  Set
+  this option to get accurate stack tracebacks when using the 
+  built-in kernel debugger.
+
 ISDN subsystem
 CONFIG_ISDN
   ISDN ("Integrated Services Digital Networks", called RNIS in France)
--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb.mm.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb.mm	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,97 @@
+.ND "March 10, 1999"
+.TL
+Built-in Kernel Debugger for Linux
+.AU "Scott Lurndal" SL 8U500 OS 33158
+.AT "Member Technical Staff"
+.AF "Silicon Graphics, Inc."
+.MT 2
+.AS
+These programmer notes describe the built-in kernel debugger 
+for linux.  
+.AE
+.H 1 "Overview"
+This document describes the built-in kernel debugger available
+for linux.   This debugger allows the programmer to interactivly
+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 which enables all
+symbols with global scope (including static symbols) to be used
+as arguments to the kernel debugger commands.
+.H 1 "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_KDB_FRAMEPTR\fP
+option be enabled.   \fBCONFIG_KDB_FRAMEPTR\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
+When booting the new kernel using \fIlilo\fP(1), the 'kdb' flag
+may be added after the image name on the \fBLILO\fP boot line to
+force the kernel to stop in the kernel debugger early in the 
+kernel initialization process.     If the kdb flag isn't provided, 
+then kdb will automatically be invoked upon system panic or 
+when the 
+\fBPAUSE\fP
+key is used from the keyboard.
+.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).
+The \fBControl-A\fP key sequence on the serial port will cause the
+kernel debugger to be entered with input from the serial port and
+output to the serial console.
+.H 2 "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.
+.P
+The following table shows the currently implemented 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
+bpa	Set or Display breakpoint globally
+cpu	Switch cpus
+env	Show environment
+go	Restart execution
+help	Display help message
+id	Disassemble Instructions
+ll	Follow Linked Lists
+md	Display memory contents
+mds	Display memory contents symbolically
+mm	Modify memory contents
+reboot	Reboot the machine
+rd	Display register contents
+rm	Modify register contents
+set	Add/change environment variable
+.TE
+.DE
+.P
+Further information on the above commands can be found in
+the appropriate manual pages.   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.
+.H 1 Writing new commands
+.H 2 Writing a built-in command
+.H 2 Writing a modular command
--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_bp.man.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_bp.man	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,131 @@
+.TH BD 1 "09 March 1999"
+.SH NAME
+bc, bd, be, bl, bp, bpa \- breakpoint commands
+.SH SYNOPSIS
+bp \fIaddress-expression\fP [\f(CWDATAR|DATAW|IO\fP [\fIlength\fP]]
+.LP
+bpa \fIaddress-expression\fP [\f(CWDATAR|DATAW|IO\fP [\fIlength\fP]]
+.LP
+bd \fIbreakpoint-number\fP
+.LP
+bc \fIbreakpoint-number\fP
+.LP
+be \fIbreakpoint-number\fP
+.LP
+bl
+.SH DESCRIPTION
+The
+.B bp 
+command is 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
+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
+Three 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.
+
+.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 
+thus placing a limit of four on the number of data and I/O 
+breakpoints that may be established.
+
+.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 will 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.
+
+.TP 8
+IO
+Enters the kernel debugger when an \fBin\fP or \fBout\fP instruction
+targets the specified I/O address.
+
+.P
+The
+.B bpa
+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 debuggers breakpoint table.   This can be used to 
+keep more than 4 breakpoints in the breakpoint table without
+exceeding the processor breakpoint register count.
+.P
+The
+.B be
+command will re-enable a disabled breakpoint.
+.P
+The
+.B bc
+command will clear a breakpoint from the breakpoint table.
+.P
+The 
+.B bl
+command will list the existing set of breakpoints.
+.SH LIMITATIONS
+Currently the kernel debugger does not use the int 03 method
+of establishing instruction breakpoints, so there may only be
+four active instruction and data breakpoints at any given time.
+.P
+There is a compile time limit of sixteen entries in the 
+breakpoint table at any one time.
+.SH ENVIRONMENT
+The breakpoint subsystem does not currently use any environment
+variables.
+.SH SMP CONSIDERATIONS
+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 'bpa' command.
+.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
+bp 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
+bp 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.
+
--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_bt.man.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_bt.man	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,67 @@
+.TH BT 1 "15 March 1999"
+.SH NAME
+bt \- Stack Traceback command
+.SH SYNOPSIS
+bt [ <stack-frame-address> ]
+.LP
+btp <pid>
+.SH DESCRIPTION
+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).
+.P
+A kernel configuration option \fBCONFIG_KDB_FRAMEPTR\fP should
+be enabled so that the compiler will utilize the frame pointer
+register properly to maintain a stack which can be correctly 
+analyzed. 
+.P
+The \fBbt\fP command will attempt to analyze the stack without
+frame pointers if the \fBCONFIG_KDB_FRAMEPTR\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).
+.SH LIMITATIONS
+If the kernel is compiled without frame pointers, stack tracebacks
+may be incomplete.  The \fBmds %esp\fP command may be useful in
+attemping to determine the actual stack traceback manually.
+.P
+The \fBbt\fP command may print more arguments for a function
+than that function accepts;  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.
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.nf
+.na
+.ft CW
+[root@host /root]# cat /proc/partitions
+Entering kdb on processor 0 due to Debug Exception @ 0xc01845e3
+Read/Write breakpoint #1 at 0xc024ddf4
+kdb> bt
+    EBP     Caller        Function(args)
+0xc74f5f44 0xc0146166  get_partition_list(0xc74d8000)
+0xc74f5f8c 0xc01463f3  get_root_array(0xc74d8000, 0x13, 0xc74f5f88, 0xf3, 0xc00)
+0xc74f5fbc 0xc0126138  array_read(0xc76cd80, 0x804aef8, 0xc00, 0xc76cdf94)
+0xbffffcd4 0xc0108b30  sys_read(0x3, 0x804aef8, 0x1000, 0x1000, 0x804aef8)
+kdb> bp
+Instruction Breakpoint #0 at 0xc0111ab8 (schedule) in dr0 is disabled on cpu 0
+Data Access Breakpoint #1 at 0xc024ddf4 (gendisk_head) in dr1 is enabled on cpu 0
+for 4 bytes
+kdb> go
+[root@host /root]# 
--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_env.man.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_env.man	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,46 @@
+.TH ENV 1 "09 March 1999"
+.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 FUTURE
+Allow compile-time initialization of customized environment
+settings.
+.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.
--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_ll.man.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_ll.man	Wed Oct 25 19:09:54 2000
@@ -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>
--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_md.man.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_md.man	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,86 @@
+.TH MD 1 "09 March 1999"
+.SH NAME
+md, mds, mm\- Memory manipulation commands
+.SH SYNOPSIS
+md [ \fIaddress-expression\fP [ \fIline-count\fP [\fIoutput-radix\fP ] ] ]
+.LP
+mds [ \fIaddress-expression\fP [ \fIline-count\fP [\fIoutput-radix\fP ] ] ]
+.LP
+mm \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 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].
+.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.
+.P
+The
+.B mm
+command allows modification of memory.   The word at the address
+represented by \fIaddress-expression\fP is changed to 
+\fInew-contents\fP.  \fInew-contents\fP is allowed to be an
+\fIaddress-expression\fP.
+.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.
+.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.
--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_rd.man.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_rd.man	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,54 @@
+.TH RD 1 "09 March 1999"
+.SH NAME
+rd, rm\- Register manipulation commands
+.SH SYNOPSIS
+rd [c|d|u]
+.LP
+rm \fIregister-name\fP \fInew-contents\fP
+.SH DESCRIPTION
+The
+.B rd 
+command is used to display the contents of processor 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.  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
+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.
+.SH LIMITATIONS
+Currently the 'rm' command will not allow modification of the
+control or debug registers.
+.P
+Currently neither the 'rd' command nor the 'rm' command will
+display or modify the model specific registers on the Pentium
+and Pentium Pro families.
+.SH ENVIRONMENT
+None.
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.TP 8
+rd
+Display general register set.
+
+.TP 8
+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.
--- linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_ss.man.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Documentation/kdb/kdb_ss.man	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,71 @@
+.TH SS 1 "29 March 1999"
+.SH NAME
+ss, ssb \- Single Step 
+.SH SYNOPSIS
+ss [<count>]
+.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
+will be printed as it is executed; 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
+None.
+.SH ENVIRONMENT
+None.
+.SH SMP CONSIDERATIONS
+Other processors will be released from the kernel debugger
+when the instruction is traced, and will be brought back to
+a barrier in the kernel debugger when the traced instruction
+completes.
+.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>
+
--- linux-2.2.18pre17.ext3-0.0.5a/Makefile.~1~	Wed Oct 25 18:57:50 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/Makefile	Wed Oct 25 19:09:54 2000
@@ -37,6 +37,7 @@
 STRIP	=$(CROSS_COMPILE)strip
 OBJCOPY	=$(CROSS_COMPILE)objcopy
 OBJDUMP	=$(CROSS_COMPILE)objdump
+AWK	=awk
 MAKE	=make
 GENKSYMS=/sbin/genksyms
 
@@ -95,7 +96,11 @@
 # standard CFLAGS
 #
 
+ifdef CONFIG_KDB_FRAMEPTR
+CFLAGS = -Wall -Wstrict-prototypes -O2 
+else
 CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+endif
 
 # use '-fno-strict-aliasing', but only if the compiler can take it
 CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi)
@@ -231,6 +236,38 @@
 boot: vmlinux
 	@$(MAKE) -C arch/$(ARCH)/boot
 
+ifeq ($(CONFIG_KDB),y)
+vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
+	echo "c0000000 t firstaddr\n" > System.map 
+	rm -f map map.out
+	$(AWK) -f scripts/genkdbsym.awk System.map > dummy_sym.c 
+	$(CC) -c -o dummy_sym.o dummy_sym.c 
+	$(LD) $(LINKFLAGS) $(HEAD) -Map map init/main.o init/version.o \
+		--start-group \
+		$(CORE_FILES) \
+		$(FILESYSTEMS) \
+		$(NETWORKS) \
+		$(DRIVERS) \
+		$(LIBS) \
+		dummy_sym.o \
+		--end-group \
+		-o vmlinux
+	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map 
+	cp System.map System.map.sv 
+	$(AWK) -f scripts/genkdbsym.awk System.map > ksym.c 
+	$(CC) -c -o ksym.o ksym.c > ksym.o 
+	$(LD) $(LINKFLAGS) $(HEAD) -Map map.out init/main.o init/version.o \
+		--start-group \
+		$(CORE_FILES) \
+		$(FILESYSTEMS) \
+		$(NETWORKS) \
+		$(DRIVERS) \
+		$(LIBS) \
+		ksym.o \
+		--end-group \
+		-o vmlinux
+	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map 
+else
 vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
 	$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
 		--start-group \
@@ -242,6 +279,7 @@
 		--end-group \
 		-o vmlinux
 	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
+endif
 
 symlinks:
 	rm -f include/asm
@@ -385,6 +423,7 @@
 		-o -regex '.*ksymoops/.*' \) -print`
 	rm -f core `find . -type f -name 'core' -print`
 	rm -f core `find . -name '.*.flags' -print`
+	rm -f ksym.[ch] dummy_sym.c System.map.sv
 	rm -f vmlinux System.map
 	rm -f .tmp*
 	rm -f drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/Makefile.~1~	Thu May  4 01:16:30 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/Makefile	Wed Oct 25 19:09:54 2000
@@ -49,6 +49,12 @@
 CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(CORE_FILES)
 LIBS := $(TOPDIR)/arch/i386/lib/lib.a $(LIBS) $(TOPDIR)/arch/i386/lib/lib.a
 
+ifdef CONFIG_KDB
+LIBS := $(LIBS) $(TOPDIR)/arch/i386/kdb/kdb.a
+CORE_FILES := $(CORE_FILES) arch/i386/kdb/kdb.o
+SUBDIRS := $(SUBDIRS) arch/i386/kdb
+endif
+
 ifdef CONFIG_MATH_EMULATION
 SUBDIRS := $(SUBDIRS) arch/i386/math-emu
 DRIVERS := $(DRIVERS) arch/i386/math-emu/math.a
@@ -59,6 +65,11 @@
 
 arch/i386/mm: dummy
 	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/mm
+
+ifdef CONFIG_KDB
+arch/i386/kdb: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/kdb
+endif
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/config.in.~1~	Wed Oct 25 18:57:50 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/config.in	Wed Oct 25 19:09:54 2000
@@ -210,5 +210,9 @@
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Built-in Kernel Debugger support' CONFIG_KDB
+if [ "$CONFIG_KDB" = "y" ]; then
+  bool 'Compile the kernel with frame pointers' CONFIG_KDB_FRAMEPTR
+fi
 endmenu
 
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/Makefile.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/Makefile	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,21 @@
+#
+# Makefile for i386-specific kdb files..
+#
+#  Copyright 1999, Silicon Graphics Inc.
+#
+#  Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+#
+
+SUB_DIRS     :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+L_TARGET = kdb.a
+L_OBJS  = kdb.o i386-dis.o kd_id.o kdbsupport.o kdb_io.o kdb_bp.o kdb_bt.o
+
+MOD_SUB_DIRS += modules
+
+include $(TOPDIR)/Rules.make
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/dis-asm.h.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/dis-asm.h	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,242 @@
+/* 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 */
+
+#ifndef DIS_ASM_H
+#define DIS_ASM_H
+
+	/*
+	 * Misc definitions
+	 */
+#define ARGS(x)	x
+#define UNINITIALIZED(x) x
+#define PTR void *
+#define FILE int
+#if !defined(NULL)
+#define NULL 0
+#endif
+
+#include <bfd.h>
+
+typedef int (*fprintf_ftype) PARAMS((FILE*, 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;
+  FILE *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;
+  /* The symbol at the start of the function being disassembled.  This
+     is not set reliably, but if it is not NULL, it is correct.  */
+  asymbol *symbol;
+
+  /* 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, 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;
+  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;
+
+  /* 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 */
+
+} 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		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_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_m32r		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m88k		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 int print_insn_d10v		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*));
+
+/* Fetch the disassembler for a given BFD, if that support is available.  */
+extern disassembler_ftype disassembler	PARAMS ((bfd *));
+
+
+/* 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 *, 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, \
+  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 seperatly.  */
+
+#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \
+  (INFO).fprintf_func = (FPRINTF_FUNC), \
+  (INFO).stream = (STREAM), \
+  (INFO).symbol = NULL, \
+  (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
+
+#endif /* ! defined (DIS_ASM_H) */
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/i386-dis.c.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/i386-dis.c	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,2307 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+   Copyright (C) 1988, 89, 91, 93, 94, 95, 96, 1997
+   Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ *  modified by John Hassey (hassey@dg-rtp.dg.com)
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual.  Usually, there is a capital letter, followed
+ * by a small letter.  The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size.  Refer to 
+ * the Intel manual for details.
+ */
+
+#include "dis-asm.h"
+#if defined(__KERNEL__)
+#include <linux/kernel.h>
+#include <linux/string.h>
+#endif
+
+#define MAXLEN 20
+
+#if defined(STANDALONE)
+#include <setjmp.h>
+#endif	/* STANDALONE */
+
+static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
+
+struct dis_private
+{
+  /* Points to first byte not fetched.  */
+  bfd_byte *max_fetched;
+  bfd_byte the_buffer[MAXLEN];
+  bfd_vma insn_start;
+#if defined(STANDALONE)
+  jmp_buf bailout;
+#endif	/* STANDALONE */
+};
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
+   on error.  */
+#define FETCH_DATA(info, addr) \
+  ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \
+   ? 1 : fetch_data ((info), (addr)))
+
+static int
+fetch_data (info, addr)
+     struct disassemble_info *info;
+     bfd_byte *addr;
+{
+  int status;
+  struct dis_private *priv = (struct dis_private *)info->private_data;
+  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
+
+  status = (*info->read_memory_func) (start,
+				      priv->max_fetched,
+				      addr - priv->max_fetched,
+				      info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, start, info);
+#if defined(STANDALONE)
+      longjmp (priv->bailout, 1);
+#else
+	/* XXX - what to do? */
+	printk("Hmm. longjmp.\n");
+#endif
+    }
+  else
+    priv->max_fetched = addr;
+  return 1;
+}
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0
+#define Mp OP_E, 0		/* ? */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rw OP_rm, w_mode
+#define Rd OP_rm, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode	/* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#if 0
+#define ONE OP_ONE, 0
+#endif
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, lptr
+#define Av OP_DIR, v_mode
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSSI, b_mode
+#define Xv OP_DSSI, v_mode
+#define Yb OP_ESDI, b_mode
+#define Yv OP_ESDI, v_mode
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+#define MX OP_MMX, 0
+#define EM OP_EM, v_mode
+#define MS OP_MS, b_mode
+
+typedef int (*op_rtn) PARAMS ((int bytemode, int aflag, int dflag));
+
+static int OP_E PARAMS ((int, int, int));
+static int OP_G PARAMS ((int, int, int));
+static int OP_I PARAMS ((int, int, int));
+static int OP_indirE PARAMS ((int, int, int));
+static int OP_sI PARAMS ((int, int, int));
+static int OP_REG PARAMS ((int, int, int));
+static int OP_J PARAMS ((int, int, int));
+static int OP_DIR PARAMS ((int, int, int));
+static int OP_OFF PARAMS ((int, int, int));
+static int OP_ESDI PARAMS ((int, int, int));
+static int OP_DSSI PARAMS ((int, int, int));
+static int OP_SEG PARAMS ((int, int, int));
+static int OP_C PARAMS ((int, int, int));
+static int OP_D PARAMS ((int, int, int));
+static int OP_T PARAMS ((int, int, int));
+static int OP_rm PARAMS ((int, int, int));
+static int OP_ST PARAMS ((int, int, int));
+static int OP_STi  PARAMS ((int, int, int));
+#if 0
+static int OP_ONE PARAMS ((int, int, int));
+#endif
+static int OP_MMX PARAMS ((int, int, int));
+static int OP_EM PARAMS ((int, int, int));
+static int OP_MS PARAMS ((int, int, int));
+
+static void append_prefix PARAMS ((void));
+static void set_op PARAMS ((int op));
+static void putop PARAMS ((char *template, int aflag, int dflag));
+static void dofloat PARAMS ((int aflag, int dflag));
+static int get16 PARAMS ((void));
+static int get32 PARAMS ((void));
+static void ckprefix PARAMS ((void));
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+#define eAX_reg 107
+#define eCX_reg 108
+#define eDX_reg 109
+#define eBX_reg 110
+#define eSP_reg 111
+#define eBP_reg 112
+#define eSI_reg 113
+#define eDI_reg 114
+
+#define lptr 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define GRP1b NULL, NULL, 0
+#define GRP1S NULL, NULL, 1
+#define GRP1Ss NULL, NULL, 2
+#define GRP2b NULL, NULL, 3
+#define GRP2S NULL, NULL, 4
+#define GRP2b_one NULL, NULL, 5
+#define GRP2S_one NULL, NULL, 6
+#define GRP2b_cl NULL, NULL, 7
+#define GRP2S_cl NULL, NULL, 8
+#define GRP3b NULL, NULL, 9
+#define GRP3S NULL, NULL, 10
+#define GRP4  NULL, NULL, 11
+#define GRP5  NULL, NULL, 12
+#define GRP6  NULL, NULL, 13
+#define GRP7 NULL, NULL, 14
+#define GRP8 NULL, NULL, 15
+#define GRP9 NULL, NULL, 16
+#define GRP10 NULL, NULL, 17
+#define GRP11 NULL, NULL, 18
+#define GRP12 NULL, NULL, 19
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE
+
+struct dis386 {
+  char *name;
+  op_rtn op1;
+  int bytemode1;
+  op_rtn op2;
+  int bytemode2;
+  op_rtn op3;
+  int bytemode3;
+};
+
+static struct dis386 dis386[] = {
+  /* 00 */
+  { "addb",	Eb, Gb },
+  { "addS",	Ev, Gv },
+  { "addb",	Gb, Eb },
+  { "addS",	Gv, Ev },
+  { "addb",	AL, Ib },
+  { "addS",	eAX, Iv },
+  { "pushS",	es },
+  { "popS",	es },
+  /* 08 */
+  { "orb",	Eb, Gb },
+  { "orS",	Ev, Gv },
+  { "orb",	Gb, Eb },
+  { "orS",	Gv, Ev },
+  { "orb",	AL, Ib },
+  { "orS",	eAX, Iv },
+  { "pushS",	cs },
+  { "(bad)" },	/* 0x0f extended opcode escape */
+  /* 10 */
+  { "adcb",	Eb, Gb },
+  { "adcS",	Ev, Gv },
+  { "adcb",	Gb, Eb },
+  { "adcS",	Gv, Ev },
+  { "adcb",	AL, Ib },
+  { "adcS",	eAX, Iv },
+  { "pushS",	ss },
+  { "popS",	ss },
+  /* 18 */
+  { "sbbb",	Eb, Gb },
+  { "sbbS",	Ev, Gv },
+  { "sbbb",	Gb, Eb },
+  { "sbbS",	Gv, Ev },
+  { "sbbb",	AL, Ib },
+  { "sbbS",	eAX, Iv },
+  { "pushS",	ds },
+  { "popS",	ds },
+  /* 20 */
+  { "andb",	Eb, Gb },
+  { "andS",	Ev, Gv },
+  { "andb",	Gb, Eb },
+  { "andS",	Gv, Ev },
+  { "andb",	AL, Ib },
+  { "andS",	eAX, Iv },
+  { "(bad)" },			/* SEG ES prefix */
+  { "daa" },
+  /* 28 */
+  { "subb",	Eb, Gb },
+  { "subS",	Ev, Gv },
+  { "subb",	Gb, Eb },
+  { "subS",	Gv, Ev },
+  { "subb",	AL, Ib },
+  { "subS",	eAX, Iv },
+  { "(bad)" },			/* SEG CS prefix */
+  { "das" },
+  /* 30 */
+  { "xorb",	Eb, Gb },
+  { "xorS",	Ev, Gv },
+  { "xorb",	Gb, Eb },
+  { "xorS",	Gv, Ev },
+  { "xorb",	AL, Ib },
+  { "xorS",	eAX, Iv },
+  { "(bad)" },			/* SEG SS prefix */
+  { "aaa" },
+  /* 38 */
+  { "cmpb",	Eb, Gb },
+  { "cmpS",	Ev, Gv },
+  { "cmpb",	Gb, Eb },
+  { "cmpS",	Gv, Ev },
+  { "cmpb",	AL, Ib },
+  { "cmpS",	eAX, Iv },
+  { "(bad)" },			/* SEG DS prefix */
+  { "aas" },
+  /* 40 */
+  { "incS",	eAX },
+  { "incS",	eCX },
+  { "incS",	eDX },
+  { "incS",	eBX },
+  { "incS",	eSP },
+  { "incS",	eBP },
+  { "incS",	eSI },
+  { "incS",	eDI },
+  /* 48 */
+  { "decS",	eAX },
+  { "decS",	eCX },
+  { "decS",	eDX },
+  { "decS",	eBX },
+  { "decS",	eSP },
+  { "decS",	eBP },
+  { "decS",	eSI },
+  { "decS",	eDI },
+  /* 50 */
+  { "pushS",	eAX },
+  { "pushS",	eCX },
+  { "pushS",	eDX },
+  { "pushS",	eBX },
+  { "pushS",	eSP },
+  { "pushS",	eBP },
+  { "pushS",	eSI },
+  { "pushS",	eDI },
+  /* 58 */
+  { "popS",	eAX },
+  { "popS",	eCX },
+  { "popS",	eDX },
+  { "popS",	eBX },
+  { "popS",	eSP },
+  { "popS",	eBP },
+  { "popS",	eSI },
+  { "popS",	eDI },
+  /* 60 */
+  { "pusha" },
+  { "popa" },
+  { "boundS",	Gv, Ma },
+  { "arpl",	Ew, Gw },
+  { "(bad)" },			/* seg fs */
+  { "(bad)" },			/* seg gs */
+  { "(bad)" },			/* op size prefix */
+  { "(bad)" },			/* adr size prefix */
+  /* 68 */
+  { "pushS",	Iv },		/* 386 book wrong */
+  { "imulS",	Gv, Ev, Iv },
+  { "pushS",	sIb },		/* push of byte really pushes 2 or 4 bytes */
+  { "imulS",	Gv, Ev, Ib },
+  { "insb",	Yb, indirDX },
+  { "insS",	Yv, indirDX },
+  { "outsb",	indirDX, Xb },
+  { "outsS",	indirDX, Xv },
+  /* 70 */
+  { "jo",	Jb },
+  { "jno",	Jb },
+  { "jb",	Jb },
+  { "jae",	Jb },
+  { "je",	Jb },
+  { "jne",	Jb },
+  { "jbe",	Jb },
+  { "ja",	Jb },
+  /* 78 */
+  { "js",	Jb },
+  { "jns",	Jb },
+  { "jp",	Jb },
+  { "jnp",	Jb },
+  { "jl",	Jb },
+  { "jnl",	Jb },
+  { "jle",	Jb },
+  { "jg",	Jb },
+  /* 80 */
+  { GRP1b },
+  { GRP1S },
+  { "(bad)" },
+  { GRP1Ss },
+  { "testb",	Eb, Gb },
+  { "testS",	Ev, Gv },
+  { "xchgb",	Eb, Gb },
+  { "xchgS",	Ev, Gv },
+  /* 88 */
+  { "movb",	Eb, Gb },
+  { "movS",	Ev, Gv },
+  { "movb",	Gb, Eb },
+  { "movS",	Gv, Ev },
+  { "movw",	Ew, Sw },
+  { "leaS",	Gv, M },
+  { "movw",	Sw, Ew },
+  { "popS",	Ev },
+  /* 90 */
+  { "nop" },
+  { "xchgS",	eCX, eAX },
+  { "xchgS",	eDX, eAX },
+  { "xchgS",	eBX, eAX },
+  { "xchgS",	eSP, eAX },
+  { "xchgS",	eBP, eAX },
+  { "xchgS",	eSI, eAX },
+  { "xchgS",	eDI, eAX },
+  /* 98 */
+  { "cWtS" },
+  { "cStd" },
+  { "lcall",	Ap },
+  { "(bad)" },		/* fwait */
+  { "pushf" },
+  { "popf" },
+  { "sahf" },
+  { "lahf" },
+  /* a0 */
+  { "movb",	AL, Ob },
+  { "movS",	eAX, Ov },
+  { "movb",	Ob, AL },
+  { "movS",	Ov, eAX },
+  { "movsb",	Yb, Xb },
+  { "movsS",	Yv, Xv },
+  { "cmpsb",	Yb, Xb },
+  { "cmpsS",	Yv, Xv },
+  /* a8 */
+  { "testb",	AL, Ib },
+  { "testS",	eAX, Iv },
+  { "stosb",	Yb, AL },
+  { "stosS",	Yv, eAX },
+  { "lodsb",	AL, Xb },
+  { "lodsS",	eAX, Xv },
+  { "scasb",	AL, Yb },
+  { "scasS",	eAX, Yv },
+  /* b0 */
+  { "movb",	AL, Ib },
+  { "movb",	CL, Ib },
+  { "movb",	DL, Ib },
+  { "movb",	BL, Ib },
+  { "movb",	AH, Ib },
+  { "movb",	CH, Ib },
+  { "movb",	DH, Ib },
+  { "movb",	BH, Ib },
+  /* b8 */
+  { "movS",	eAX, Iv },
+  { "movS",	eCX, Iv },
+  { "movS",	eDX, Iv },
+  { "movS",	eBX, Iv },
+  { "movS",	eSP, Iv },
+  { "movS",	eBP, Iv },
+  { "movS",	eSI, Iv },
+  { "movS",	eDI, Iv },
+  /* c0 */
+  { GRP2b },
+  { GRP2S },
+  { "ret",	Iw },
+  { "ret" },
+  { "lesS",	Gv, Mp },
+  { "ldsS",	Gv, Mp },
+  { "movb",	Eb, Ib },
+  { "movS",	Ev, Iv },
+  /* c8 */
+  { "enter",	Iw, Ib },
+  { "leave" },
+  { "lret",	Iw },
+  { "lret" },
+  { "int3" },
+  { "int",	Ib },
+  { "into" },
+  { "iret" },
+  /* d0 */
+  { GRP2b_one },
+  { GRP2S_one },
+  { GRP2b_cl },
+  { GRP2S_cl },
+  { "aam",	Ib },
+  { "aad",	Ib },
+  { "(bad)" },
+  { "xlat" },
+  /* d8 */
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  /* e0 */
+  { "loopne",	Jb },
+  { "loope",	Jb },
+  { "loop",	Jb },
+  { "jCcxz",	Jb },
+  { "inb",	AL, Ib },
+  { "inS",	eAX, Ib },
+  { "outb",	Ib, AL },
+  { "outS",	Ib, eAX },
+  /* e8 */
+  { "call",	Av },
+  { "jmp",	Jv },
+  { "ljmp",	Ap },
+  { "jmp",	Jb },
+  { "inb",	AL, indirDX },
+  { "inS",	eAX, indirDX },
+  { "outb",	indirDX, AL },
+  { "outS",	indirDX, eAX },
+  /* f0 */
+  { "(bad)" },			/* lock prefix */
+  { "(bad)" },
+  { "(bad)" },			/* repne */
+  { "(bad)" },			/* repz */
+  { "hlt" },
+  { "cmc" },
+  { GRP3b },
+  { GRP3S },
+  /* f8 */
+  { "clc" },
+  { "stc" },
+  { "cli" },
+  { "sti" },
+  { "cld" },
+  { "std" },
+  { GRP4 },
+  { GRP5 },
+};
+
+static struct dis386 dis386_twobyte[] = {
+  /* 00 */
+  { GRP6 },
+  { GRP7 },
+  { "larS", Gv, Ew },
+  { "lslS", Gv, Ew },  
+  { "(bad)" },
+  { "(bad)" },
+  { "clts" },
+  { "(bad)" },  
+  /* 08 */
+  { "invd" },
+  { "wbinvd" },
+  { "(bad)" },  { "ud2a" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 10 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 18 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 20 */
+  /* these are all backward in appendix A of the intel book */
+  { "movl", Rd, Cd },
+  { "movl", Rd, Dd },
+  { "movl", Cd, Rd },
+  { "movl", Dd, Rd },  
+  { "movl", Rd, Td },
+  { "(bad)" },
+  { "movl", Td, Rd },
+  { "(bad)" },  
+  /* 28 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 30 */
+  { "wrmsr" },  { "rdtsc" },  { "rdmsr" },  { "rdpmc" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 38 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 40 */
+  { "cmovo", Gv,Ev }, { "cmovno", Gv,Ev }, { "cmovb", Gv,Ev }, { "cmovae", Gv,Ev },
+  { "cmove", Gv,Ev }, { "cmovne", Gv,Ev }, { "cmovbe", Gv,Ev }, { "cmova", Gv,Ev },
+  /* 48 */
+  { "cmovs", Gv,Ev }, { "cmovns", Gv,Ev }, { "cmovp", Gv,Ev }, { "cmovnp", Gv,Ev },
+  { "cmovl", Gv,Ev }, { "cmovge", Gv,Ev }, { "cmovle", Gv,Ev }, { "cmovg", Gv,Ev },  
+  /* 50 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 58 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 60 */
+  { "punpcklbw", MX, EM },
+  { "punpcklwd", MX, EM },
+  { "punpckldq", MX, EM },
+  { "packsswb", MX, EM },
+  { "pcmpgtb", MX, EM },
+  { "pcmpgtw", MX, EM },
+  { "pcmpgtd", MX, EM },
+  { "packuswb", MX, EM },
+  /* 68 */
+  { "punpckhbw", MX, EM },
+  { "punpckhwd", MX, EM },
+  { "punpckhdq", MX, EM },
+  { "packssdw", MX, EM },
+  { "(bad)" },  { "(bad)" },
+  { "movd", MX, Ev },
+  { "movq", MX, EM },
+  /* 70 */
+  { "(bad)" },
+  { GRP10 },
+  { GRP11 },
+  { GRP12 },
+  { "pcmpeqb", MX, EM },
+  { "pcmpeqw", MX, EM },
+  { "pcmpeqd", MX, EM },
+  { "emms" },
+  /* 78 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },
+  { "movd", Ev, MX },
+  { "movq", EM, MX },
+  /* 80 */
+  { "jo", Jv },
+  { "jno", Jv },
+  { "jb", Jv },
+  { "jae", Jv },  
+  { "je", Jv },
+  { "jne", Jv },
+  { "jbe", Jv },
+  { "ja", Jv },  
+  /* 88 */
+  { "js", Jv },
+  { "jns", Jv },
+  { "jp", Jv },
+  { "jnp", Jv },  
+  { "jl", Jv },
+  { "jge", Jv },
+  { "jle", Jv },
+  { "jg", Jv },  
+  /* 90 */
+  { "seto", Eb },
+  { "setno", Eb },
+  { "setb", Eb },
+  { "setae", Eb },
+  { "sete", Eb },
+  { "setne", Eb },
+  { "setbe", Eb },
+  { "seta", Eb },
+  /* 98 */
+  { "sets", Eb },
+  { "setns", Eb },
+  { "setp", Eb },
+  { "setnp", Eb },
+  { "setl", Eb },
+  { "setge", Eb },
+  { "setle", Eb },
+  { "setg", Eb },  
+  /* a0 */
+  { "pushS", fs },
+  { "popS", fs },
+  { "cpuid" },
+  { "btS", Ev, Gv },  
+  { "shldS", Ev, Gv, Ib },
+  { "shldS", Ev, Gv, CL },
+  { "(bad)" },
+  { "(bad)" },  
+  /* a8 */
+  { "pushS", gs },
+  { "popS", gs },
+  { "rsm" },
+  { "btsS", Ev, Gv },  
+  { "shrdS", Ev, Gv, Ib },
+  { "shrdS", Ev, Gv, CL },
+  { "(bad)" },
+  { "imulS", Gv, Ev },  
+  /* b0 */
+  { "cmpxchgb", Eb, Gb },
+  { "cmpxchgS", Ev, Gv },
+  { "lssS", Gv, Mp },	/* 386 lists only Mp */
+  { "btrS", Ev, Gv },  
+  { "lfsS", Gv, Mp },	/* 386 lists only Mp */
+  { "lgsS", Gv, Mp },	/* 386 lists only Mp */
+  { "movzbS", Gv, Eb },
+  { "movzwS", Gv, Ew },  
+  /* b8 */
+  { "ud2b" },
+  { "(bad)" },
+  { GRP8 },
+  { "btcS", Ev, Gv },  
+  { "bsfS", Gv, Ev },
+  { "bsrS", Gv, Ev },
+  { "movsbS", Gv, Eb },
+  { "movswS", Gv, Ew },  
+  /* c0 */
+  { "xaddb", Eb, Gb },
+  { "xaddS", Ev, Gv },
+  { "(bad)" },
+  { "(bad)" },  
+  { "(bad)" },
+  { "(bad)" },
+  { "(bad)" },
+  { GRP9 },  
+  /* c8 */
+  { "bswap", eAX },
+  { "bswap", eCX },
+  { "bswap", eDX },
+  { "bswap", eBX },
+  { "bswap", eSP },
+  { "bswap", eBP },
+  { "bswap", eSI },
+  { "bswap", eDI },
+  /* d0 */
+  { "(bad)" },
+  { "psrlw", MX, EM },
+  { "psrld", MX, EM },
+  { "psrlq", MX, EM },
+  { "(bad)" },
+  { "pmullw", MX, EM },
+  { "(bad)" },  { "(bad)" },  
+  /* d8 */
+  { "psubusb", MX, EM },
+  { "psubusw", MX, EM },
+  { "(bad)" },
+  { "pand", MX, EM },
+  { "paddusb", MX, EM },
+  { "paddusw", MX, EM },
+  { "(bad)" },
+  { "pandn", MX, EM },
+  /* e0 */
+  { "(bad)" },
+  { "psraw", MX, EM },
+  { "psrad", MX, EM },
+  { "(bad)" },
+  { "(bad)" },
+  { "pmulhw", MX, EM },
+  { "(bad)" },  { "(bad)" },  
+  /* e8 */
+  { "psubsb", MX, EM },
+  { "psubsw", MX, EM },
+  { "(bad)" },
+  { "por", MX, EM },
+  { "paddsb", MX, EM },
+  { "paddsw", MX, EM },
+  { "(bad)" },
+  { "pxor", MX, EM },
+  /* f0 */
+  { "(bad)" },
+  { "psllw", MX, EM },
+  { "pslld", MX, EM },
+  { "psllq", MX, EM },
+  { "(bad)" },
+  { "pmaddwd", MX, EM },
+  { "(bad)" },  { "(bad)" },  
+  /* f8 */
+  { "psubb", MX, EM },
+  { "psubw", MX, EM },
+  { "psubd", MX, EM },
+  { "(bad)" },  
+  { "paddb", MX, EM },
+  { "paddw", MX, EM },
+  { "paddd", MX, EM },
+  { "(bad)" }
+};
+
+static const unsigned char onebyte_has_modrm[256] = {
+  1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+  1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+  1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+  1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
+  1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1
+};
+
+static const unsigned char twobyte_has_modrm[256] = {
+  /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
+  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+  /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1, /* 6f */
+  /* 70 */ 0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
+  /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
+  /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
+  /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,1,1,1,0,1,0,0,1,1,0,1,1,1,0,1, /* df */
+  /* e0 */ 0,1,1,0,0,1,0,0,1,1,0,1,1,1,0,1, /* ef */
+  /* f0 */ 0,1,1,1,0,1,0,0,1,1,1,0,1,1,1,0  /* ff */
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *codep;
+static disassemble_info *the_info;
+static int mod;
+static int rm;
+static int reg;
+static void oappend PARAMS ((char *s));
+
+static char *names32[]={
+  "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static char *names16[] = {
+  "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static char *names8[] = {
+  "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static char *names_seg[] = {
+  "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+static char *index16[] = {
+  "bx+si","bx+di","bp+si","bp+di","si","di","bp","bx"
+};
+
+static struct dis386 grps[][8] = {
+  /* GRP1b */
+  {
+    { "addb",	Eb, Ib },
+    { "orb",	Eb, Ib },
+    { "adcb",	Eb, Ib },
+    { "sbbb",	Eb, Ib },
+    { "andb",	Eb, Ib },
+    { "subb",	Eb, Ib },
+    { "xorb",	Eb, Ib },
+    { "cmpb",	Eb, Ib }
+  },
+  /* GRP1S */
+  {
+    { "addS",	Ev, Iv },
+    { "orS",	Ev, Iv },
+    { "adcS",	Ev, Iv },
+    { "sbbS",	Ev, Iv },
+    { "andS",	Ev, Iv },
+    { "subS",	Ev, Iv },
+    { "xorS",	Ev, Iv },
+    { "cmpS",	Ev, Iv }
+  },
+  /* GRP1Ss */
+  {
+    { "addS",	Ev, sIb },
+    { "orS",	Ev, sIb },
+    { "adcS",	Ev, sIb },
+    { "sbbS",	Ev, sIb },
+    { "andS",	Ev, sIb },
+    { "subS",	Ev, sIb },
+    { "xorS",	Ev, sIb },
+    { "cmpS",	Ev, sIb }
+  },
+  /* GRP2b */
+  {
+    { "rolb",	Eb, Ib },
+    { "rorb",	Eb, Ib },
+    { "rclb",	Eb, Ib },
+    { "rcrb",	Eb, Ib },
+    { "shlb",	Eb, Ib },
+    { "shrb",	Eb, Ib },
+    { "(bad)" },
+    { "sarb",	Eb, Ib },
+  },
+  /* GRP2S */
+  {
+    { "rolS",	Ev, Ib },
+    { "rorS",	Ev, Ib },
+    { "rclS",	Ev, Ib },
+    { "rcrS",	Ev, Ib },
+    { "shlS",	Ev, Ib },
+    { "shrS",	Ev, Ib },
+    { "(bad)" },
+    { "sarS",	Ev, Ib },
+  },
+  /* GRP2b_one */
+  {
+    { "rolb",	Eb },
+    { "rorb",	Eb },
+    { "rclb",	Eb },
+    { "rcrb",	Eb },
+    { "shlb",	Eb },
+    { "shrb",	Eb },
+    { "(bad)" },
+    { "sarb",	Eb },
+  },
+  /* GRP2S_one */
+  {
+    { "rolS",	Ev },
+    { "rorS",	Ev },
+    { "rclS",	Ev },
+    { "rcrS",	Ev },
+    { "shlS",	Ev },
+    { "shrS",	Ev },
+    { "(bad)" },
+    { "sarS",	Ev },
+  },
+  /* GRP2b_cl */
+  {
+    { "rolb",	Eb, CL },
+    { "rorb",	Eb, CL },
+    { "rclb",	Eb, CL },
+    { "rcrb",	Eb, CL },
+    { "shlb",	Eb, CL },
+    { "shrb",	Eb, CL },
+    { "(bad)" },
+    { "sarb",	Eb, CL },
+  },
+  /* GRP2S_cl */
+  {
+    { "rolS",	Ev, CL },
+    { "rorS",	Ev, CL },
+    { "rclS",	Ev, CL },
+    { "rcrS",	Ev, CL },
+    { "shlS",	Ev, CL },
+    { "shrS",	Ev, CL },
+    { "(bad)" },
+    { "sarS",	Ev, CL }
+  },
+  /* GRP3b */
+  {
+    { "testb",	Eb, Ib },
+    { "(bad)",	Eb },
+    { "notb",	Eb },
+    { "negb",	Eb },
+    { "mulb",	AL, Eb },
+    { "imulb",	AL, Eb },
+    { "divb",	AL, Eb },
+    { "idivb",	AL, Eb }
+  },
+  /* GRP3S */
+  {
+    { "testS",	Ev, Iv },
+    { "(bad)" },
+    { "notS",	Ev },
+    { "negS",	Ev },
+    { "mulS",	eAX, Ev },
+    { "imulS",	eAX, Ev },
+    { "divS",	eAX, Ev },
+    { "idivS",	eAX, Ev },
+  },
+  /* GRP4 */
+  {
+    { "incb", Eb },
+    { "decb", Eb },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* GRP5 */
+  {
+    { "incS",	Ev },
+    { "decS",	Ev },
+    { "call",	indirEv },
+    { "lcall",	indirEv },
+    { "jmp",	indirEv },
+    { "ljmp",	indirEv },
+    { "pushS",	Ev },
+    { "(bad)" },
+  },
+  /* GRP6 */
+  {
+    { "sldt",	Ew },
+    { "str",	Ew },
+    { "lldt",	Ew },
+    { "ltr",	Ew },
+    { "verr",	Ew },
+    { "verw",	Ew },
+    { "(bad)" },
+    { "(bad)" }
+  },
+  /* GRP7 */
+  {
+    { "sgdt", Ew },
+    { "sidt", Ew },
+    { "lgdt", Ew },
+    { "lidt", Ew },
+    { "smsw", Ew },
+    { "(bad)" },
+    { "lmsw", Ew },
+    { "invlpg", Ew },
+  },
+  /* GRP8 */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "btS",	Ev, Ib },
+    { "btsS",	Ev, Ib },
+    { "btrS",	Ev, Ib },
+    { "btcS",	Ev, Ib },
+  },
+  /* GRP9 */
+  {
+    { "(bad)" },
+    { "cmpxchg8b", Ev },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* GRP10 */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "psrlw", MS, Ib },
+    { "(bad)" },
+    { "psraw", MS, Ib },
+    { "(bad)" },
+    { "psllw", MS, Ib },
+    { "(bad)" },
+  },
+  /* GRP11 */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "psrld", MS, Ib },
+    { "(bad)" },
+    { "psrad", MS, Ib },
+    { "(bad)" },
+    { "pslld", MS, Ib },
+    { "(bad)" },
+  },
+  /* GRP12 */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "psrlq", MS, Ib },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "psllq", MS, Ib },
+    { "(bad)" },
+  }
+};
+
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADR 0x400
+#define PREFIX_FWAIT 0x800
+
+static int prefixes;
+
+static void
+ckprefix ()
+{
+  prefixes = 0;
+  while (1)
+    {
+      FETCH_DATA (the_info, codep + 1);
+      switch (*codep)
+	{
+	case 0xf3:
+	  prefixes |= PREFIX_REPZ;
+	  break;
+	case 0xf2:
+	  prefixes |= PREFIX_REPNZ;
+	  break;
+	case 0xf0:
+	  prefixes |= PREFIX_LOCK;
+	  break;
+	case 0x2e:
+	  prefixes |= PREFIX_CS;
+	  break;
+	case 0x36:
+	  prefixes |= PREFIX_SS;
+	  break;
+	case 0x3e:
+	  prefixes |= PREFIX_DS;
+	  break;
+	case 0x26:
+	  prefixes |= PREFIX_ES;
+	  break;
+	case 0x64:
+	  prefixes |= PREFIX_FS;
+	  break;
+	case 0x65:
+	  prefixes |= PREFIX_GS;
+	  break;
+	case 0x66:
+	  prefixes |= PREFIX_DATA;
+	  break;
+	case 0x67:
+	  prefixes |= PREFIX_ADR;
+	  break;
+	case 0x9b:
+	  prefixes |= PREFIX_FWAIT;
+	  break;
+	default:
+	  return;
+	}
+      codep++;
+    }
+}
+
+static char op1out[100], op2out[100], op3out[100];
+static int op_address[3], op_ad, op_index[3];
+static int start_pc;
+
+
+/*
+ *   On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ *   (see topic "Redundant prefixes" in the "Differences from 8086"
+ *   section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ *   be used to print the target address if this is a relative jump or call
+ * The function returns the length of this instruction in bytes.
+ */
+
+int print_insn_x86 PARAMS ((bfd_vma pc, disassemble_info *info, int aflag,
+			    int dflag));
+int
+print_insn_i386 (pc, info)
+     bfd_vma pc;
+     disassemble_info *info;
+{
+  if (info->mach == bfd_mach_i386_i386)
+    return print_insn_x86 (pc, info, 1, 1);
+  else if (info->mach == bfd_mach_i386_i8086)
+    return print_insn_x86 (pc, info, 0, 0);
+  else
+#if defined(__KERNEL__)
+    printk("Bad machine type\n");
+#else
+    abort ();
+#endif
+}
+
+int
+print_insn_x86 (pc, info, aflag, dflag)
+     bfd_vma pc;
+     disassemble_info *info;
+{
+  struct dis386 *dp;
+  int i;
+  int enter_instruction;
+  char *first, *second, *third;
+  int needcomma;
+  unsigned char need_modrm;
+
+  struct dis_private priv;
+  bfd_byte *inbuf = priv.the_buffer;
+
+  /* The output looks better if we put 5 bytes on a line, since that
+     puts long word instructions on a single line.  */
+  info->bytes_per_line = 5;
+
+  info->private_data = (PTR) &priv;
+  priv.max_fetched = priv.the_buffer;
+  priv.insn_start = pc;
+#if defined(STANDALONE)
+  if (setjmp (priv.bailout) != 0)
+    /* Error return.  */
+    return -1;
+#endif
+
+  obuf[0] = 0;
+  op1out[0] = 0;
+  op2out[0] = 0;
+  op3out[0] = 0;
+
+  op_index[0] = op_index[1] = op_index[2] = -1;
+
+  the_info = info;
+  start_pc = pc;
+  start_codep = inbuf;
+  codep = inbuf;
+  
+  ckprefix ();
+
+  FETCH_DATA (info, codep + 1);
+  if (*codep == 0xc8)
+    enter_instruction = 1;
+  else
+    enter_instruction = 0;
+  
+  obufp = obuf;
+  
+  if (prefixes & PREFIX_REPZ)
+    oappend ("repz ");
+  if (prefixes & PREFIX_REPNZ)
+    oappend ("repnz ");
+  if (prefixes & PREFIX_LOCK)
+    oappend ("lock ");
+  
+  if ((prefixes & PREFIX_FWAIT)
+      && ((*codep < 0xd8) || (*codep > 0xdf)))
+    {
+      /* fwait not followed by floating point instruction */
+      (*info->fprintf_func) (info->stream, "fwait");
+      return (1);
+    }
+  
+  if (prefixes & PREFIX_DATA)
+    dflag ^= 1;
+  
+  if (prefixes & PREFIX_ADR)
+    {
+      aflag ^= 1;
+      if (aflag)
+        oappend ("addr32 ");
+      else
+	oappend ("addr16 ");
+    }
+  
+  if (*codep == 0x0f)
+    {
+      FETCH_DATA (info, codep + 2);
+      dp = &dis386_twobyte[*++codep];
+      need_modrm = twobyte_has_modrm[*codep];
+    }
+  else
+    {
+      dp = &dis386[*codep];
+      need_modrm = onebyte_has_modrm[*codep];
+    }
+  codep++;
+
+  if (need_modrm)
+    {
+      FETCH_DATA (info, codep + 1);
+      mod = (*codep >> 6) & 3;
+      reg = (*codep >> 3) & 7;
+      rm = *codep & 7;
+    }
+
+  if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+    {
+      dofloat (aflag, dflag);
+    }
+  else
+    {
+      if (dp->name == NULL)
+	dp = &grps[dp->bytemode1][reg];
+      
+      putop (dp->name, aflag, dflag);
+      
+      obufp = op1out;
+      op_ad = 2;
+      if (dp->op1)
+	(*dp->op1)(dp->bytemode1, aflag, dflag);
+      
+      obufp = op2out;
+      op_ad = 1;
+      if (dp->op2)
+	(*dp->op2)(dp->bytemode2, aflag, dflag);
+      
+      obufp = op3out;
+      op_ad = 0;
+      if (dp->op3)
+	(*dp->op3)(dp->bytemode3, aflag, dflag);
+    }
+  
+  obufp = obuf + strlen (obuf);
+  for (i = strlen (obuf); i < 6; i++)
+    oappend (" ");
+  oappend (" ");
+  (*info->fprintf_func) (info->stream, "%s", obuf);
+  
+  /* enter instruction is printed with operands in the
+   * same order as the intel book; everything else
+   * is printed in reverse order 
+   */
+  if (enter_instruction)
+    {
+      first = op1out;
+      second = op2out;
+      third = op3out;
+      op_ad = op_index[0];
+      op_index[0] = op_index[2];
+      op_index[2] = op_ad;
+    }
+  else
+    {
+      first = op3out;
+      second = op2out;
+      third = op1out;
+    }
+  needcomma = 0;
+  if (*first)
+    {
+      if (op_index[0] != -1)
+	(*info->print_address_func) (op_address[op_index[0]], info);
+      else
+	(*info->fprintf_func) (info->stream, "%s", first);
+      needcomma = 1;
+    }
+  if (*second)
+    {
+      if (needcomma)
+	(*info->fprintf_func) (info->stream, ",");
+      if (op_index[1] != -1)
+	(*info->print_address_func) (op_address[op_index[1]], info);
+      else
+	(*info->fprintf_func) (info->stream, "%s", second);
+      needcomma = 1;
+    }
+  if (*third)
+    {
+      if (needcomma)
+	(*info->fprintf_func) (info->stream, ",");
+      if (op_index[2] != -1)
+	(*info->print_address_func) (op_address[op_index[2]], info);
+      else
+	(*info->fprintf_func) (info->stream, "%s", third);
+    }
+  return (codep - inbuf);
+}
+
+static char *float_mem[] = {
+  /* d8 */
+  "fadds",
+  "fmuls",
+  "fcoms",
+  "fcomps",
+  "fsubs",
+  "fsubrs",
+  "fdivs",
+  "fdivrs",
+  /*  d9 */
+  "flds",
+  "(bad)",
+  "fsts",
+  "fstps",
+  "fldenv",
+  "fldcw",
+  "fNstenv",
+  "fNstcw",
+  /* da */
+  "fiaddl",
+  "fimull",
+  "ficoml",
+  "ficompl",
+  "fisubl",
+  "fisubrl",
+  "fidivl",
+  "fidivrl",
+  /* db */
+  "fildl",
+  "(bad)",
+  "fistl",
+  "fistpl",
+  "(bad)",
+  "fldt",
+  "(bad)",
+  "fstpt",
+  /* dc */
+  "faddl",
+  "fmull",
+  "fcoml",
+  "fcompl",
+  "fsubl",
+  "fsubrl",
+  "fdivl",
+  "fdivrl",
+  /* dd */
+  "fldl",
+  "(bad)",
+  "fstl",
+  "fstpl",
+  "frstor",
+  "(bad)",
+  "fNsave",
+  "fNstsw",
+  /* de */
+  "fiadd",
+  "fimul",
+  "ficom",
+  "ficomp",
+  "fisub",
+  "fisubr",
+  "fidiv",
+  "fidivr",
+  /* df */
+  "fild",
+  "(bad)",
+  "fist",
+  "fistp",
+  "fbld",
+  "fildll",
+  "fbstp",
+  "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+
+#define FGRPd9_2 NULL, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1
+#define FGRPd9_5 NULL, NULL, 2
+#define FGRPd9_6 NULL, NULL, 3
+#define FGRPd9_7 NULL, NULL, 4
+#define FGRPda_5 NULL, NULL, 5
+#define FGRPdb_4 NULL, NULL, 6
+#define FGRPde_3 NULL, NULL, 7
+#define FGRPdf_4 NULL, NULL, 8
+
+static struct dis386 float_reg[][8] = {
+  /* d8 */
+  {
+    { "fadd",	ST, STi },
+    { "fmul",	ST, STi },
+    { "fcom",	STi },
+    { "fcomp",	STi },
+    { "fsub",	ST, STi },
+    { "fsubr",	ST, STi },
+    { "fdiv",	ST, STi },
+    { "fdivr",	ST, STi },
+  },
+  /* d9 */
+  {
+    { "fld",	STi },
+    { "fxch",	STi },
+    { FGRPd9_2 },
+    { "(bad)" },
+    { FGRPd9_4 },
+    { FGRPd9_5 },
+    { FGRPd9_6 },
+    { FGRPd9_7 },
+  },
+  /* da */
+  {
+    { "fcmovb",	ST, STi },
+    { "fcmove",	ST, STi },
+    { "fcmovbe",ST, STi },
+    { "fcmovu",	ST, STi },
+    { "(bad)" },
+    { FGRPda_5 },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* db */
+  {
+    { "fcmovnb",ST, STi },
+    { "fcmovne",ST, STi },
+    { "fcmovnbe",ST, STi },
+    { "fcmovnu",ST, STi },
+    { FGRPdb_4 },
+    { "fucomi",	ST, STi },
+    { "fcomi",	ST, STi },
+    { "(bad)" },
+  },
+  /* dc */
+  {
+    { "fadd",	STi, ST },
+    { "fmul",	STi, ST },
+    { "(bad)" },
+    { "(bad)" },
+    { "fsub",	STi, ST },
+    { "fsubr",	STi, ST },
+    { "fdiv",	STi, ST },
+    { "fdivr",	STi, ST },
+  },
+  /* dd */
+  {
+    { "ffree",	STi },
+    { "(bad)" },
+    { "fst",	STi },
+    { "fstp",	STi },
+    { "fucom",	STi },
+    { "fucomp",	STi },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* de */
+  {
+    { "faddp",	STi, ST },
+    { "fmulp",	STi, ST },
+    { "(bad)" },
+    { FGRPde_3 },
+    { "fsubp",	STi, ST },
+    { "fsubrp",	STi, ST },
+    { "fdivp",	STi, ST },
+    { "fdivrp",	STi, ST },
+  },
+  /* df */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { FGRPdf_4 },
+    { "fucomip",ST, STi },
+    { "fcomip", ST, STi },
+    { "(bad)" },
+  },
+};
+
+
+static char *fgrps[][8] = {
+  /* d9_2  0 */
+  {
+    "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* d9_4  1 */
+  {
+    "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+  },
+
+  /* d9_5  2 */
+  {
+    "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+  },
+
+  /* d9_6  3 */
+  {
+    "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+  },
+
+  /* d9_7  4 */
+  {
+    "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+  },
+
+  /* da_5  5 */
+  {
+    "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* db_4  6 */
+  {
+    "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+    "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+  },
+
+  /* de_3  7 */
+  {
+    "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* df_4  8 */
+  {
+    "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+};
+
+static void
+dofloat (aflag, dflag)
+     int aflag;
+     int dflag;
+{
+  struct dis386 *dp;
+  unsigned char floatop;
+  
+  floatop = codep[-1];
+  
+  if (mod != 3)
+    {
+      putop (float_mem[(floatop - 0xd8) * 8 + reg], aflag, dflag);
+      obufp = op1out;
+      OP_E (v_mode, aflag, dflag);
+      return;
+    }
+  codep++;
+  
+  dp = &float_reg[floatop - 0xd8][reg];
+  if (dp->name == NULL)
+    {
+      putop (fgrps[dp->bytemode1][rm], aflag, dflag);
+      /* instruction fnstsw is only one with strange arg */
+      if (floatop == 0xdf
+	  && FETCH_DATA (the_info, codep + 1)
+	  && *codep == 0xe0)
+	strcpy (op1out, "%eax");
+    }
+  else
+    {
+      putop (dp->name, aflag, dflag);
+      obufp = op1out;
+      if (dp->op1)
+	(*dp->op1)(dp->bytemode1, aflag, dflag);
+      obufp = op2out;
+      if (dp->op2)
+	(*dp->op2)(dp->bytemode2, aflag, dflag);
+    }
+}
+
+/* ARGSUSED */
+static int
+OP_ST (ignore, aflag, dflag)
+     int ignore;
+     int aflag;
+     int dflag;
+{
+  oappend ("%st");
+  return (0);
+}
+
+/* ARGSUSED */
+static int
+OP_STi (ignore, aflag, dflag)
+     int ignore;
+     int aflag;
+     int dflag;
+{
+  sprintf (scratchbuf, "%%st(%d)", rm);
+  oappend (scratchbuf);
+  return (0);
+}
+
+
+/* capital letters in template are macros */
+static void
+putop (template, aflag, dflag)
+     char *template;
+     int aflag;
+     int dflag;
+{
+  char *p;
+  
+  for (p = template; *p; p++)
+    {
+      switch (*p)
+	{
+	default:
+	  *obufp++ = *p;
+	  break;
+	case 'C':		/* For jcxz/jecxz */
+	  if (aflag)
+	    *obufp++ = 'e';
+	  break;
+	case 'N':
+	  if ((prefixes & PREFIX_FWAIT) == 0)
+	    *obufp++ = 'n';
+	  break;
+	case 'S':
+	  /* operand size flag */
+	  if (dflag)
+	    *obufp++ = 'l';
+	  else
+	    *obufp++ = 'w';
+	  break;
+	case 'W':
+	  /* operand size flag for cwtl, cbtw */
+	  if (dflag)
+	    *obufp++ = 'w';
+	  else
+	    *obufp++ = 'b';
+	  break;
+	}
+    }
+  *obufp = 0;
+}
+
+static void
+oappend (s)
+     char *s;
+{
+  strcpy (obufp, s);
+  obufp += strlen (s);
+  *obufp = 0;
+}
+
+static void
+append_prefix ()
+{
+  if (prefixes & PREFIX_CS)
+    oappend ("%cs:");
+  if (prefixes & PREFIX_DS)
+    oappend ("%ds:");
+  if (prefixes & PREFIX_SS)
+    oappend ("%ss:");
+  if (prefixes & PREFIX_ES)
+    oappend ("%es:");
+  if (prefixes & PREFIX_FS)
+    oappend ("%fs:");
+  if (prefixes & PREFIX_GS)
+    oappend ("%gs:");
+}
+
+static int
+OP_indirE (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  oappend ("*");
+  return OP_E (bytemode, aflag, dflag);
+}
+
+static int
+OP_E (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  int disp;
+
+  /* skip mod/rm byte */
+  codep++;
+
+  if (mod == 3)
+    {
+      switch (bytemode)
+	{
+	case b_mode:
+	  oappend (names8[rm]);
+	  break;
+	case w_mode:
+	  oappend (names16[rm]);
+	  break;
+	case v_mode:
+	  if (dflag)
+	    oappend (names32[rm]);
+	  else
+	    oappend (names16[rm]);
+	  break;
+	default:
+	  oappend ("<bad dis table>");
+	  break;
+	}
+      return 0;
+    }
+
+  disp = 0;
+  append_prefix ();
+
+  if (aflag) /* 32 bit address mode */
+    {
+      int havesib;
+      int havebase;
+      int base;
+      int index=0;
+      int scale=0;
+
+      havesib = 0;
+      havebase = 1;
+      base = rm;
+
+      if (base == 4)
+	{
+	  havesib = 1;
+	  FETCH_DATA (the_info, codep + 1);
+	  scale = (*codep >> 6) & 3;
+	  index = (*codep >> 3) & 7;
+	  base = *codep & 7;
+	  codep++;
+	}
+
+      switch (mod)
+	{
+	case 0:
+	  if (base == 5)
+	    {
+	      havebase = 0;
+	      disp = get32 ();
+	    }
+	  break;
+	case 1:
+	  FETCH_DATA (the_info, codep + 1);
+	  disp = *codep++;
+	  if ((disp & 0x80) != 0)
+	    disp -= 0x100;
+	  break;
+	case 2:
+	  disp = get32 ();
+	  break;
+	}
+
+      if (mod != 0 || base == 5)
+	{
+	  sprintf (scratchbuf, "0x%x", disp);
+	  oappend (scratchbuf);
+	}
+
+      if (havebase || (havesib && (index != 4 || scale != 0)))
+	{
+	  oappend ("(");
+	  if (havebase)
+	    oappend (names32[base]);
+	  if (havesib)
+	    {
+	      if (index != 4)
+		{
+		  sprintf (scratchbuf, ",%s", names32[index]);
+		  oappend (scratchbuf);
+		}
+	      sprintf (scratchbuf, ",%d", 1 << scale);
+	      oappend (scratchbuf);
+	    }
+	  oappend (")");
+	}
+    }
+  else
+    { /* 16 bit address mode */
+      switch (mod)
+	{
+	case 0:
+	  if (rm == 6)
+	    {
+	      disp = get16 ();
+	      if ((disp & 0x8000) != 0)
+		disp -= 0x10000;
+	    }
+	  break;
+	case 1:
+	  FETCH_DATA (the_info, codep + 1);
+	  disp = *codep++;
+	  if ((disp & 0x80) != 0)
+	    disp -= 0x100;
+	  break;
+	case 2:
+	  disp = get16 ();
+	  if ((disp & 0x8000) != 0)
+	    disp -= 0x10000;
+	  break;
+	}
+
+      if (mod != 0 || rm == 6)
+	{
+	  sprintf (scratchbuf, "0x%x", disp);
+	  oappend (scratchbuf);
+	}
+
+      if (mod != 0 || rm != 6)
+	{
+	  oappend ("(");
+	  oappend (index16[rm]);
+	  oappend (")");
+	}
+    }
+  return 0;
+}
+
+static int
+OP_G (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  switch (bytemode) 
+    {
+    case b_mode:
+      oappend (names8[reg]);
+      break;
+    case w_mode:
+      oappend (names16[reg]);
+      break;
+    case d_mode:
+      oappend (names32[reg]);
+      break;
+    case v_mode:
+      if (dflag)
+	oappend (names32[reg]);
+      else
+	oappend (names16[reg]);
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      break;
+    }
+  return (0);
+}
+
+static int
+get32 ()
+{
+  int x = 0;
+
+  FETCH_DATA (the_info, codep + 4);
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  x |= (*codep++ & 0xff) << 16;
+  x |= (*codep++ & 0xff) << 24;
+  return (x);
+}
+
+static int
+get16 ()
+{
+  int x = 0;
+
+  FETCH_DATA (the_info, codep + 2);
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  return (x);
+}
+
+static void
+set_op (op)
+     int op;
+{
+  op_index[op_ad] = op_ad;
+  op_address[op_ad] = op;
+}
+
+static int
+OP_REG (code, aflag, dflag)
+     int code;
+     int aflag;
+     int dflag;
+{
+  char *s;
+  
+  switch (code) 
+    {
+    case indir_dx_reg: s = "(%dx)"; break;
+	case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+	case sp_reg: case bp_reg: case si_reg: case di_reg:
+		s = names16[code - ax_reg];
+		break;
+	case es_reg: case ss_reg: case cs_reg:
+	case ds_reg: case fs_reg: case gs_reg:
+		s = names_seg[code - es_reg];
+		break;
+	case al_reg: case ah_reg: case cl_reg: case ch_reg:
+	case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+		s = names8[code - al_reg];
+		break;
+	case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+	case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+      if (dflag)
+	s = names32[code - eAX_reg];
+      else
+	s = names16[code - eAX_reg];
+      break;
+    default:
+      s = "<internal disassembler error>";
+      break;
+    }
+  oappend (s);
+  return (0);
+}
+
+static int
+OP_I (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  int op;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++ & 0xff;
+      break;
+    case v_mode:
+      if (dflag)
+	op = get32 ();
+      else
+	op = get16 ();
+      break;
+    case w_mode:
+      op = get16 ();
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return (0);
+    }
+  sprintf (scratchbuf, "$0x%x", op);
+  oappend (scratchbuf);
+  return (0);
+}
+
+static int
+OP_sI (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  int op;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++;
+      if ((op & 0x80) != 0)
+	op -= 0x100;
+      break;
+    case v_mode:
+      if (dflag)
+	op = get32 ();
+      else
+	{
+	  op = get16();
+	  if ((op & 0x8000) != 0)
+	    op -= 0x10000;
+	}
+      break;
+    case w_mode:
+      op = get16 ();
+      if ((op & 0x8000) != 0)
+	op -= 0x10000;
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return (0);
+    }
+  sprintf (scratchbuf, "$0x%x", op);
+  oappend (scratchbuf);
+  return (0);
+}
+
+static int
+OP_J (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  int disp;
+  int mask = -1;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      disp = *codep++;
+      if ((disp & 0x80) != 0)
+	disp -= 0x100;
+      break;
+    case v_mode:
+      if (dflag)
+	disp = get32 ();
+      else
+	{
+	  disp = get16 ();
+	  if ((disp & 0x8000) != 0)
+	    disp -= 0x10000;
+	  /* for some reason, a data16 prefix on a jump instruction
+	     means that the pc is masked to 16 bits after the
+	     displacement is added!  */
+	  mask = 0xffff;
+	}
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return (0);
+    }
+  disp = (start_pc + codep - start_codep + disp) & mask;
+  set_op (disp);
+  sprintf (scratchbuf, "0x%x", disp);
+  oappend (scratchbuf);
+  return (0);
+}
+
+/* ARGSUSED */
+static int
+OP_SEG (dummy, aflag, dflag)
+     int dummy;
+     int aflag;
+     int dflag;
+{
+  static char *sreg[] = {
+    "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+  };
+
+  oappend (sreg[reg]);
+  return (0);
+}
+
+static int
+OP_DIR (size, aflag, dflag)
+     int size;
+     int aflag;
+     int dflag;
+{
+  int seg, offset;
+  
+  switch (size) 
+    {
+    case lptr:
+      if (aflag) 
+	{
+	  offset = get32 ();
+	  seg = get16 ();
+	} 
+      else 
+	{
+	  offset = get16 ();
+	  seg = get16 ();
+	}
+      sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+      oappend (scratchbuf);
+      break;
+    case v_mode:
+      if (aflag)
+	offset = get32 ();
+      else
+	{
+	  offset = get16 ();
+	  if ((offset & 0x8000) != 0)
+	    offset -= 0x10000;
+	}
+      
+      offset = start_pc + codep - start_codep + offset;
+      set_op (offset);
+      sprintf (scratchbuf, "0x%x", offset);
+      oappend (scratchbuf);
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      break;
+    }
+  return (0);
+}
+
+/* ARGSUSED */
+static int
+OP_OFF (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  int off;
+
+  append_prefix ();
+
+  if (aflag)
+    off = get32 ();
+  else
+    off = get16 ();
+  
+  sprintf (scratchbuf, "0x%x", off);
+  oappend (scratchbuf);
+  return (0);
+}
+
+/* ARGSUSED */
+static int
+OP_ESDI (dummy, aflag, dflag)
+     int dummy;
+     int aflag;
+     int dflag;
+{
+  oappend ("%es:(");
+  oappend (aflag ? "%edi" : "%di");
+  oappend (")");
+  return (0);
+}
+
+/* ARGSUSED */
+static int
+OP_DSSI (dummy, aflag, dflag)
+     int dummy;
+     int aflag;
+     int dflag;
+{
+  oappend ("%ds:(");
+  oappend (aflag ? "%esi" : "%si");
+  oappend (")");
+  return (0);
+}
+
+#if 0
+/* Not used.  */
+
+/* ARGSUSED */
+static int
+OP_ONE (dummy, aflag, dflag)
+     int dummy;
+     int aflag;
+     int dflag;
+{
+  oappend ("1");
+  return (0);
+}
+
+#endif
+
+/* ARGSUSED */
+static int
+OP_C (dummy, aflag, dflag)
+     int dummy;
+     int aflag;
+     int dflag;
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%cr%d", reg);
+  oappend (scratchbuf);
+  return (0);
+}
+
+/* ARGSUSED */
+static int
+OP_D (dummy, aflag, dflag)
+     int dummy;
+     int aflag;
+     int dflag;
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%db%d", reg);
+  oappend (scratchbuf);
+  return (0);
+}
+
+/* ARGSUSED */
+static int
+OP_T (dummy, aflag, dflag)
+     int dummy;
+     int aflag;
+     int dflag;
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%tr%d", reg);
+  oappend (scratchbuf);
+  return (0);
+}
+
+static int
+OP_rm (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  switch (bytemode) 
+    {
+    case d_mode:
+      oappend (names32[rm]);
+      break;
+    case w_mode:
+      oappend (names16[rm]);
+      break;
+    }
+  return (0);
+}
+
+static int
+OP_MMX (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  sprintf (scratchbuf, "%%mm%d", reg);
+  oappend (scratchbuf);
+  return 0;
+}
+
+static int
+OP_EM (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  if (mod != 3)
+    return OP_E (bytemode, aflag, dflag);
+
+  codep++;
+  sprintf (scratchbuf, "%%mm%d", rm);
+  oappend (scratchbuf);
+  return 0;
+}
+
+static int
+OP_MS (bytemode, aflag, dflag)
+     int bytemode;
+     int aflag;
+     int dflag;
+{
+  ++codep;
+  sprintf (scratchbuf, "%%mm%d", rm);
+  oappend (scratchbuf);
+  return 0;
+}
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kd_id.c.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kd_id.c	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,273 @@
+/*
+ * Kernel Debugger.
+ *
+ * 	This module parses the instruction disassembly (id) command
+ *	and invokes the disassembler. 
+ *
+ * Copyright 1999, Silicon Graphics, Inc.
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ */
+
+#if defined(STANDALONE)
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include "kdb.h"
+#include "sakdbsupport.h"
+#include "dis-asm.h"
+#else
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kdb.h>
+#include "dis-asm.h"
+#include "kdbsupport.h"
+#endif
+
+static disassemble_info	kdb_di;
+
+/* ARGSUSED */
+static int
+kdbgetsym(bfd_vma addr, struct disassemble_info *dip)
+{
+
+	return 0;
+}
+
+/* ARGSUSED */
+static void
+kdbprintintaddr(bfd_vma addr, struct disassemble_info *dip, int flag)
+{
+	char	*sym = kdbnearsym(addr);
+	int	offset = 0;
+
+	if (sym) {
+		offset = addr - kdbgetsymval(sym);
+	}
+
+	/*
+	 * Print a symbol name or address as necessary.
+	 */
+	if (sym) {
+		if (offset)
+			dip->fprintf_func(dip->stream, "%s+0x%x", sym, offset);
+		else
+			dip->fprintf_func(dip->stream, "%s", sym);
+	} else {
+		dip->fprintf_func(dip->stream, "0x%x", addr);
+	}
+
+	if (flag) 
+		dip->fprintf_func(dip->stream, ":   ");
+}
+
+static void
+kdbprintaddr(bfd_vma addr, struct disassemble_info *dip)
+{
+	kdbprintintaddr(addr, dip, 0);
+}
+
+/* ARGSUSED */
+static int
+kdbgetidmem(bfd_vma addr, bfd_byte *buf, int length, struct disassemble_info *dip)
+{
+	bfd_byte	*bp = buf;
+	int		i;
+
+	/*
+	 * Fill the provided buffer with bytes from 
+	 * memory, starting at address 'addr' for 'length bytes.
+	 *
+	 */
+
+	for(i=0; i<length; i++ ){
+		*bp++ = (bfd_byte)kdbgetword(addr++, sizeof(bfd_byte));
+	}
+
+	return 0;
+}
+
+static int
+kdbfprintf(FILE* file, const char *fmt, ...)
+{
+	char buffer[256];
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsprintf(buffer, fmt, ap);
+	va_end(ap);
+
+	printk("%s", buffer);
+
+	return 0;
+}
+
+/*
+ * kdb_bt
+ *
+ * 	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)
+{
+	unsigned long		pc;
+	int			icount;
+	int			diag;
+	int			i;
+	char *			mode;
+	int			nextarg;
+	long			offset = 0;
+	static unsigned long	lastpc=0;
+
+	if (argc != 1) 
+		if (lastpc == 0)
+			return KDB_ARGCOUNT;
+		else {
+			char lastbuf[50];
+			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;
+
+	/*
+	 * Number of lines to display
+	 */
+	diag = kdbgetintenv("IDCOUNT", &icount);
+	if (diag) 
+		return diag;
+
+	mode = kdbgetenv("IDMODE");
+	if (mode) {
+		if (strcmp(mode, "x86") == 0) {
+			kdb_di.mach = bfd_mach_i386_i386;
+		} else if (strcmp(mode, "8086") == 0) {
+			kdb_di.mach = bfd_mach_i386_i8086;
+		} else {
+			return KDB_BADMODE;
+		}
+	}
+
+	for(i=0; i<icount; i++) {
+		kdbprintintaddr(pc, &kdb_di, 1);
+		pc += print_insn_i386(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;
+
+	/*
+	 * Allow the user to specify that this instruction
+	 * should be treated as a 16-bit insn.
+	 */
+	mode = kdbgetenv("IDMODE");
+	if (mode) {
+		kdb_di.mach = bfd_mach_i386_i386;
+		if (strcmp(mode, "8086") == 0) {
+			kdb_di.mach = bfd_mach_i386_i8086;
+		}
+	}
+
+	kdbprintintaddr(pc, &kdb_di, 1);
+	(void) print_insn_i386(pc, &kdb_di);
+	kdb_printf("\n");
+}
+
+/*
+ * 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
+kdb_disinit(void)
+{
+	kdb_di.fprintf_func     = kdbfprintf;
+	kdb_di.stream	    = NULL;
+	kdb_di.application_data = NULL;
+	kdb_di.flavour          = bfd_target_elf_flavour;
+	kdb_di.arch		    = bfd_arch_i386;
+	kdb_di.mach		    = bfd_mach_i386_i386;
+	kdb_di.endian	    = BFD_ENDIAN_LITTLE;
+	kdb_di.symbol	    = NULL;
+	kdb_di.flags	    = 0;
+	kdb_di.private_data	    = NULL;
+	kdb_di.read_memory_func = kdbgetidmem;
+	kdb_di.print_address_func = kdbprintaddr;
+	kdb_di.symbol_at_address_func = kdbgetsym;
+	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.display_endian   = BFD_ENDIAN_LITTLE;
+	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;
+}
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdb.c.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdb.c	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,1756 @@
+/*
+ * Minimalist Kernel Debugger 
+ *
+ * Copyright 1999, Silicon Graphics, Inc.
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ *
+ * Modifications from:
+ *	Richard Bass			1999/07/20
+ *		Many bug fixes and enhancements.
+ *
+ */
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#if defined(__SMP__)
+#include <linux/smp.h>
+#endif
+#include <linux/kdb.h>
+#include <asm/system.h>
+#include "kdbsupport.h"
+
+int kdb_active = 0;
+int kdb_flags = 0;
+int kdb_nextline = 1;
+int kdb_new_cpu = -1;
+
+kdb_jmp_buf	kdbjmpbuf;
+
+	/*
+	 * Describe the command table.
+	 */
+typedef struct _kdbtab {
+	char	*cmd_name;	/* Command name */
+	kdb_func 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 */
+} kdbtab_t;
+
+	/*
+	 * Provide space for KDB_MAX_COMMANDS commands.
+ 	 */
+#define KDB_MAX_COMMANDS	100
+
+static kdbtab_t kdb_commands[KDB_MAX_COMMANDS];
+
+	/*
+	 * Error messages.  XXX - use a macro for this...
+	 */
+static char kdb_notfound[]   = "Command Not Found";
+static char kdb_argcount[]   = "Improper argument count, see usage.";
+static char kdb_badwidth[]   = "Illegal value for BYTESPERWORD use 1, 2 or 4";
+static char kdb_badradix[]   = "Illegal value for RADIX use 8, 10 or 16";
+static char kdb_notenv[]     = "Cannot find environment variable";
+static char kdb_noenvvalue[] = "Environment variable should have value";
+static char kdb_notimp[]     = "Command not implemented";
+static char kdb_envfull[]    = "Environment full";
+static char kdb_envbuffull[] = "Environment buffer full";
+static char kdb_toomanybpt[]  = "Too many breakpoints defined";
+static char kdb_toomanydbregs[] = "More breakpoints than db registers defined";
+static char kdb_dupbpt[]     = "Duplicate breakpoint address";
+static char kdb_bptnotfound[] = "Breakpoint not found";
+static char kdb_badmode[]    = "IDMODE should be x86 or 8086";
+static char kdb_badint[]     = "Illegal numeric value";
+static char kdb_invaddrfmt[] = "Invalid symbolic address format";
+static char kdb_badreg[]     = "Invalid register name";
+static char kdb_badcpunum[]  = "Invalid cpu number";
+static char kdb_badlength[]  = "Invalid length field";
+static char kdb_nobp[]       = "No Breakpoint exists";
+
+static char *kdb_messages[] = {
+	(char *)0,
+	kdb_notfound, 
+	(char *)0,
+	kdb_argcount,
+	kdb_badwidth,
+	kdb_badradix,
+	kdb_notenv,
+	kdb_noenvvalue,
+	kdb_notimp,
+	kdb_envfull,
+	kdb_envbuffull,
+	kdb_toomanybpt,
+	kdb_toomanydbregs,
+	kdb_dupbpt,
+	kdb_bptnotfound,
+	kdb_badmode,
+	kdb_badint,
+	kdb_invaddrfmt,
+	kdb_badreg,
+	(char *)0,   /* KDB_CPUSWITCH */
+	kdb_badcpunum,
+	kdb_badlength,
+	kdb_nobp,
+	(char *)0
+};
+static const int __nkdb_err = sizeof(kdb_messages) / sizeof(char *);
+
+
+/*
+ * 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).
+ */
+
+#if defined(CONFIG_SMP)
+static char prompt_str[] = "PROMPT=[%d]kdb> ";
+static char more_str[] = "MOREPROMPT=[%d]more> ";
+#else
+static char prompt_str[] = "PROMPT=kdb> ";
+static char more_str[] = "MOREPROMPT=more> ";
+#endif
+static char radix_str[] = "RADIX=16";
+static char lines_str[] = "LINES=24";
+static char columns_str[] = "COLUMNS=80";
+static char mdcount_str[] = "MDCOUNT=8";	/* lines of md output */
+static char idcount_str[] = "IDCOUNT=16";	/* lines of id output */
+static char bperword_str[] = "BYTESPERWORD=4";	/* Word size for md output */
+static char idmode_str[] = "IDMODE=x86";	/* 32-bit mode */
+static char btargs_str[] = "BTARGS=5";		/* 5 possible args in bt */
+static char sscount_str[] = "SSCOUNT=20";	/* lines of ssb output */
+
+static char *__env[] = {
+	bperword_str,
+	columns_str,
+	idcount_str,
+	lines_str,
+	mdcount_str,
+	prompt_str, 
+	radix_str, 
+	idmode_str,
+	btargs_str,
+	sscount_str,
+	more_str,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0,
+	(char *)0
+};
+static const int __nenv = (sizeof(__env) / sizeof(char *));
+
+/*
+ * kdbgetenv
+ *
+ *	This function will return the character string value of
+ *	an environment variable.
+ *
+ * Parameters:
+ *	match	A character string representing an environment variable.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	NULL	No environment variable matches 'match'
+ *	char*	Pointer to string value of environment variable.
+ * Locking:
+ *	No locking considerations required.
+ * Remarks:
+ */
+char *
+kdbgetenv(const char *match)
+{
+	char **ep = __env;
+	int    matchlen = strlen(match);
+	int i;
+
+	for(i=0; i<__nenv; i++) {
+		char *e = *ep++;
+
+		if (!e) continue;
+
+		if ((strncmp(match, e, matchlen) == 0)
+		 && ((e[matchlen] == '\0')
+		   ||(e[matchlen] == '='))) {
+			char *cp = strchr(e, '=');
+			return (cp)?++cp:"";
+		}
+	}
+	return (char *)0;
+}
+
+/*
+ * kdballocenv
+ *
+ *	This function is used to allocate bytes for environment entries. 
+ *
+ * Parameters:
+ *	match	A character string representing a numeric value
+ * Outputs:
+ *	*value  the unsigned long represntation of the env variable 'match'
+ * Returns:
+ *	Zero on success, a kdb diagnostic on failure.
+ * Locking:
+ *	No locking considerations required.  Must be called with all 
+ *	processors halted.
+ * Remarks:
+ *	We use a static environment buffer (envbuffer) to hold the values
+ *	of dynamically generated environment variables (see kdb_set).  Buffer
+ *	space once allocated is never free'd, so over time, the amount of space
+ *	(currently 512 bytes) will be exhausted if env variables are changed
+ *	frequently.
+ */
+static char *
+kdballocenv(size_t bytes)
+{
+#define	KDB_ENVBUFSIZE	512
+	static char envbuffer[KDB_ENVBUFSIZE];
+	static int  envbufsize = 0;
+	char *ep = (char *)0;
+
+	if ((KDB_ENVBUFSIZE - envbufsize) >= bytes) {
+		ep = &envbuffer[envbufsize];
+		envbufsize += bytes;
+	}
+	return ep;
+}
+
+/*
+ * kdbgetulenv
+ *
+ *	This function will return the value of an unsigned long-valued
+ *	environment variable.
+ *
+ * Parameters:
+ *	match	A character string representing a numeric value
+ * Outputs:
+ *	*value  the unsigned long represntation of the env variable 'match'
+ * Returns:
+ *	Zero on success, a kdb diagnostic on failure.
+ * Locking:
+ *	No locking considerations required.
+ * Remarks:
+ */
+
+int
+kdbgetulenv(const char *match, unsigned long *value) 
+{
+	char *ep;
+
+	ep = kdbgetenv(match);
+	if (!ep) return KDB_NOTENV;
+	if (strlen(ep) == 0) return KDB_NOENVVALUE;
+
+	*value = simple_strtoul(ep, 0, 0);
+
+	return 0;
+}
+	
+/*
+ * kdbgetintenv
+ *
+ *	This function will return the value of an integer-valued
+ *	environment variable.
+ *
+ * Parameters:
+ *	match	A character string representing an integer-valued env variable
+ * Outputs:
+ *	*value  the integer representation of the environment variable 'match'
+ * Returns:
+ *	Zero on success, a kdb diagnostic on failure.
+ * Locking:
+ *	No locking considerations required.
+ * Remarks:
+ */
+
+int
+kdbgetintenv(const char *match, int *value) {
+	unsigned long val;
+	int           diag;
+
+	diag = kdbgetulenv(match, &val);
+	if (!diag) {
+		*value = (int) val;
+	}
+	return diag;
+}
+
+/*
+ * kdbgetularg
+ *
+ *	This function will convert a numeric string
+ *	into an unsigned long value.
+ *
+ * Parameters:
+ *	arg	A character string representing a numeric value
+ * Outputs:
+ *	*value  the unsigned long represntation of arg.
+ * Returns:
+ *	Zero on success, a kdb diagnostic on failure.
+ * Locking:
+ *	No locking considerations required.
+ * Remarks:
+ */
+
+int
+kdbgetularg(const char *arg, unsigned long *value)
+{
+	char *endp;
+	unsigned long val;
+
+	val = simple_strtoul(arg, &endp, 0);
+
+	if (endp == arg) {
+		/*
+		 * Try base 16, for us folks too lazy to type the
+		 * leading 0x...
+		 */
+		val = simple_strtoul(arg, &endp, 16);
+		if (endp == arg)
+			return KDB_BADINT;
+	}
+
+	*value = val;
+
+	return 0;
+}
+
+/*
+ * 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[]
+ *
+ * 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, 
+	      unsigned long *value,  long *offset, 
+	      char **name, struct pt_regs *regs)
+{
+	unsigned long addr;
+	long	      off = 0;
+	int	      positive;
+	int	      diag;
+	char	     *symname;
+	char	      symbol = '\0';
+	char	     *cp;
+
+	/*
+	 * 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 = kdbgetregcontents(&symname[1], regs, &addr);
+		if (diag) 
+			return diag;
+	} else {
+		addr = kdbgetsymval(symname);
+		if (addr == 0) {
+			diag = kdbgetularg(argv[*nextarg], &addr);
+			if (diag) 
+				return diag;
+		}
+	}
+
+	symname = kdbnearsym(addr);
+
+	(*nextarg)++;
+
+	if (name)
+		*name = symname; 
+	if (value) 
+		*value = addr;
+	if (offset && name && *name)
+		*offset = addr - kdbgetsymval(*name);
+	
+	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)
+{
+	if (diag >= 0) {
+		kdb_printf("no error detected\n");
+		return;
+	}
+	diag = -diag;
+	if (diag >= __nkdb_err) {
+		kdb_printf("Illegal diag %d\n", -diag);
+		return;
+	}
+	kdb_printf("diag: %d: %s\n", diag, kdb_messages[diag]);
+}
+
+/*
+ * kdb_parse
+ *
+ *	Parse the command line, search the command table for a 
+ *	matching command and invoke the command function.
+ *	
+ * 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
+
+static int
+kdb_parse(char *cmdstr, struct pt_regs *regs)
+{
+	char *argv[MAXARGC];
+	int  argc=0;
+	char *cp;
+	kdbtab_t *tp;
+	int i;
+
+	/*
+	 * First tokenize the command string.   
+	 */
+	cp = cmdstr;
+
+	/*
+	 * If a null statement is provided, do nothing.
+	 */
+	if ((*cp == '\n') || (*cp == '\0'))
+		return 0;
+
+	while (*cp) {
+		/* skip whitespace */
+		while (isspace(*cp)) cp++;
+		if ((*cp == '\0') || (*cp == '\n'))
+			break;
+		argv[argc++] = cp;
+		/* Skip to next whitespace */
+		for(; *cp && (!isspace(*cp) && (*cp != '=')); cp++);
+		*cp++ = '\0';		/* Squash a ws or '=' character */
+	}
+
+	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 (i < KDB_MAX_COMMANDS) {
+		return (*tp->cmd_func)(argc-1, 
+				       (const char**)argv, 
+				       (const char**)__env, 
+				       regs);
+	}
+
+	/*
+	 * 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.
+	 */
+	{
+		unsigned long 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 = 0x%8.8x  ", argv[0], value);
+		if (name) {
+			kdb_printf("(%s+0x%lx)", name, offset);
+		}
+		kdb_printf("\n");
+		return 0;
+	}
+}
+
+/*
+ * 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_ENTER
+ *	(XXX - note that the regs aren't set up this way - could
+ *	       use a software interrupt to enter kdb to get regs...)
+ *
+ *	The breakpoint trap code should invoke this function with
+ *	one of KDB_REASON_BREAK (int 03) or KDB_REASON_DEBUG (debug register)
+ *
+ *	the panic function should invoke this function with 
+ *	KDB_REASON_PANIC.
+ *
+ *	The kernel fault handler should invoke this function with
+ *	reason == KDB_REASON_FAULT and error == trap vector #.
+ *
+ * Inputs:
+ *	reason		The reason KDB was invoked
+ *	error		The hardware-defined error code
+ *	regs		The registers at time of fault/breakpoint
+ * Outputs:
+ *	none
+ * 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.
+ */
+
+int
+kdb(int reason, int error, struct pt_regs *regs)
+{
+	char	cmdbuf[255];
+	char	*cmd;
+	int	diag;
+	unsigned long flags;
+	struct  pt_regs func_regs;
+
+	kdb_new_cpu = -1;
+
+	/*
+	 * Remove the breakpoints to prevent double-faults
+	 * if kdb happens to use a function where a breakpoint
+	 * has been enabled.
+	 */
+
+	kdb_bp_remove();
+
+	if (reason != KDB_REASON_DEBUG) {
+		kdb_printf("Entering kdb ");
+#if defined(__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.
+		 */
+		diag = kdb_db_trap(regs);
+		if (diag == 0) {
+			kdb_printf("Entering kdb ");
+#if defined(__SMP__)
+			kdb_printf("on processor %d ", smp_processor_id());
+#endif
+		} else if (diag == 2) {
+			/*
+			 * in middle of ssb command.  Just return.
+			 */
+			return 0;
+		}
+		break;
+	case KDB_REASON_FAULT:
+		break;
+	case KDB_REASON_INT:
+		kdb_printf("due to KDB_ENTER() call\n");
+		break;
+	case KDB_REASON_KEYBOARD:
+		kdb_printf("due to Keyboard Entry\n");
+		break;
+	case KDB_REASON_SWITCH:
+		kdb_printf("due to cpu switch\n");
+		break;
+	case KDB_REASON_ENTER:
+		kdb_printf("due to function call\n");
+		regs = &func_regs;
+		regs->xcs = 0;
+#if defined(CONFIG_KDB_FRAMEPTR)
+		asm volatile("movl %%ebp,%0":"=m" (*(int *)&regs->ebp));
+#endif
+		asm volatile("movl %%esp,%0":"=m" (*(int *)&regs->esp));
+		regs->eip = (long) &kdb;	/* for traceback. */
+		break;
+	case KDB_REASON_PANIC:
+		kdb_printf("due to panic @ 0x%8.8x\n", regs->eip);
+		kdbdumpregs(regs, NULL, NULL);
+		break;
+	case KDB_REASON_BREAK:
+		kdb_printf("due to Breakpoint @ 0x%8.8x\n", regs->eip);
+		break;
+	default:
+		break;
+	}
+
+#if defined(__SMP__)
+	/*
+	 * If SMP, stop other processors
+	 */
+	if (smp_num_cpus > 1) {
+		/*
+		 * Stop all other processors
+		 */
+		smp_kdb_stop(1);
+	}
+#endif	/* __SMP__ */
+
+	/*
+	 * Disable interrupts during kdb command processing 
+	 */
+	__save_flags(flags);
+	__cli();
+
+	while (1) {
+		/*
+		 * Initialize pager context.
+		 */
+		kdb_nextline = 1;
+
+		/*
+		 * Use kdb_setjmp/kdb_longjmp to break out of 
+		 * the pager early.
+		 */
+		if (kdb_setjmp(&kdbjmpbuf)) {
+			/*
+			 * Command aborted (usually in pager)
+			 */
+
+			/*
+		 	 * XXX - need to abort a SSB ?
+			 */
+			continue;
+		}
+
+		/*
+		 * Fetch command from keyboard
+		 */
+		cmd = kbd_getstr(cmdbuf, sizeof(cmdbuf), kdbgetenv("PROMPT"));
+
+		diag = kdb_parse(cmd, regs);
+		if (diag == KDB_NOTFOUND) {
+			kdb_printf("Unknown kdb command: '%s'\n", cmd);
+			diag = 0;
+		}
+		if ((diag == KDB_GO)
+		 || (diag == KDB_CPUSWITCH))
+			break;	/* Go or cpu switch command */
+
+		if (diag)
+			kdb_cmderror(diag);
+	}
+
+	/*
+	 * Set up debug registers.
+	 */
+	kdb_bp_install();
+
+#if defined(__SMP__)
+	if ((diag == KDB_CPUSWITCH)
+	 && (kdb_new_cpu != -1)) {
+		/*
+		 * Leaving the other CPU's at the barrier, except the
+		 * one we are switching to, we'll send ourselves a 
+		 * kdb IPI before allowing interrupts so it will get
+		 * caught ASAP and get this CPU back waiting at the barrier.
+		 */
+		
+		smp_kdb_stop(0);	/* Stop ourself */
+
+		/*
+	 	 * let the new cpu go.
+		 */
+		clear_bit(kdb_new_cpu, &smp_kdb_wait);
+	} else {
+		/*
+		 * Let the other processors continue.
+		 */
+		smp_kdb_wait = 0;
+	}
+#endif
+
+	kdb_flags &= ~(KDB_FLAG_SUPRESS|KDB_FLAG_FAULT);
+
+	__restore_flags(flags);
+
+
+	return 0;
+}
+
+/*
+ * kdb_md
+ *
+ *	This function implements the 'md' and 'mds' commands.
+ *
+ *	md|mds  [<addr arg> [<line count> [<radix>]]]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_md(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	char fmtchar;
+	char fmtstr[64];
+	int radix, count, width;
+	unsigned long addr;
+	unsigned long word;
+	long	offset = 0;
+	int	diag;
+	int	nextarg;
+	static unsigned long lastaddr = 0;
+	static unsigned long lastcount = 0;
+	static unsigned long lastradix = 0;
+	char	lastbuf[50];
+	int	symbolic = 0;
+
+	/*
+	 * Defaults in case the relevent environment variables are unset
+	 */
+	radix = 16;
+	count = 8;
+	width = 4;
+
+	if (argc == 0) {
+		if (lastaddr == 0)
+			return KDB_ARGCOUNT;
+		sprintf(lastbuf, "0x%lx", lastaddr);
+		argv[1] = lastbuf;
+		argc = 1;
+		count = lastcount;
+		radix = lastradix;
+	} else {
+		unsigned long val;
+
+		if (argc >= 2) { 
+
+			diag = kdbgetularg(argv[2], &val);
+			if (!diag) 
+				count = (int) val;
+		} else {
+			diag = kdbgetintenv("MDCOUNT", &count);
+		}
+
+		if (argc >= 3) {
+			diag = kdbgetularg(argv[3], &val);
+			if (!diag) 
+				radix = (int) val;
+		} else {
+			diag = kdbgetintenv("RADIX",&radix);
+		}
+	}
+
+	switch (radix) {
+	case 10:
+		fmtchar = 'd';
+		break;
+	case 16:
+		fmtchar = 'x';
+		break;
+	case 8:
+		fmtchar = 'o';
+		break;
+	default:
+		return KDB_BADRADIX;
+	}
+
+	diag = kdbgetintenv("BYTESPERWORD", &width);
+
+	if (strcmp(argv[0], "mds") == 0) {
+		symbolic = 1;
+		width = 4;
+	}
+
+	switch (width) {
+	case 4:
+		sprintf(fmtstr, "%%8.8%c ", fmtchar);
+		break;
+	case 2:
+		sprintf(fmtstr, "%%4.4%c ", fmtchar);
+		break;
+	case 1:
+		sprintf(fmtstr, "%%2.2%c ", fmtchar);
+		break;
+	default:
+		return KDB_BADWIDTH;
+	}
+
+	
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+	if (diag)
+		return diag;
+
+	/* Round address down modulo BYTESPERWORD */
+	
+	addr &= ~(width-1);
+
+	/*
+	 * Remember count and radix for next 'md'
+	 */
+	lastcount = count;
+	lastradix = radix;
+
+	while (count--) {
+		int	num = (symbolic?1 :(16 / width));
+		char	cbuf[32];
+		char	*c = cbuf;
+		char	t;
+		int     i;
+	
+		for(i=0; i<sizeof(cbuf); i++) {
+			cbuf[i] = '\0';
+		}
+
+		kdb_printf("%8.8x: ", addr);
+	
+		for(i=0; i<num; i++) {
+			char *name = NULL;
+
+			word = kdbgetword(addr, width);
+			if (kdb_flags & KDB_FLAG_SUPRESS) {
+				kdb_flags &= ~KDB_FLAG_SUPRESS;
+				return 0;  /* Error message already printed */
+			}
+
+			kdb_printf(fmtstr, word);
+			if (symbolic) {
+				name = kdbnearsym(word);
+			}
+			if (name) {
+				unsigned long offset;
+	
+				offset = word - kdbgetsymval(name);
+				kdb_printf("%s+0x%x", name, offset);
+				addr += 4;
+			} else {
+				switch (width) {
+				case 4:
+					*c++ = isprint(t=kdbgetword(addr++, 1))
+							?t:'.'; 
+					*c++ = isprint(t=kdbgetword(addr++, 1))
+							?t:'.'; 
+				case 2:
+					*c++ = isprint(t=kdbgetword(addr++, 1))
+							?t:'.'; 
+				case 1:
+					*c++ = isprint(t=kdbgetword(addr++, 1))
+							?t:'.'; 
+					break;
+				}
+			}
+		}
+		kdb_printf(" %s\n", cbuf);
+	}
+
+	lastaddr = 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:
+ *	Restricted to working on 4-byte words at this time.
+ */
+
+int
+kdb_mm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	unsigned long addr;
+	long 	      offset = 0;
+	unsigned long contents;
+	unsigned long word;
+	int nextarg;
+
+	if (argc != 2) {
+		return KDB_ARGCOUNT;
+	}
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+	if (diag)
+		return diag;
+
+	if (nextarg > argc) 
+		return KDB_ARGCOUNT;
+
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &contents, NULL, NULL, regs);
+	if (diag)
+		return diag;
+
+	if (nextarg != argc + 1)
+		return KDB_ARGCOUNT;
+
+	/*
+	 * To prevent modification of invalid addresses, check first.
+	 */
+	word = kdbgetword(addr, sizeof(word));
+	if (kdb_flags & KDB_FLAG_SUPRESS) {
+		kdb_flags &= ~KDB_FLAG_SUPRESS;
+		return 0;
+	}
+
+	*(unsigned long *)(addr) = contents;
+
+	kdb_printf("0x%x = 0x%x\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:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_go(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	unsigned long addr;
+	int diag;
+	int nextarg;
+	long offset;
+
+	if (argc == 1) {
+		nextarg = 1;
+		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+		if (diag)
+			return diag;
+
+		regs->eip = addr;
+	} else if (argc) 
+		return KDB_ARGCOUNT;
+
+	return KDB_GO;
+}
+
+/*
+ * kdb_rd
+ *
+ *	This function implements the 'rd' command.
+ *
+ *	rd		display all general registers.
+ *	rd  c		display all control registers.
+ *	rd  d		display all debug registers.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_rd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	/*
+	 */
+	
+	if (argc == 0) {
+		return kdbdumpregs(regs, NULL, NULL);
+	} 
+
+	if (argc > 2) {
+		return KDB_ARGCOUNT;
+	}
+
+	return kdbdumpregs(regs, argv[1], argv[2]);
+}
+
+/*
+ * kdb_rm
+ *
+ *	This function implements the 'rm' (register modify)  command.
+ *
+ *	rm register-name new-contents
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	Currently doesn't allow modification of control or
+ *	debug registers, nor does it allow modification 
+ *	of model-specific registers (MSR).
+ */
+
+int
+kdb_rm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	int ind = 0;
+	unsigned long 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 = kdbsetregcontents(&argv[1][ind], regs, contents);
+	if (diag)
+		return diag;
+
+	return 0;
+}
+
+/*
+ * kdb_ef
+ *
+ *	This function implements the 'ef' (display exception frame) 
+ *	command.  This command takes an address and expects to find
+ *	an exception frame at that address, formats and prints it.
+ *
+ *	ef address-expression
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	Not done yet.
+ */
+
+int
+kdb_ef(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+
+	return KDB_NOTIMP;
+}
+
+/*
+ * kdb_reboot
+ *
+ *	This function implements the 'reboot' command.  Reboot the system
+ *	immediately.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	Shouldn't return from this function.
+ */
+
+int 
+kdb_reboot(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	machine_restart(0);
+	/* NOTREACHED */
+	return 0;
+}
+
+/*
+ * kdb_env
+ *
+ *	This function implements the 'env' command.  Display the current
+ *	environment variables.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_env(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int i;
+
+	for(i=0; i<__nenv; i++) {
+		if (__env[i]) {
+			kdb_printf("%s\n", __env[i]);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * kdb_set
+ *
+ *	This function implements the 'set' command.  Alter an existing
+ *	environment variable or create a new one.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_set(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int i;
+	char *ep;
+	size_t varlen, vallen;
+
+	/*
+	 * we can be invoked two ways:
+	 *   set var=value    argv[1]="var", argv[2]="value"
+	 *   set var = value  argv[1]="var", argv[2]="=", argv[3]="value"
+	 * - if the latter, shift 'em down.
+	 */
+	if (argc == 3) {
+		argv[2] = argv[3];
+		argc--;
+	}
+
+	if (argc != 2) 
+		return KDB_ARGCOUNT;
+
+	/*
+	 * 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;
+}
+
+#if defined(__SMP__)
+/*
+ * 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:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_cpu(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	unsigned long cpunum;
+	int diag;
+
+	if (argc == 0) {
+		int i;
+
+		kdb_printf("Currently on cpu %d\n", smp_processor_id());
+		kdb_printf("Available cpus: ");
+		for (i=0; i<NR_CPUS; i++) {
+			if (test_bit(i, &cpu_online_map)) {
+				if (i) kdb_printf(", ");
+				kdb_printf("%d", i);
+			}
+		}
+		kdb_printf("\n");
+		return 0;
+	}
+
+	if (argc != 1) 
+		return KDB_ARGCOUNT;
+
+	diag = kdbgetularg(argv[1], &cpunum);
+	if (diag)
+		return diag;
+
+	/*
+	 * Validate cpunum
+	 */
+	if ((cpunum > NR_CPUS)
+	 || !test_bit(cpunum, &cpu_online_map))
+		return KDB_BADCPUNUM;
+
+	kdb_new_cpu = cpunum;
+
+	/*
+	 * Switch to other cpu
+	 */
+	return KDB_CPUSWITCH;
+}
+#endif	/* __SMP__ */
+
+/*
+ * kdb_ps
+ *
+ *	This function implements the 'ps' command which shows
+ *	a list of the active processes.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_ps(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct task_struct	*p;
+
+	kdb_printf("Task Addr     Pid       Parent   cpu  lcpu    Tss     Command\n");
+	for_each_task(p) {
+		kdb_printf("0x%8.8x %10.10d %10.10d %4.4d %4.4d 0x%8.8x %s\n",
+			   p, p->pid, p->p_pptr->pid, p->processor, 
+			   p->last_processor,
+			   &p->tss,
+			   p->comm);
+	}
+
+	return 0;
+}
+
+/*
+ * kdb_ll
+ *
+ *	This function implements the 'll' command which follows a linked
+ *	list and executes an arbitrary command for each element.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_ll(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	unsigned long addr;
+	long 	      offset = 0;
+	unsigned long va;
+	unsigned long linkoffset;
+	int nextarg;
+
+	if (argc != 3) {
+		return KDB_ARGCOUNT;
+	}
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+	if (diag)
+		return diag;
+
+	diag = kdbgetularg(argv[2], &linkoffset);
+	if (diag)
+		return diag;
+
+	/*
+	 * Using the starting address as 
+	 * the first element in the list, and assuming that
+	 * the list ends with a null pointer.
+	 */
+
+	va = addr;
+
+	while (va) {
+		char buf[80];
+
+		sprintf(buf, "%s 0x%lx\n", argv[3], va);
+		diag = kdb_parse(buf, regs);
+		if (diag)
+			return diag;
+
+		addr = va + linkoffset;
+		va = kdbgetword(addr, sizeof(va));
+		if (kdb_flags & KDB_FLAG_SUPRESS) {
+			kdb_flags &= ~KDB_FLAG_SUPRESS;
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * kdb_help
+ *
+ *	This function implements the 'help' and '?' commands.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+
+int
+kdb_help(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	kdbtab_t *kt;
+
+	kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
+	kdb_printf("----------------------------------------------------------\n");
+	for(kt=kdb_commands; kt->cmd_name; kt++) {
+		kdb_printf("%-15.15s %-20.20s %s\n", kt->cmd_name, 
+			kt->cmd_usage, kt->cmd_help);
+	}
+	return 0;
+}
+
+/*
+ * kdb_register
+ *
+ *	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
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, one if a duplicate command.
+ * Locking:
+ *	none.
+ * Remarks:
+ *
+ */
+
+int
+kdb_register(char *cmd, 
+	     kdb_func func, 
+	     char *usage,
+	     char *help, 
+	     short minlen)
+{
+	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) {
+			kp->cmd_name   = cmd;
+			kp->cmd_func   = func;
+			kp->cmd_usage  = usage;
+			kp->cmd_help   = help;
+			kp->cmd_flags  = 0;
+			kp->cmd_minlen = minlen;
+			break;
+		}
+	}
+	return 0;
+}
+
+/*
+ * 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.
+ *
+ * Inputs:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ */
+
+void
+kdb_inittab(void)
+{
+	int i;
+	kdbtab_t *kp;
+
+	for(i=0, kp=kdb_commands; i < KDB_MAX_COMMANDS; i++,kp++) {
+		kp->cmd_name = NULL;
+	}
+
+	kdb_register("md", kdb_md, "<vaddr>",   "Display Memory Contents", 1);
+	kdb_register("mds", kdb_md, "<vaddr>", 	"Display Memory Symbolically", 0);
+	kdb_register("mm", kdb_mm, "<vaddr> <contents>",   "Modify Memory Contents", 0);
+	kdb_register("id", kdb_id, "<vaddr>",   "Display Instructions", 1);
+	kdb_register("go", kdb_go, "[<vaddr>]", "Continue Execution", 1);
+	kdb_register("rd", kdb_rd, "",		"Display Registers", 1);
+	kdb_register("rm", kdb_rm, "<reg> <contents>", "Modify Registers", 0);
+	kdb_register("ef", kdb_ef, "<vaddr>",   "Display exception frame", 0);
+	kdb_register("bt", kdb_bt, "[<vaddr>]", "Stack traceback", 1);
+	kdb_register("btp", kdb_bt, "<pid>", 	"Display stack for process <pid>", 0);
+	kdb_register("bp", kdb_bp, "[<vaddr>]", "Set/Display breakpoints", 0);
+	kdb_register("bl", kdb_bp, "[<vaddr>]", "Display breakpoints", 0);
+	kdb_register("bpa", kdb_bp, "[<vaddr>]", "Set/Display global breakpoints", 0);
+	kdb_register("bc", kdb_bc, "<bpnum>",   "Clear Breakpoint", 0);
+	kdb_register("be", kdb_bc, "<bpnum>",   "Enable Breakpoint", 0);
+	kdb_register("bd", kdb_bc, "<bpnum>",   "Disable Breakpoint", 0);
+	kdb_register("ss", kdb_ss, "[<#steps>]", "Single Step", 1);
+	kdb_register("ssb", kdb_ss, "", 	"Single step to branch/call", 0);
+	kdb_register("ll", kdb_ll, "<first-element> <linkoffset> <cmd>", "Execute cmd for each element in linked list", 0);
+	kdb_register("env", kdb_env, "", 	"Show environment variables", 0);
+	kdb_register("set", kdb_set, "", 	"Set environment variables", 0);
+	kdb_register("help", kdb_help, "", 	"Display Help Message", 1);
+	kdb_register("?", kdb_help, "",         "Display Help Message", 0);
+#if defined(__SMP__)
+	kdb_register("cpu", kdb_cpu, "<cpunum>","Switch to new cpu", 0);
+#endif	/* __SMP__ */
+	kdb_register("ps", kdb_ps, "", 		"Display active task list", 0);
+	kdb_register("reboot", kdb_reboot, "",  "Reboot the machine immediately", 0);
+}
+
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdb_bp.c.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdb_bp.c	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,707 @@
+/*
+ * Kernel Debugger Breakpoint Handler
+ *
+ * Copyright 1999, Silicon Graphics, Inc.
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/kdb.h>
+#if defined(__SMP__)
+#include <linux/smp.h>
+#include <linux/sched.h>
+#endif
+#include <asm/system.h>
+#include "kdbsupport.h"
+
+/*
+ * Table of breakpoints
+ */
+#define KDB_MAXBPT	16
+static 	kdb_bp_t    breakpoints[KDB_MAXBPT];
+
+static char *rwtypes[] = {"Instruction", "Data Write", "I/O", "Data Access"};
+
+/*
+ * kdb_bp_install
+ *
+ * 	Install breakpoints prior to returning from the kernel debugger. 
+ * 	This allows the breakpoints to be set upon functions that are
+ * 	used internally by kdb, such as printk().
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdb_bp_install(void)
+{
+	int i;
+
+	for(i=0; i<KDB_MAXBPT; i++) {
+		if (breakpoints[i].bp_enabled){
+			kdbinstalldbreg(&breakpoints[i]);
+		}
+	}
+}
+
+#if defined(__SMP__)
+/*
+ * kdb_global
+ *
+ * 	Called from each processor when leaving the kernel debugger
+ *	barrier IPI to establish the debug register contents for 
+ *	global breakpoints.
+ *
+ * Parameters:
+ *	cpuid		Calling logical cpu number
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+/* ARGSUSED */
+void
+kdb_global(int cpuid)
+{
+	int i;
+
+	for(i=0; i<KDB_MAXBPT; i++) {
+		if (breakpoints[i].bp_enabled && breakpoints[i].bp_global){
+			kdbinstalldbreg(&breakpoints[i]);
+		}
+	}
+
+}
+#endif	/* __SMP__ */
+
+/*
+ * kdb_bp_remove
+ *
+ * 	Remove breakpoints upon entry to the kernel debugger. 
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdb_bp_remove(void)
+{
+	int i;
+
+	for(i=0; i<KDB_MAXBPT; i++) {
+		if (breakpoints[i].bp_enabled) {
+			kdbremovedbreg(breakpoints[i].bp_reg);
+		}
+	}
+}
+
+/*
+ * Handle a debug register trap.   
+ */
+
+/*
+ * kdb_db_trap
+ *
+ * 	Perform breakpoint processing upon entry to the
+ *	processor debugger fault.   Determine and print
+ *	the active breakpoint.
+ *
+ * Parameters:
+ *	ef	Exception frame containing machine register state
+ * Outputs:
+ *	None.
+ * Returns:
+ *	0	Standard instruction or data breakpoint encountered
+ *	1	Single Step fault ('ss' command)
+ *	2	Single Step fault, caller should continue ('ssb' command)
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Yup, there be goto's here.
+ */
+
+int
+kdb_db_trap(struct pt_regs *ef)
+{
+	k_machreg_t  dr6;
+	k_machreg_t  dr7;
+	int rw, reg;
+	int i;
+	int rv = 0;
+
+	dr6 = kdb_getdr6();
+	dr7 = kdb_getdr7();
+
+	if (dr6 & DR6_BS) {
+		/* single step */
+		rv = 1;		/* Indicate single step */
+		if (kdb_flags & KDB_FLAG_SSB) {
+			unsigned char op1, op2;
+
+			op1 = *(unsigned char *)(ef->eip);
+			if (op1 == 0x0f) 
+				op2 = *(unsigned char *)(ef->eip+1);
+			if (((op1&0xf0) == 0xe0)  /* short disp jumps */
+			 || ((op1&0xf0) == 0x70)  /* Misc. jumps */
+			 ||  (op1       == 0xc2)  /* ret */
+			 ||  (op1       == 0x9a)  /* call */
+			 || ((op1&0xf8) == 0xc8)  /* enter, leave, iret, int, */
+			 || ((op1       == 0x0f)
+			  && ((op2&0xf0)== 0x80))) {
+				/*
+				 * End the ssb command here.
+				 */
+				kdb_flags &= ~KDB_FLAG_SSB;
+			} else {
+				kdb_id1(ef->eip);
+				rv = 2;	/* Indicate ssb - dismiss immediately */
+			}
+		} else {
+			/*
+			 * Print current insn
+			 */
+			kdb_printf("SS trap at 0x%x\n", ef->eip);
+			kdb_id1(ef->eip);
+		}
+
+		if (rv != 2)
+			ef->eflags &= ~EF_TF;
+	}
+
+	if (dr6 & DR6_B0) {
+		rw = DR7_RW0(dr7);
+		reg = 0;
+		goto handle;
+	}
+
+	if (dr6 & DR6_B1) {
+		rw = DR7_RW1(dr7);
+		reg = 1;
+		goto handle;
+	}
+
+	if (dr6 & DR6_B2) {
+		rw = DR7_RW2(dr7);
+		reg = 2;
+		goto handle;
+	}
+
+	if (dr6 & DR6_B3) {
+		rw = DR7_RW3(dr7);
+		reg = 3;
+		goto handle;
+	}
+
+	if (rv > 0) 
+		goto handled;
+
+	goto unknown;	/* dismiss */
+
+handle:
+	/*
+	 * Set Resume Flag
+	 */
+	ef->eflags |= EF_RF;
+
+	/*
+	 * Determine which breakpoint was encountered.
+	 */
+	for(i=0; i<KDB_MAXBPT; i++) {
+		if ((breakpoints[i].bp_enabled)
+		 && (breakpoints[i].bp_reg == reg)) {
+			/*
+			 * Hit this breakpoint.  Remove it while we are
+			 * handling hit to avoid recursion. XXX ??
+			 */
+			kdb_printf("%s breakpoint #%d at 0x%x\n", 
+				  rwtypes[rw],
+				  i, breakpoints[i].bp_addr);
+
+			/*
+			 * For an instruction breakpoint, disassemble
+			 * the current instruction.
+			 */
+			if (rw == 0) {
+				kdb_id1(ef->eip);
+			}
+
+			goto handled;
+		}
+	}
+
+unknown: 
+	kdb_printf("Unknown breakpoint.  Should forward. \n");
+
+handled:
+
+	/*
+	 * Clear the pending exceptions.
+	 */
+	kdb_putdr6(0);
+	
+	return rv;
+}
+
+/*
+ * 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)
+{
+	char *symname;
+	long  offset;
+
+	kdb_printf("%s ", rwtypes[bp->bp_mode]);
+
+	kdb_printf("BP #%d at 0x%x ",
+		   i, bp->bp_addr);
+	symname = kdbnearsym(bp->bp_addr);
+	if (symname){
+		kdb_printf("(%s", symname);
+
+		offset = bp->bp_addr - kdbgetsymval(symname);
+		if (offset) {
+			if (offset > 0)
+				kdb_printf("+0x%x", offset);
+			else
+				kdb_printf("-0x%x", offset);
+		}
+		kdb_printf(") ");
+	} 
+
+	if (bp->bp_enabled) {
+		kdb_printf("\n    is enabled in dr%d", bp->bp_reg);
+		if (bp->bp_global)
+			kdb_printf(" globally");
+		else 
+			kdb_printf(" on cpu %d", bp->bp_cpu);
+
+		if (bp->bp_mode != 0) {
+			kdb_printf(" for %d bytes", bp->bp_length + 1);
+		}
+	} else {
+		kdb_printf("\n    is disabled");
+	}
+
+	kdb_printf("\n");
+}
+
+/*
+ * kdb_bp
+ *
+ * 	Handle the bp, and bpa commands.
+ *
+ *	[bp|bpa] <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:
+ */
+
+int
+kdb_bp(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int     i;
+	kdb_bp_t *bp;
+	int     diag;
+	int     free, same;
+	k_machreg_t addr;
+	char   *symname = NULL;
+	long    offset = 0ul;
+	int	nextarg;
+	unsigned long 	mode, length;
+#if defined(__SMP__)
+	int	global;
+#endif
+
+	if (argc == 0) {
+		/*
+		 * Display breakpoint table
+		 */
+		for(i=0,bp=breakpoints; i<KDB_MAXBPT; i++, bp++) {
+			if (bp->bp_free) continue;
+
+			kdb_printbp(bp, i);
+		}
+
+		return 0;
+	}
+	
+#if defined(__SMP__)
+	global = (strcmp(argv[0], "bpa") == 0);
+#endif
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, &symname, regs);
+	if (diag)
+		return diag;
+
+	mode = 0;		/* Default to instruction breakpoint */
+	length = 0;		/* Length must be zero for insn bp */
+	if ((argc + 1) != nextarg) {
+		if (strnicmp(argv[nextarg], "datar", sizeof("datar")) == 0) {
+			mode = 3;
+		} else if (strnicmp(argv[nextarg], "dataw", sizeof("dataw")) == 0) {
+			mode = 1;
+		} else if (strnicmp(argv[nextarg], "io", sizeof("io")) == 0) {
+			mode = 2;
+		} else {
+			return KDB_ARGCOUNT;
+		}
+
+		length = 3;	/* Default to 4 byte */
+
+		nextarg++;
+
+		if ((argc + 1) != nextarg) {
+			diag = kdbgetularg((char *)argv[nextarg], &length);
+			if (diag)
+				return diag;
+
+			if ((length > 4) || (length == 3)) 
+				return KDB_BADLENGTH;
+
+			length--;	/* Normalize for debug register */
+			nextarg++;
+		}
+
+		if ((argc + 1) != nextarg) 
+			return KDB_ARGCOUNT;
+	}
+	
+	/*
+	 * Allocate a new bp structure 
+	 */
+	free = same = KDB_MAXBPT;
+	for(i=0; i<KDB_MAXBPT; i++) {
+		if (breakpoints[i].bp_free) {
+			if (free == KDB_MAXBPT) 
+				free = i;
+		} else if (breakpoints[i].bp_addr == addr) {
+			same = i;
+		}
+	}
+	if (same != KDB_MAXBPT) 
+		return KDB_DUPBPT;
+
+	if (free == KDB_MAXBPT)
+		return KDB_TOOMANYBPT;
+
+	bp = &breakpoints[free];
+
+	bp->bp_addr = addr;
+	bp->bp_mode = mode;
+	bp->bp_length = length;
+	
+	/*
+	 * Find a free register 
+	 */
+	for(i=0; i<KDB_DBREGS; i++) {
+		if (dbregs[i] == 0xffffffff) {
+			/*
+			 * Set this to zero to indicate that it has been
+			 * allocated.  We'll actually store it when leaving
+			 * kdb when we reinstall the debug registers.
+			 *
+			 * This allows breakpoints to be set on kernel 
+			 * functions that are also called by kdb without 
+			 * interfering with kdb operations.
+			 */
+			dbregs[i] = 0;
+			bp->bp_reg = i;
+			bp->bp_free = 0;
+			bp->bp_enabled = 1;
+#if defined(__SMP__)
+			if (global) 
+				bp->bp_global = 1;
+			else
+				bp->bp_cpu = smp_processor_id();
+#endif
+
+			kdb_printbp(bp, free);
+
+			break;
+		}
+	}
+	/*
+	 * XXX if not enough regs, fail.  Eventually replace
+	 *     first byte of instruction with int03.
+	 */
+	if (i==KDB_DBREGS)
+		return KDB_TOOMANYDBREGS;
+
+	return 0;
+}
+
+/*
+ * kdb_bc
+ *
+ * 	Handles the 'bc', 'be', and 'bd' commands
+ *
+ *	[bd|bc|be] <breakpoint-number>
+ *
+ * Parameters:
+ *	argc	Count of arguments in argv
+ *	argv	Space delimited command line arguments
+ *	envp	Environment value
+ *	regs	Exception frame at entry to kernel debugger
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+#define KDBCMD_BC	0
+#define KDBCMD_BE	1
+#define KDBCMD_BD	2
+
+int
+kdb_bc(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	k_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 = &breakpoints[addr];
+			lowbp = highbp = addr;
+			highbp++;
+		} else {
+			for(i=0; i<KDB_MAXBPT; i++) {
+				if (breakpoints[i].bp_addr == addr) {
+					lowbp = highbp = i;
+					highbp++;
+					break;
+				}
+			}
+		}
+	}
+
+	for(bp=&breakpoints[lowbp], i=lowbp; 
+	    i < highbp;
+	    i++, bp++) {
+		if (bp->bp_free) 
+			continue;
+		
+		done++;
+
+		switch (cmd) {
+		case KDBCMD_BC:
+			kdbremovedbreg(bp->bp_reg);
+			dbregs[bp->bp_reg] = 0xffffffff;
+			kdb_printf("Breakpoint %d at 0x%x in dr%d cleared\n",
+				i, bp->bp_addr, bp->bp_reg);
+			bp->bp_free = 1;
+			bp->bp_addr = 0;
+			break;
+		case KDBCMD_BE:
+		{
+			int r;
+
+			for(r=0; r<KDB_DBREGS; r++) {
+				if (dbregs[r] == 0xffffffff){
+					bp->bp_reg = r;
+					bp->bp_enabled = 1;
+					kdb_printf("Breakpoint %d at 0x%x in dr%d enabled\n",
+						i, bp->bp_addr, bp->bp_reg);
+					break;
+				}
+			}
+			if (r == KDB_DBREGS) 
+				return KDB_TOOMANYDBREGS;
+
+			break;
+		}
+		case KDBCMD_BD:
+			kdbremovedbreg(bp->bp_reg);
+			dbregs[bp->bp_reg] = 0xffffffff;
+			bp->bp_enabled = 0;
+			kdb_printf("Breakpoint %d at 0x%x in dr%d disabled\n",
+				i, bp->bp_addr, bp->bp_reg);
+			break;
+		}
+	}
+
+	return (!done)?KDB_BPTNOTFOUND:0;
+}
+
+/*
+ * kdb_initbptab
+ *
+ *	Initialize the breakpoint table.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdb_initbptab(void)
+{
+	int i;
+
+	/*
+	 * First time initialization.  
+	 */
+	for (i=0; i<KDB_MAXBPT; i++) {
+		breakpoints[i].bp_free = 1;
+		breakpoints[i].bp_enabled = 0;
+		breakpoints[i].bp_global = 0;
+		breakpoints[i].bp_reg = 0;
+		breakpoints[i].bp_mode = 0;
+		breakpoints[i].bp_length = 0;
+	}
+
+	/*
+	 * Don't allow setting breakpoint at address 0xffffffff
+	 */
+	for(i=0; i<KDB_DBREGS; i++) {
+		dbregs[i] = 0xffffffff;
+	}
+}
+
+/*
+ * kdb_ss
+ *
+ *	Process the 'ss' (Single Step) and 'ssb' (Single Step to Branch)
+ *	commands.
+ *
+ *	ss [<insn-count>]
+ *	ssb
+ *
+ * Parameters:
+ *	argc	Argument count
+ *	argv	Argument vector
+ *	envp	Environment vector
+ *	regs	Registers at time of entry to kernel debugger
+ * Outputs:
+ *	None.
+ * Returns:
+ *	0 for success, a kdb error if failure.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ *	Set the trace flag in the EFLAGS register to trigger 
+ *	a debug trap after the next instruction.   Print the 
+ *	current 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 or SSCOUNT lines are printed.
+ */
+
+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 ((ssb && (argc != 0)) 
+	 || (!ssb && (argc > 1))) {
+		return KDB_ARGCOUNT;
+	}
+
+#if 0
+	/*
+	 * Fetch provided count
+	 */
+	diag = kdbgetularg(argv[1], &sscount);
+	if (diag)
+		return diag;
+#endif
+
+	/*
+	 * Print current insn
+	 */
+	kdb_id1(regs->eip);	
+
+	/*
+  	 * Set trace flag and go.
+	 */
+	regs->eflags |= EF_TF;		
+
+	if (ssb) 
+		kdb_flags |= KDB_FLAG_SSB;
+
+	return KDB_GO;
+}
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdb_bt.c.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdb_bt.c	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,389 @@
+	/*
+	 * Minimalist Kernel Debugger 
+	 *
+	 * 	Machine dependent stack traceback code.
+	 *
+	 * Copyright 1999, Silicon Graphics, Inc.
+	 *
+	 * Written by Scott Lurndal at Silicon Graphics, March 1999.
+	 */
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kdb.h>
+#include <asm/system.h>
+#include "kdbsupport.h"
+
+
+#if defined(CONFIG_KDB_FRAMEPTR)
+/*
+ * kdb_prologue
+ *
+ *	This function analyzes a gcc-generated function prototype
+ *	when frame pointers are enabled to determine the amount of
+ *	automatic storage and register save storage is used on the
+ *	stack of the target function.
+ * Parameters:
+ *	eip	Address of function to analyze
+ * Outputs:
+ *	*nauto	# bytes of automatic storage
+ *	*nsave  # of saved registers
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ * 	A prologue generally looks like:
+ *
+ *		pushl  %ebp		(All functions)
+ *		movl   %esp, %ebp	(All functions)
+ *		subl   $auto, %esp	[some functions]
+ *		pushl   reg		[some functions]
+ *		pushl   reg		[some functions]
+ */
+
+void
+kdb_prologue(unsigned long eip, unsigned long *nauto, unsigned long *nsave)
+{
+	size_t insn_size = sizeof(unsigned char);
+
+	*nauto = 0;
+	*nsave = 0;
+
+	if (eip == 0) 
+		return;
+
+	if ((kdbgetword(eip, insn_size) != 0x55)	/* pushl %ebp */
+	 || (kdbgetword(eip+1, insn_size) != 0x89)){/* movl esp, ebp */
+		/*
+		 * Unknown prologue type.
+		 */
+		return;
+	}
+
+	if (kdbgetword(eip+3, insn_size) == 0x83) {
+		*nauto = kdbgetword(eip+5, sizeof(unsigned char));
+		eip += 6;
+	} else if (kdbgetword(eip+3, insn_size) == 0x81) {
+		*nauto = kdbgetword(eip+5, sizeof(unsigned long));
+		eip += 9;
+	} else 
+		eip += 3;
+
+
+	while ((kdbgetword(eip, insn_size)&0xf8) == 0x50) 
+		(*nsave)++, eip++;
+}
+#endif
+
+/*
+ * 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>)
+ *
+ * 	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:
+ *	Doing this without a frame pointer is _hard_.  some simple
+ *	things are done here, but we usually don't find more than the
+ *	first couple of frames yet.   More coming in this area.
+ *
+ *	mds comes in handy when examining the stack to do a manual
+ *	traceback.
+ */
+
+int
+kdb_bt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int done = 0;
+#if !defined(CONFIG_KDB_FRAMEPTR)
+	unsigned long sp;
+#endif
+	unsigned long base, limit, esp, ebp, eip;
+	unsigned long start = 0;	/* Start address of current function */
+	unsigned long addr;
+	long offset = 0;
+	int nextarg;
+	int argcount=5;
+	char	*name;
+	int	diag;
+	struct pt_regs	   taskregs;
+	struct frame {
+		unsigned long ebp;
+		unsigned long eip;
+	} old;
+	unsigned long stackbase = (unsigned long)current;
+
+	/*
+	 * Determine how many possible arguments to print.
+	 */
+	diag = kdbgetintenv("BTARGS", &argcount);
+
+	if (strcmp(argv[0], "btp") == 0){
+		struct task_struct *p;
+		int		   pid;
+		
+		diag = kdbgetularg((char *)argv[1], (unsigned long*)&pid);
+		if (diag)
+			return diag;
+
+		taskregs.eax = 1;
+		for_each_task(p) {
+			if (p->pid == pid) {
+				taskregs.eip = p->tss.eip;
+				taskregs.esp = p->tss.esp;
+				taskregs.ebp = p->tss.ebp;
+				/*
+				 * Since we don't really use the TSS
+				 * to store register between task switches,
+				 * attempt to locate real ebp (should be
+				 * top of stack if task is in schedule)
+				 */
+				if (taskregs.ebp == 0) {
+					taskregs.ebp = 
+					 *(unsigned long *)(taskregs.esp);
+				}
+
+				taskregs.eax = 0;
+				stackbase = (unsigned long)p;
+				break;
+			}
+		}
+
+		if (taskregs.eax == 1) {
+			kdb_printf("No process with pid == %d found\n",
+				   pid);
+			return 0;
+		}
+		regs = &taskregs;
+	} else {
+		if (argc) {
+			nextarg = 1;
+			diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+			if (diag)
+				return diag;
+
+			/*
+			 * We assume the supplied address is points to an
+			 * EIP value on the stack, and the word pushed above
+			 * it is an EBP value.   Start as if we were in the
+			 * middle of that frame.
+			 */
+			taskregs.eip = kdbgetword(addr, sizeof(unsigned long));
+			taskregs.ebp = kdbgetword(addr-4, sizeof(unsigned long));
+			taskregs.ebp = kdbgetword(taskregs.ebp, sizeof(unsigned long));
+			regs = &taskregs;
+		}
+	}
+
+	name = kdbnearsym(regs->eip);
+	if (name) {
+		start = kdbgetsymval(name);
+	} else {
+		kdb_printf("Cannot determine function for eip = 0x%x\n", 
+			   regs->eip);
+		return 0;
+	}
+#if !defined(CONFIG_KDB_FRAMEPTR)
+	/*
+	 * starting with %esp value, track the stack back to 
+	 * the end.
+	 */
+
+	sp = (unsigned long) (1+regs);	/* Point past exception frame */
+	sp -= 8;			/* Adjust to encompass return addr */
+	if (regs->xcs & 3) {
+		/* User space? */
+		sp = regs->esp;
+	}
+	sp -= 8;			/* Adjust to encompass return addr */
+	base = sp & ~0x1fff;		/* XXX - use stack size constant */
+
+
+	kdb_printf("    ESP       EIP         Function(args)\n");
+	kdb_printf("0x%x 0x%x  %s ()\n", 
+		   sp, regs->eip, name);
+
+	while (!done) {
+		extern char _text, _etext;
+		extern char __init_begin, __init_end;
+		unsigned long word;
+
+		word = *(unsigned long *)(sp);
+		if (  ((word >= (unsigned long)&_text) 
+		    && (word <= (unsigned long)&_etext))
+		 ||   ((word >= (unsigned long)&__init_begin)
+		    && (word <= (unsigned long)&__init_end))) {
+			/* text address */
+
+#if defined(NOTNOW)
+			kdb_printf("word %x sp %x char %x off %x\n",
+				   word, sp, *(unsigned char *)(word - 5),
+				   *(signed long *)(word - 4));
+#endif
+			/*
+			 * If the instruction 5 bytes before the
+			 * return instruction is a call, treat this
+			 * entry as a probable activation record
+			 */
+			if (*(unsigned char *)(word - 5) == 0xe8) {
+				signed long val = *(signed long *)(word - 4);
+				int         i;
+	
+				/*
+				 * Is this a real activation record?
+				 */
+				/*
+				 * Of course, this misses all the 
+				 * indirect calls, etc. XXX XXX
+				 */
+				if ((val + word) == start) {
+					kdb_printf("0x%x 0x%x  ", 
+						   sp,  word);
+					name = kdbnearsym(word);
+					if (name) {
+						kdb_printf("%s (", name);
+					}
+					for(i=0; i<argcount; i++) {
+						kdb_printf("0x%x, ", 
+						   *(unsigned long *)(sp+(4*i)));
+					}
+					kdb_printf(")\n");
+				}
+	
+			}
+		}
+		sp += sizeof(unsigned long);
+		if (sp >= base+0x2000) 	/* XXX - use stack size constant */
+			done = 1;
+	}
+#else
+	kdb_printf("    EBP       EIP         Function(args)\n");
+
+	base = stackbase;
+
+	esp = regs->esp;
+	ebp = regs->ebp;
+	eip = regs->eip;
+
+	limit = base + 0x2000;			/* stack limit */
+
+#if 0
+	printk("stackbase = 0x%lx base = 0x%lx limit = 0x%lx ebp = 0x%lx esp = 0x%lx eip = 0x%lx\n",
+		stackbase, base, limit, ebp, esp, eip);
+#endif
+
+	if ((eip == start)		/* Beginning of function */
+	 || (eip == start+1)) {		/* Right after pushl %ebp */
+		/*
+		 * If at start of function, create a dummy frame
+		 */
+		old.ebp = ebp;
+		if (kdb_flags & KDB_FLAG_FAULT) {
+			if ((regs->xcs&0xffff) == 0x10) {
+				/*
+				 * For instruction breakpoint on a target of a 
+				 * call instruction, we must fetch the caller's
+				 * eip shall we say, differently.
+				 */
+				old.eip = regs->esp;	/* Don't Ask */
+			} else {
+				old.eip = *(unsigned long *)(regs+1);
+			}
+		} else {
+			old.eip = (eip == start)
+				 ?kdbgetword(esp, sizeof(unsigned long))
+				 :kdbgetword(esp+4, sizeof(unsigned long));
+		}
+		ebp = (unsigned long)&old;
+	}
+
+	/*
+	 * While the ebp remains within the stack, continue to 
+	 * print stack entries.
+	 *
+	 * XXX - this code depends on the fact that kernel
+	 *       stacks are aligned on address boundaries 
+	 *       congruent to 0 modulo 8192 and are 8192 bytes
+	 *       in length and are part of the 8k bytes based
+	 *	 at the process structure (e.g. current).
+	 *
+	 */
+
+	while (!done) {
+		unsigned long nebp, neip;
+		char *newname;
+
+		kdb_printf("0x%x 0x%x  ", ebp, eip);
+		kdb_printf("%s", name);
+
+		if (ebp < PAGE_OFFSET) {
+			done++;
+			kdb_printf("\n");
+			continue;
+		}
+
+		nebp = kdbgetword(ebp, sizeof(unsigned long));
+		neip = kdbgetword(ebp+4, sizeof(unsigned long));
+
+		if (eip != start) {
+			kdb_printf("+0x%x", eip - start);
+		}
+
+		/*
+		 * Get frame for caller to determine the frame size
+		 * and argument count.
+		 */
+		newname = kdbnearsym(neip);
+		if (newname) {
+			int i;
+			unsigned long nauto, nsave, nargs;
+
+			start = kdbgetsymval(newname);
+			name = newname;
+
+			kdb_printf("( ");
+
+			kdb_prologue(kdbgetsymval(newname), &nauto, &nsave);
+
+			nargs = (nebp - ebp - 8 - nauto - (nsave * 4))/4;
+			if (nargs > argcount)
+				nargs = argcount;
+			for(i=0; i<nargs; i++){
+				unsigned long argp = ebp + 8 + (4*i);
+
+				if (i) 
+					kdb_printf(", ");
+				kdb_printf("0x%x", 
+				     kdbgetword(argp, sizeof(unsigned long)));
+			}
+		}
+		kdb_printf(")\n");
+
+
+		ebp = nebp;
+		eip = neip;
+	}
+#endif	/* CONFIG_KDB_FRAMEPTR */
+	return 0;
+}
+
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdb_io.c.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdb_io.c	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,264 @@
+/*
+ * Kernel Debugger Console I/O handler
+ *
+ * Copyright 1999, Silicon Graphics, Inc.
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ *
+ * Modifications from:
+ *	Chuck Fleckenstein		1999/07/20
+ *		Move kdb_info struct declaration to this file
+ *		for cases where serial support is not compiled into
+ *		the kernel.
+ *
+ *	Masahiro Adegawa		1999/07/20
+ *		Handle some peculiarities of japanese 86/106
+ *		keyboards.
+ *
+ *	marc@mucom.co.il		1999/07/20
+ *		Catch buffer overflow for serial input.
+ */
+
+#include "linux/kernel.h"
+#include "asm/io.h"
+#include "pc_keyb.h"
+#include "linux/console.h"
+#include "linux/serial_reg.h"
+
+
+int kdb_port = 0;
+
+/*
+ * This module contains code to read characters from the keyboard or a serial
+ * port.
+ * 
+ * It is used by the kernel debugger, and is polled, not interrupt driven.
+ *
+ */
+
+/*
+ * send:  Send a byte to the keyboard controller.  Used primarily to 
+ * 	  alter LED settings.
+ */
+
+static void
+kdb_kbdsend(unsigned char byte) 
+{
+	while (inb(KBD_STATUS_REG) & KBD_STAT_IBF)
+		;
+	outb(KBD_DATA_REG, byte);
+}
+
+static void
+kdb_kbdsetled(int leds)
+{
+	kdb_kbdsend(KBD_CMD_SET_LEDS);
+	kdb_kbdsend((unsigned char)leds);
+}
+
+
+char *
+kdb_getscancode(char *buffer, size_t bufsize)
+{
+	char	*cp = buffer;
+	int	scancode, scanstatus;
+	static int shift_lock = 0;	/* CAPS LOCK state (0-off, 1-on) */
+	static int shift_key  = 0;	/* Shift next keypress */
+	static int ctrl_key   = 0;
+	static int leds       = 2;	/* Num lock */
+	u_short keychar;
+	extern u_short plain_map[], shift_map[], ctrl_map[];
+
+	bufsize -= 2;	/* Reserve space for newline and null byte */
+
+	/*
+	 * If we came in via a serial console, we allow that to
+	 * be the input window for kdb.
+	 */
+	if (kdb_port != 0) {
+		char ch;
+		int status;
+#define serial_inp(info, offset) inb((info) + (offset))
+#define serial_out(info, offset, v) outb((v), (info) + (offset))
+
+		while(1) {
+			while ((status = serial_inp(kdb_port, UART_LSR)) 
+							& UART_LSR_DR) {
+readchar:
+				ch = serial_inp(kdb_port, UART_RX);
+				if (ch == 8) {		/* BS */
+					if (cp > buffer) {
+						--cp, bufsize++;
+						printk("%c %c", 0x08, 0x08);
+					}
+					continue;
+				}
+				serial_out(kdb_port, UART_TX, ch);
+				if (ch == 13) {		/* CR */
+					*cp++ = '\n';
+					*cp++ = '\0';
+					serial_out(kdb_port, UART_TX, 10);
+					return(buffer);
+				}
+				/*
+				 * Discard excess characters
+				 */
+				if (bufsize > 0) {
+					*cp++ = ch;
+					bufsize--;
+				} 
+			}
+			while (((status = serial_inp(kdb_port, UART_LSR)) 
+					& UART_LSR_DR) == 0);
+		}
+	}
+
+	while (1) {
+
+		/*
+		 * Wait for a valid scancode
+		 */
+
+		while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+			;
+
+		/*
+		 * Fetch the scancode
+		 */
+		scancode = inb(KBD_DATA_REG);
+		scanstatus = inb(KBD_STATUS_REG);
+
+		/*
+		 * Ignore mouse events.
+		 */
+		if (scanstatus & KBD_STAT_MOUSE_OBF)
+			continue;
+
+		/*
+		 * Ignore release, trigger on make
+		 * (except for shift keys, where we want to 
+		 *  keep the shift state so long as the key is
+		 *  held down).
+		 */
+
+		if (((scancode&0x7f) == 0x2a) 
+		 || ((scancode&0x7f) == 0x36)) {
+			/*
+			 * Next key may use shift table
+			 */
+			if ((scancode & 0x80) == 0) {
+				shift_key=1;
+			} else {
+				shift_key=0;
+			}
+			continue;
+		}
+
+		if ((scancode&0x7f) == 0x1d) {
+			/*
+			 * Left ctrl key
+			 */
+			if ((scancode & 0x80) == 0) {
+				ctrl_key = 1;
+			} else {
+				ctrl_key = 0;
+			}
+			continue;
+		}
+
+		if ((scancode & 0x80) != 0) 
+			continue;
+
+		scancode &= 0x7f;
+
+		/*
+	 	 * Translate scancode
+		 */
+		
+		if (scancode == 0x3a) {
+			/*
+			 * Toggle caps lock
+			 */
+			shift_lock ^= 1;
+			leds ^= 0x4;	/* toggle caps lock led */
+			
+			kdb_kbdsetled(leds);
+			continue;
+		}
+			
+		if (scancode == 0x0e) {
+			/*
+			 * Backspace
+			 */
+			if (cp > buffer) {
+				--cp, bufsize++;
+
+				/*
+				 * XXX - erase character on screen
+				 */
+				printk("%c %c", 0x08, 0x08);
+			}
+			continue;
+		}
+	
+		if (scancode == 0xe0) {
+			continue;
+		}
+
+		/*
+		 * For Japanese 86/106 keyboards 
+		 * 	See comment in drivers/char/pc_keyb.c.
+		 * 	- Masahiro Adegawa
+		 */
+		if (scancode == 0x73) {
+			scancode = 0x59;
+		} else if (scancode == 0x7d) {
+			scancode = 0x7c;
+		}
+			
+		if (!shift_lock && !shift_key) {
+			keychar = plain_map[scancode];
+		} else if (shift_lock || shift_key) {
+			keychar = shift_map[scancode];
+		} else if (ctrl_key) {
+			keychar = ctrl_map[scancode];
+		} else {
+			keychar = 0x0020;
+			printk("Unknown state/scancode (%d)\n", scancode);
+		}
+		 
+		if ((scancode & 0x7f) == 0x1c) {
+			/*
+			 * enter key.  All done.
+			 */
+			printk("\n");
+			break;
+		}
+
+		/*
+		 * echo the character.
+		 */
+		printk("%c", keychar&0xff);
+
+		if (bufsize) {
+			--bufsize;
+			*cp++ = keychar&0xff;
+		} else {
+			printk("buffer overflow\n");
+			break;
+		}
+
+	}
+
+	*cp++ = '\n';		/* White space for parser */
+	*cp++ = '\0';		/* String termination */
+
+#if defined(NOTNOW)
+	cp = buffer;
+	while (*cp) {
+		printk("char 0x%x\n", *cp++);
+	}
+#endif
+
+	return buffer;
+}
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdbsupport.c.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdbsupport.c	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,936 @@
+/*
+ * Kernel Debugger Breakpoint Handler
+ *
+ * Copyright 1999, Silicon Graphics, Inc.
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ */
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kdb.h>
+#include <linux/stddef.h> 
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+
+#include "kdbsupport.h"
+
+k_machreg_t dbregs[KDB_DBREGS];
+
+void
+kdb_init(void)
+{
+	extern void kdb_inittab(void);
+
+	kdb_inittab();
+	kdb_initbptab();
+	kdb_disinit();
+	kdb_printf("kdb version %d.%d by Scott Lurndal. "\
+		   "Copyright SGI, All Rights Reserved\n",
+		   KDB_MAJOR_VERSION, KDB_MINOR_VERSION);
+}
+
+/*
+ * kdbprintf
+ * kdbgetword
+ * kdb_getstr
+ */
+
+char *
+kbd_getstr(char *buffer, size_t bufsize, char *prompt)
+{
+	extern char* kdb_getscancode(char *, size_t);
+
+#if defined(CONFIG_SMP)
+	kdb_printf(prompt, smp_processor_id());
+#else
+	kdb_printf("%s", prompt);
+#endif
+
+	return kdb_getscancode(buffer, bufsize);
+
+}
+
+int
+kdb_printf(const char *fmt, ...)
+{
+	char buffer[256];
+	va_list	ap;
+	int diag;
+	int linecount;
+
+	diag = kdbgetintenv("LINES", &linecount);
+	if (diag) 
+		linecount = 22;
+
+	va_start(ap, fmt);
+	vsprintf(buffer, fmt, ap);
+	va_end(ap);
+
+	printk("%s", buffer);
+
+	if (strchr(buffer, '\n') != NULL) {
+		kdb_nextline++;
+	}
+
+	if (kdb_nextline == linecount) {
+		char buf1[16];
+		char buf2[32];
+		extern char* kdb_getscancode(char *, size_t);
+		char *moreprompt;
+
+		/*
+		 * Pause until cr.
+		 */
+		moreprompt = kdbgetenv("MOREPROMPT");
+		if (moreprompt == NULL) {
+			moreprompt = "more> ";
+		}
+
+#if defined(CONFIG_SMP)
+		if (strchr(moreprompt, '%')) {
+			sprintf(buf2, moreprompt, smp_processor_id());
+			moreprompt = buf2;
+		}
+#endif
+
+		printk(moreprompt);
+		(void) kdb_getscancode(buf1, sizeof(buf1));
+
+		kdb_nextline = 1;
+
+		if ((buf1[0] == 'q') 
+		 || (buf1[0] == 'Q')) {
+			kdb_longjmp(&kdbjmpbuf, 1);
+		}
+	}
+	
+	return 0;
+}
+
+unsigned long
+kdbgetword(unsigned long addr, int width)
+{
+	/*
+	 * This function checks the address for validity.  Any address
+	 * in the range PAGE_OFFSET to high_memory is legal, any address
+	 * which maps to a vmalloc region is legal, and any address which
+	 * is a user address, we use get_user() to verify validity.
+	 */
+
+	if (addr < PAGE_OFFSET) {
+		/*
+		 * Usermode address.
+		 */
+		unsigned long diag;
+		unsigned long ulval;
+
+		switch (width) {
+		case 4:
+		{	unsigned long *lp;
+
+			lp = (unsigned long *) addr;
+			diag = get_user(ulval, lp);
+			break;
+		}
+		case 2:
+		{	unsigned short *sp;
+
+			sp = (unsigned short *) addr;
+			diag = get_user(ulval, sp);
+			break;
+		}
+		case 1:
+		{	unsigned char *cp;
+
+			cp = (unsigned char *) addr;
+			diag = get_user(ulval, cp);
+			break;
+		}
+		default:
+			printk("kdbgetword: Bad width\n");
+			return 0L;
+		}
+			
+		if (diag) {
+			if ((kdb_flags & KDB_FLAG_SUPRESS) == 0) {
+				printk("kdb: Bad user address 0x%lx\n", addr);
+				kdb_flags |= KDB_FLAG_SUPRESS;
+			}
+			return 0L;
+		}
+		kdb_flags &= ~KDB_FLAG_SUPRESS;
+		return ulval;
+	}
+
+	if (addr > (unsigned long)high_memory) {
+		extern int kdb_vmlist_check(unsigned long, unsigned long);
+
+		if (!kdb_vmlist_check(addr, addr+width)) {
+			/*
+			 * Would appear to be an illegal kernel address; 
+			 * Print a message once, and don't print again until
+			 * a legal address is used.
+			 */
+			if ((kdb_flags & KDB_FLAG_SUPRESS) == 0) {
+				printk("kdb: Bad kernel address 0x%lx\n", addr);
+				kdb_flags |= KDB_FLAG_SUPRESS;
+			}
+			return 0L;
+		}
+	}
+
+	/*
+	 * A good address.  Reset error flag.
+	 */
+	kdb_flags &= ~KDB_FLAG_SUPRESS;
+
+	switch (width) {
+	case 4:
+	{	unsigned long *lp;
+
+		lp = (unsigned long *)(addr);
+		return *lp;
+	}
+	case 2:
+	{	unsigned short *sp;
+
+		sp = (unsigned short *)(addr);
+		return *sp;
+	}
+	case 1:
+	{	unsigned char *cp;
+
+		cp = (unsigned char *)(addr);
+		return *cp;
+	}
+	}
+
+	printk("kdbgetword: Bad width\n");
+	return 0L;
+}
+
+int
+kdbinstalltrap(int type, handler_t newh, handler_t *oldh)
+{
+	/*
+	 * Usurp INTn.  XXX - TBD.
+	 */
+
+	return 0;
+}
+
+int
+kdbinstalldbreg(kdb_bp_t *bp)
+{
+	k_machreg_t	dr7;
+
+	dr7 = kdb_getdr7();
+
+	kdb_putdr(bp->bp_reg, bp->bp_addr);
+
+	dr7 |= DR7_GE;
+
+	switch (bp->bp_reg){
+	case 0:
+		DR7_RW0SET(dr7,bp->bp_mode);
+		DR7_LEN0SET(dr7,bp->bp_length);
+		DR7_G0SET(dr7);
+		break;
+	case 1:
+		DR7_RW1SET(dr7,bp->bp_mode);
+		DR7_LEN1SET(dr7,bp->bp_length);
+		DR7_G1SET(dr7);
+		break;
+	case 2:
+		DR7_RW2SET(dr7,bp->bp_mode);
+		DR7_LEN2SET(dr7,bp->bp_length);
+		DR7_G2SET(dr7);
+		break;
+	case 3:
+		DR7_RW3SET(dr7,bp->bp_mode);
+		DR7_LEN3SET(dr7,bp->bp_length);
+		DR7_G3SET(dr7);
+		break;
+	default:
+		kdb_printf("Bad debug register!! %d\n", bp->bp_reg);
+		break;
+	} 
+
+	kdb_putdr7(dr7);
+	return 0;
+}
+
+void
+kdbremovedbreg(int regnum)
+{
+	k_machreg_t	dr7;
+
+	dr7 = kdb_getdr7();
+	
+	kdb_putdr(regnum, 0);
+
+	switch (regnum) {
+	case 0:
+		DR7_G0CLR(dr7);
+		DR7_L0CLR(dr7);
+		break;
+	case 1:
+		DR7_G1CLR(dr7);
+		DR7_L1CLR(dr7);
+		break;
+	case 2:
+		DR7_G2CLR(dr7);
+		DR7_L2CLR(dr7);
+		break;
+	case 3:
+		DR7_G3CLR(dr7);
+		DR7_L3CLR(dr7);
+		break;
+	default:
+		kdb_printf("Bad debug register!! %d\n", regnum);
+		break;
+	}
+
+	kdb_putdr7(dr7);
+}
+
+k_machreg_t
+kdb_getdr6(void)
+{
+	return kdb_getdr(6);
+}
+
+k_machreg_t
+kdb_getdr7(void)
+{
+	return kdb_getdr(7);
+}
+
+k_machreg_t
+kdb_getdr(int regnum)
+{
+	k_machreg_t contents = 0;
+#if defined(__GNUC__)
+	switch(regnum) {
+	case 0:
+		__asm__ ("movl %%db0,%0\n\t":"=r"(contents));
+		break;
+	case 1:
+		__asm__ ("movl %%db1,%0\n\t":"=r"(contents));
+		break;
+	case 2:
+		__asm__ ("movl %%db2,%0\n\t":"=r"(contents));
+		break;
+	case 3:
+		__asm__ ("movl %%db3,%0\n\t":"=r"(contents));
+		break;
+	case 4:
+	case 5:
+		break;
+	case 6:
+		__asm__ ("movl %%db6,%0\n\t":"=r"(contents));
+		break;
+	case 7:
+		__asm__ ("movl %%db7,%0\n\t":"=r"(contents));
+		break;
+	default:
+		break;
+	}
+	  
+#endif	/* __GNUC__ */
+	return contents;
+}
+
+
+k_machreg_t
+kdb_getcr(int regnum)
+{
+	k_machreg_t contents = 0;
+#if defined(__GNUC__)
+	switch(regnum) {
+	case 0:
+		__asm__ ("movl %%cr0,%0\n\t":"=r"(contents));
+		break;
+	case 1:
+		break;
+	case 2:
+		__asm__ ("movl %%cr2,%0\n\t":"=r"(contents));
+		break;
+	case 3:
+		__asm__ ("movl %%cr3,%0\n\t":"=r"(contents));
+		break;
+	case 4:
+		__asm__ ("movl %%cr4,%0\n\t":"=r"(contents));
+		break;
+	default:
+		break;
+	}
+	  
+#endif	/* __GNUC__ */
+	return contents;
+}
+
+void
+kdb_putdr6(k_machreg_t contents)
+{
+	kdb_putdr(6, contents);
+}
+
+void
+kdb_putdr7(k_machreg_t contents)
+{
+	kdb_putdr(7, contents);
+}
+
+void
+kdb_putdr(int regnum, k_machreg_t contents)
+{
+#if defined(__GNUC__)
+	switch(regnum) {
+	case 0:
+		__asm__ ("movl %0,%%db0\n\t"::"r"(contents));
+		break;
+	case 1:
+		__asm__ ("movl %0,%%db1\n\t"::"r"(contents));
+		break;
+	case 2:
+		__asm__ ("movl %0,%%db2\n\t"::"r"(contents));
+		break;
+	case 3:
+		__asm__ ("movl %0,%%db3\n\t"::"r"(contents));
+		break;
+	case 4:
+	case 5:
+		break;
+	case 6:
+		__asm__ ("movl %0,%%db6\n\t"::"r"(contents));
+		break;
+	case 7:
+		__asm__ ("movl %0,%%db7\n\t"::"r"(contents));
+		break;
+	default:
+		break;
+	}
+#endif
+}
+
+/*
+ * Symbol table functions.
+ */
+
+/*
+ * kdbgetsym
+ *
+ *	Return the symbol table entry for the given symbol
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ * Outputs:
+ * Returns:
+ *	NULL	Symbol doesn't exist
+ *	ksp	Pointer to symbol table entry
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+__ksymtab_t *
+kdbgetsym(const char *symname)
+{
+	__ksymtab_t *ksp = __kdbsymtab;
+	int i;
+
+	if (symname == NULL)
+		return NULL;
+
+	for (i=0; i<__kdbsymtabsize; i++, ksp++) {
+		if (ksp->name && (strcmp(ksp->name, symname)==0)) {
+			return ksp;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * kdbgetsymval
+ *
+ *	Return the address of the given symbol.
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ * Outputs:
+ * Returns:
+ *	0	Symbol name is NULL
+ *	addr	Address corresponding to symname
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+unsigned long
+kdbgetsymval(const char *symname)
+{
+	__ksymtab_t *ksp = kdbgetsym(symname);
+
+	return (ksp?ksp->value:0);
+}
+
+/*
+ * kdbaddmodsym
+ *
+ *	Add a symbol to the kernel debugger symbol table.  Called when
+ *	a new module is loaded into the kernel.
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ *	value	Value of symbol
+ * Outputs:
+ * Returns:
+ *	0	Successfully added to table.
+ *	1	Duplicate symbol
+ *	2	Symbol table full
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdbaddmodsym(char *symname, unsigned long value) 
+{
+
+	/*
+	 * Check for duplicate symbols.
+	 */
+	if (kdbgetsym(symname)) {
+		printk("kdb: Attempt to register duplicate symbol '%s' @ 0x%lx\n",
+			symname, value);
+		return 1;
+	}
+
+	if (__kdbsymtabsize < __kdbmaxsymtabsize) {
+		__ksymtab_t *ksp = &__kdbsymtab[__kdbsymtabsize++];
+		
+		ksp->name = symname;
+		ksp->value = value;
+		return 0;
+	}
+
+	/*
+	 * No room left in kernel symbol table.
+	 */
+	{
+		static int __kdbwarn = 0;
+
+		if (__kdbwarn == 0) {
+			__kdbwarn++;
+			printk("kdb: Exceeded symbol table size.  Increase KDBMAXSYMTABSIZE in scripts/genkdbsym.awk\n");
+		}
+	}
+
+	return 2;
+}
+
+/*
+ * kdbdelmodsym
+ *
+ *	Add a symbol to the kernel debugger symbol table.  Called when
+ *	a new module is loaded into the kernel.
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ *	value	Value of symbol
+ * Outputs:
+ * Returns:
+ *	0	Successfully added to table.
+ *	1	Symbol not found
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdbdelmodsym(const char *symname)
+{
+	__ksymtab_t *ksp, *endksp;
+
+	if (symname == NULL)
+		return 1;
+
+	/*
+	 * Search for the symbol.  If found, move 
+	 * all successive symbols down one position
+	 * in the symbol table to avoid leaving holes.
+	 */
+	endksp = &__kdbsymtab[__kdbsymtabsize];
+	for (ksp = __kdbsymtab; ksp < endksp; ksp++) {
+		if (ksp->name && (strcmp(ksp->name, symname) == 0)) {
+			endksp--;
+			for ( ; ksp < endksp; ksp++) {
+				*ksp = *(ksp + 1);
+			}
+			__kdbsymtabsize--;
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * kdbnearsym
+ *
+ *	Return the name of the symbol with the nearest address
+ *	less than 'addr'.
+ *
+ * Parameters:
+ * 	addr	Address to check for symbol near
+ * Outputs:
+ * Returns:
+ *	NULL	No symbol with address less than 'addr'
+ *	symbol	Returns the actual name of the symbol.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+char *
+kdbnearsym(unsigned long addr)
+{
+	__ksymtab_t *ksp = __kdbsymtab;
+	__ksymtab_t *kpp = NULL;
+	int i;
+
+	for(i=0; i<__kdbsymtabsize; i++, ksp++) {
+		if (!ksp->name) 
+			continue;
+
+		if (addr == ksp->value) {
+			kpp = ksp;
+			break;
+		}
+		if (addr > ksp->value) {
+			if ((kpp == NULL) 
+			 || (ksp->value > kpp->value)) {
+				kpp = ksp;
+			}
+		}
+	}
+
+	/*
+	 * If more than 128k away, don't bother.
+	 */
+	if ((kpp == NULL)
+	 || ((addr - kpp->value) > 0x20000)) {
+		return NULL;
+	}
+
+	return kpp->name;
+}
+
+/*
+ * kdbgetregcontents
+ *
+ *	Return the contents of the register specified by the 
+ *	input string argument.   Return an error if the string
+ *	does not match a machine register.
+ *
+ *	The following pseudo register names are supported:
+ *	   &regs	 - Prints address of exception frame
+ *	   kesp		 - Prints kernel stack pointer at time of fault
+ *	   %<regname>	 - Uses the value of the registers at the 
+ *			   last time the user process entered kernel
+ *			   mode, instead of the registers at the time
+ *			   kdb was entered.
+ *
+ * Parameters:
+ *	regname		Pointer to string naming register
+ *	regs		Pointer to structure containing registers.
+ * Outputs:
+ *	*contents	Pointer to unsigned long to recieve register contents
+ * Returns:
+ *	0		Success
+ *	KDB_BADREG	Invalid register name
+ * Locking:
+ * 	None.
+ * Remarks:
+ *
+ * 	Note that this function is really machine independent.   The kdb
+ *	register list is not, however.
+ */
+
+static struct kdbregs {
+	char   *reg_name;
+	size_t	reg_offset;
+} kdbreglist[] = {
+	{ "eax",	offsetof(struct pt_regs, eax) },
+	{ "ebx",	offsetof(struct pt_regs, ebx) },
+	{ "ecx",	offsetof(struct pt_regs, ecx) },
+	{ "edx",	offsetof(struct pt_regs, edx) },
+
+	{ "esi",	offsetof(struct pt_regs, esi) },
+	{ "edi",	offsetof(struct pt_regs, edi) },
+	{ "esp",	offsetof(struct pt_regs, esp) },
+	{ "eip",	offsetof(struct pt_regs, eip) },
+
+	{ "ebp",	offsetof(struct pt_regs, ebp) },
+	{ " ss", 	offsetof(struct pt_regs, xss) },
+	{ " cs",	offsetof(struct pt_regs, xcs) },
+	{ "eflags", 	offsetof(struct pt_regs, eflags) },
+
+	{ " ds", 	offsetof(struct pt_regs, xds) },
+	{ " es", 	offsetof(struct pt_regs, xes) },
+	{ "origeax",	offsetof(struct pt_regs, orig_eax) },
+
+};
+
+static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs);
+
+int
+kdbgetregcontents(const char *regname, 
+		  struct pt_regs *regs,
+		  unsigned long *contents)
+{
+	int i;
+
+	if (strcmp(regname, "&regs") == 0) {
+		*contents = (unsigned long)regs;
+		return 0;
+	}
+
+	if (strcmp(regname, "kesp") == 0) {
+		*contents = (unsigned long)regs + sizeof(struct pt_regs);
+		return 0;
+	}
+
+	if (regname[0] == '%') {
+		/* User registers:  %%e[a-c]x, etc */
+		regname++;
+		regs = (struct pt_regs *)
+			(current->tss.esp0 - sizeof(struct pt_regs));
+	}
+
+	for (i=0; i<nkdbreglist; i++) {
+		if (strnicmp(kdbreglist[i].reg_name, 
+			     regname, 
+			     strlen(regname)) == 0)
+			break;
+	}
+
+	if ((i == nkdbreglist) 
+	 || (strlen(kdbreglist[i].reg_name) != strlen(regname))) {
+		return KDB_BADREG;
+	}
+
+	*contents = *(unsigned long *)((unsigned long)regs +
+			kdbreglist[i].reg_offset);
+
+	return 0;
+}
+
+/*
+ * kdbsetregcontents
+ *
+ *	Set the contents of the register specified by the 
+ *	input string argument.   Return an error if the string
+ *	does not match a machine register.
+ *
+ *	Supports modification of user-mode registers via
+ *	%<register-name>
+ *
+ * Parameters:
+ *	regname		Pointer to string naming register
+ *	regs		Pointer to structure containing registers.
+ *	contents	Unsigned long containing new register contents
+ * Outputs:
+ * Returns:
+ *	0		Success
+ *	KDB_BADREG	Invalid register name
+ * Locking:
+ * 	None.
+ * Remarks:
+ */
+
+int
+kdbsetregcontents(const char *regname, 
+		  struct pt_regs *regs,
+		  unsigned long contents)
+{
+	int i;
+
+	if (regname[0] == '%') {
+		regname++;
+		regs = (struct pt_regs *)
+			(current->tss.esp0 - sizeof(struct pt_regs));
+	}
+
+	for (i=0; i<nkdbreglist; i++) {
+		if (strnicmp(kdbreglist[i].reg_name, 
+			     regname, 
+			     strlen(regname)) == 0)
+			break;
+	}
+
+	if ((i == nkdbreglist) 
+	 || (strlen(kdbreglist[i].reg_name) != strlen(regname))) {
+		return KDB_BADREG;
+	}
+
+	*(unsigned long *)((unsigned long)regs + kdbreglist[i].reg_offset) = 
+		contents;
+
+	return 0;
+}
+
+/*
+ * kdbdumpregs
+ *
+ *	Dump the specified register set to the display.
+ *
+ * Parameters:
+ *	regs		Pointer to structure containing registers.
+ *	type		Character string identifying register set to dump
+ *	extra		string further identifying register (optional)
+ * Outputs:
+ * Returns:
+ *	0		Success
+ * Locking:
+ * 	None.
+ * Remarks:
+ *	This function will dump the general register set if the type
+ *	argument is NULL (struct pt_regs).   The alternate register 
+ *	set types supported by this function:
+ *
+ *	d 		Debug registers
+ *	c		Control registers
+ *	u		User registers at most recent entry to kernel
+ * Following not yet implemented:
+ *	m		Model Specific Registers (extra defines register #)
+ *	r		Memory Type Range Registers (extra defines register)
+ */
+
+int
+kdbdumpregs(struct pt_regs *regs,
+	    const char *type,
+	    const char *extra)
+{
+	int i;
+	int count = 0;
+
+	if (type 
+	 && (type[0] == 'u')) {
+		type = NULL;
+		regs = (struct pt_regs *)
+			(current->tss.esp0 - sizeof(struct pt_regs));
+	}
+
+	if (type == NULL) {
+		for (i=0; i<nkdbreglist; i++) {
+			kdb_printf("%s = 0x%8.8x  ", 
+				   kdbreglist[i].reg_name, 
+				   *(unsigned long *)((unsigned long)regs + 
+						  kdbreglist[i].reg_offset));
+
+			if ((++count % 4) == 0)
+				kdb_printf("\n");
+		}
+
+		kdb_printf("&regs = 0x%8.8x\n", regs);
+
+		return 0;
+	}
+
+	switch (type[0]) {
+	case 'd':
+	{
+		unsigned long dr[8];
+
+		for(i=0; i<8; i++) {
+			if ((i == 4) || (i == 5)) continue;
+			dr[i] = kdb_getdr(i);
+		}
+		kdb_printf("dr0 = 0x%8.8x  dr1 = 0x%8.8x  dr2 = 0x%8.8x  dr3 = 0x%8.8x\n",
+			   dr[0], dr[1], dr[2], dr[3]);
+		kdb_printf("dr6 = 0x%8.8x  dr7 = 0x%8.8x\n", 
+			   dr[6], dr[7]);
+		return 0;
+	}
+	case 'c':
+	{
+		unsigned long cr[5];
+
+		for (i=0; i<5; i++) {
+			cr[i] = kdb_getcr(i);
+		}
+		kdb_printf("cr0 = 0x%8.8x  cr1 = 0x%8.8x  cr2 = 0x%8.8x  cr3 = 0x%8.8x\ncr4 = 0x%8.8x\n",
+			   cr[0], cr[1], cr[2], cr[3], cr[4]);
+		return 0;
+	}
+	case 'm':
+		break;
+	case 'r':
+		break;
+	default:
+		return KDB_BADREG;
+	}
+
+	/* NOTREACHED */
+	return 0;
+}
+
+int
+kdb_setjmp(kdb_jmp_buf *jb)
+{
+#if defined(CONFIG_KDB_FRAMEPTR)
+	__asm__ ("movl 8(%esp), %eax\n\t"
+		 "movl %ebx, 0(%eax)\n\t"
+		 "movl %esi, 4(%eax)\n\t"
+		 "movl %edi, 8(%eax)\n\t"
+		 "movl (%esp), %ecx\n\t"
+		 "movl %ecx, 12(%eax)\n\t"
+		 "leal 8(%esp), %ecx\n\t"
+		 "movl %ecx, 16(%eax)\n\t"
+		 "movl 4(%esp), %ecx\n\t"
+		 "movl %ecx, 20(%eax)\n\t");
+#else	 /* CONFIG_KDB_FRAMEPTR */
+	__asm__ ("movl 4(%esp), %eax\n\t"
+		 "movl %ebx, 0(%eax)\n\t"
+		 "movl %esi, 4(%eax)\n\t"
+		 "movl %edi, 8(%eax)\n\t"
+		 "movl %ebp, 12(%eax)\n\t"
+		 "leal 4(%esp), %ecx\n\t"
+		 "movl %ecx, 16(%eax)\n\t"
+		 "movl 0(%esp), %ecx\n\t"
+		 "movl %ecx, 20(%eax)\n\t");
+#endif   /* CONFIG_KDB_FRAMEPTR */
+	return 0;
+}
+
+void
+kdb_longjmp(kdb_jmp_buf *jb, int reason)
+{
+#if defined(CONFIG_KDB_FRAMEPTR)
+	__asm__("movl 8(%esp), %ecx\n\t"
+		"movl 12(%esp), %eax\n\t"
+		"movl 20(%ecx), %edx\n\t"
+		"movl 0(%ecx), %ebx\n\t"
+		"movl 4(%ecx), %esi\n\t"
+		"movl 8(%ecx), %edi\n\t"
+		"movl 12(%ecx), %ebp\n\t"
+		"movl 16(%ecx), %esp\n\t"
+		"jmp *%edx\n");
+#else    /* CONFIG_KDB_FRAMEPTR */
+	__asm__("movl 4(%esp), %ecx\n\t"
+		"movl 8(%esp), %eax\n\t"
+		"movl 20(%ecx), %edx\n\t"
+		"movl 0(%ecx), %ebx\n\t"
+		"movl 4(%ecx), %esi\n\t"
+		"movl 8(%ecx), %edi\n\t"
+		"movl 12(%ecx), %ebp\n\t"
+		"movl 16(%ecx), %esp\n\t"
+		"jmp *%edx\n");
+#endif	 /* CONFIG_KDB_FRAMEPTR */
+}
+
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdbsupport.h.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/kdbsupport.h	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,163 @@
+/*
+ * Kernel Debugger Breakpoint Handler
+ *
+ * Copyright 1999, Silicon Graphics, Inc.
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ */
+
+#if !defined(_KDSUPPORT)
+#define _KDSUPPORT
+
+#include <asm/ptrace.h>
+
+	/*
+	 * This file provides definitions for functions that
+	 * are dependent upon the product into which  kdb is
+	 * linked. 
+	 *
+	 * This version is for linux.
+	 */
+typedef void (*handler_t)(struct pt_regs *);
+typedef unsigned long k_machreg_t;
+
+extern char*         kbd_getstr(char *, size_t, char *);
+extern int           kdbinstalltrap(int, handler_t, handler_t*);
+extern int           kdbinstalldbreg(kdb_bp_t*);
+extern void          kdbremovedbreg(int);
+extern void          kdb_initbptab(void);
+extern int	     kdbgetregcontents(const char *, struct pt_regs *, unsigned long *);
+extern int	     kdbsetregcontents(const char *, struct pt_regs *, unsigned long);
+extern int	     kdbdumpregs(struct pt_regs *, const char *, const char *);
+
+
+/*
+ * kdb_db_trap is a processor dependent routine invoked
+ * from kdb() via the #db trap handler.   It handles breakpoints involving
+ * the processor debug registers and handles single step traps
+ * using the processor trace flag.
+ */
+
+#define KDB_DB_BPT	0	/* Straight breakpoint */
+#define KDB_DB_SS	1	/* Single Step trap */
+#define KDB_DB_SSB	2	/* Single Step, caller should continue */
+
+extern int 	     kdb_db_trap(struct pt_regs *);
+
+
+	/*
+	 *  Support for ia32 architecture debug registers.
+	 */
+#define KDB_DBREGS	4
+extern k_machreg_t dbregs[];
+
+#define DR6_BT  0x00008000
+#define DR6_BS	0x00004000
+#define DR6_BD  0x00002000
+
+#define DR6_B3  0x00000008
+#define DR6_B2	0x00000004
+#define DR6_B1  0x00000002
+#define DR6_B0	0x00000001
+
+#define DR7_RW_VAL(dr, drnum) \
+       (((dr) >> (16 + (4 * (drnum)))) & 0x3)
+
+#define DR7_RW_SET(dr, drnum, rw)                              \
+       do {                                                    \
+               (dr) &= ~(0x3 << (16 + (4 * (drnum))));         \
+               (dr) |= (((rw) & 0x3) << (16 + (4 * (drnum)))); \
+       } while (0)
+
+#define DR7_RW0(dr)       DR7_RW_VAL(dr, 0)
+#define DR7_RW0SET(dr,rw)  DR7_RW_SET(dr, 0, rw)
+#define DR7_RW1(dr)       DR7_RW_VAL(dr, 1)
+#define DR7_RW1SET(dr,rw)  DR7_RW_SET(dr, 1, rw)
+#define DR7_RW2(dr)       DR7_RW_VAL(dr, 2)
+#define DR7_RW2SET(dr,rw)  DR7_RW_SET(dr, 2, rw)
+#define DR7_RW3(dr)       DR7_RW_VAL(dr, 3)
+#define DR7_RW3SET(dr,rw)  DR7_RW_SET(dr, 3, rw)
+
+
+#define DR7_LEN_VAL(dr, drnum) \
+       (((dr) >> (18 + (4 * (drnum)))) & 0x3)
+
+#define DR7_LEN_SET(dr, drnum, rw)                             \
+       do {                                                    \
+               (dr) &= ~(0x3 << (18 + (4 * (drnum))));         \
+               (dr) |= (((rw) & 0x3) << (18 + (4 * (drnum)))); \
+       } while (0)
+
+#define DR7_LEN0(dr)        DR7_LEN_VAL(dr, 0)
+#define DR7_LEN0SET(dr,len)  DR7_LEN_SET(dr, 0, len)
+#define DR7_LEN1(dr)        DR7_LEN_VAL(dr, 1)
+#define DR7_LEN1SET(dr,len)  DR7_LEN_SET(dr, 1, len)
+#define DR7_LEN2(dr)        DR7_LEN_VAL(dr, 2)
+#define DR7_LEN2SET(dr,len)  DR7_LEN_SET(dr, 2, len)
+#define DR7_LEN3(dr)        DR7_LEN_VAL(dr, 3)
+#define DR7_LEN3SET(dr,len)  DR7_LEN_SET(dr, 3, len)
+
+#define DR7_G0(dr)    (((dr)>>1)&0x1)
+#define DR7_G0SET(dr) ((dr) |= 0x2)
+#define DR7_G0CLR(dr) ((dr) &= ~0x2)
+#define DR7_G1(dr)    (((dr)>>3)&0x1)
+#define DR7_G1SET(dr) ((dr) |= 0x8)
+#define DR7_G1CLR(dr) ((dr) &= ~0x8)
+#define DR7_G2(dr)    (((dr)>>5)&0x1)
+#define DR7_G2SET(dr) ((dr) |= 0x20)
+#define DR7_G2CLR(dr) ((dr) &= ~0x20)
+#define DR7_G3(dr)    (((dr)>>7)&0x1)
+#define DR7_G3SET(dr) ((dr) |= 0x80)
+#define DR7_G3CLR(dr) ((dr) &= ~0x80)
+
+#define DR7_L0(dr)    (((dr))&0x1)
+#define DR7_L0SET(dr) ((dr) |= 0x1)
+#define DR7_L0CLR(dr) ((dr) &= ~0x1)
+#define DR7_L1(dr)    (((dr)>>2)&0x1)
+#define DR7_L1SET(dr) ((dr) |= 0x4)
+#define DR7_L1CLR(dr) ((dr) &= ~0x4)
+#define DR7_L2(dr)    (((dr)>>4)&0x1)
+#define DR7_L2SET(dr) ((dr) |= 0x10)
+#define DR7_L2CLR(dr) ((dr) &= ~0x10)
+#define DR7_L3(dr)    (((dr)>>6)&0x1)
+#define DR7_L3SET(dr) ((dr) |= 0x40)
+#define DR7_L3CLR(dr) ((dr) &= ~0x40)
+
+#define DR7_GD		0x00002000		/* General Detect Enable */
+#define DR7_GE		0x00000200		/* Global exact */
+#define DR7_LE		0x00000100		/* Local exact */
+
+extern k_machreg_t kdb_getdr6(void);
+extern void kdb_putdr6(k_machreg_t);
+
+extern k_machreg_t kdb_getdr7(void);
+extern void kdb_putdr7(k_machreg_t);
+
+extern k_machreg_t kdb_getdr(int);
+extern void kdb_putdr(int, k_machreg_t);
+
+extern k_machreg_t kdb_getcr(int);
+
+extern void kdb_bp_install(void);
+extern void kdb_bp_remove(void);
+
+/*
+ * Support for setjmp/longjmp
+ */
+#define JB_BX   0
+#define JB_SI   1
+#define JB_DI   2
+#define JB_BP   3
+#define JB_SP   4
+#define JB_PC   5
+
+typedef struct __kdb_jmp_buf {
+	unsigned long   regs[6];
+} kdb_jmp_buf;
+
+extern int kdb_setjmp(kdb_jmp_buf *);
+extern void kdb_longjmp(kdb_jmp_buf *, int);
+
+extern kdb_jmp_buf  kdbjmpbuf;
+
+#endif	/* KDSUPPORT */
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/modules/Makefile.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/modules/Makefile	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,17 @@
+#
+# Makefile for i386-specific kdb files..
+#
+#  Copyright 1999, Silicon Graphics Inc.
+# 
+#  Written April 1999 by Scott Lurndal at Silicon Graphics, Inc.
+#
+
+SUB_DIRS     :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+#O_TARGET     := kdbm_vm.o
+
+M_OBJS       := kdbm_vm.o
+
+include $(TOPDIR)/Rules.make
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/modules/kdbm_vm.c.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/modules/kdbm_vm.c	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,82 @@
+#define MODULE
+#include <linux/kdb.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+
+struct __vmflags {
+	unsigned long mask;
+	char *name;
+} vmflags[] = {
+	{ VM_READ, "READ" },
+	{ VM_WRITE, "WRITE" },
+	{ VM_EXEC, "EXEC" },
+	{ VM_SHARED, "SHARED" },
+	{ VM_MAYREAD, "MAYREAD" },
+	{ VM_MAYWRITE, "MAYWRITE" },
+	{ VM_MAYEXEC, "MAYEXEC" },
+	{ VM_MAYSHARE, "MAYSHARE" },
+	{ VM_GROWSDOWN, "GROWSDOWN" },
+	{ VM_GROWSUP, "GROWSUP" },
+	{ VM_SHM, "SHM" },
+	{ VM_DENYWRITE, "DENYWRITE" },
+	{ VM_EXECUTABLE, "EXECUTABLE" },
+	{ VM_LOCKED, "LOCKED" },
+	{ VM_IO , "IO " },
+	{ 0, "" }
+};
+
+int
+kdbm_vm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct vm_area_struct vp;
+	unsigned char *bp = (unsigned char *)&vp;
+	unsigned long addr;
+	long	offset=0;
+	int nextarg;
+	int diag;
+	struct __vmflags *tp;
+	int i;
+	
+	if (argc != 1) 
+		return KDB_ARGCOUNT;
+
+	nextarg = 1;
+	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+	if (diag) 
+		return diag;
+
+	addr += offset;
+
+	for (i=0; i<sizeof(struct vm_area_struct); i++) {
+		*bp++ = kdbgetword(addr+i, 1);
+	}
+
+	printk("struct vm_area_struct at 0x%lx for %d bytes\n", 
+		addr, sizeof(struct vm_area_struct));
+	printk("vm_start = 0x%lx   vm_end = 0x%lx\n", vp.vm_start, vp.vm_end);
+	printk("page_prot = 0x%x   avl_height = %d    vm_offset = 0x%x\n",
+		vp.vm_page_prot, vp.vm_avl_height, vp.vm_offset);
+	printk("flags:  ");
+	for(tp=vmflags; tp->mask; tp++) {
+		if (vp.vm_flags & tp->mask) {
+			printk("%s ", tp->name);
+		}
+	}
+	printk("\n");
+
+	return 0;
+}
+
+int
+init_module(void)
+{
+	kdb_register("vm", kdbm_vm, "<vaddr>", "Display vm_area_struct", 0);
+	
+	return 0;
+}
+
+void
+cleanup_module(void)
+{
+	kdb_unregister("vm");
+}
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/pc_keyb.h.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kdb/pc_keyb.h	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,126 @@
+/*
+ *	linux/drivers/char/pc_keyb.h
+ *
+ *	PC Keyboard And Keyboard Controller
+ *
+ *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+/*
+ *	Configuration Switches
+ */
+
+#undef KBD_REPORT_ERR			/* Report keyboard errors */
+#define KBD_REPORT_UNKN			/* Report unknown scan codes */
+#define KBD_REPORT_TIMEOUTS		/* Report keyboard timeouts */
+#undef KBD_IS_FOCUS_9000		/* We have the brain-damaged FOCUS-9000 keyboard */
+#undef INITIALIZE_MOUSE			/* Define if your PS/2 mouse needs initialization. */
+
+
+
+#define KBD_INIT_TIMEOUT 1000		/* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250			/* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 1000		/* Timeout in ms for keyboard command acknowledge */
+
+/*
+ *	Internal variables of the driver
+ */
+
+extern unsigned char pckbd_read_mask;
+extern unsigned char aux_device_present;
+
+/*
+ *	Keyboard Controller Registers
+ */
+
+#define KBD_STATUS_REG		0x64	/* Status register (R) */
+#define KBD_CNTL_REG		0x64	/* Controller command register (W) */
+#define KBD_DATA_REG		0x60	/* Keyboard data register (R/W) */
+
+/*
+ *	Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE	0x20	/* Read mode bits */
+#define KBD_CCMD_WRITE_MODE	0x60	/* Write mode bits */
+#define KBD_CCMD_GET_VERSION	0xA1	/* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE	0xA7	/* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE	0xA8	/* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE	0xA9	/* Mouse interface test */
+#define KBD_CCMD_SELF_TEST	0xAA	/* Controller self test */
+#define KBD_CCMD_KBD_TEST	0xAB	/* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE	0xAD	/* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE	0xAE	/* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF	0xD3    /* Write to output buffer as if
+					   initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE	0xD4	/* Write the following byte to the mouse */
+
+/*
+ *	Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
+#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
+#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
+#define KBD_CMD_DISABLE		0xF5	/* Disable scanning */
+#define KBD_CMD_RESET		0xFF	/* Reset */
+
+/*
+ *	Keyboard Replies
+ */
+
+#define KBD_REPLY_POR		0xAA	/* Power on reset */
+#define KBD_REPLY_ACK		0xFA	/* Command ACK */
+#define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again */
+
+/*
+ *	Status Register Bits
+ */
+
+#define KBD_STAT_OBF 		0x01	/* Keyboard output buffer full */
+#define KBD_STAT_IBF 		0x02	/* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST	0x04	/* Self test successful */
+#define KBD_STAT_CMD		0x08	/* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED	0x10	/* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF	0x20	/* Mouse output buffer full */
+#define KBD_STAT_GTO 		0x40	/* General receive/xmit timeout */
+#define KBD_STAT_PERR 		0x80	/* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ *	Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT	0x01	/* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT	0x02	/* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS 		0x04	/* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK	0x08	/* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD	0x10	/* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE	0x20	/* Disable mouse interface */
+#define KBD_MODE_KCC 		0x40	/* Scan code conversion to PC format */
+#define KBD_MODE_RFU		0x80
+
+/*
+ *	Mouse Commands
+ */
+
+#define AUX_SET_RES		0xE8	/* Set resolution */
+#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
+#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
+#define AUX_GET_SCALE		0xE9	/* Get scaling factor */
+#define AUX_SET_STREAM		0xEA	/* Set stream mode */
+#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
+#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
+#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
+#define AUX_RESET		0xFF	/* Reset aux device */
+
+#define AUX_BUF_SIZE		2048
+
+struct aux_queue {
+	unsigned long head;
+	unsigned long tail;
+	struct wait_queue *proc_list;
+	struct fasync_struct *fasync;
+	unsigned char buf[AUX_BUF_SIZE];
+};
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/entry.S.~1~	Mon Sep  4 18:39:16 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/entry.S	Wed Oct 25 19:09:54 2000
@@ -161,6 +161,19 @@
 	GET_CURRENT(%ebx)
 	jmp	ret_from_sys_call
 
+#if defined(CONFIG_KDB)
+ENTRY(kdb_call)
+	pushl %eax		# save orig EAX
+	SAVE_ALL		
+	pushl %esp		# struct pt_regs
+	pushl $0		# error_code
+	pushl $7		# KDB_REASON_INT
+	call  kdb
+	addl  $12,%esp		# remove args
+	RESTORE_ALL
+
+#endif
+
 /*
  * Return to user mode is not as complex as all this looks,
  * but we want the default path for a system call return to
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/i386_ksyms.c.~1~	Wed Oct 25 18:57:50 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/i386_ksyms.c	Wed Oct 25 19:09:54 2000
@@ -17,6 +17,9 @@
 #include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+#endif
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(elf_fpregset_t *);
@@ -119,6 +122,20 @@
 
 #ifdef CONFIG_VT
 EXPORT_SYMBOL(screen_info);
+#endif
+
+#if defined(CONFIG_KDB)
+EXPORT_SYMBOL(kdb_register);
+EXPORT_SYMBOL(kdb_unregister);
+EXPORT_SYMBOL(kdbgetword);
+EXPORT_SYMBOL(kdbgetularg);
+EXPORT_SYMBOL(kdbgetenv);
+EXPORT_SYMBOL(kdbgetintenv);
+EXPORT_SYMBOL(kdbgetaddrarg);
+EXPORT_SYMBOL(kdb);
+EXPORT_SYMBOL(kdbgetsymval);
+EXPORT_SYMBOL(kdbnearsym);
+EXPORT_SYMBOL(kdb_printf);
 #endif
 
 EXPORT_SYMBOL(rtc_lock);
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/irq.c.~1~	Wed Jun  7 22:26:42 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/irq.c	Wed Oct 25 19:09:54 2000
@@ -324,6 +324,9 @@
 BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
 BUILD_SMP_INTERRUPT(call_function_interrupt)
 BUILD_SMP_INTERRUPT(spurious_interrupt)
+#if defined(CONFIG_KDB)
+BUILD_SMP_INTERRUPT(kdb_interrupt)
+#endif	/* CONFIG_KDB */
 
 /*
  * every pentium local APIC has two 'local interrupts', with a
@@ -1099,7 +1102,11 @@
 	 */
 	for (i = 0; i < NR_IRQS; i++) {
 		int vector = FIRST_EXTERNAL_VECTOR + i;
-		if (vector != SYSCALL_VECTOR) 
+		if ((vector != SYSCALL_VECTOR) 
+#if defined(CONFIG_KDB)
+		 && (vector != KDBENTER_VECTOR)
+#endif
+						)
 			set_intr_gate(vector, interrupt[i]);
 	}
 
@@ -1131,6 +1138,11 @@
 
 	/* IPI vector for APIC spurious interrupts */
 	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+
+#if defined(__SMP__) && defined(CONFIG_KDB)
+	/* IPI vector for Kernel Debugger */
+	set_intr_gate(KDB_VECTOR, kdb_interrupt);
+#endif	/* CONFIG_SMP */
 #endif	
 	request_region(0x20,0x20,"pic1");
 	request_region(0xa0,0x20,"pic2");
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/irq.h.~1~	Tue Jan  4 18:12:11 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/irq.h	Wed Oct 25 19:09:54 2000
@@ -50,6 +50,9 @@
 #define FIRST_EXTERNAL_VECTOR	0x20
 
 #define SYSCALL_VECTOR		0x80
+#if defined(CONFIG_KDB)
+#define KDBENTER_VECTOR		0x81
+#endif
 
 /*
  * Vectors 0x20-0x2f are used for ISA interrupts.
@@ -66,6 +69,9 @@
 #define INVALIDATE_TLB_VECTOR	0x31
 #define STOP_CPU_VECTOR		0x40
 #define LOCAL_TIMER_VECTOR	0x41
+#if defined(CONFIG_KDB)
+#define KDB_VECTOR		0x42
+#endif	/* CONFIG_KDB */
 #define CALL_FUNCTION_VECTOR	0x50
 
 /*
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/smp.c.~1~	Wed Oct 25 18:57:50 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/smp.c	Wed Oct 25 19:09:54 2000
@@ -42,6 +42,10 @@
 #include <asm/mtrr.h>
 #include <asm/msr.h>
 
+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+#endif
+
 #include "irq.h"
 
 #define JIFFIE_TIMEOUT 100
@@ -104,6 +108,9 @@
 
 unsigned long cpu_present_map = 0;			/* Bitmask of physically existing CPUs 				*/
 unsigned long cpu_online_map = 0;			/* Bitmask of currently online CPUs 				*/
+#if defined(__SMP__)
+unsigned long smp_kdb_wait = 0;				/* Bitmask of waiters */
+#endif	/* CONFIG_SMP */
 int smp_num_cpus = 1;					/* Total count of live CPUs 				*/
 int smp_threads_ready=0;				/* Set when the idlers are all forked 			*/
 volatile int cpu_number_map[NR_CPUS];			/* which CPU maps to which logical number		*/
@@ -1978,6 +1985,21 @@
 	return 0;
 }
 
+
+#if defined(CONFIG_KDB)
+void smp_kdb_stop(int all)
+{
+	if (all)  {
+		smp_kdb_wait = 0xffffffff;
+		clear_bit(smp_processor_id(), &smp_kdb_wait);
+		send_IPI_allbutself(KDB_VECTOR);
+	} else {
+		set_bit(smp_processor_id(), &smp_kdb_wait);
+		send_IPI_self(KDB_VECTOR);
+	}
+}
+#endif
+
 /*
  * Local timer interrupt handler. It does both profiling and
  * process statistics/rescheduling.
@@ -2113,6 +2135,51 @@
 {
 	stop_this_cpu();
 }
+
+#if defined(CONFIG_KDB)
+asmlinkage void smp_kdb_interrupt(int a)
+{
+	/*
+	 * The stub function which calls this routine pushes
+	 * the register context on the stack prior to calling
+	 * this routine.  No arguments are pushed on the stack,
+	 * so taking the address of a non-existant first argument
+	 * will obtain the address of the preserved register context
+	 *
+	 * This is a gross hack, but it works and doesn't require
+	 * changes to BUILD_SMP_INTERRUPT.
+	 */
+	struct pt_regs *regs = &a;
+	extern unsigned long smp_kdb_wait;
+	extern int kdb_new_cpu;
+	ack_APIC_irq();
+
+	/*
+	 * Wait for kdb to set us free.
+	 */
+#if 0
+	printk("stopping cpu %d for kdb\n", smp_processor_id());
+#endif
+
+	while (test_bit(smp_processor_id(), &smp_kdb_wait))
+		;
+#if 0
+	printk("restarting cpu %d for kdb\n", smp_processor_id());
+#endif
+
+	/*
+	 * If we are the new CPU, call the kernel debugger here.
+	 */
+	if (kdb_new_cpu == smp_processor_id()) {
+		kdb(KDB_REASON_SWITCH, 0, regs);
+	}
+
+	/*
+	 * Re-establish any global breakpoint state
+	 */
+	kdb_global(smp_processor_id());
+}
+#endif	/* CONFIG_KDB */
 
 asmlinkage void smp_call_function_interrupt(void)
 {
--- linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/traps.c.~1~	Wed Oct 25 18:57:50 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/arch/i386/kernel/traps.c	Wed Oct 25 19:09:54 2000
@@ -26,6 +26,10 @@
 #include <asm/processor.h>
 #endif
 
+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+#endif
+
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -45,6 +49,9 @@
 #include "irq.h"
 
 asmlinkage int system_call(void);
+#if defined(CONFIG_KDB)
+asmlinkage int kdb_call(void);
+#endif
 asmlinkage void lcall7(void);
 
 struct desc_struct default_ldt = { 0, 0 };
@@ -208,6 +215,9 @@
 {
 	console_verbose();
 	spin_lock_irq(&die_lock);
+#if defined(CONFIG_KDB)
+	kdb(KDB_REASON_PANIC, err, regs);
+#endif
 	printk("%s: %04lx\n", str, err & 0xffff);
 	show_registers(regs);
 	spin_unlock_irq(&die_lock);
@@ -410,9 +420,15 @@
 	return;
 
 clear_dr7:
+
+#if defined(CONFIG_KDB)
+	kdb(KDB_REASON_DEBUG, error_code, regs);
+#else
+
 	__asm__("movl %0,%%db7"
 		: /* no output */
 		: "r" (0));
+#endif	/* CONFIG_KDB */
 	return;
 
 clear_TF:
@@ -706,6 +722,13 @@
 	set_trap_gate(17,&alignment_check);
 	set_trap_gate(18,&machine_check);
 	set_system_gate(SYSCALL_VECTOR,&system_call);
+#if defined(CONFIG_KDB)
+	/*
+	 * A trap gate, used by the kernel to enter the
+	 * debugger preserving all registers.
+	 */
+	set_trap_gate(KDBENTER_VECTOR,&kdb_call);
+#endif
 
 	/* set up GDT task & ldt entries */
 	set_tss_desc(0, &init_task.tss);
--- linux-2.2.18pre17.ext3-0.0.5a/drivers/char/keyboard.c.~1~	Wed Oct 25 18:57:51 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/drivers/char/keyboard.c	Wed Oct 25 19:09:54 2000
@@ -42,6 +42,9 @@
 #include <linux/vt_kern.h>
 #include <linux/kbd_ll.h>
 #include <linux/sysrq.h>
+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+#endif
 
 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
@@ -244,6 +247,12 @@
 		    up_flag = kbd_unexpected_up(keycode);
 	} else
 		rep = test_and_set_bit(keycode, key_down);
+
+#if defined(CONFIG_KDB)
+	if (!up_flag && (keycode == E1_PAUSE)) {
+		kdb(KDB_REASON_KEYBOARD, 0, kbd_pt_regs);
+	}
+#endif
 
 #ifdef CONFIG_MAGIC_SYSRQ		/* Handle the SysRq Hack */
 	if (keycode == SYSRQ_KEY) {
--- linux-2.2.18pre17.ext3-0.0.5a/drivers/char/serial.c.~1~	Wed Jun  7 22:26:42 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/drivers/char/serial.c	Wed Oct 25 19:09:54 2000
@@ -375,8 +375,27 @@
 	mark_bh(SERIAL_BH);
 }
 
+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+/*
+ * kdb_serial_line records the serial line number of the 
+ * first serial console.  kdb_info will be set upon receipt 
+ * of the first ^A (which cannot happen until the port is
+ * opened and the interrupt handler attached).  To enter 
+ * kdb before this on a serial console-only system, you must
+ * use the 'kdb' flag to lilo and set the appropriate breakpoints.
+ */
+
+extern int  kdb_port;
+static int  kdb_serial_line = -1;
+#endif	/* CONFIG_KDB */
+
 static _INLINE_ void receive_chars(struct async_struct *info,
+#if defined(CONFIG_KDB)
+				 int *status, struct pt_regs * regs)
+#else
 				 int *status)
+#endif
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch;
@@ -386,6 +405,13 @@
 	icount = &info->state->icount;
 	do {
 		ch = serial_inp(info, UART_RX);
+#if defined(CONFIG_KDB)
+		if ((info->line == kdb_serial_line)
+		 && (ch == 1)) /* CNTRL-A */ {
+			kdb(KDB_REASON_KEYBOARD, 0, regs);
+			break;
+		}
+#endif
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 			break;
 		*tty->flip.char_buf_ptr = ch;
@@ -612,7 +638,11 @@
 		printk("status = %x...", status);
 #endif
 		if (status & UART_LSR_DR)
+#if defined(CONFIG_KDB)
+			receive_chars(info, &status, regs);
+#else
 			receive_chars(info, &status);
+#endif
 		check_modem_status(info);
 		if (status & UART_LSR_THRE)
 			transmit_chars(info, 0);
@@ -676,7 +706,11 @@
 		printk("status = %x...", status);
 #endif
 		if (status & UART_LSR_DR)
+#if defined(CONFIG_KDB)
+			receive_chars(info, &status, regs);
+#else
 			receive_chars(info, &status);
+#endif
 		check_modem_status(info);
 		if (status & UART_LSR_THRE)
 			transmit_chars(info, 0);
@@ -739,7 +773,11 @@
 		printk("status = %x...", status);
 #endif
 		if (status & UART_LSR_DR)
+#if defined(CONFIG_KDB)
+			receive_chars(info, &status, regs);
+#else
 			receive_chars(info, &status);
+#endif
 		check_modem_status(info);
 		if (status & UART_LSR_THRE)
 			transmit_chars(info, 0);
@@ -3367,6 +3405,7 @@
 	unsigned i;
 
 	ser = rs_table + co->index;
+
 	/*
 	 *	First save the IER then disable the interrupts
 	 */
@@ -3543,6 +3582,18 @@
 	 */
 	if (inb(ser->port + UART_LSR) == 0xff)
 		return -1;
+
+#if defined(CONFIG_KDB)
+	/*
+	 * Remember the line number of the first serial
+	 * console.  We'll make this the kdb serial console too.
+	 */
+	if (kdb_serial_line == -1) {
+		kdb_serial_line = co->index;
+		kdb_port = ser->port;
+	}
+#endif	/* CONFIG_KDB */
+
 	return 0;
 }
 
--- linux-2.2.18pre17.ext3-0.0.5a/drivers/char/sysrq.c.~1~	Thu May  4 01:16:39 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/drivers/char/sysrq.c	Wed Oct 25 19:09:54 2000
@@ -1,6 +1,6 @@
 /* -*- linux-c -*-
  *
- *	$Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $
+ *	$Id: sysrq.c,v 1.2 1999/03/09 22:35:19 slurn Exp $
  *
  *	Linux Magic System Request Key Hacks
  *
--- linux-2.2.18pre17.ext3-0.0.5a/include/asm-i386/keyboard.h.~1~	Mon Aug  9 20:04:41 1999
+++ linux-2.2.18pre17.ext3-0.0.5a/include/asm-i386/keyboard.h	Wed Oct 25 19:09:54 2000
@@ -38,6 +38,9 @@
 #define kbd_sysrq_xlate		pckbd_sysrq_xlate
 
 #define SYSRQ_KEY 0x54
+#if defined(CONFIG_KDB)
+#define E1_PAUSE  119			/* PAUSE key */
+#endif
 
 /* resource allocation */
 #define kbd_request_region() request_region(0x60, 16, "keyboard")
--- linux-2.2.18pre17.ext3-0.0.5a/include/asm-i386/ptrace.h.~1~	Mon Aug  9 20:05:02 1999
+++ linux-2.2.18pre17.ext3-0.0.5a/include/asm-i386/ptrace.h	Wed Oct 25 19:09:54 2000
@@ -47,6 +47,29 @@
 #define PTRACE_GETFPREGS          14
 #define PTRACE_SETFPREGS          15
 
+enum EFLAGS {
+        EF_CF   = 0x00000001,
+        EF_PF   = 0x00000004,
+        EF_AF   = 0x00000010,
+        EF_ZF   = 0x00000040,
+        EF_SF   = 0x00000080,
+        EF_TF   = 0x00000100,
+        EF_IE   = 0x00000200,
+        EF_DF   = 0x00000400,
+        EF_OF   = 0x00000800,
+        EF_IOPL = 0x00003000,
+        EF_IOPL_RING0 = 0x00000000,
+        EF_IOPL_RING1 = 0x00001000,
+        EF_IOPL_RING2 = 0x00002000,
+        EF_NT   = 0x00004000,   // nested task
+        EF_RF   = 0x00010000,   // resume
+        EF_VM   = 0x00020000,   // virtual mode
+        EF_AC   = 0x00040000,   // alignment
+        EF_VIF  = 0x00080000,   // virtual interrupt
+        EF_VIP  = 0x00100000,   // virtual interrupt pending
+        EF_ID   = 0x00200000,   // id
+};
+
 #ifdef __KERNEL__
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
--- linux-2.2.18pre17.ext3-0.0.5a/include/linux/kdb.h.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/include/linux/kdb.h	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,177 @@
+/*
+ * Kernel Debugger
+ *
+ * Copyright 1999, Silicon Graphics, Inc.
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ */
+
+#if !defined(__KDB_H)
+#define __KDB_H
+
+#include "bfd.h"
+
+#define KDB_MAJOR_VERSION	0
+#define KDB_MINOR_VERSION	5
+
+/*
+ * Kernel Debugger Error codes 
+ */
+
+#define KDB_NOTFOUND	-1
+#define KDB_GO		-2
+#define KDB_ARGCOUNT	-3
+#define KDB_BADWIDTH	-4
+#define KDB_BADRADIX	-5
+#define KDB_NOTENV	-6
+#define KDB_NOENVVALUE	-7
+#define KDB_NOTIMP	-8
+#define KDB_ENVFULL	-9
+#define KDB_ENVBUFFULL	-10
+#define KDB_TOOMANYBPT	-11
+#define KDB_TOOMANYDBREGS -12
+#define KDB_DUPBPT	-13
+#define KDB_BPTNOTFOUND	-14
+#define KDB_BADMODE	-15
+#define KDB_BADINT	-16
+#define KDB_INVADDRFMT  -17
+#define KDB_BADREG      -18
+#define KDB_CPUSWITCH	-19
+#define KDB_BADCPUNUM   -20
+#define KDB_BADLENGTH	-21
+#define KDB_NOBP	-22
+
+	/*
+	 * XXX - machine dependent.
+	 */
+#define KDB_ENTER()	asm("\tint $129\n")
+
+	/*
+	 * kdb_active is initialized to zero, and is set 
+	 * to KDB_REASON_xxx whenever the kernel debugger is entered.
+	 */
+extern int kdb_active;	
+
+	/*
+	 * KDB_FLAG_EARLYKDB is set when the 'kdb' option is specified
+	 * as a boot parameter (e.g. via lilo).   It indicates that the
+	 * kernel debugger should be entered as soon as practical.
+	 */
+#define KDB_FLAG_EARLYKDB	0x00000001
+	/*
+	 * KDB_FLAG_SSB is set when the 'ssb' command is in progress.  It
+	 * indicates to the debug fault trap code that a trace fault
+	 * (single step) should be continued rather than the debugger
+	 * be entered.
+	 */
+#define KDB_FLAG_SSB		0x00000002
+	/*
+	 * KDB_FLAG_SUPRESS is set when an error message is printed
+	 * by a helper function such as kdbgetword.  No further error messages
+	 * will be printed until this flag is reset.  Used to prevent 
+	 * an illegal address from causing voluminous error messages.
+	 */
+#define KDB_FLAG_SUPRESS	0x00000004
+	/*
+	 * KDB_FLAG_FAULT is set when handling a debug register instruction
+	 * fault.  The backtrace code needs to know.
+	 */
+#define KDB_FLAG_FAULT		0x00000008
+
+extern int kdb_flags;
+
+extern int kdb_nextline;
+
+	/*
+	 * 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.
+	 */
+
+struct pt_regs;
+extern int   kdb(int reason, int error_code, struct pt_regs *);
+#define KDB_REASON_ENTER    1		/* call debugger from source */
+#define KDB_REASON_FAULT    2		/* called from fault, eframe valid */
+#define KDB_REASON_BREAK    3		/* called from int 3, eframe valid */
+#define KDB_REASON_DEBUG    4		/* Called from int #DB, eframe valid */
+#define KDB_REASON_PANIC    5		/* Called from panic(), eframe valid */
+#define KDB_REASON_SWITCH   6		/* Called via CPU switch */
+#define KDB_REASON_INT      7		/* Called via int 129 */
+#define KDB_REASON_KEYBOARD 8           /* Called via keyboard interrupt */
+
+	/*
+	 * The entire contents of this file from this point forward are
+	 * private to the kernel debugger.     They are subject to change
+	 * without notice.
+	 */
+
+	/*
+	 * Breakpoint state 
+	 */
+
+typedef struct _kdb_bp {
+	bfd_vma 	bp_addr;	/* Address breakpoint is present at */
+	unsigned char	bp_prevbyte;	/* Byte which the int3 replaced */
+
+	unsigned int 	bp_regtype:1;	/* Uses a debug register (0-4) */
+	unsigned int	bp_enabled:1;	/* Breakpoint is active in register */
+	unsigned int	bp_global:1;	/* Global to all processors */
+	unsigned int	bp_free:1;	/* This entry is available */
+	unsigned int	bp_data:1;	/* Data breakpoint */
+	unsigned int    bp_write:1;	/* Write data breakpoint */
+	unsigned int	bp_mode:2;	/* 0=inst, 1=write, 2=io, 3=read */
+	unsigned int	bp_length:2;	/* 0=1 byte, 1=2 bytes, 2=BAD, 3=4 */
+
+	int		bp_reg;		/* Register that this breakpoint uses */
+	int		bp_cpu;		/* Cpu #  (if bp_global == 0) */
+} kdb_bp_t;
+
+extern void  kdb_global(int);		/* Set global actions */
+
+	/*
+	 * External Function Declarations
+	 */
+extern char *kdbgetenv(const char *);
+extern int   kdbgetintenv(const char *, int *);
+extern int   kdbgetularg(const char *, unsigned long *);
+extern int   kdbgetaddrarg(int, const char**, int*, unsigned long *, long *, char **, struct pt_regs *);
+extern unsigned long kdbgetword(unsigned long, int);
+extern void  kdb_id1(unsigned long);
+extern void  kdb_disinit(void);
+
+
+	/*
+	 * External command function declarations
+	 */
+
+extern int kdb_id	(int argc, const char **argv, const char **envp, struct pt_regs *);
+extern int kdb_bp	(int argc, const char **argv, const char **envp, struct pt_regs *);
+extern int kdb_bc	(int argc, const char **argv, const char **envp, struct pt_regs *);
+extern int kdb_bt	(int argc, const char **argv, const char **envp, struct pt_regs *);
+extern int kdb_ss	(int argc, const char **argv, const char **envp, struct pt_regs *);
+
+	/*
+	 * Symbol table format
+	 */
+
+typedef struct __symtab {
+		char *name;
+		unsigned long value;
+		} __ksymtab_t;
+
+extern __ksymtab_t __kdbsymtab[];
+extern int __kdbsymtabsize;
+extern int __kdbmaxsymtabsize;
+
+extern unsigned long kdbgetsymval(const char *);
+extern char *        kdbnearsym(unsigned long);
+extern int           kdbaddmodsym(char *, unsigned long);
+extern int           kdbdelmodsym(const char *);
+
+typedef int (*kdb_func)(int, const char **, const char **, struct pt_regs*);
+
+extern int           kdb_register(char *, kdb_func, char *, char *, short);
+extern int           kdb_unregister(char *);
+
+extern int	     kdb_printf(const char *,...);
+#endif	/* __KDB_H */
--- linux-2.2.18pre17.ext3-0.0.5a/include/linux/smp.h.~1~	Wed Oct 25 18:57:53 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/include/linux/smp.h	Wed Oct 25 19:09:54 2000
@@ -54,6 +54,10 @@
 
 extern int smp_num_cpus;
 
+#if defined(CONFIG_KDB)
+extern volatile unsigned long smp_kdb_wait;
+extern void smp_kdb_stop(int);
+#endif	/* CONFIG_KDB */
 extern volatile unsigned long smp_msg_data;
 extern volatile int smp_src_cpu;
 extern volatile int smp_msg_id;
--- linux-2.2.18pre17.ext3-0.0.5a/init/main.c.~1~	Wed Oct 25 18:57:53 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/init/main.c	Wed Oct 25 19:09:54 2000
@@ -57,6 +57,10 @@
 
 extern int irda_device_init(void);
 
+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+#endif
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -1293,6 +1297,12 @@
 			console_loglevel = 4;
 			continue;
 		}
+#if defined(CONFIG_KDB)
+		if (!strcmp(line,"kdb")) {
+			kdb_flags = KDB_FLAG_EARLYKDB;
+			continue;
+		}
+#endif	/* CONFIG_KDB */
 		if (!strncmp(line,"init=",5)) {
 			line += 5;
 			execute_command = line;
@@ -1421,6 +1431,13 @@
 	}
 #endif
 	mem_init(memory_start,memory_end);
+#if defined(CONFIG_KDB)
+	{
+		extern void kdb_init(void);
+
+		kdb_init();
+	}
+#endif
 	kmem_cache_sizes_init();
 #ifdef CONFIG_3215_CONSOLE
         con3215_activate();
@@ -1449,6 +1466,10 @@
 	check_bugs();
 	printk("POSIX conformance testing by UNIFIX\n");
 
+#if defined(CONFIG_KDB)
+	if (kdb_flags & KDB_FLAG_EARLYKDB)
+		KDB_ENTER();
+#endif
 	/* 
 	 *	We count on the initial thread going ok 
 	 *	Like idlers init is an unlocked kernel thread, which will
@@ -1655,6 +1676,10 @@
 	(void) dup(0);
 	(void) dup(0);
 	
+#if defined(CONFIG_KDB)
+	if (kdb_flags & KDB_FLAG_EARLYKDB)
+		KDB_ENTER();
+#endif
 	/*
 	 * We try each of these until one succeeds.
 	 *
--- linux-2.2.18pre17.ext3-0.0.5a/kernel/module.c.~1~	Thu May  4 01:16:53 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/kernel/module.c	Wed Oct 25 19:09:54 2000
@@ -6,6 +6,9 @@
 #include <linux/smp_lock.h>
 #include <asm/pgtable.h>
 #include <linux/init.h>
+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+#endif
 
 /*
  * Originally by Anonymous (as far as I know...)
@@ -170,6 +173,9 @@
 	long namelen, n_namelen, i, error = -EPERM;
 	unsigned long mod_user_size;
 	struct module_ref *dep;
+#if defined(CONFIG_KDB)
+	struct module_symbol *s;
+#endif
 
 	lock_kernel();
 	if (!capable(CAP_SYS_MODULE))
@@ -340,6 +346,11 @@
 	}
 	atomic_dec(&mod->uc.usecount);
 
+#if defined(CONFIG_KDB)
+	for(i=0,s=mod->syms; i<mod->nsyms; i++, s++){
+		kdbaddmodsym(s->name, s->value);
+	}
+#endif
 	/* And set it running.  */
 	mod->flags = (mod->flags | MOD_RUNNING) & ~MOD_INITIALIZING;
 	error = 0;
@@ -778,6 +789,9 @@
 {
 	struct module_ref *dep;
 	unsigned i;
+#if defined(CONFIG_KDB)
+	struct module_symbol *s;
+#endif
 
 	/* Let the module clean up.  */
 
@@ -788,6 +802,15 @@
 			mod->cleanup();
 		mod->flags &= ~MOD_RUNNING;
 	}
+
+#if defined(CONFIG_KDB)
+	/*
+	 * Remove symbols from kernel debugger 
+	 */
+	for(i=0,s=mod->syms; i<mod->nsyms; i++, s++){
+		kdbdelmodsym(s->name);
+	}
+#endif
 
 	/* Remove the module from the dependency lists.  */
 
--- linux-2.2.18pre17.ext3-0.0.5a/mm/vmalloc.c.~1~	Thu Apr 22 07:12:32 1999
+++ linux-2.2.18pre17.ext3-0.0.5a/mm/vmalloc.c	Wed Oct 25 19:09:54 2000
@@ -11,6 +11,43 @@
 
 static struct vm_struct * vmlist = NULL;
 
+#if defined(CONFIG_KDB)
+/* kdb_vmlist_check
+ *     Check to determine if an address is within a vmalloced range.
+ * Parameters:
+ *      starta -- Starting address of region to check
+ *     enda    -- Ending address of region to check
+ * Returns:
+ *     0       -- [starta,enda] not within a vmalloc area
+ *     1       -- [starta,enda] within a vmalloc area
+ * Locking:
+ *     None.
+ * Remarks:
+ *     Shouldn't acquire locks.  Always called with all interrupts
+ *     disabled and other cpus halted.  Yet, if a breakpoint or fault
+ *     occurs while the vmlist is in an indeterminate state, this
+ *     function could fail.
+ */
+int
+kdb_vmlist_check(unsigned long starta, unsigned long enda)
+{
+	struct vm_struct *vp;
+
+	for(vp=vmlist; vp; vp = vp->next) {
+		unsigned long end = (unsigned long)vp->addr + vp->size;
+
+		end -= PAGE_SIZE; 	/* Unbias for guard page */
+
+		if ((starta >= (unsigned long)vp->addr)
+		 && (starta < end)
+		 && (enda < end)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+#endif
+
 static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size)
 {
 	pte_t * pte;
--- linux-2.2.18pre17.ext3-0.0.5a/scripts/genkdbsym.awk.~1~	Wed Oct 25 19:09:54 2000
+++ linux-2.2.18pre17.ext3-0.0.5a/scripts/genkdbsym.awk	Wed Oct 25 19:09:54 2000
@@ -0,0 +1,21 @@
+BEGIN	{
+		printf("#include <linux/kdb.h>\n");
+		printf("#include \"ksym.h\"\n\n");
+		printf("#define   KDBMAXSYMTABSIZE 7500\n");
+		printf("\n__ksymtab_t __attribute__ ((section(\"kdbsymtab\"))) __kdbsymtab[KDBMAXSYMTABSIZE] = {\n");
+		symcount = 0
+		printf("/* Generated file */\n") > "ksym.h";
+		printf("char __attribute__ ((section(\"kdbstrings\"))) kdb_null[]=\"\";\n") >> "ksym.h";
+	}
+
+	{ symname = sprintf("_kdbs%d", symcount);
+	  printf("{%s, 0x%s},\n", symname, $1);
+	  printf("char __attribute__ ((section(\"kdbstrings\"))) %s[] = \"%s\";\n", symname, $3) >> "ksym.h";
+	  symcount = symcount + 1
+        }
+
+END	{
+		printf(" [%d ... KDBMAXSYMTABSIZE-1] = {kdb_null, 0xf}};\n", symcount);
+		printf("int __attribute__ ((section(\"kdbsymtab\"))) __kdbsymtabsize = %d;\n", symcount);
+		printf("int __attribute__ ((section(\"kdbsymtab\"))) __kdbmaxsymtabsize = KDBMAXSYMTABSIZE;\n");
+	}
