ia64/xen-unstable

changeset 1069:5fc679c3c810

bitkeeper revision 1.698.1.1 (4022a73eOGiwh6ZU9-EU4LZoLcVnuQ)

pervasive debugger
author ach61@labyrinth.cl.cam.ac.uk
date Thu Feb 05 20:27:42 2004 +0000 (2004-02-05)
parents 871510593652
children d261b3bfa00c
files .rootkeys README.CD docs/pdb.txt tools/nsplitd/Makefile tools/nsplitd/nsplitd.c xen/arch/i386/pdb-stub.c xen/arch/i386/setup.c xen/arch/i386/traps.c xen/common/debug-linux.c xen/common/debug-linux.h xen/common/debug.c xen/common/kernel.c xen/drivers/char/xen_serial.c xen/include/asm-i386/pdb.h xen/include/hypervisor-ifs/dom0_ops.h xen/include/xeno/sched.h
line diff
     1.1 --- a/.rootkeys	Fri Jan 30 15:55:06 2004 +0000
     1.2 +++ b/.rootkeys	Thu Feb 05 20:27:42 2004 +0000
     1.3 @@ -12,6 +12,7 @@ 3fafbf11blCNItRsHe0UHwyu5CCDkw docs/Xeno
     1.4  3f9e7d60PWZJeVh5xdnk0nLUdxlqEA docs/eps/xenlogo.eps
     1.5  3f9e7d63lTwQbp2fnx7yY93epWS-eQ docs/figs/dummy
     1.6  3f9e7d564bWFB-Czjv1qdmE6o0GqNg docs/interface.tex
     1.7 +4022a73cgxX1ryj1HgS-IwwB6NUi2A docs/pdb.txt
     1.8  3f9e7d58t7N6hjjBMxSn-NMxBphchA docs/style.tex
     1.9  3f9e7d5bz8BwYkNuwyiPVu7JJG441A docs/xenstyle.cls
    1.10  3f815144d1vI2777JI-dO4wk49Iw7g extras/mini-os/Makefile
    1.11 @@ -73,6 +74,8 @@ 3f13d81eQ9Vz-h-6RDGFkNR9CRP95g tools/mis
    1.12  3f13d81e6Z6806ihYYUw8GVKNkYnuw tools/misc/xen_nat_enable.README
    1.13  3f1668d4F29Jsw0aC0bJEIkOBiagiQ tools/misc/xen_read_console.c
    1.14  3f87ba90EUVPQLVOlFG0sW89BCwouQ tools/misc/xen_refresh_dev.c
    1.15 +4022a73cEKvrYe_DVZW2JlAxobg9wg tools/nsplitd/Makefile
    1.16 +4022a73cKms4Oq030x2JBzUB426lAQ tools/nsplitd/nsplitd.c
    1.17  3fbca441SjQr8vJwTQIgH1laysaWog tools/xc/Makefile
    1.18  3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/xc/lib/Makefile
    1.19  3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/xc/lib/rpm.spec
    1.20 @@ -118,6 +121,7 @@ 3ddb79bdeJ7_86z03yTAPIeeywOg3Q xen/arch/
    1.21  3ddb79bdIKgipvGoqExEQ7jawfVowA xen/arch/i386/pci-i386.h
    1.22  3ddb79bdHe6_Uij4-glW91vInNtBYQ xen/arch/i386/pci-irq.c
    1.23  3ddb79bcZ_2FxINljqNSkqa17ISyJw xen/arch/i386/pci-pc.c
    1.24 +4022a73czgX7d-2zfF_cb33oVemApQ xen/arch/i386/pdb-stub.c
    1.25  3ddb79bc1_2bAt67x9MFCP4AZrQnvQ xen/arch/i386/process.c
    1.26  3ddb79bc7KxGCEJsgBnkDX7XjD_ZEQ xen/arch/i386/rwlock.c
    1.27  3ddb79bcrD6Z_rUvSDgrvjyb4846Eg xen/arch/i386/setup.c
    1.28 @@ -133,6 +137,8 @@ 3e397e66AyyD5fYraAySWuwi9uqSXg xen/commo
    1.29  3ddb79bddEYJbcURvqqcx99Yl2iAhQ xen/common/block.c
    1.30  3ddb79bdrqnW93GR9gZk1OJe1qK-iQ xen/common/brlock.c
    1.31  3fb10d07GscSWPKxBqpvNfU-dYfa0g xen/common/console.c
    1.32 +4022a73c_BbDFd2YJ_NQYVvKX5Oz7w xen/common/debug-linux.c
    1.33 +4022a73c_KPZ1VEbYOrpAhQffd01kA xen/common/debug-linux.h
    1.34  3fa152581E5KhrAtqZef2Sr5NKTz4w xen/common/debug.c
    1.35  3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c
    1.36  3e6377e4i0c9GtKN65e99OtRbw3AZw xen/common/dom_mem_ops.c
    1.37 @@ -394,6 +400,7 @@ 3ddb79c2wa0dA_LGigxOelSGbJ284Q xen/inclu
    1.38  3ddb79c3xjYnrv5t3VqYlR4tNEOl4Q xen/include/asm-i386/page.h
    1.39  3e450943kzme29HPCtq5HNOVQkddfw xen/include/asm-i386/param.h
    1.40  3ddb79c3ysKUbxZuwKBRK3WXU2TlEg xen/include/asm-i386/pci.h
    1.41 +4022a73diKn2Ax4-R4gzk59lm1YdDg xen/include/asm-i386/pdb.h
    1.42  3ddb79c3nm2zdzeO6Mj8g7ex3txgGw xen/include/asm-i386/pgalloc.h
    1.43  3ddb79c2QF5-pZGzuX4QukPCDAl59A xen/include/asm-i386/processor.h
    1.44  3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-i386/ptrace.h
     2.1 --- a/README.CD	Fri Jan 30 15:55:06 2004 +0000
     2.2 +++ b/README.CD	Thu Feb 05 20:27:42 2004 +0000
     2.3 @@ -240,10 +240,16 @@ that may be able to help diagnose proble
     2.4  
     2.5   ifname=dummy	  Don't use any network interface.
     2.6  
     2.7 - ser_baud=xxx	  Enable serial I/O and set the baud rate.
     2.8 + ser_baud=xxx	  Enable serial I/O and set the baud rate (COM1)
     2.9  
    2.10   dom0_mem=xxx 	  Set the initial amount of memory for domain0.
    2.11 -		  
    2.12 +
    2.13 + pdb=xxx          Enable the pervasive debugger.  See docs/pdb.txt
    2.14 +                  xxx defines how the gdb stub will communicate:
    2.15 +                     com1    use com1
    2.16 +                     com1H   use com1 (with high bit set)
    2.17 +                     com2    use on com2
    2.18 +                     com2H   use com2 (with high bit set)
    2.19  
    2.20  It's probably a good idea to join the Xen developer's mailing list on
    2.21  Sourceforge:    http://lists.sourceforge.net/lists/listinfo/xen-devel   
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/docs/pdb.txt	Thu Feb 05 20:27:42 2004 +0000
     3.3 @@ -0,0 +1,215 @@
     3.4 +Pervasive Debugging 
     3.5 +===================
     3.6 +
     3.7 +040205 Alex Ho (alex.ho@cl.cam.ac.uk)
     3.8 +
     3.9 +Introduction
    3.10 +------------
    3.11 +
    3.12 +The pervasive debugging project is leveraging Xen to 
    3.13 +debug distributed systems.  We have added a gdb stub
    3.14 +to Xen to allow for remote debugging of both Xen and
    3.15 +guest operating systems.  More information about the
    3.16 +pervasive debugger is available at: http://www.cl.cam.ac.uk/netos/pdb
    3.17 +
    3.18 +
    3.19 +Implementation
    3.20 +--------------
    3.21 +
    3.22 +The gdb stub communicates with gdb running over a serial line.
    3.23 +The main entry point is pdb_handle_exception() which is invoked
    3.24 +from:    pdb_key_pressed()    ('D' on the console)
    3.25 +         do_int3_exception()  (interrupt 3: breakpoint exception)
    3.26 +         do_debug()           (interrupt 1: debug exception)
    3.27 +
    3.28 +This accepts characters from the serial port and passes gdb
    3.29 +commands to pdb_process_command() which implements the gdb stub
    3.30 +interface.  This file draws heavily from the kgdb project and
    3.31 +sample gdbstub provided with gdb.
    3.32 +
    3.33 +The stub can examine registers, single step and continue, and
    3.34 +read and write memory (in Xen, a domain, or a Linux process'
    3.35 +address space).  The debugger does not currently trace the 
    3.36 +current process, so all bets are off if context switch occurs
    3.37 +in the domain.
    3.38 +
    3.39 +
    3.40 +Setup
    3.41 +-----
    3.42 +
    3.43 + +-------+ telnet +-----------+ serial +-------+ 
    3.44 + |  GDB  |--------|  nsplitd  |--------|  Xen  |
    3.45 + +-------+        +-----------+        +-------+ 
    3.46 +
    3.47 +To run pdb, Xen must be appropriately configured and 
    3.48 +a suitable serial interface attached to the target machine.
    3.49 +GDB and nsplitd can run on the same machine.
    3.50 +
    3.51 +Xen Configuration
    3.52 +
    3.53 +  Add the "pdb=xxx" option to your Xen boot command line
    3.54 +  where xxx is one of the following values:
    3.55 +     com1    gdb stub should communicate on com1
    3.56 +     com1H   gdb stub should communicate on com1 (with high bit set)
    3.57 +     com2    gdb stub should communicate on com2
    3.58 +     com2H   gdb stub should communicate on com2 (with high bit set)
    3.59 +
    3.60 +  Symbolic debugging infomration is quite helpful too:
    3.61 +  xeno.bk/xen/arch/i386/Rules.mk
    3.62 +    add -g to CFLAGS to compile Xen with symbols
    3.63 +  xeno.bk/xenolinux-2.4.24-sparse/arch/xeno/Makefile
    3.64 +    add -g to CFLAGS to compile XenoLinux with symbols
    3.65 +
    3.66 +  You may also want to consider dedicating a register to the
    3.67 +  frame pointer (disable the -fomit-frame-pointer compile flag).
    3.68 +
    3.69 +  When booting Xen and domain 0, look for the console text 
    3.70 +  "Initializing pervasive debugger (PDB)" just before DOM0 starts up.
    3.71 +
    3.72 +Serial Port Configuration
    3.73 +
    3.74 +  pdb expects to communicate with gdb using the serial port.  Since 
    3.75 +  this port is often shared with the machine's console output, pdb can
    3.76 +  discriminate its communication by setting the high bit of each char.
    3.77 +
    3.78 +  A new tool has been added to the source tree which splits 
    3.79 +  the serial output from a remote machine into two streams: 
    3.80 +  one stream (without the high bit) is the console and 
    3.81 +  one stream (with the high bit stripped) is the pdb communication.
    3.82 +
    3.83 +  See:  xeno.bk/tools/nsplitd
    3.84 +
    3.85 +  Note: nsplitd was originally written for the Nemesis project
    3.86 +  at Cambridge.
    3.87 +
    3.88 +  Usage:
    3.89 +    %telnet <hostname> <port>
    3.90 +    This is the console of the remote machine.  You will probably
    3.91 +    want to set telnet in char mode (or create a .telnetrc file).
    3.92 +    <hostname> and <port> are for your instance of nsplitd.
    3.93 +    You should be able to press 'h' to display a list of keyboard
    3.94 +    handlers.  In particular, you should see:
    3.95 +       key 'D' (ascii '44') => enter pervasive debugger
    3.96 +
    3.97 +  After nsplitd accepts a connection on <port>, it starts listening
    3.98 +  on port <port + 1>.  Characters sent to the <port + 1> will have the
    3.99 +  high bit set and vice versa for characters received.
   3.100 +
   3.101 +  Note: if you are not using a serial console and can dedicate your
   3.102 +  serial line to pdb messages, then edit pdb_put_char and pdb_get_char 
   3.103 +  in pdb-stub.c to remove the high bit tests.
   3.104 +
   3.105 +GDB 6.0
   3.106 +  pdb has been tested with gdb 6.0.  It should also work with
   3.107 +  earlier versions.
   3.108 +
   3.109 +
   3.110 +Usage
   3.111 +-----
   3.112 +
   3.113 +1. Boot Xen and XenoLinux
   3.114 +2. Interrupt Xen by pressing 'D' at the console
   3.115 +   You should see the console message: 
   3.116 +   pdb_handle_exception [0x88][0xfc5c9d88]
   3.117 +   At this point Xen is waiting for gdb commands on the serial line.
   3.118 +3. Attach with gdb
   3.119 +   (gdb) file xeno.bk/xen/xen
   3.120 +   Reading symbols from xeno.bk/xen/xen...done.
   3.121 +   (gdb) target remote <hostname>:<port + 1>              /* contact nsplitd */
   3.122 +   Remote debugging using serial.srg:12131
   3.123 +   continue_cpu_idle_loop () at current.h:10
   3.124 +   warning: shared library handler failed to enable breakpoint
   3.125 +   (gdb) break __enter_scheduler
   3.126 +   Breakpoint 1 at 0xfc510a94: file schedule.c, line 330.
   3.127 +   (gdb) cont
   3.128 +   Continuing.
   3.129 +
   3.130 +   Program received signal SIGTRAP, Trace/breakpoint trap.
   3.131 +   __enter_scheduler () at schedule.c:330
   3.132 +   (gdb) step
   3.133 +   (gdb) step
   3.134 +   (gdb) print next            /* the variable prev has been optimized away! */
   3.135 +   $1 = (struct task_struct *) 0x0
   3.136 +   (gdb) delete
   3.137 +   Delete all breakpoints? (y or n) y
   3.138 +4. You can add additional symbols to gdb
   3.139 +   (gdb) add-sym xenolinux-2.4.24/vmlinux
   3.140 +   add symbol table from file "xenolinux-2.4.24/vmlinux" at
   3.141 +   (y or n) y
   3.142 +   Reading symbols from xenolinux-2.4.24/vmlinux...done.
   3.143 +   (gdb) x/s cpu_vendor_names[0]
   3.144 +   0xc01530d2 <cpdext+62898>:	 "Intel"
   3.145 +   (gdb) break free_uid
   3.146 +   Breakpoint 2 at 0xc0012250
   3.147 +   (gdb) cont
   3.148 +   Continuing.                                  /* run a command in domain 0 */
   3.149 +
   3.150 +   Program received signal SIGTRAP, Trace/breakpoint trap.
   3.151 +   free_uid (up=0xbffff738) at user.c:77
   3.152 +
   3.153 +   (gdb) print *up
   3.154 +   $2 = {__count = {counter = 0}, processes = {counter = 135190120}, files = {
   3.155 +       counter = 0}, next = 0x395, pprev = 0xbffff878, uid = 134701041}
   3.156 +   (gdb) finish
   3.157 +   Run till exit from #0  free_uid (up=0xbffff738) at user.c:77
   3.158 +
   3.159 +   Program received signal SIGTRAP, Trace/breakpoint trap.
   3.160 +   release_task (p=0xc2da0000) at exit.c:51
   3.161 +   (gdb) print *p
   3.162 +$3 = {state = 4, flags = 4, sigpending = 0, addr_limit = {seg = 3221225472}, 
   3.163 +  exec_domain = 0xc016a040, need_resched = 0, ptrace = 0, lock_depth = -1, 
   3.164 +  counter = 1, nice = 0, policy = 0, mm = 0x0, processor = 0, 
   3.165 +  cpus_runnable = 1, cpus_allowed = 4294967295, run_list = {next = 0x0, 
   3.166 +    prev = 0x0}, sleep_time = 18995, next_task = 0xc017c000, 
   3.167 +  prev_task = 0xc2f94000, active_mm = 0x0, local_pages = {next = 0xc2da0054, 
   3.168 +    prev = 0xc2da0054}, allocation_order = 0, nr_local_pages = 0, 
   3.169 +  binfmt = 0xc016c6a0, exit_code = 0, exit_signal = 17, pdeath_signal = 0, 
   3.170 +  personality = 0, did_exec = -1, task_dumpable = 1, pid = 917, pgrp = 914, 
   3.171 +  tty_old_pgrp = 0, session = 914, tgid = 917, leader = 0, 
   3.172 +  p_opptr = 0xc2f94000, p_pptr = 0xc2f94000, p_cptr = 0x0, p_ysptr = 0x0, 
   3.173 +  p_osptr = 0x0, thread_group = {next = 0xc2da00a8, prev = 0xc2da00a8}, 
   3.174 +  pidhash_next = 0x0, pidhash_pprev = 0xc01900b8, wait_chldexit = {
   3.175 +    lock = <incomplete type>, task_list = {next = 0xc2da00b8, 
   3.176 +      prev = 0xc2da00b8}}, vfork_done = 0x0, rt_priority = 0, 
   3.177 +  it_real_value = 0, it_prof_value = 0, it_virt_value = 0, it_real_incr = 0, 
   3.178 +  it_prof_incr = 0, it_virt_incr = 0, real_timer = {list = {next = 0x0, 
   3.179 +      prev = 0x0}, expires = 18950, data = 3269066752, 
   3.180 +    function = 0xc000ce30 <it_real_fn>}, times = {tms_utime = 0, 
   3.181 +    tms_stime = 0, tms_cutime = 0, tms_cstime = 0}, start_time = 18989, 
   3.182 +  per_cpu_utime = {1}, per_cpu_stime = {310}, min_flt = 13, maj_flt = 104, 
   3.183 +  nswap = 0, cmin_flt = 0, cmaj_flt = 0, cnswap = 0, swappable = -1, uid = 0, 
   3.184 +  euid = 0, suid = 0, fsuid = 0, gid = 0, egid = 0, sgid = 0, fsgid = 0, 
   3.185 +  ngroups = 7, groups = {0, 1, 2, 3, 4, 6, 10, 0 <repeats 25 times>}, 
   3.186 +  cap_effective = 4294967039, cap_inheritable = 0, cap_permitted = 4294967039, 
   3.187 +  keep_capabilities = 0, user = 0xc016b18c, rlim = {{rlim_cur = 4294967295, 
   3.188 +      rlim_max = 4294967295}, {rlim_cur = 4294967295, rlim_max = 4294967295}, {
   3.189 +      rlim_cur = 4294967295, rlim_max = 4294967295}, {rlim_cur = 8388608, 
   3.190 +      rlim_max = 4294967295}, {rlim_cur = 0, rlim_max = 4294967295}, {
   3.191 +      rlim_cur = 4294967295, rlim_max = 4294967295}, {rlim_cur = 512, 
   3.192 +      rlim_max = 512}, {rlim_cur = 1024, rlim_max = 1024}, {
   3.193 +      rlim_cur = 4294967295, rlim_max = 4294967295}, {rlim_cur = 4294967295, 
   3.194 +      rlim_max = 4294967295}, {rlim_cur = 4294967295, rlim_max = 4294967295}}, 
   3.195 +  used_math = 0, comm = "id\000h\000og\000\000\000\000\000\000\000\000", 
   3.196 +  link_count = 0, total_link_count = 1, tty = 0xc3ed1000, locks = 0, 
   3.197 +  semundo = 0x0, semsleeping = 0x0, thread = {esp0 = 3269074944, 
   3.198 +    eip = 3221249046, esp = 3269074792, fs = 0, gs = 0, io_pl = 3, debugreg = {
   3.199 +      0, 0, 0, 0, 0, 0, 0, 0}, cr2 = 0, trap_no = 0, error_code = 0, i387 = {
   3.200 +      fsave = {cwd = 2098047, swd = 125632512, twd = 1073944696, fip = 2091, 
   3.201 +        fcs = -1073745032, foo = 2099, fos = 8064, st_space = {
   3.202 +          0 <repeats 20 times>}, status = 0}, fxsave = {cwd = 895, swd = 32, 
   3.203 +        twd = 0, fop = 1917, fip = 1073944696, fcs = 2091, foo = -1073745032, 
   3.204 +        fos = 2099, mxcsr = 8064, reserved = 0, st_space = {
   3.205 +          0 <repeats 24 times>, 1449431204, -1774489361, 16383, 0, 1, 
   3.206 +          -1891252224, 16404, 0}, xmm_space = {0 <repeats 32 times>}, 
   3.207 +        padding = {0 <repeats 56 times>}}, soft = {cwd = 2098047, 
   3.208 +        swd = 125632512, twd = 1073944696, fip = 2091, fcs = -1073745032, 
   3.209 +        foo = 2099, fos = 8064, st_space = {0 <repeats 20 times>}, 
   3.210 +        ftop = 0 '\0', changed = 0 '\0', lookahead = 0 '\0', 
   3.211 +        no_update = 0 '\0', rm = 0 '\0', alimit = 0 '\0', info = 0x0, 
   3.212 +        entry_eip = 0}}, vm86_info = 0x0, screen_bitmap = 0, v86flags = 0, 
   3.213 +    v86mask = 0, saved_esp0 = 0}, fs = 0x0, files = 0x0, namespace = 0x0, 
   3.214 +  sigmask_lock = <incomplete type>, sig = 0x0, blocked = {sig = {0, 0}}, 
   3.215 +  pending = {head = 0x0, tail = 0xc2da04f8, signal = {sig = {0, 0}}}, 
   3.216 +  sas_ss_sp = 0, sas_ss_size = 0, notifier = 0, notifier_data = 0x0, 
   3.217 +  notifier_mask = 0x0, parent_exec_id = 7, self_exec_id = 8, 
   3.218 +  alloc_lock = <incomplete type>, journal_info = 0x0}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/nsplitd/Makefile	Thu Feb 05 20:27:42 2004 +0000
     4.3 @@ -0,0 +1,11 @@
     4.4 +ROOT	= ..
     4.5 +
     4.6 +CFILES	= $(wildcard *.c)
     4.7 +
     4.8 +INSTALL_BINS := nsplitd
     4.9 +
    4.10 +include $(ROOT)/mk/rules.mk
    4.11 +
    4.12 +nsplitd: $(OBJS)
    4.13 +	$(CC) $(CFLAGS) -o nsplitd $(OBJS)
    4.14 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/nsplitd/nsplitd.c	Thu Feb 05 20:27:42 2004 +0000
     5.3 @@ -0,0 +1,686 @@
     5.4 +/*
     5.5 + *	nsplitd.c
     5.6 + *	---------
     5.7 + *
     5.8 + * $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $
     5.9 + *
    5.10 + * Copyright (c) 1995, University of Cambridge Computer Laboratory,
    5.11 + * Copyright (c) 1995, Richard Black, All Rights Reserved.
    5.12 + *
    5.13 + *
    5.14 + * A complete re-implementation of DME's nsplitd for use from inetd
    5.15 + *
    5.16 + */
    5.17 +
    5.18 +/* The basic stream comes in (via inetd) and we then conenct to
    5.19 + * somewhere else providing a loop-through service, except we offer
    5.20 + * two other ports for connection - one of which gets a second channel
    5.21 + * using the top bit to distinguish, and the other is a master control
    5.22 + * port (normally used for gdb) which gets complete exclusive access
    5.23 + * for its duration.
    5.24 + *
    5.25 + * Originally designed for multiplexing a xwcons/telnet with a gdb
    5.26 + * post-mortem debugging session.
    5.27 + *
    5.28 + * Here is a picture:
    5.29 + *
    5.30 + * 					    port0 (from inetd)
    5.31 + *      8-bit connection     	       	   /
    5.32 + * 	   made by us	   <----> nsplitd <-----gdbport (default port0+2)
    5.33 + * 	to host:port/tcp		  |\
    5.34 + * 					  | port1 (default port0+1)
    5.35 + *                                         \
    5.36 + *                                          control (default port0+3)
    5.37 + *
    5.38 + * If port1 is explicitly disabled (through a command-line option) then
    5.39 + * port0 becomes 8-bit clean.
    5.40 + */
    5.41 +
    5.42 +/*
    5.43 + * N.B.: We do NOT support 8 bit stdin/stdout usage on a
    5.44 + * /dev/... because to do that right involves much messing with ioctl
    5.45 + * and TIOC... etc.  If you want to do that sort of thing then the
    5.46 + * right way to do it is to chain this onto wconsd (which does know
    5.47 + * about and understand all the ioctl and TIOC grief).
    5.48 + */
    5.49 +
    5.50 +#include <sys/types.h>
    5.51 +#include <stdarg.h>
    5.52 +#include <stdio.h>
    5.53 +#include <stdlib.h>
    5.54 +#include <assert.h>
    5.55 +#include <errno.h>
    5.56 +#include <unistd.h>
    5.57 +#include <ctype.h>
    5.58 +#include <netdb.h>
    5.59 +#include <string.h>
    5.60 +
    5.61 +#include <sys/time.h>
    5.62 +#include <sys/signal.h>
    5.63 +#include <sys/socket.h>
    5.64 +#include <netinet/in.h>
    5.65 +#include <netinet/tcp.h>
    5.66 +#include <arpa/inet.h>
    5.67 +#include <sys/ioctl.h>
    5.68 +#include <syslog.h>
    5.69 +
    5.70 +#ifndef FALSE
    5.71 +#define FALSE 0
    5.72 +#endif
    5.73 +#ifndef TRUE
    5.74 +#define TRUE 1
    5.75 +#endif
    5.76 +
    5.77 +#ifndef LOG_DAEMON
    5.78 +#define LOG_DAEMON 0
    5.79 +#endif
    5.80 +
    5.81 +#define DB(x)  /* ((x), fflush(stderr)) */
    5.82 +
    5.83 +extern char *optarg;
    5.84 +
    5.85 +extern int optind, opterr, optopt;
    5.86 +
    5.87 +static char *prog_name;
    5.88 +
    5.89 +static void usage(void)
    5.90 +{
    5.91 +    fprintf(stderr, "This program (%s) should be run via inetd (tcp)\n\n",
    5.92 +	    prog_name);
    5.93 +    fprintf(stderr, "usage: %s [-h<highport>][-g<gdbport>]"
    5.94 +	    "[-c<ctlport>][-8] host:service\n",
    5.95 +	    prog_name);
    5.96 +    exit(1);
    5.97 +}
    5.98 +
    5.99 +static void fault(char *format, ...)
   5.100 +{
   5.101 +    va_list		ap;
   5.102 +    char		logbuf[1024];
   5.103 +
   5.104 +    va_start(ap, format);
   5.105 +    fprintf(stderr, "%s: ", prog_name);
   5.106 +    vfprintf(stderr, format, ap);
   5.107 +    fflush(stderr);
   5.108 +    va_end(ap);
   5.109 +    
   5.110 +    /* XXX This is a bit dubious, but there is no vsyslog */
   5.111 +    va_start(ap, format);
   5.112 +    vsprintf(logbuf, format, ap);
   5.113 +    syslog(LOG_ERR, logbuf);
   5.114 +    va_end(ap);
   5.115 +    exit(1);
   5.116 +}
   5.117 +
   5.118 +static int getservice(char *name, unsigned short *port)
   5.119 +{
   5.120 +    struct servent		*se;
   5.121 +
   5.122 +    if (!name) return -1;
   5.123 +
   5.124 +    if (isdigit(name[0]))
   5.125 +	*port = atoi(name);
   5.126 +    else
   5.127 +    {
   5.128 +	if (!(se = getservbyname(name, "tcp")))
   5.129 +	    return -1;
   5.130 +	*port = ntohs(se->s_port);
   5.131 +    }
   5.132 +    return 0;
   5.133 +}
   5.134 +
   5.135 +/* 
   5.136 + *  connect_host: connect to ("name", "port")
   5.137 + */
   5.138 +static int connect_host (char *name, unsigned int port)
   5.139 +{
   5.140 +    int			fd;
   5.141 +    struct hostent	*hostent;
   5.142 +    struct sockaddr_in	sin;
   5.143 +    int			on;
   5.144 +    
   5.145 +    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
   5.146 +	fault("socket");
   5.147 +    
   5.148 +    if (!(hostent = gethostbyname(name)))
   5.149 +	fault("gethostbyname: %s: %s\n", name, strerror(errno));
   5.150 +    
   5.151 +    memset(&sin, 0, sizeof(sin));
   5.152 +    sin.sin_family = AF_INET;
   5.153 +    sin.sin_port   = htons (port);
   5.154 +    memcpy(&sin.sin_addr.s_addr, hostent->h_addr, sizeof(struct in_addr));
   5.155 +    
   5.156 +    if (connect(fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
   5.157 +	fault("connect: %s:%u: %s\n", name, port, strerror(errno));
   5.158 +    
   5.159 +    on = 1;
   5.160 +    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
   5.161 +	syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
   5.162 +
   5.163 +    on = 1;
   5.164 +    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
   5.165 +	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
   5.166 +
   5.167 +    return fd;
   5.168 +}
   5.169 +
   5.170 +/*
   5.171 + * open a tcp socket and start listening for connections on it
   5.172 + */
   5.173 +static int startlistening(unsigned short port)
   5.174 +{
   5.175 +    int			fd, on;
   5.176 +    struct sockaddr_in	sin;
   5.177 +
   5.178 +    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
   5.179 +	fault("socket");
   5.180 +    
   5.181 +    on = 1;
   5.182 +    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
   5.183 +      syslog(LOG_WARNING, "setsockopt (SO_REUSEADDR): %m");
   5.184 +
   5.185 +    memset(&sin, 0, sizeof(sin));
   5.186 +    sin.sin_family      = AF_INET;
   5.187 +    sin.sin_port        = htons (port);
   5.188 +    sin.sin_addr.s_addr = INADDR_ANY;
   5.189 +    if (bind(fd, &sin, sizeof(sin)) < 0)
   5.190 +	fault("bind: %u: %s\n", port, strerror(errno));
   5.191 +    
   5.192 +    if (listen(fd, 1) < 0)
   5.193 +	fault("listen: %s\n", strerror(errno));
   5.194 +    
   5.195 +    return fd;
   5.196 +}
   5.197 +
   5.198 +static void noblock(int fd)
   5.199 +{
   5.200 +    int on=1;
   5.201 +    
   5.202 +    if (ioctl(fd, FIONBIO, &on) < 0)
   5.203 +	fault("ioctl: FIONBIO: %s\n", strerror(errno));
   5.204 +}
   5.205 +
   5.206 +
   5.207 +/* You might not believe this, but fd_sets don't have to be a 32-bit
   5.208 + * integer.  In particular, in glibc2 it is an array of unsigned
   5.209 + * longs.  Hence, this hacked up FD_SET_rjb() that works out if it
   5.210 + * would have been a nop. */
   5.211 +#define FD_SET_rjb(fd, setp) \
   5.212 +do {						\
   5.213 +    if ((fd) != 32)				\
   5.214 +	FD_SET((fd), (setp));			\
   5.215 +} while(0)
   5.216 +
   5.217 +#define FD_ISSET_rjb(fd, setp) (((fd) != 32)? FD_ISSET((fd), (setp)) : 0)
   5.218 +
   5.219 +#define MAXSIZE	256
   5.220 +
   5.221 +/* -----------------------------------------------------------------
   5.222 + * The main bit of the algorithm. Note we use 32 to mean not connected
   5.223 + * because this gives us 1<<32 == 0. We could have done this one
   5.224 + * character at a time, but that would have been very inefficient and
   5.225 + * not the unix way.  */
   5.226 +static int debug;
   5.227 +
   5.228 +static void doit(int actl, int acto, int lish, int lisg, int lisc)
   5.229 +{
   5.230 +    int		acth, actg, actc;
   5.231 +    int		gdbmode = FALSE;
   5.232 +    char	gibuf[MAXSIZE], oibuf[MAXSIZE];
   5.233 +    char	libuf[MAXSIZE], lobuf[MAXSIZE];
   5.234 +    char	hibuf[MAXSIZE], hobuf[MAXSIZE];
   5.235 +    char	ctlbuf[MAXSIZE];
   5.236 +    fd_set	rdfs, wrfs, exfs;
   5.237 +    int		gicc, oicc, licc, locc, hicc, hocc, ctlcc;
   5.238 +    char	*giptr, *oiptr, *liptr, *loptr, *hiptr, *hoptr;
   5.239 +    int		rc, fromlen;
   5.240 +    struct sockaddr_in		from;
   5.241 +    
   5.242 +    gicc = oicc = licc = locc = hicc = hocc = ctlcc = 0;
   5.243 +    acth = actg = actc = 32;			/* XXX yummy */
   5.244 +
   5.245 +    noblock(actl);
   5.246 +    noblock(acto);
   5.247 +
   5.248 +    for(;;)
   5.249 +    {
   5.250 +	FD_ZERO(&rdfs);
   5.251 +	FD_ZERO(&wrfs);
   5.252 +	FD_ZERO(&exfs);
   5.253 +
   5.254 +	/* always take input from the control port (if it's connected) */
   5.255 +	FD_SET_rjb(actc, &rdfs);
   5.256 +
   5.257 +	if (gdbmode)
   5.258 +	{
   5.259 +	    if (oicc)
   5.260 +		FD_SET_rjb(actg, &wrfs);
   5.261 +	    else
   5.262 +		FD_SET_rjb(acto, &rdfs);
   5.263 +	    
   5.264 +	    if (gicc)
   5.265 +		FD_SET_rjb(acto, &wrfs);
   5.266 +	    else
   5.267 +		FD_SET_rjb(actg, &rdfs);
   5.268 +	}
   5.269 +	else
   5.270 +	{
   5.271 +	    /* There is no such thing as oibuf because its been split into
   5.272 +	     * lobuf and hobuf
   5.273 +	     */
   5.274 +	    if (locc || hocc)
   5.275 +	    {
   5.276 +		if (locc)
   5.277 +		    FD_SET_rjb(actl, &wrfs);
   5.278 +		if (hocc)
   5.279 +		    FD_SET_rjb(acth, &wrfs);
   5.280 +	    }
   5.281 +	    else
   5.282 +		FD_SET_rjb(acto, &rdfs);
   5.283 +	    
   5.284 +	    if (licc)
   5.285 +		FD_SET_rjb(acto, &wrfs);
   5.286 +	    else
   5.287 +		FD_SET_rjb(actl, &rdfs);
   5.288 +	    
   5.289 +	    if (hicc)
   5.290 +		FD_SET_rjb(acto, &wrfs);
   5.291 +	    else
   5.292 +		FD_SET_rjb(acth, &rdfs);
   5.293 +	}
   5.294 +	
   5.295 +	if (acth == 32 && lish>=0)	FD_SET_rjb(lish, &rdfs);
   5.296 +	if (actg == 32)			FD_SET_rjb(lisg, &rdfs);
   5.297 +	if (actc == 32)			FD_SET_rjb(lisc, &rdfs);
   5.298 +
   5.299 +	/* now make exfs the union of the read and write fd sets, plus
   5.300 +	 * "actl" */
   5.301 +	{
   5.302 +	    int i;
   5.303 +	    exfs = rdfs;
   5.304 +	    for(i=0; i<32; i++)  /* XXX we only copy fd numbers up to 31 */
   5.305 +		if (FD_ISSET(i, &wrfs))
   5.306 +		    FD_SET_rjb(i, &exfs);
   5.307 +	    FD_SET_rjb(actl, &exfs);
   5.308 +	}
   5.309 +
   5.310 +	/* XXX AND: can't print something of type fd_set as %x - it
   5.311 +         * might be an array */
   5.312 +	DB(fprintf(stderr, "%s: before select: %08x %08x %08x\n",
   5.313 +		   prog_name, rdfs, wrfs, exfs));
   5.314 +	
   5.315 +	if (select(32, &rdfs, &wrfs, &exfs, NULL) < 0)
   5.316 +	    fault("select: %s\n", strerror(errno));
   5.317 +	
   5.318 +	DB(fprintf(stderr, "%s: after  select: %08x %08x %08x\n",
   5.319 +		   prog_name, rdfs, wrfs, exfs));
   5.320 +	
   5.321 +	/* XXX it appears that a non-blocking socket may not show up
   5.322 +	 * correctly in exfs but instead goes readable with no data in
   5.323 +	 * it. Thus we check for zero and goto the appropriate close
   5.324 +	 * method.  */
   5.325 +
   5.326 +	/* Deal with exceptions */
   5.327 +	if (FD_ISSET_rjb(actg, &exfs))
   5.328 +	{
   5.329 +	exfs_actg:
   5.330 +	    close(actg);
   5.331 +	    gdbmode = FALSE;
   5.332 +	    oicc = 0;
   5.333 +	    oiptr = oibuf;
   5.334 +	    actg = 32;
   5.335 +	    continue;		/* because assumptions changed */
   5.336 +	}
   5.337 +	if (FD_ISSET_rjb(acth, &exfs))
   5.338 +	{
   5.339 +	exfs_acth:
   5.340 +	    close(acth);
   5.341 +	    hicc = hocc = 0;
   5.342 +	    hiptr = hibuf;
   5.343 +	    hoptr = hibuf;
   5.344 +	    acth = 32;
   5.345 +	    continue;		/* because assumptions changed */
   5.346 +	}
   5.347 +	if (FD_ISSET_rjb(actl, &exfs) ||
   5.348 +	    FD_ISSET_rjb(acto, &exfs))
   5.349 +	{
   5.350 +	exfs_actl:
   5.351 +	exfs_acto:
   5.352 +	    /* Thats all folks ... */
   5.353 +	    break;
   5.354 +	}
   5.355 +	if (FD_ISSET_rjb(actc, &exfs))
   5.356 +	{
   5.357 +	exfs_ctl:
   5.358 +	    close(actc);
   5.359 +	    actc = 32;
   5.360 +	    ctlcc = 0;
   5.361 +	    continue;
   5.362 +	}
   5.363 +
   5.364 +	/* Deal with reading */
   5.365 +	if (FD_ISSET_rjb(acto, &rdfs))
   5.366 +	{
   5.367 +	    if ((oicc = read(acto, oiptr = oibuf, MAXSIZE)) < 0)
   5.368 +		fault("read acto: %d: %s\n", oicc, strerror(errno));
   5.369 +	    if (!oicc) goto exfs_acto;
   5.370 +	    
   5.371 +	    if (!gdbmode)
   5.372 +	    {
   5.373 +		int t;
   5.374 +
   5.375 +		assert((locc == 0) && (hocc == 0));
   5.376 +		loptr = lobuf;
   5.377 +		hoptr = hobuf;
   5.378 +		
   5.379 +		if (lish>=0) {
   5.380 +		    for(t=0; t<oicc; t++)
   5.381 +			if (oibuf[t] & 0x80)
   5.382 +			    hobuf[hocc++] = oibuf[t] & 0x7f;
   5.383 +			else
   5.384 +			    lobuf[locc++] = oibuf[t];
   5.385 +		} else {
   5.386 +		    for (t=0; t<oicc; t++)
   5.387 +			lobuf[locc++] = oibuf[t];
   5.388 +		}
   5.389 +		/* If no high connection scratch that */
   5.390 +		if (acth == 32)
   5.391 +		    hocc=0;
   5.392 +	    }
   5.393 +	}
   5.394 +	if (FD_ISSET_rjb(actl, &rdfs))
   5.395 +	{
   5.396 +	    if ((licc = read(actl, liptr = libuf, MAXSIZE)) < 0)
   5.397 +		fault("read actl: %d: %s\n", licc, strerror(errno));
   5.398 +	    if (!licc) goto exfs_actl;
   5.399 +	}
   5.400 +	if (FD_ISSET_rjb(acth, &rdfs))
   5.401 +	{
   5.402 +	    int t;
   5.403 +	    
   5.404 +	    if ((hicc = read(acth, hiptr = hibuf, MAXSIZE)) < 0)
   5.405 +		fault("read acth: %d: %s\n", hicc, strerror(errno));
   5.406 +	    if (!hicc) goto exfs_acth;
   5.407 +	    for(t=0; t<hicc; t++)
   5.408 +		hibuf[t] |= 0x80;
   5.409 +	}
   5.410 +	if (FD_ISSET_rjb(actg, &rdfs))
   5.411 +	{
   5.412 +	    if ((gicc = read(actg, giptr = gibuf, MAXSIZE)) < 0)
   5.413 +		fault("read actg: %d: %s\n", gicc, strerror(errno));
   5.414 +	    if (debug) write(1, giptr, gicc);		/* XXX */
   5.415 +	    if (!gicc) goto exfs_actg;
   5.416 +	}
   5.417 +	if (FD_ISSET_rjb(actc, &rdfs))
   5.418 +	{
   5.419 +	    if ((ctlcc = read(actc, ctlbuf, MAXSIZE)) < 0)
   5.420 +		fault("read actc: %d: %s\n", ctlcc, strerror(errno));
   5.421 +	    if (debug) write(1, ctlbuf, gicc);
   5.422 +	    if (!ctlcc) goto exfs_ctl;
   5.423 +	    if (ctlbuf[0] == 'r') /* reset command */
   5.424 +	    {
   5.425 +		syslog(LOG_INFO, "reset command read, exiting");
   5.426 +		if (debug) write(1, "reseting\n", sizeof("reseting\n"));
   5.427 +		break;
   5.428 +	    }
   5.429 +	}
   5.430 +	
   5.431 +	/* Deal with writing */
   5.432 +	if (FD_ISSET_rjb(actg, &wrfs))
   5.433 +	{
   5.434 +	    /* We must be in gdb mode so send oi buffer data */
   5.435 +	    assert(gdbmode);
   5.436 +	    if (debug) write(2, oiptr, oicc);		/* XXX */
   5.437 +	    if ((rc = write(actg, oiptr, oicc)) <= 0)
   5.438 +		fault("write actg: %d: %s\n", rc, strerror(errno));
   5.439 +	    oiptr += rc;
   5.440 +	    oicc  -= rc;
   5.441 +	}
   5.442 +	if (FD_ISSET_rjb(actl, &wrfs))
   5.443 +	{
   5.444 +	    if ((rc = write(actl, loptr, locc)) <= 0)
   5.445 +		fault("write actl: %d: %s\n", rc, strerror(errno));
   5.446 +	    loptr += rc;
   5.447 +	    locc  -= rc;
   5.448 +	}
   5.449 +	if (FD_ISSET_rjb(acth, &wrfs))
   5.450 +	{
   5.451 +	    if ((rc = write(acth, hoptr, hocc)) <= 0)
   5.452 +		fault("write acth: %d: %s\n", rc, strerror(errno));
   5.453 +	    hoptr += rc;
   5.454 +	    hocc  -= rc;
   5.455 +	}
   5.456 +	if (FD_ISSET_rjb(acto, &wrfs))
   5.457 +	{
   5.458 +	    /* If in gdb mode send gdb input, otherwise send low data
   5.459 +	       preferentially */
   5.460 +	    if (gdbmode)
   5.461 +	    {
   5.462 +		assert(gicc);
   5.463 +		if ((rc = write(acto, giptr, gicc)) <= 0)
   5.464 +		    fault("write acto: %d: %s\n", rc, strerror(errno));
   5.465 +		giptr += rc;
   5.466 +		gicc  -= rc;
   5.467 +	    }
   5.468 +	    else
   5.469 +	    {
   5.470 +		if (licc)
   5.471 +		{
   5.472 +		    if ((rc = write(acto, liptr, licc)) <= 0)
   5.473 +			fault("write acto: %d: %s\n", rc, strerror(errno));
   5.474 +		    liptr += rc;
   5.475 +		    licc  -= rc;
   5.476 +		}
   5.477 +		else
   5.478 +		{
   5.479 +		    assert(hicc);
   5.480 +		    if ((rc = write(acto, hiptr, hicc)) <= 0)
   5.481 +			fault("write acto: %d: %s\n", rc, strerror(errno));
   5.482 +		    hiptr += rc;
   5.483 +		    hicc  -= rc;
   5.484 +		}
   5.485 +	    }
   5.486 +	}
   5.487 +	
   5.488 +	/* Deals with new connections */
   5.489 +	if ((acth == 32) && lish>=0 && (FD_ISSET_rjb(lish, &rdfs)))
   5.490 +	{
   5.491 +	    fromlen = sizeof(from);
   5.492 +	    if ((acth = accept(lish, &from, &fromlen)) < 0)
   5.493 +	    {
   5.494 +		syslog(LOG_WARNING, "accept: %m");
   5.495 +		acth = 32;
   5.496 +	    }
   5.497 +	    else
   5.498 +	    {
   5.499 +		noblock(acth);
   5.500 +		hicc = hocc = 0;
   5.501 +		syslog(LOG_INFO, "highbit client peer is %s:%u\n",
   5.502 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   5.503 +	    }
   5.504 +	}
   5.505 +	
   5.506 +	if ((actg == 32) && (FD_ISSET_rjb(lisg, &rdfs)))
   5.507 +	{
   5.508 +	    fromlen = sizeof(from);
   5.509 +	    if ((actg = accept(lisg, &from, &fromlen)) < 0)
   5.510 +	    {
   5.511 +		syslog(LOG_WARNING, "accept: %m");
   5.512 +		actg = 32;
   5.513 +	    }
   5.514 +	    else
   5.515 +	    {
   5.516 +		noblock(actg);
   5.517 +		gicc = 0;
   5.518 +		gdbmode = TRUE;
   5.519 +		syslog(LOG_INFO, "gdb client peer is %s:%u\n",
   5.520 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   5.521 +	    }
   5.522 +	}
   5.523 +
   5.524 +	if ((actc == 32) && (FD_ISSET_rjb(lisc, &rdfs)))
   5.525 +	{
   5.526 +	    fromlen = sizeof(from);
   5.527 +	    if ((actc = accept(lisc, &from, &fromlen)) < 0)
   5.528 +	    {
   5.529 +		syslog(LOG_WARNING, "accept (ctl): %m");
   5.530 +		actc = 32;
   5.531 +	    }
   5.532 +	    else
   5.533 +	    {
   5.534 +		noblock(actc);
   5.535 +		syslog(LOG_INFO, "ctl client peer is %s:%u\n",
   5.536 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   5.537 +	    }
   5.538 +	}
   5.539 +	    
   5.540 +	/* Back to top of loop */
   5.541 +    }
   5.542 +    
   5.543 +    /* We are bailing because one of the primary connections has gone
   5.544 +     * away. We close these all explicitly here because that way the
   5.545 +     * timeout on reusing the port numbers is smnaller. */
   5.546 +    
   5.547 +    close(acth);
   5.548 +    close(actg);
   5.549 +    /* XXX AND: why are we closing all these "character counts" ?? */
   5.550 +    close(gicc);
   5.551 +    close(oicc);
   5.552 +    close(licc);
   5.553 +    close(locc);
   5.554 +    close(hicc);
   5.555 +    close(hocc);
   5.556 +}
   5.557 +
   5.558 +/*
   5.559 + * ------------------------------------------------------------
   5.560 + */
   5.561 +int main(int argc, char **argv)
   5.562 +{
   5.563 +    /* In general, suffix "l" is low channel, "h" is high channel, "g"
   5.564 +     * is gdb channel, "c" is control channel and "o" is output channel.
   5.565 +     */
   5.566 +    struct sockaddr_in		from;
   5.567 +    int				infd = 0, outfd;
   5.568 +    unsigned short		portl, porth, portg, portc, porto;
   5.569 +    int				on = 1, c;
   5.570 +    char			*outname, *outservice;
   5.571 +    int				fromlen;
   5.572 +    int				lish, lisg, lisc;
   5.573 +#if 0
   5.574 +    FILE			*newerr;
   5.575 +#endif /* 0 */
   5.576 +    
   5.577 +    prog_name = argv[0];
   5.578 +
   5.579 +    if (isatty(infd))
   5.580 +	usage();
   5.581 +
   5.582 +    /* Here, then not just a simple idiot. */
   5.583 +
   5.584 +    signal(SIGPIPE, SIG_IGN);
   5.585 +
   5.586 +    openlog(prog_name, LOG_PID, LOG_DAEMON);
   5.587 +
   5.588 +    fromlen = sizeof(from);
   5.589 +    if (getsockname(infd, &from, &fromlen) < 0)
   5.590 +	fault("getsockname: %s", strerror(errno));
   5.591 +    if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET))
   5.592 +	fault("not an inet socket (family=%d)\n", from.sin_family);
   5.593 +    
   5.594 +    portl = ntohs(from.sin_port);
   5.595 +    porth = portl+1;
   5.596 +    portg = porth+1;
   5.597 +    portc = portg+1;
   5.598 +
   5.599 +    fromlen = sizeof(from);
   5.600 +    if (getpeername(infd, &from, &fromlen) < 0)
   5.601 +	fault("getpeername: %s", strerror(errno));
   5.602 +    if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET))
   5.603 +	fault("not an inet socket (family=%d)\n", from.sin_family);
   5.604 +
   5.605 +    syslog(LOG_INFO, "on port %u peer is %s:%u\n", portl,
   5.606 +	   inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   5.607 +    
   5.608 +    if (setsockopt(infd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
   5.609 +	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
   5.610 +
   5.611 +    /* from here on, we map stderr to output on the connection so we can
   5.612 +     * report errors to the remote user.
   5.613 +     */
   5.614 +#if 0
   5.615 +    if (!(newerr = fdopen(infd, "w")))
   5.616 +	syslog(LOG_WARNING, "fdopen: %m");
   5.617 +    else
   5.618 +	*stderr = *newerr;
   5.619 +#endif
   5.620 +	
   5.621 +    while((c = getopt(argc, argv, "d8h:g:c:")) != EOF)
   5.622 +    {
   5.623 +	switch(c)
   5.624 +	{
   5.625 +	case 'd':
   5.626 +	    debug++;
   5.627 +	    break;
   5.628 +	    
   5.629 +	case 'h':
   5.630 +	    /* high bit port */
   5.631 +	    if (getservice(optarg, &porth) < 0)
   5.632 +		fault("getservice failed (high port '%s')\n", optarg);
   5.633 +	    break;
   5.634 +	    
   5.635 +	case 'g':
   5.636 +	    /* gdb port */
   5.637 +	    if (getservice(optarg, &portg) < 0)
   5.638 +		fault("getservice failed (gdb port '%s')\n", optarg);
   5.639 +	    break;
   5.640 +
   5.641 +	case 'c':
   5.642 +	    /* control port */
   5.643 +	    if (getservice(optarg, &portc) < 0)
   5.644 +		fault("getservice failed (control port '%s')\n", optarg);
   5.645 +	    break;
   5.646 +
   5.647 +	case '8':
   5.648 +	    /* 8-bit clean; no high port */
   5.649 +	    porth=0;
   5.650 +	    break;
   5.651 +
   5.652 +	default:
   5.653 +	    fault("bad argument list!\n");
   5.654 +	}
   5.655 +    }
   5.656 +    
   5.657 +    if (argc != optind + 1)
   5.658 +	fault("unparsed arguments (%d!=%d)\n", argc, optind+1);
   5.659 +
   5.660 +    outname = argv[optind];
   5.661 +    if (!(outservice = strchr(outname, ':')))
   5.662 +	fault("output arg '%s' doesn't contain ':'\n", outname);
   5.663 +    *outservice++ = 0;
   5.664 +    if (getservice(outservice, &porto) < 0)
   5.665 +	fault("getservice failed (output port '%s')\n", outservice);
   5.666 +    
   5.667 +    /* Time to start the sockets */
   5.668 +
   5.669 +    if (porth) {
   5.670 +	lish  = startlistening(porth);
   5.671 +    } else {
   5.672 +	lish  = -1;
   5.673 +    }
   5.674 +    lisg  = startlistening(portg);
   5.675 +    lisc  = startlistening(portc);
   5.676 +    
   5.677 +    outfd = connect_host(outname, porto);
   5.678 +    
   5.679 +    doit(infd, outfd, lish, lisg, lisc);
   5.680 +
   5.681 +    syslog(LOG_INFO, "terminating normally\n");
   5.682 +
   5.683 +    fclose(stderr);
   5.684 +
   5.685 +    closelog();
   5.686 +    exit(0); 
   5.687 +}
   5.688 +
   5.689 +/* End $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/i386/pdb-stub.c	Thu Feb 05 20:27:42 2004 +0000
     6.3 @@ -0,0 +1,831 @@
     6.4 +#include <xeno/lib.h>
     6.5 +#include <xeno/sched.h>
     6.6 +#include <asm-i386/ptrace.h>
     6.7 +#include <xeno/keyhandler.h> 
     6.8 +#include <asm/pdb.h>
     6.9 +#include <xeno/list.h>
    6.10 +
    6.11 +#undef DEBUG_TRACE
    6.12 +#ifdef DEBUG_TRACE
    6.13 +#define TRC(_x) _x
    6.14 +#else
    6.15 +#define TRC(_x)
    6.16 +#endif
    6.17 +
    6.18 +#define BUFMAX 400
    6.19 +
    6.20 +#define PDB_DOMAIN_OFFSET 2              /* all domains are positive numbers */
    6.21 +
    6.22 +static const char hexchars[]="0123456789abcdef";
    6.23 +
    6.24 +int remote_debug;
    6.25 +
    6.26 +int pdb_foobar = 0x123456;                                        /* testing */
    6.27 +char *pdb_foobaz = "cambridge";                                   /* testing */
    6.28 +
    6.29 +#define PDB_BUFMAX 1024
    6.30 +static char pdb_in_buffer[PDB_BUFMAX];
    6.31 +static char pdb_out_buffer[PDB_BUFMAX];
    6.32 +static char pdb_buffer[PDB_BUFMAX];
    6.33 +static int  pdb_in_buffer_ptr;
    6.34 +static unsigned char  pdb_in_checksum;
    6.35 +static unsigned char  pdb_xmit_checksum;
    6.36 +
    6.37 +int pdb_ctrl_thread = -1;
    6.38 +int pdb_info_thread = -1;
    6.39 +int pdb_stepping = 0;
    6.40 +
    6.41 +int   hex (char);
    6.42 +char *mem2hex (char *, char *, int);
    6.43 +char *hex2mem (char *, char *, int);
    6.44 +int   hexToInt (char **ptr, int *intValue);
    6.45 +
    6.46 +void pdb_put_packet (unsigned char *buffer, int ack);
    6.47 +void pdb_put_char (u_char c);
    6.48 +u_char pdb_get_char ();
    6.49 +
    6.50 +static volatile int mem_err = 0;
    6.51 +void set_mem_err (void)                                   /* NOT USED YET... */
    6.52 +{
    6.53 +  mem_err = 1;
    6.54 +}
    6.55 +
    6.56 +/* These are separate functions so that they are so short and sweet
    6.57 +   that the compiler won't save any registers (if there is a fault
    6.58 +   to mem_fault, they won't get restored, so there better not be any
    6.59 +   saved).  */
    6.60 +int
    6.61 +get_char (char *addr)
    6.62 +{
    6.63 +    return *addr;
    6.64 +}
    6.65 +
    6.66 +void
    6.67 +set_char (char *addr, int val)
    6.68 +{
    6.69 +    *addr = val;
    6.70 +}
    6.71 +
    6.72 +void
    6.73 +pdb_process_query (char *ptr)
    6.74 +{
    6.75 +    if (strcmp(ptr, "C") == 0)
    6.76 +    {
    6.77 +        /* empty string */
    6.78 +    }
    6.79 +    else if (strcmp(ptr, "fThreadInfo") == 0)
    6.80 +    {
    6.81 +        struct task_struct *p = &idle0_task;
    6.82 +        u_long flags;
    6.83 +	int count = 0, buf_idx = 0;
    6.84 +
    6.85 +        read_lock_irqsave (&tasklist_lock, flags);
    6.86 +
    6.87 +	pdb_out_buffer[buf_idx++] = 'm';
    6.88 +        while ( (p = p->next_task) != &idle0_task )
    6.89 +	{
    6.90 +	    int domain = p->domain + PDB_DOMAIN_OFFSET;
    6.91 +
    6.92 +	    if (count > 0)
    6.93 +	        pdb_out_buffer[buf_idx++] = ',';
    6.94 +	    /*
    6.95 +	    if (domain < 0)
    6.96 +	    {   pdb_out_buffer[buf_idx++] = '-'; domain = domain * -1; }
    6.97 +	    */
    6.98 +	    if (domain > 15)
    6.99 +	    {
   6.100 +	        pdb_out_buffer[buf_idx++] = hexchars[domain >> 4];
   6.101 +	    }
   6.102 +	    pdb_out_buffer[buf_idx++] = hexchars[domain % 16];
   6.103 +	    count++;
   6.104 +	}
   6.105 +	pdb_out_buffer[buf_idx++] = 'l';
   6.106 +	pdb_out_buffer[buf_idx++] = 0;
   6.107 +
   6.108 +        read_unlock_irqrestore(&tasklist_lock, flags);
   6.109 +    }
   6.110 +    else if (strcmp(ptr, "sThreadInfo") == 0)
   6.111 +    {
   6.112 +    }
   6.113 +    else if (strncmp(ptr, "ThreadExtraInfo,", 16) == 0)
   6.114 +    {
   6.115 +        int thread = 0;
   6.116 +	char *message = "whatever!";
   6.117 +
   6.118 +	ptr += 16;
   6.119 +        if (hexToInt (&ptr, &thread))
   6.120 +	{
   6.121 +	  mem2hex ((char *)message, pdb_out_buffer, strlen(message) + 1);
   6.122 +	}
   6.123 +    }
   6.124 +    else if (strcmp(ptr, "Offsets") == 0)
   6.125 +    {
   6.126 +        /* empty string */
   6.127 +    }
   6.128 +    else if (strncmp(ptr, "Symbol", 6) == 0)
   6.129 +    {
   6.130 +        strcpy (pdb_out_buffer, "OK");
   6.131 +    }
   6.132 +    else
   6.133 +    {
   6.134 +        printk("pdb_process_query: unknown query [%s]\n", ptr);
   6.135 +    }
   6.136 +}
   6.137 +
   6.138 +int
   6.139 +pdb_process_command (char *ptr, struct pt_regs *regs)
   6.140 +{
   6.141 +    int sigval = 10;
   6.142 +    int length;
   6.143 +    unsigned long addr;
   6.144 +    int ack = 1;                           /* wait for ack in pdb_put_packet */
   6.145 +    int go = 0;
   6.146 +
   6.147 +    TRC(printk("pdb: [%s]\n", ptr));
   6.148 +    {
   6.149 +        pdb_out_buffer[0] = 0;
   6.150 +
   6.151 +	switch (*ptr++)
   6.152 +	{
   6.153 +	case '?':
   6.154 +          pdb_out_buffer[0] = 'S';
   6.155 +          pdb_out_buffer[1] = hexchars[sigval >> 4];
   6.156 +          pdb_out_buffer[2] = hexchars[sigval % 16];
   6.157 +          pdb_out_buffer[3] = 0;
   6.158 +	  break;
   6.159 +        case 'S':                                        /* step with signal */
   6.160 +        case 's':                                                    /* step */
   6.161 +	  regs->eflags |= 0x100;
   6.162 +	  pdb_stepping = 1;
   6.163 +	  return 1;                                        
   6.164 +	  /* not reached */
   6.165 +        case 'C':                                    /* continue with signal */
   6.166 +        case 'c':                                                /* continue */
   6.167 +	  regs->eflags &= ~0x100;
   6.168 +	  /* jump out before replying to gdb */
   6.169 +	  return 1;
   6.170 +	  /* not reached */
   6.171 +	case 'd':
   6.172 +	  remote_debug = !(remote_debug);               /* toggle debug flag */
   6.173 +	  break;
   6.174 +	case 'D':                                                  /* detach */
   6.175 +	  return go;
   6.176 +	  /* not reached */
   6.177 +	case 'g':                   /* return the value of the CPU registers */
   6.178 +	{
   6.179 +	    int idx = 0;
   6.180 +	    mem2hex ((char *)&regs->eax, &pdb_out_buffer[idx], sizeof(regs->eax));
   6.181 +	    idx += sizeof(regs->eax) * 2;
   6.182 +	    mem2hex ((char *)&regs->ecx, &pdb_out_buffer[idx], sizeof(regs->ecx));
   6.183 +	    idx += sizeof(regs->ecx) * 2;
   6.184 +	    mem2hex ((char *)&regs->edx, &pdb_out_buffer[idx], sizeof(regs->edx));
   6.185 +	    idx += sizeof(regs->edx) * 2;
   6.186 +	    mem2hex ((char *)&regs->ebx, &pdb_out_buffer[idx], sizeof(regs->ebx));
   6.187 +	    idx += sizeof(regs->ebx) * 2;
   6.188 +	    mem2hex ((char *)&regs->esp, &pdb_out_buffer[idx], sizeof(regs->esp));
   6.189 +	    idx += sizeof(regs->esp) * 2;
   6.190 +	    mem2hex ((char *)&regs->ebp, &pdb_out_buffer[idx], sizeof(regs->ebp));
   6.191 +	    idx += sizeof(regs->ebp) * 2;
   6.192 +	    mem2hex ((char *)&regs->esi, &pdb_out_buffer[idx], sizeof(regs->esi));
   6.193 +	    idx += sizeof(regs->esi) * 2;
   6.194 +	    mem2hex ((char *)&regs->edi, &pdb_out_buffer[idx], sizeof(regs->edi));
   6.195 +	    idx += sizeof(regs->edi) * 2;
   6.196 +	    mem2hex ((char *)&regs->eip, &pdb_out_buffer[idx], sizeof(regs->eip));
   6.197 +	    idx += sizeof(regs->eip) * 2;
   6.198 +	    mem2hex ((char *)&regs->eflags, &pdb_out_buffer[idx], sizeof(regs->eflags));
   6.199 +	    idx += sizeof(regs->eflags) * 2;
   6.200 +	    mem2hex ((char *)&regs->xcs, &pdb_out_buffer[idx], sizeof(regs->xcs));
   6.201 +	    idx += sizeof(regs->xcs) * 2;
   6.202 +	    mem2hex ((char *)&regs->xss, &pdb_out_buffer[idx], sizeof(regs->xss));
   6.203 +	    idx += sizeof(regs->xss) * 2;
   6.204 +	    mem2hex ((char *)&regs->xds, &pdb_out_buffer[idx], sizeof(regs->xds));
   6.205 +	    idx += sizeof(regs->xds) * 2;
   6.206 +	    mem2hex ((char *)&regs->xes, &pdb_out_buffer[idx], sizeof(regs->xes));
   6.207 +	    idx += sizeof(regs->xes) * 2;
   6.208 +	    mem2hex ((char *)&regs->xfs, &pdb_out_buffer[idx], sizeof(regs->xfs));
   6.209 +	    idx += sizeof(regs->xfs) * 2;
   6.210 +	    mem2hex ((char *)&regs->xgs, &pdb_out_buffer[idx], sizeof(regs->xgs));
   6.211 +
   6.212 +	    /*
   6.213 +	    TRC(printk ("  reg: %s \n", pdb_out_buffer));
   6.214 +	    TRC(printk ("  ebx: 0x%08lx\n", regs->ebx));
   6.215 +	    TRC(printk ("  ecx: 0x%08lx\n", regs->ecx));
   6.216 +	    TRC(printk ("  edx: 0x%08lx\n", regs->edx));
   6.217 +	    TRC(printk ("  esi: 0x%08lx\n", regs->esi));
   6.218 +	    TRC(printk ("  edi: 0x%08lx\n", regs->edi));
   6.219 +	    TRC(printk ("  ebp: 0x%08lx\n", regs->ebp));
   6.220 +	    TRC(printk ("  eax: 0x%08lx\n", regs->eax));
   6.221 +	    TRC(printk ("  xds: 0x%08x\n", regs->xds));
   6.222 +	    TRC(printk ("  xes: 0x%08x\n", regs->xes));
   6.223 +	    TRC(printk ("  xfs: 0x%08x\n", regs->xfs));
   6.224 +	    TRC(printk ("  xgs: 0x%08x\n", regs->xgs));
   6.225 +	    TRC(printk ("  eip: 0x%08lx\n", regs->eip));
   6.226 +	    TRC(printk ("  xcs: 0x%08x\n", regs->xcs));
   6.227 +	    TRC(printk ("  efl: 0x%08lx\n", regs->eflags));
   6.228 +	    TRC(printk ("  esp: 0x%08lx\n", regs->esp));
   6.229 +	    TRC(printk ("  xss: 0x%08x\n", regs->xss));
   6.230 +	    */
   6.231 +
   6.232 +	    break;
   6.233 +	}
   6.234 +	case 'G':          /* set the value of the CPU registers - return OK */
   6.235 +	    break;
   6.236 +
   6.237 +	case 'H':
   6.238 +	{
   6.239 +	    int thread;
   6.240 +	    char *next = &ptr[1];
   6.241 +	    if (hexToInt (&next, &thread))
   6.242 +	    {
   6.243 +	        if (thread > 0)
   6.244 +		{
   6.245 +		    thread = thread - PDB_DOMAIN_OFFSET;
   6.246 +		}
   6.247 +		if (*ptr == 'c')
   6.248 +		{
   6.249 +		    pdb_ctrl_thread = thread;
   6.250 +		}
   6.251 +		else if (*ptr == 'g')
   6.252 +		{
   6.253 +		    pdb_info_thread = thread;
   6.254 +		}
   6.255 +		else
   6.256 +		{
   6.257 +		    printk ("ack, unknown command %c (thread: %d)\n", 
   6.258 +			    *ptr, thread);
   6.259 +		}
   6.260 +	    }
   6.261 +	    strcpy (pdb_out_buffer, "OK");
   6.262 +	    break;
   6.263 +	}
   6.264 +	case 'k':                                            /* kill request */
   6.265 +	{
   6.266 +	    strcpy (pdb_out_buffer, "OK");                    /* ack for fun */
   6.267 +	    printk ("don't kill bill...\n");
   6.268 +	    ack = 0;
   6.269 +	    break;
   6.270 +	}
   6.271 +
   6.272 +	case 'q':
   6.273 +	{
   6.274 +	    pdb_process_query(ptr);
   6.275 +	    break;
   6.276 +	}
   6.277 +
   6.278 +	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
   6.279 +	case 'm':
   6.280 +	{
   6.281 +	    /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
   6.282 +	    if (hexToInt (&ptr, (int *)&addr))
   6.283 +	        if (*(ptr++) == ',')
   6.284 +		    if (hexToInt (&ptr, &length))
   6.285 +		    {
   6.286 +		        ptr = 0;
   6.287 +			mem_err = 0;
   6.288 +
   6.289 +			if (pdb_info_thread >= 0)
   6.290 +			{
   6.291 +			    pdb_get_values(pdb_info_thread, pdb_buffer, addr, length);
   6.292 +			    mem2hex (pdb_buffer, pdb_out_buffer, length);
   6.293 +			}
   6.294 +			else
   6.295 +			    mem2hex ((char *) addr, pdb_out_buffer, length); 
   6.296 +			if (mem_err)
   6.297 +			{
   6.298 +			    strcpy (pdb_out_buffer, "E03");
   6.299 +			}
   6.300 +		    }
   6.301 +	    
   6.302 +	    if (ptr)
   6.303 +	    {
   6.304 +	      strcpy (pdb_out_buffer, "E01");
   6.305 +	    }
   6.306 +	    break;
   6.307 +	}
   6.308 +
   6.309 +	/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
   6.310 +	case 'M':
   6.311 +	{
   6.312 +	    /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
   6.313 +	    if (hexToInt (&ptr, (int *)&addr))
   6.314 +	        if (*(ptr++) == ',')
   6.315 +		    if (hexToInt (&ptr, &length))
   6.316 +		        if (*(ptr++) == ':')
   6.317 +			{
   6.318 +			    mem_err = 0;
   6.319 +
   6.320 +			    pdb_set_values(pdb_info_thread, 
   6.321 +					   ptr, addr, length);
   6.322 +
   6.323 +			    if (mem_err)
   6.324 +			    {
   6.325 +			        strcpy (pdb_out_buffer, "E03");
   6.326 +			    }
   6.327 +			    else
   6.328 +			    {
   6.329 +			        strcpy (pdb_out_buffer, "OK");
   6.330 +			    }
   6.331 +
   6.332 +			    ptr = 0;
   6.333 +			}
   6.334 +	    if (ptr)
   6.335 +	    {
   6.336 +	        strcpy (pdb_out_buffer, "E02");
   6.337 +	    }
   6.338 +	    break;
   6.339 +	}
   6.340 +	case 'T':
   6.341 +	{
   6.342 +	    int thread;
   6.343 +	    if (hexToInt (&ptr, &thread))
   6.344 +	    {
   6.345 +	        thread -= PDB_DOMAIN_OFFSET;
   6.346 +	        struct task_struct *p = find_domain_by_id(thread);
   6.347 +		if (p == NULL)
   6.348 +		{
   6.349 +		    strcpy (pdb_out_buffer, "E00");
   6.350 +		}
   6.351 +		else
   6.352 +		{
   6.353 +		    strcpy (pdb_out_buffer, "OK");
   6.354 +		}
   6.355 +		put_task_struct(p);
   6.356 +	    }
   6.357 +	    break;
   6.358 +	}
   6.359 +	}                                                          /* switch */
   6.360 +
   6.361 +	/* reply to the request */
   6.362 +	pdb_put_packet (pdb_out_buffer, ack);
   6.363 +    }
   6.364 +
   6.365 +    return go;
   6.366 +}
   6.367 +
   6.368 +/*
   6.369 + * process an input character from the serial line.
   6.370 + *
   6.371 + * return "1" if the character is a gdb debug string
   6.372 + * (and hence shouldn't be further processed).
   6.373 + */
   6.374 +
   6.375 +int pdb_debug_state = 0;                /* small parser state machine */
   6.376 +
   6.377 +int pdb_serial_input(u_char c, struct pt_regs *regs)
   6.378 +{
   6.379 +    int out = 1;
   6.380 +    int loop, count;
   6.381 +
   6.382 +    switch (pdb_debug_state)
   6.383 +    {
   6.384 +    case 0:                         /* not currently processing debug string */
   6.385 +        if ( c == '$' )                                      /* start token */
   6.386 +	{
   6.387 +	    pdb_debug_state = 1;
   6.388 +	    pdb_in_buffer_ptr = 0;
   6.389 +	    pdb_in_checksum = 0;
   6.390 +	    pdb_xmit_checksum = 0;
   6.391 +	}
   6.392 +	else 
   6.393 +	{
   6.394 +	    out = 0;
   6.395 +	}
   6.396 +	break;
   6.397 +    case 1:                                                       /* saw '$' */
   6.398 +        if ( c == '#' )                                    /* checksum token */
   6.399 +	{
   6.400 +	    pdb_debug_state = 2;
   6.401 +	    pdb_in_buffer[pdb_in_buffer_ptr] = 0;
   6.402 +	}
   6.403 +	else
   6.404 +	{
   6.405 +	    pdb_in_checksum += c;
   6.406 +	    pdb_in_buffer[pdb_in_buffer_ptr++] = c;
   6.407 +	}
   6.408 +	break;
   6.409 +    case 2:                                            /* 1st checksum digit */
   6.410 +        pdb_xmit_checksum = hex(c) << 4;
   6.411 +	pdb_debug_state = 3;
   6.412 +	break;
   6.413 +    case 3:                                            /* 2nd checksum digit */
   6.414 +        pdb_xmit_checksum += hex(c);
   6.415 +	if (pdb_in_checksum != pdb_xmit_checksum) 
   6.416 +	{
   6.417 +	    pdb_put_char('-');                           /* checksum failure */
   6.418 +	    printk ("checksum failure [%s.%02x.%02x]\n", pdb_in_buffer,
   6.419 +		    pdb_in_checksum, pdb_xmit_checksum);
   6.420 +	}
   6.421 +	else 
   6.422 +	{
   6.423 +	    pdb_put_char('+');                              /* checksum okay */
   6.424 +	    if ( pdb_in_buffer_ptr > 1 && pdb_in_buffer[2] == ':' ) 
   6.425 +	    {
   6.426 +	        pdb_put_char(pdb_in_buffer[0]);
   6.427 +		pdb_put_char(pdb_in_buffer[1]);
   6.428 +		/* remove sequence chars from buffer */
   6.429 +		count = strlen(pdb_in_buffer);
   6.430 +		for (loop = 3; loop < count; loop++)
   6.431 +		    pdb_in_buffer[loop - 3] = pdb_in_buffer[loop];
   6.432 +	    }
   6.433 +
   6.434 +	    pdb_process_command (pdb_in_buffer, regs);
   6.435 +	}
   6.436 +	pdb_debug_state = 0;
   6.437 +	break;
   6.438 +    }
   6.439 +
   6.440 +    return out;
   6.441 +}
   6.442 +
   6.443 +int hex(char ch)
   6.444 +{
   6.445 +  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
   6.446 +  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
   6.447 +  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
   6.448 +  return (-1);
   6.449 +}
   6.450 +
   6.451 +/* convert the memory pointed to by mem into hex, placing result in buf */
   6.452 +/* return a pointer to the last char put in buf (null) */
   6.453 +char *
   6.454 +mem2hex (mem, buf, count)
   6.455 +     char *mem;
   6.456 +     char *buf;
   6.457 +     int count;
   6.458 +{
   6.459 +  int i;
   6.460 +  unsigned char ch;
   6.461 +
   6.462 +  for (i = 0; i < count; i++)
   6.463 +    {
   6.464 +      ch = get_char (mem++);
   6.465 +      *buf++ = hexchars[ch >> 4];
   6.466 +      *buf++ = hexchars[ch % 16];
   6.467 +    }
   6.468 +  *buf = 0;
   6.469 +  return (buf);
   6.470 +}
   6.471 +
   6.472 +/* convert the hex array pointed to by buf into binary to be placed in mem */
   6.473 +/* return a pointer to the character AFTER the last byte written */
   6.474 +char *
   6.475 +hex2mem (buf, mem, count)
   6.476 +     char *buf;
   6.477 +     char *mem;
   6.478 +     int count;
   6.479 +{
   6.480 +  int i;
   6.481 +  unsigned char ch;
   6.482 +
   6.483 +  for (i = 0; i < count; i++)
   6.484 +    {
   6.485 +      ch = hex (*buf++) << 4;
   6.486 +      ch = ch + hex (*buf++);
   6.487 +      set_char (mem++, ch);
   6.488 +    }
   6.489 +  return (mem);
   6.490 +}
   6.491 +
   6.492 +int
   6.493 +hexToInt (char **ptr, int *intValue)
   6.494 +{
   6.495 +  int numChars = 0;
   6.496 +  int hexValue;
   6.497 +  int negative = 0;
   6.498 +
   6.499 +  *intValue = 0;
   6.500 +
   6.501 +  if (**ptr == '-')
   6.502 +  {
   6.503 +    negative = 1;
   6.504 +    numChars++;
   6.505 +    (*ptr)++;
   6.506 +  }
   6.507 +  while (**ptr)
   6.508 +  {
   6.509 +      hexValue = hex (**ptr);
   6.510 +      if (hexValue >= 0)
   6.511 +      {
   6.512 +          *intValue = (*intValue << 4) | hexValue;
   6.513 +          numChars++;
   6.514 +      }
   6.515 +      else
   6.516 +        break;
   6.517 +
   6.518 +      (*ptr)++;
   6.519 +  }
   6.520 +  if (negative)
   6.521 +  {
   6.522 +      *intValue *= -1;
   6.523 +  }
   6.524 +  
   6.525 +  return (numChars);
   6.526 +}
   6.527 +
   6.528 +/***********************************************************************/
   6.529 +/***********************************************************************/
   6.530 +
   6.531 +
   6.532 +/*
   6.533 + * Add a breakpoint to the list of known breakpoints.
   6.534 + * For now there should only be two or three breakpoints so
   6.535 + * we use a simple linked list.  In the future, maybe a red-black tree?
   6.536 + */
   6.537 +struct pdb_breakpoint breakpoints;
   6.538 +
   6.539 +
   6.540 +void pdb_bkpt_add (unsigned long address)
   6.541 +{
   6.542 +    struct pdb_breakpoint *bkpt;
   6.543 +
   6.544 +    bkpt = kmalloc(sizeof(struct pdb_breakpoint), GFP_KERNEL);
   6.545 +    INIT_LIST_HEAD(&bkpt->list);
   6.546 +
   6.547 +    bkpt->address = address;
   6.548 +
   6.549 +    list_add(&bkpt->list, &breakpoints.list);
   6.550 +
   6.551 +    return;
   6.552 +}
   6.553 +
   6.554 +/*
   6.555 + * Check to see of the breakpoint is in the list of known breakpoints 
   6.556 + *
   6.557 + * return 1 if it has been set, 0 otherwise
   6.558 + */
   6.559 +
   6.560 +struct pdb_breakpoint* pdb_bkpt_search (unsigned long address)
   6.561 +{
   6.562 +    struct pdb_breakpoint *found = NULL;
   6.563 +    struct list_head *list_entry;
   6.564 +    struct pdb_breakpoint *bkpt;
   6.565 +
   6.566 +    list_for_each(list_entry, &breakpoints.list)
   6.567 +    {
   6.568 +        bkpt = list_entry(list_entry, struct pdb_breakpoint, list);
   6.569 +
   6.570 +	if (bkpt->address == address)
   6.571 +	{
   6.572 +	    found = bkpt;
   6.573 +	    break;
   6.574 +	}
   6.575 +    }
   6.576 +
   6.577 +    return found;
   6.578 +}
   6.579 +
   6.580 +/*
   6.581 + * Remove a breakpoint to the list of known breakpoints.
   6.582 + *
   6.583 + * Return 1 if the element was not found, otherwise 0.
   6.584 + */
   6.585 +
   6.586 +void pdb_bkpt_remove_ptr (struct pdb_breakpoint *bkpt)
   6.587 +{
   6.588 +    struct list_head *list_entry = &bkpt->list;
   6.589 +    list_del(list_entry);
   6.590 +    kfree(bkpt);
   6.591 +}
   6.592 +
   6.593 +int pdb_bkpt_remove (unsigned long address)
   6.594 +{
   6.595 +    struct list_head *list_entry;
   6.596 +    struct pdb_breakpoint *bkpt;
   6.597 +    int found = 1;
   6.598 +
   6.599 +    list_for_each(list_entry, &breakpoints.list)
   6.600 +    {
   6.601 +        bkpt = list_entry(list_entry, struct pdb_breakpoint, list);
   6.602 +
   6.603 +	if (bkpt->address == address)
   6.604 +	{
   6.605 +	    pdb_bkpt_remove_ptr (bkpt);
   6.606 +	    found = 0;
   6.607 +	    break;
   6.608 +	}
   6.609 +    }
   6.610 +
   6.611 +    return found;
   6.612 +}
   6.613 +
   6.614 +/***********************************************************************/
   6.615 +
   6.616 +void breakpoint(void);
   6.617 +
   6.618 +int pdb_initialized = 0;
   6.619 +int pdb_high_bit = 1;
   6.620 +
   6.621 +void pdb_put_char (u_char c)
   6.622 +{
   6.623 +  extern void   debug_putchar(u_char);
   6.624 +  u_char cc = pdb_high_bit ? c | 0x80 : c;
   6.625 +  debug_putchar(cc);
   6.626 +}
   6.627 +
   6.628 +u_char pdb_get_char ()
   6.629 +{
   6.630 +  extern u_char debug_getchar();
   6.631 +  u_char cc = debug_getchar();
   6.632 +  return cc & 0x7f;
   6.633 +}
   6.634 +
   6.635 +/* send the packet in buffer.  */
   6.636 +void pdb_put_packet (unsigned char *buffer, int ack)
   6.637 +{
   6.638 +    unsigned char checksum;
   6.639 +    int count;
   6.640 +    char ch;
   6.641 +    
   6.642 +    /*  $<packet info>#<checksum> */
   6.643 +    /*  do */
   6.644 +    {
   6.645 +        pdb_put_char ('$');
   6.646 +	checksum = 0;
   6.647 +	count = 0;
   6.648 +
   6.649 +	while ((ch = buffer[count]))
   6.650 +	{
   6.651 +            pdb_put_char (ch);
   6.652 +	    checksum += ch;
   6.653 +	    count += 1;
   6.654 +        }
   6.655 +
   6.656 +	pdb_put_char('#');
   6.657 +	pdb_put_char(hexchars[checksum >> 4]);
   6.658 +	pdb_put_char(hexchars[checksum % 16]);
   6.659 +    }
   6.660 +
   6.661 +    if (ack)
   6.662 +    {
   6.663 +	if ((ch = pdb_get_char()) != '+')
   6.664 +	{
   6.665 +	    printk(" pdb return error: %c 0x%x [%s]\n", ch, ch, buffer);
   6.666 +	}
   6.667 +    }
   6.668 +}
   6.669 +
   6.670 +void pdb_get_packet(char *buffer)
   6.671 +{
   6.672 +    int count;
   6.673 +    char ch;
   6.674 +    unsigned char checksum = 0;
   6.675 +    unsigned char xmitcsum = 0;
   6.676 +
   6.677 +    do
   6.678 +    {
   6.679 +        while ((ch = pdb_get_char()) != '$');
   6.680 +
   6.681 +	count = 0;
   6.682 +	checksum = 0;
   6.683 +
   6.684 +	while (count < BUFMAX)
   6.685 +	{
   6.686 +	    ch = pdb_get_char();
   6.687 +	    if (ch  == '#') break;
   6.688 +	    checksum += ch;
   6.689 +	    buffer[count] = ch;
   6.690 +	    count++;
   6.691 +	}
   6.692 +	buffer[count] = 0;
   6.693 +
   6.694 +	if (ch == '#')
   6.695 +	{
   6.696 +	    xmitcsum = hex(pdb_get_char()) << 4;
   6.697 +	    xmitcsum += hex(pdb_get_char());
   6.698 +
   6.699 +	    if (xmitcsum == checksum)
   6.700 +	    {
   6.701 +	        pdb_put_char('+');
   6.702 +		if (buffer[2] == ':')
   6.703 +		{
   6.704 +		    printk ("gdb packet found with sequence ID\n");
   6.705 +		}
   6.706 +	    }
   6.707 +	    else
   6.708 +	    {
   6.709 +	        pdb_put_char('-');
   6.710 +	    }
   6.711 +	}
   6.712 +    } while (checksum != xmitcsum);
   6.713 +
   6.714 +    return;
   6.715 +}
   6.716 +
   6.717 +/*
   6.718 + * process a machine interrupt or exception
   6.719 + * return 1 if pdb is not interested in the exception; it should
   6.720 + * be propagated to the guest os.
   6.721 + */
   6.722 +
   6.723 +int pdb_handle_exception(int exceptionVector,
   6.724 +			 struct pt_regs *xen_regs)
   6.725 +{
   6.726 +    int signal = 0;
   6.727 +
   6.728 +    printk ("pdb_handle_exception [0x%x][0x%lx]\n",
   6.729 +	    exceptionVector, xen_regs->eip);
   6.730 +
   6.731 +    /* if  pdb didn't set the breakpoint, and 
   6.732 +           pdb is not single stepping, and
   6.733 +	   the user didn't press the magic debug key on the console,
   6.734 +       then pass the exception up to the guest os */
   6.735 +    if (pdb_bkpt_search(xen_regs->eip - 1) == NULL &&
   6.736 +	pdb_stepping == 0 &&
   6.737 +	exceptionVector != 0x88)
   6.738 +    {
   6.739 +        TRC(printk("pdb: external breakpoint at 0x%lx\n", xen_regs->eip));
   6.740 +	return 1;
   6.741 +    }
   6.742 +
   6.743 +    if (pdb_stepping == 1)
   6.744 +    {
   6.745 +        xen_regs->eflags &= ~0x100;
   6.746 +        pdb_stepping = 0;
   6.747 +    }
   6.748 +
   6.749 +    if (exceptionVector == 0x03)
   6.750 +    {
   6.751 +        xen_regs->eip --;
   6.752 +    }
   6.753 +
   6.754 +    /* generate a signal for gdb */
   6.755 +    switch (exceptionVector)
   6.756 +    {
   6.757 +    case 136 : signal = 2; break;                                  /* SIGINT */
   6.758 +    case 1   : signal = 5; break;                                 /* SIGTRAP */
   6.759 +    case 3   : signal = 5; break;                                 /* SIGTRAP */
   6.760 +    default  :
   6.761 +      printk ("can't generate signal for unknown exception vector %d\n",
   6.762 +	      exceptionVector);
   6.763 +      break;
   6.764 +    }
   6.765 +
   6.766 +    pdb_out_buffer[0] = 'S';
   6.767 +    pdb_out_buffer[1] = hexchars[signal >> 4];
   6.768 +    pdb_out_buffer[2] = hexchars[signal % 16];
   6.769 +    pdb_out_buffer[3] = 0;
   6.770 +    pdb_put_packet(pdb_out_buffer, 1);
   6.771 +
   6.772 +    while (1)
   6.773 +    {
   6.774 +        pdb_out_buffer[0] = 0;
   6.775 +	pdb_get_packet(pdb_in_buffer);
   6.776 +	if (pdb_process_command(pdb_in_buffer, xen_regs))
   6.777 +	{
   6.778 +	    return 0;
   6.779 +	}
   6.780 +    }
   6.781 +
   6.782 +    return 0;
   6.783 +}
   6.784 +
   6.785 +void pdb_key_pressed(u_char key, void *dev_id, struct pt_regs *regs) 
   6.786 +{
   6.787 +    pdb_handle_exception(136, regs);
   6.788 +    return;
   6.789 +}
   6.790 +
   6.791 +void initialize_pdb()
   6.792 +{
   6.793 +    extern char opt_pdb[];
   6.794 +    int pdb_com_port;
   6.795 +
   6.796 +    if (strncmp(opt_pdb, "com", 3) == 0)
   6.797 +    {
   6.798 +        extern void debug_set_com_port(int port);
   6.799 +
   6.800 +        pdb_com_port = opt_pdb[3] - '0';                 /* error checking ? */
   6.801 +	debug_set_com_port(pdb_com_port);
   6.802 +	pdb_high_bit = opt_pdb[4] == 'H' ? 1 : 0;
   6.803 +    }
   6.804 +    else
   6.805 +    {
   6.806 +        if (strcmp(opt_pdb, "none") != 0)
   6.807 +	{
   6.808 +	    printk ("pdb: unknown option\n");
   6.809 +	}
   6.810 +        return;
   6.811 +    }
   6.812 +
   6.813 +    printk ("Initializing pervasive debugger (PDB) [%s] port %d, high %d\n",
   6.814 +	    opt_pdb, pdb_com_port, pdb_high_bit);
   6.815 +
   6.816 +    breakpoints.address = 0;
   6.817 +    INIT_LIST_HEAD(&breakpoints.list);
   6.818 +
   6.819 +    pdb_stepping = 0;
   6.820 +
   6.821 +    /* ack any spurrious gdb packets */
   6.822 +    pdb_put_char ('+');
   6.823 +
   6.824 +    /* serial console */
   6.825 +    add_key_handler('D', pdb_key_pressed, "enter pervasive debugger");
   6.826 +
   6.827 +    pdb_initialized = 1;
   6.828 +}
   6.829 +
   6.830 +void breakpoint(void)
   6.831 +{
   6.832 +    if (pdb_initialized)
   6.833 +        asm("int $3");
   6.834 +}
     7.1 --- a/xen/arch/i386/setup.c	Fri Jan 30 15:55:06 2004 +0000
     7.2 +++ b/xen/arch/i386/setup.c	Thu Feb 05 20:27:42 2004 +0000
     7.3 @@ -12,6 +12,7 @@
     7.4  #include <asm/apic.h>
     7.5  #include <asm/desc.h>
     7.6  #include <asm/domain_page.h>
     7.7 +#include <asm/pdb.h>
     7.8  
     7.9  struct cpuinfo_x86 boot_cpu_data = { 0 };
    7.10  /* Lots of nice things, since we only target PPro+. */
    7.11 @@ -428,6 +429,7 @@ void __init start_of_day(void)
    7.12      do_initcalls();
    7.13      initialize_serial();   /* setup serial 'driver' (for debugging) */
    7.14      initialize_keyboard(); /* setup keyboard (also for debugging)   */
    7.15 +    initialize_pdb();      /* pervasive debugger */
    7.16  
    7.17      if ( !setup_network_devices() )
    7.18          panic("Must have a network device!\n");
     8.1 --- a/xen/arch/i386/traps.c	Fri Jan 30 15:55:06 2004 +0000
     8.2 +++ b/xen/arch/i386/traps.c	Thu Feb 05 20:27:42 2004 +0000
     8.3 @@ -49,6 +49,7 @@
     8.4  #include <asm/pgalloc.h>
     8.5  #include <asm/uaccess.h>
     8.6  #include <asm/i387.h>
     8.7 +#include <asm/pdb.h>
     8.8  
     8.9  #define GTBF_TRAP        1
    8.10  #define GTBF_TRAP_NOCODE 2
    8.11 @@ -223,6 +224,30 @@ static inline void do_trap(int trapnr, c
    8.12            smp_processor_id(), trapnr, str, error_code);
    8.13  }
    8.14  
    8.15 +static inline void do_int3_exception(int trapnr,
    8.16 +				     struct pt_regs *regs, 
    8.17 +				     long error_code)
    8.18 +{
    8.19 +    struct task_struct *p = current;
    8.20 +    struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
    8.21 +    trap_info_t *ti;
    8.22 +
    8.23 +    if ((regs->xcs & 3) != 3)
    8.24 +    {
    8.25 +        pdb_handle_exception(trapnr, regs);
    8.26 +	return;
    8.27 +    }
    8.28 +
    8.29 +    ti = current->thread.traps + trapnr;
    8.30 +    gtb->flags      =  GTBF_TRAP_NOCODE;
    8.31 +    gtb->error_code = error_code;
    8.32 +    gtb->cs         = ti->cs;
    8.33 +    gtb->eip        = ti->address;
    8.34 +    if ( TI_GET_IF(ti) )
    8.35 +        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
    8.36 +    return; 
    8.37 +}
    8.38 +
    8.39  #define DO_ERROR_NOCODE(trapnr, str, name) \
    8.40  asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
    8.41  { \
    8.42 @@ -236,7 +261,6 @@ do_trap(trapnr, str, regs, error_code, 1
    8.43  }
    8.44  
    8.45  DO_ERROR_NOCODE( 0, "divide error", divide_error)
    8.46 -DO_ERROR_NOCODE( 3, "int3", int3)
    8.47  DO_ERROR_NOCODE( 4, "overflow", overflow)
    8.48  DO_ERROR_NOCODE( 5, "bounds", bounds)
    8.49  DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
    8.50 @@ -251,6 +275,12 @@ DO_ERROR(17, "alignment check", alignmen
    8.51  DO_ERROR_NOCODE(18, "machine check", machine_check)
    8.52  DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
    8.53  
    8.54 +asmlinkage void do_int3(struct pt_regs * regs, long error_code)
    8.55 +{
    8.56 +    if (pdb_initialized)   do_int3_exception(3, regs, error_code);
    8.57 +    else                   do_trap(3, "int3", regs, error_code, 0);
    8.58 +}
    8.59 +
    8.60  asmlinkage void do_double_fault(void)
    8.61  {
    8.62      extern spinlock_t console_lock;
    8.63 @@ -489,8 +519,39 @@ asmlinkage void math_state_restore(struc
    8.64      }
    8.65  }
    8.66  
    8.67 +asmlinkage void do_debug(struct pt_regs * regs, long error_code)
    8.68 +{
    8.69 +    unsigned int condition;
    8.70 +    struct task_struct *tsk = current;
    8.71 +    struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
    8.72  
    8.73 -asmlinkage void do_debug(struct pt_regs * regs, long error_code)
    8.74 +    /*
    8.75 +    printk("do_debug_exceptionn [%lx][%lx][%x]\n",
    8.76 +	   error_code, regs->eip, regs->xcs);
    8.77 +    */
    8.78 +
    8.79 +    __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
    8.80 +
    8.81 +    if ((condition & (1 << 14)) != (1 << 14))
    8.82 +    {
    8.83 +        printk ("\nwarning: debug trap w/o BS bit [0x%x]\n\n", condition);
    8.84 +    }
    8.85 +    __asm__("movl %0,%%db6" : : "r" (0));
    8.86 +
    8.87 +    if (pdb_handle_exception(1, regs))                /* propagate to domain */
    8.88 +    {
    8.89 +        tsk->thread.debugreg[6] = condition;
    8.90 +
    8.91 +	gtb->flags = GTBF_TRAP_NOCODE;
    8.92 +	gtb->cs    = tsk->thread.traps[1].cs;
    8.93 +	gtb->eip   = tsk->thread.traps[1].address;
    8.94 +    }
    8.95 +
    8.96 +    return;
    8.97 +}
    8.98 +
    8.99 +
   8.100 +asmlinkage void do_debug_orig(struct pt_regs * regs, long error_code)
   8.101  {
   8.102      unsigned int condition;
   8.103      struct task_struct *tsk = current;
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/common/debug-linux.c	Thu Feb 05 20:27:42 2004 +0000
     9.3 @@ -0,0 +1,82 @@
     9.4 +#include <xeno/config.h>
     9.5 +#include <xeno/types.h>
     9.6 +#include <xeno/lib.h>
     9.7 +#include <hypervisor-ifs/dom0_ops.h>
     9.8 +
     9.9 +#include "debug-linux.h"
    9.10 +
    9.11 +/* 
    9.12 + * linux specific pdb stuff 
    9.13 + */
    9.14 +
    9.15 +/*
    9.16 +  static inline struct task_struct *find_task_by_pid(int pid)
    9.17 +  {
    9.18 +    struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)];
    9.19 +
    9.20 +    for(p = *htable; p && p->pid != pid; p = p->pidhash_next) ;
    9.21 +    return p;
    9.22 +  }
    9.23 +*/
    9.24 +
    9.25 +/* read a byte from a process */
    9.26 +u_char pdb_linux_get_value (int domain, int pid, unsigned long addr)
    9.27 +{
    9.28 +  u_char result = 0;
    9.29 +  unsigned long task_struct_p, mm_p, pgd, task_struct_pid;
    9.30 +  unsigned long l2tab, page;
    9.31 +
    9.32 +  /* find the task_struct of the given process */
    9.33 +  pdb_get_values(domain, (u_char *) &task_struct_p, 
    9.34 +		 pidhash_addr + pid_hashfn(pid) * 4,
    9.35 +		 sizeof(task_struct_p));
    9.36 +
    9.37 +  /* find the correct task struct */
    9.38 +  while (task_struct_p != (unsigned long)NULL)
    9.39 +  {
    9.40 +    pdb_get_values(domain, (u_char *) &task_struct_pid, 
    9.41 +		   task_struct_p + task_struct_pid_offset,
    9.42 +		   sizeof(task_struct_pid));
    9.43 +    if (task_struct_pid == pid)
    9.44 +    {
    9.45 +      break;
    9.46 +    }
    9.47 +    
    9.48 +    pdb_get_values(domain, (u_char *) &task_struct_p, 
    9.49 +		   task_struct_p + task_struct_pidhash_next_offset,
    9.50 +		   sizeof(task_struct_p));
    9.51 +  }
    9.52 +  if (task_struct_p == (unsigned long)NULL)
    9.53 +  {
    9.54 +    /* oops */
    9.55 +    printk ("error: couldn't find process 0x%x in domain %d\n", pid, domain);
    9.56 +    return 0;
    9.57 +  }
    9.58 +
    9.59 +  /* get the mm_struct within the task_struct */
    9.60 +  pdb_get_values(domain, (u_char *) &mm_p, 
    9.61 +		 task_struct_p + task_struct_mm_offset,
    9.62 +		 sizeof(mm_p));
    9.63 +  /* get the page global directory (cr3) within the mm_struct */
    9.64 +  pdb_get_values(domain, (u_char *) &pgd, 
    9.65 +		 mm_p + mm_struct_pgd_offset,
    9.66 +		 sizeof(pgd));
    9.67 +
    9.68 +  /* get the l2 table entry */
    9.69 +  pdb_get_values(domain, (u_char *) &l2tab, 
    9.70 +		 pgd + (addr >> PGDIR_SHIFT) * 4,
    9.71 +		 sizeof(l2tab));
    9.72 +  l2tab = (unsigned long)__va(machine_to_phys(domain, l2tab) & PAGE_MASK);
    9.73 +
    9.74 +  /* get the page table entry */
    9.75 +  pdb_get_values(domain, (u_char *) &page,
    9.76 +		 l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4,
    9.77 +		 sizeof(page));
    9.78 +  page = (unsigned long)__va(machine_to_phys(domain, page) & PAGE_MASK);
    9.79 +
    9.80 +  /* get the byte */
    9.81 +  pdb_get_values(domain, (u_char *) &result, page + (addr & ~PAGE_MASK),
    9.82 +		 sizeof(result));
    9.83 +
    9.84 +  return result;
    9.85 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen/common/debug-linux.h	Thu Feb 05 20:27:42 2004 +0000
    10.3 @@ -0,0 +1,45 @@
    10.4 +#include <asm/pdb.h>
    10.5 +
    10.6 +/* from linux/sched.h */
    10.7 +#define PIDHASH_SZ (4096 >> 2)
    10.8 +#define pid_hashfn(x)	((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
    10.9 +
   10.10 +/* from asm-xeno/pgtable-2level.h */
   10.11 +#define PGDIR_SHIFT	22
   10.12 +#define PTRS_PER_PGD	1024
   10.13 +
   10.14 +/* from asm-xeno/page.h */
   10.15 +#define PAGE_SHIFT	12
   10.16 +#define PAGE_SIZE	(1UL << PAGE_SHIFT)
   10.17 +#define PAGE_MASK	(~(PAGE_SIZE-1))
   10.18 +
   10.19 +#define __PAGE_OFFSET		(0xC0000000)
   10.20 +#define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
   10.21 +#define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
   10.22 +#define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
   10.23 +
   10.24 +/* from debug.h */
   10.25 +#define ENTRIES_PER_L1_PAGETABLE 1024
   10.26 +#define L1_PAGE_BITS ( (ENTRIES_PER_L1_PAGETABLE - 1) << PAGE_SHIFT )
   10.27 +
   10.28 +
   10.29 +/* adapted from asm-xeno/page.h */
   10.30 +static inline unsigned long machine_to_phys(int domain, unsigned long machine)
   10.31 +{
   10.32 +  unsigned long phys;
   10.33 +  pdb_get_values(domain, (u_char *) &phys,
   10.34 +		 (unsigned long) machine_to_phys_mapping + (machine >> PAGE_SHIFT) * 4,
   10.35 +		 sizeof(phys));
   10.36 +  phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
   10.37 +  return phys;
   10.38 +}
   10.39 +
   10.40 +
   10.41 +#define pidhash_addr 0xc018f260UL
   10.42 +
   10.43 +#define task_struct_mm_offset  0x2c
   10.44 +#define task_struct_pid_offset 0x7c
   10.45 +#define task_struct_pidhash_next_offset 0xb0
   10.46 +#define mm_struct_pgd_offset   0x0c
   10.47 +
   10.48 +extern u_char pdb_linux_get_value (int domain, int pid, unsigned long addr);
    11.1 --- a/xen/common/debug.c	Fri Jan 30 15:55:06 2004 +0000
    11.2 +++ b/xen/common/debug.c	Thu Feb 05 20:27:42 2004 +0000
    11.3 @@ -10,33 +10,182 @@
    11.4  #include <hypervisor-ifs/dom0_ops.h>
    11.5  #include <xeno/sched.h>
    11.6  #include <xeno/event.h>
    11.7 +#include <asm/page.h>
    11.8 +#include <asm/domain_page.h>                           /* [un]map_domain_mem */
    11.9 +#include <asm/pdb.h>
   11.10  
   11.11 -#define DEBUG_TRACE
   11.12 +#undef DEBUG_TRACE
   11.13  #ifdef DEBUG_TRACE
   11.14  #define TRC(_x) _x
   11.15  #else
   11.16  #define TRC(_x)
   11.17  #endif
   11.18  
   11.19 +/****************************************************************************/
   11.20 +
   11.21 +int pdb_change_values (int domain, u_char *buffer, unsigned long addr,
   11.22 +		       int length, int rw);
   11.23 +
   11.24 +/*
   11.25 + * Set memory in a domain's address space
   11.26 + * Set "length" bytes at "address" from "domain" to the values in "buffer".
   11.27 + * Return the number of bytes set, 0 if there was a problem.
   11.28 + *
   11.29 + * THIS WILL BECOME A MACRO
   11.30 + */
   11.31 +
   11.32 +int pdb_set_values (int domain, u_char *buffer, unsigned long addr, int length)
   11.33 +{
   11.34 +    int count;
   11.35 +    void *bkpt;
   11.36 +    count = pdb_change_values(domain, buffer, addr, length, 2);
   11.37 +
   11.38 +    /* this is a bit x86 specific at the moment... */
   11.39 +    if (length == 1 && buffer[0] == 'c' && buffer[1] == 'c')
   11.40 +    {
   11.41 +        /* inserting a new breakpoint */
   11.42 +        pdb_bkpt_add (addr);
   11.43 +        TRC(printk("pdb breakpoint detected at 0x%lx\n", addr));
   11.44 +    }
   11.45 +    else if ((bkpt = pdb_bkpt_search(addr)))
   11.46 +    {
   11.47 +        /* removing a breakpoint */
   11.48 +        TRC(printk("pdb breakpoint cleared at 0x%lx\n", addr));
   11.49 +        pdb_bkpt_remove_ptr(bkpt);
   11.50 +    }
   11.51 +
   11.52 +    return count;
   11.53 +}
   11.54 +
   11.55 +/*
   11.56 + * Read memory from a domain's address space.
   11.57 + * Fetch "length" bytes at "address" from "domain" into "buffer".
   11.58 + * Return the number of bytes read, 0 if there was a problem.
   11.59 + *
   11.60 + * THIS WILL BECOME A MACRO
   11.61 + */
   11.62 +
   11.63 +int pdb_get_values (int domain, u_char *buffer, unsigned long addr, int length)
   11.64 +{
   11.65 +    return pdb_change_values(domain, buffer, addr, length, 1);
   11.66 +}
   11.67 +
   11.68 +/*
   11.69 + * Change memory in  a domain's address space.
   11.70 + * Read or write "length" bytes at "address" from "domain" into/from "buffer".
   11.71 + * Return the number of bytes read, 0 if there was a problem.
   11.72 + * RW: 1 = read, 2 = write
   11.73 + */
   11.74 +
   11.75 +int pdb_change_values (int domain, u_char *buffer, unsigned long addr,
   11.76 +		       int length, int rw)
   11.77 +{
   11.78 +    struct task_struct *p;
   11.79 +    l2_pgentry_t* l2_table = NULL;
   11.80 +    l1_pgentry_t* l1_table = NULL;
   11.81 +    u_char *page;
   11.82 +    int bytes = 0;
   11.83 +
   11.84 +    extern char *hex2mem (char *, char *, int);
   11.85 +
   11.86 +    p = find_domain_by_id(domain);
   11.87 +
   11.88 +    if ((addr >> PAGE_SHIFT) == ((addr + length - 1) >> PAGE_SHIFT))
   11.89 +    {
   11.90 +        l2_table = map_domain_mem(pagetable_val(p->mm.pagetable));
   11.91 +	l2_table += l2_table_offset(addr);
   11.92 +	if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 
   11.93 +	{
   11.94 +	    printk ("L2:0x%p (0x%lx) \n", l2_table, l2_pgentry_val(*l2_table));
   11.95 +	    goto exit2;
   11.96 +	}
   11.97 +
   11.98 +	if (l2_pgentry_val(*l2_table) & _PAGE_PSE)
   11.99 +	{
  11.100 +#define PSE_PAGE_SHIFT           L2_PAGETABLE_SHIFT
  11.101 +#define PSE_PAGE_SIZE	         (1UL << PSE_PAGE_SHIFT)
  11.102 +#define PSE_PAGE_MASK	         (~(PSE_PAGE_SIZE-1))
  11.103 +
  11.104 +#define L1_PAGE_BITS ( (ENTRIES_PER_L1_PAGETABLE - 1) << L1_PAGETABLE_SHIFT )
  11.105 +
  11.106 +#define pse_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PSE_PAGE_MASK)
  11.107 +
  11.108 +	    page = map_domain_mem(pse_pgentry_to_phys(*l2_table) +/* 10 bits */
  11.109 +				  (addr & L1_PAGE_BITS));         /* 10 bits */
  11.110 +	    page += addr & (PAGE_SIZE - 1);                       /* 12 bits */
  11.111 +	}
  11.112 +	else
  11.113 +	{
  11.114 +	    l1_table = map_domain_mem(l2_pgentry_to_phys(*l2_table));
  11.115 +	    l1_table += l1_table_offset(addr); 
  11.116 +	    if (!(l1_pgentry_val(*l1_table) & _PAGE_PRESENT))
  11.117 +	    {
  11.118 +	        printk ("L2:0x%p (0x%lx) L1:0x%p (0x%lx)\n", 
  11.119 +			l2_table, l2_pgentry_val(*l2_table),
  11.120 +			l1_table, l1_pgentry_val(*l1_table));
  11.121 +		goto exit1;
  11.122 +	    }
  11.123 +
  11.124 +	    page = map_domain_mem(l1_pgentry_to_phys(*l1_table));
  11.125 +	    page += addr & (PAGE_SIZE - 1);
  11.126 +	}
  11.127 +
  11.128 +	switch (rw)
  11.129 +	{
  11.130 +	case 1:                                                      /* read */
  11.131 +	    memcpy (buffer, page, length);
  11.132 +	    bytes = length;
  11.133 +	    break;
  11.134 +	case 2:                                                     /* write */
  11.135 +	    hex2mem (buffer, page, length);
  11.136 +	    bytes = length;
  11.137 +	    break;
  11.138 +	default:                                                  /* unknown */
  11.139 +	    printk ("error: unknown RW flag: %d\n", rw);
  11.140 +	    return 0;
  11.141 +	}
  11.142 +
  11.143 +	unmap_domain_mem((void *)page); 
  11.144 +    exit1:
  11.145 +	if (l1_table != NULL)
  11.146 +	    unmap_domain_mem((void *)l1_table);
  11.147 +    exit2:
  11.148 +	unmap_domain_mem((void *)l2_table);
  11.149 +    }
  11.150 +    else
  11.151 +    {
  11.152 +        /* read spans pages. need to recurse */
  11.153 +        printk ("pdb memory SPAN! addr:0x%lx l: %x\n", addr, length);
  11.154 +    }
  11.155 +
  11.156 +    put_task_struct(p);
  11.157 +    return bytes;
  11.158 +}
  11.159 +
  11.160 +
  11.161 +/*
  11.162 + * interactively call pervasive debugger from a privileged domain
  11.163 + */
  11.164  void pdb_do_debug (dom0_op_t *op)
  11.165  {
  11.166      op->u.debug.status = 0;
  11.167 -    op->u.debug.out1 = op->u.debug.in2 + 10;
  11.168 -    op->u.debug.out2 = op->u.debug.in1 + 100;
  11.169  
  11.170 -    TRC(printk("PDB: op:%c, dom:%x, in1:%x, in2:%x\n",
  11.171 +    TRC(printk("PDB: op:%c, dom:%x, in1:%x, in2:%x, in3:%x, in4:%x\n",
  11.172  	       op->u.debug.opcode, op->u.debug.domain,
  11.173 -	       op->u.debug.in1, op->u.debug.in2));
  11.174 +	       op->u.debug.in1, op->u.debug.in2,
  11.175 +	       op->u.debug.in3, op->u.debug.in4));
  11.176  
  11.177 +    /* NOT NOW
  11.178      if (op->u.debug.domain == 0)
  11.179      {
  11.180          op->u.debug.status = 1;
  11.181  	return;
  11.182      }
  11.183 +    */
  11.184  
  11.185      switch (op->u.debug.opcode)
  11.186      {
  11.187 -        case 'r' :
  11.188 +        case 'c' :
  11.189  	{
  11.190  	    struct task_struct * p = find_domain_by_id(op->u.debug.domain);
  11.191  	    if ( p != NULL )
  11.192 @@ -54,6 +203,28 @@ void pdb_do_debug (dom0_op_t *op)
  11.193  	    }
  11.194  	    break;
  11.195  	}
  11.196 +        case 'r' :
  11.197 +        {
  11.198 +            int loop;
  11.199 +            u_char x;
  11.200 +
  11.201 +            for (loop = 0; loop < op->u.debug.in2; loop++)         /* length */
  11.202 +            { 
  11.203 +	        extern u_char pdb_linux_get_value (int domain, int pid, unsigned long addr);
  11.204 +
  11.205 +                if (loop % 8 == 0)
  11.206 +                {
  11.207 +                    printk ("\n%08x ", op->u.debug.in1 + loop);
  11.208 +                }
  11.209 +                x = pdb_linux_get_value(op->u.debug.domain,        /* domain */
  11.210 +					op->u.debug.in3,             /* pid */
  11.211 +					op->u.debug.in1 + loop);     /* addr */
  11.212 +                printk (" %02x", x);
  11.213 +            }
  11.214 +            printk ("\n");
  11.215 +            break;
  11.216 +        }
  11.217 +
  11.218          case 's' :
  11.219  	{
  11.220  	    unsigned long cpu_mask;
    12.1 --- a/xen/common/kernel.c	Fri Jan 30 15:55:06 2004 +0000
    12.2 +++ b/xen/common/kernel.c	Thu Feb 05 20:27:42 2004 +0000
    12.3 @@ -69,6 +69,8 @@ int opt_noreboot=0;
    12.4  int opt_ignorebiostables=0;
    12.5  /* opt_watchdog: If true, run a watchdog NMI on each processor. */
    12.6  int opt_watchdog=0;
    12.7 +/* opt_pdb: Name of serial port for Xen pervasive debugger (and enable pdb) */
    12.8 +unsigned char opt_pdb[10] = "none";
    12.9  
   12.10  static struct {
   12.11      unsigned char *name;
   12.12 @@ -85,6 +87,7 @@ static struct {
   12.13      { "noreboot",         OPT_BOOL, &opt_noreboot },
   12.14      { "ignorebiostables", OPT_BOOL, &opt_ignorebiostables },
   12.15      { "watchdog",         OPT_BOOL, &opt_watchdog },
   12.16 +    { "pdb",              OPT_STR,  &opt_pdb },
   12.17      { NULL,               0,        NULL     }
   12.18  };
   12.19  
    13.1 --- a/xen/drivers/char/xen_serial.c	Fri Jan 30 15:55:06 2004 +0000
    13.2 +++ b/xen/drivers/char/xen_serial.c	Thu Feb 05 20:27:42 2004 +0000
    13.3 @@ -41,31 +41,114 @@
    13.4  #define NS16550_MCR_OUT2        0x08    /* OUT2: interrupt mask */
    13.5  #define NS16550_MCR_LOOP	0x10	/* Loop			*/
    13.6  
    13.7 -#define SERIAL_BASE 0x3f8  /* XXX SMH: horrible hardwired COM1   */
    13.8 +#define LSR_DR   0x01  /* Data ready */
    13.9 +#define LSR_OE   0x02  /* Overrun */
   13.10 +#define LSR_PE   0x04  /* Parity error */
   13.11 +#define LSR_FE   0x08  /* Framing error */
   13.12 +#define LSR_BI   0x10  /* Break */
   13.13 +#define LSR_THRE 0x20  /* Xmit holding register empty */
   13.14 +#define LSR_TEMT 0x40  /* Xmitter empty */
   13.15 +#define LSR_ERR  0x80  /* Error */
   13.16  
   13.17 -static int serial_echo = 0;   /* default is not to echo; change with 'e' */
   13.18 +#define SERIAL_COM1 0x3f8
   13.19 +#define SERIAL_COM2 0x2f8
   13.20  
   13.21 +int serial_com_base = SERIAL_COM1;
   13.22 +int debug_com_base  = SERIAL_COM1;
   13.23 +
   13.24 +
   13.25 +static int serial_echo = 0;       /* default is not to echo; change with '~' */
   13.26  
   13.27  void toggle_echo(u_char key, void *dev_id, struct pt_regs *regs) 
   13.28  {
   13.29      serial_echo = !serial_echo; 
   13.30  }
   13.31  
   13.32 +void debug_set_com_port(int port)
   13.33 +{
   13.34 +    debug_com_base = port == 1 ? SERIAL_COM1 : SERIAL_COM2;
   13.35 +}
   13.36 +
   13.37 +int debug_testchar()                                /* character available? */
   13.38 +{
   13.39 +    return (inb(debug_com_base + NS16550_LSR) & LSR_DR);
   13.40 +}
   13.41 +
   13.42 +u_char debug_getchar()
   13.43 +{
   13.44 +    while (! (inb(debug_com_base + NS16550_LSR) & LSR_DR));/* wait for char */
   13.45 +    return inb(debug_com_base + NS16550_RBR);
   13.46 +}
   13.47 +
   13.48 +void debug_putch(u_char c)
   13.49 +{
   13.50 +    while (! (inb(debug_com_base + NS16550_LSR) & LSR_THRE));
   13.51 +                                                            /* wait for idle */
   13.52 +    outb(c, debug_com_base + NS16550_RBR);
   13.53 +}
   13.54 +
   13.55 +void debug_putchar(u_char c)
   13.56 +{
   13.57 +    debug_putch(c);
   13.58 +    if (c == '\n') debug_putch('\r');
   13.59 +}
   13.60 +
   13.61 +
   13.62 +
   13.63 +int serial_testchar()                                /* character available? */
   13.64 +{
   13.65 +    return (inb(serial_com_base + NS16550_LSR) & LSR_DR);
   13.66 +}
   13.67 +
   13.68 +u_char serial_getchar()
   13.69 +{
   13.70 +    while (! (inb(serial_com_base + NS16550_LSR) & LSR_DR));/* wait for char */
   13.71 +    return inb(serial_com_base + NS16550_RBR);
   13.72 +}
   13.73 +
   13.74 +void serial_putch(u_char c)
   13.75 +{
   13.76 +    while (! (inb(serial_com_base + NS16550_LSR) & LSR_THRE));
   13.77 +                                                            /* wait for idle */
   13.78 +    outb(c, serial_com_base + NS16550_RBR);
   13.79 +}
   13.80 +
   13.81 +void serial_putchar(u_char c)
   13.82 +{
   13.83 +    serial_putch(c);
   13.84 +    if (c == '\n') serial_putch('\r');
   13.85 +}
   13.86 +
   13.87 +static spinlock_t serial_lock;
   13.88 +
   13.89  static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs)
   13.90  {
   13.91      u_char c; 
   13.92      key_handler *handler; 
   13.93 +    unsigned long flags;
   13.94  
   13.95 -    while ( (inb(SERIAL_BASE + NS16550_LSR) & 1) == 1 )
   13.96 +    spin_lock_irqsave(&serial_lock, flags);
   13.97 +
   13.98 +    while (serial_testchar())
   13.99      {
  13.100 -        c = inb(SERIAL_BASE + NS16550_RBR);
  13.101 +        c = serial_getchar();
  13.102  
  13.103 -        if( (handler = get_key_handler(c)) != NULL ) 
  13.104 -            (*handler)(c, dev_id, regs); 
  13.105 +	if (c & 0x80)
  13.106 +	{
  13.107 +	    extern int pdb_serial_input(u_char, struct pt_regs *);
  13.108 +	    pdb_serial_input(c & 0x7f, regs);
  13.109 +	}
  13.110 +	else
  13.111 +	{
  13.112 +	    if ( (handler = get_key_handler(c)) != NULL ) 
  13.113 +  	        (*handler)(c, dev_id, regs); 
  13.114  
  13.115 -        if ( serial_echo ) 
  13.116 -            printk("%c", c);
  13.117 -    } 
  13.118 +	    if ( serial_echo ) 
  13.119 +	        serial_putch(c);
  13.120 +	}
  13.121 +    }
  13.122 +
  13.123 +    spin_unlock_irqrestore(&serial_lock, flags);
  13.124  }
  13.125  
  13.126  void initialize_serial() 
  13.127 @@ -74,6 +157,8 @@ void initialize_serial()
  13.128  
  13.129      if ( !SERIAL_ENABLED )
  13.130          return;
  13.131 +
  13.132 +    spin_lock_init(&serial_lock);
  13.133      
  13.134      /* setup key handler */
  13.135      add_key_handler('~', toggle_echo, "toggle serial echo");
  13.136 @@ -82,13 +167,13 @@ void initialize_serial()
  13.137      /* Clear FIFOs, enable, trigger at 1 byte */
  13.138      outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE |
  13.139           NS16550_FCR_CLRX  | NS16550_FCR_CLTX, 
  13.140 -         SERIAL_BASE+NS16550_FCR);
  13.141 +         serial_com_base + NS16550_FCR);
  13.142  
  13.143      /* Enable receive interrupts. Also remember to keep DTR/RTS asserted. */
  13.144      outb(NS16550_MCR_OUT2|NS16550_MCR_DTR|NS16550_MCR_RTS, 
  13.145 -         SERIAL_BASE + NS16550_MCR);
  13.146 +         serial_com_base + NS16550_MCR);
  13.147      outb(NS16550_IER_ERDAI, 
  13.148 -         SERIAL_BASE + NS16550_IER );
  13.149 +         serial_com_base + NS16550_IER );
  13.150  
  13.151      if( (rc = request_irq(4, serial_rx_int, SA_NOPROFILE, "serial", 0)) )
  13.152  	printk("initialize_serial: failed to get IRQ4, rc=%d\n", rc); 
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xen/include/asm-i386/pdb.h	Thu Feb 05 20:27:42 2004 +0000
    14.3 @@ -0,0 +1,41 @@
    14.4 +
    14.5 +/*
    14.6 + * pervasive debugger
    14.7 + *
    14.8 + * alex ho
    14.9 + * 2004
   14.10 + * university of cambridge computer laboratory
   14.11 + */
   14.12 +
   14.13 +
   14.14 +#ifndef __PDB_H__
   14.15 +#define __PDB_H__
   14.16 +
   14.17 +#include <asm/ptrace.h>
   14.18 +#include <xeno/list.h>
   14.19 +
   14.20 +extern int pdb_initialized;
   14.21 +extern int pdb_com_port;
   14.22 +extern int pdb_high_bit;
   14.23 +
   14.24 +extern void initialize_pdb(void);
   14.25 +extern int pdb_set_values (int domain, u_char *buffer, 
   14.26 +			   unsigned long addr, int length);
   14.27 +extern int pdb_get_values (int domain, u_char *buffer,
   14.28 +			   unsigned long addr, int length);
   14.29 +
   14.30 +extern int pdb_handle_exception(int exceptionVector,
   14.31 +				struct pt_regs *xen_regs);
   14.32 +
   14.33 +
   14.34 +struct pdb_breakpoint
   14.35 +{
   14.36 +    struct list_head list;
   14.37 +    unsigned long address;
   14.38 +};
   14.39 +extern void pdb_bkpt_add (unsigned long address);
   14.40 +extern struct pdb_breakpoint* pdb_bkpt_search (unsigned long address);
   14.41 +extern void pdb_bkpt_remove_ptr (struct pdb_breakpoint *bkpt);
   14.42 +extern int pdb_bkpt_remove (unsigned long address);
   14.43 +
   14.44 +#endif  /* __PDB_H__ */
    15.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h	Fri Jan 30 15:55:06 2004 +0000
    15.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h	Thu Feb 05 20:27:42 2004 +0000
    15.3 @@ -17,7 +17,7 @@
    15.4   * This makes sure that old versions of dom0 tools will stop working in a
    15.5   * well-defined way (rather than crashing the machine, for instance).
    15.6   */
    15.7 -#define DOM0_INTERFACE_VERSION   0xAAAA0003
    15.8 +#define DOM0_INTERFACE_VERSION   0xAAAA0004
    15.9  
   15.10  
   15.11  /*
   15.12 @@ -168,9 +168,11 @@ typedef struct dom0_debug_st
   15.13  {
   15.14      /* IN variables. */
   15.15      char opcode;
   15.16 -    int domain, in1, in2;
   15.17 +    unsigned int domain;
   15.18 +    int in1, in2, in3, in4;
   15.19      /* OUT variables. */
   15.20 -    int status, out1, out2;
   15.21 +    unsigned int status;
   15.22 +    int out1, out2;
   15.23  } dom0_debug_t;
   15.24  
   15.25  /*
    16.1 --- a/xen/include/xeno/sched.h	Fri Jan 30 15:55:06 2004 +0000
    16.2 +++ b/xen/include/xeno/sched.h	Thu Feb 05 20:27:42 2004 +0000
    16.3 @@ -159,7 +159,7 @@ struct task_struct
    16.4   *                       or expiring timer
    16.5   * TASK_UNINTERRUPTIBLE: Domain is blocked but may not be woken up by an
    16.6   *                       arbitrary event or timer.
    16.7 - * TASK_STOPPED:         Domain is sopped.
    16.8 + * TASK_STOPPED:         Domain is stopped.
    16.9   * TASK_DYING:           Domain is about to cross over to the land of the dead.
   16.10   */
   16.11