ia64/xen-unstable

changeset 2105:777ddc539761

bitkeeper revision 1.1160 (41137784IZQiNzib_RfxG3ZoH3cPag)

Merge latest version of Xen and xenolinux.
author sos22@donkeykong.cl.cam.ac.uk
date Fri Aug 06 12:20:20 2004 +0000 (2004-08-06)
parents 4c3d4467e243 89db7ebcd2ef
children 0a4b76b6b5a0
files .rootkeys BitKeeper/etc/logging_ok tools/misc/xencons xen/Rules.mk xen/arch/x86/Rules.mk xen/arch/x86/pdb-linux.c xen/arch/x86/pdb-stub.c xen/arch/x86/x86_32/xdb_trap.S xen/arch/x86/xdb.c xen/common/debug-linux.c xen/common/debug.c xen/common/domain.c xen/common/kernel.c xen/common/keyhandler.c xen/drivers/char/console.c xen/drivers/char/serial.c xen/include/asm-x86/pdb.h
line diff
     1.1 --- a/.rootkeys	Fri Aug 06 11:53:45 2004 +0000
     1.2 +++ b/.rootkeys	Fri Aug 06 12:20:20 2004 +0000
     1.3 @@ -532,10 +532,12 @@ 40f92331jfOlE7MfKwpdkEb1CEf23g xen/arch/
     1.4  3ddb79bcecupHj56ZbTa3B0FxDowMg xen/arch/x86/x86_32/entry.S
     1.5  3ddb79bcHwuCQDjBICDTSis52hWguw xen/arch/x86/x86_32/mm.c
     1.6  3ddb79bc4nTpGQOe6_-MbyZzkhlhFQ xen/arch/x86/x86_32/usercopy.c
     1.7 +4107c15e_NqNYew2EXroXz2mgTAMWQ xen/arch/x86/x86_32/xdb_trap.S
     1.8  3ddb79bcOMCu9-5mKpjIh5d0qqBDPg xen/arch/x86/x86_32/xen.lds
     1.9  40e96d3aLDI-nViMuYneD7VKYlZrVg xen/arch/x86/x86_64/entry.S
    1.10  40e96d3ahBTZqbTViInnq0lM03vs7A xen/arch/x86/x86_64/usercopy.c
    1.11  40e96d3akN3Hu_J5Bk-WXD8OGscrYQ xen/arch/x86/x86_64/xen.lds
    1.12 +4107c15e-VmEcLsE-7JCXZaabI8C7A xen/arch/x86/xdb.c
    1.13  3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile
    1.14  3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c
    1.15  4022a73c_BbDFd2YJ_NQYVvKX5Oz7w xen/common/debug-linux.c
     2.1 --- a/BitKeeper/etc/logging_ok	Fri Aug 06 11:53:45 2004 +0000
     2.2 +++ b/BitKeeper/etc/logging_ok	Fri Aug 06 12:20:20 2004 +0000
     2.3 @@ -38,6 +38,7 @@ smh22@boulderdash.cl.cam.ac.uk
     2.4  smh22@labyrinth.cl.cam.ac.uk
     2.5  smh22@tempest.cl.cam.ac.uk
     2.6  smh22@uridium.cl.cam.ac.uk
     2.7 +sos22@donkeykong.cl.cam.ac.uk
     2.8  sos22@labyrinth.cl.cam.ac.uk
     2.9  tlh20@elite.cl.cam.ac.uk
    2.10  tlh20@labyrinth.cl.cam.ac.uk
     3.1 --- a/tools/misc/xencons	Fri Aug 06 11:53:45 2004 +0000
     3.2 +++ b/tools/misc/xencons	Fri Aug 06 12:20:20 2004 +0000
     3.3 @@ -27,6 +27,8 @@ def __recv_from_sock(sock):
     3.4      while not stop:
     3.5          try:
     3.6              data = sock.recv(1024)
     3.7 +            if len(data) == 0:
     3.8 +                stop = True
     3.9              os.write(1, data)
    3.10          except socket.error, error:
    3.11              if error[0] != errno.EINTR:
     4.1 --- a/xen/Rules.mk	Fri Aug 06 11:53:45 2004 +0000
     4.2 +++ b/xen/Rules.mk	Fri Aug 06 12:20:20 2004 +0000
     4.3 @@ -48,7 +48,7 @@ CFLAGS += -DVERBOSE
     4.4  endif
     4.5  
     4.6  ifeq ($(debugger),y)
     4.7 -CFLAGS += -DXEN_DEBUGGER
     4.8 +CFLAGS += -DXEN_DEBUGGER -g
     4.9  endif
    4.10  
    4.11  ifeq ($(perfc),y)
     5.1 --- a/xen/arch/x86/Rules.mk	Fri Aug 06 11:53:45 2004 +0000
     5.2 +++ b/xen/arch/x86/Rules.mk	Fri Aug 06 12:20:20 2004 +0000
     5.3 @@ -4,8 +4,8 @@
     5.4  CC := gcc
     5.5  LD := ld
     5.6  
     5.7 -CFLAGS  := -nostdinc -fno-builtin -fno-common -fno-strict-aliasing -O3
     5.8 -CFLAGS  += -iwithprefix include -Wall -Werror -fomit-frame-pointer -pipe
     5.9 +CFLAGS  := -nostdinc -fno-builtin -fno-common -fno-strict-aliasing
    5.10 +CFLAGS  += -iwithprefix include -Wall -Werror -pipe
    5.11  CFLAGS  += -I$(BASEDIR)/include -Wno-pointer-arith -Wredundant-decls
    5.12  
    5.13  ifeq ($(TARGET_SUBARCH),x86_32)
    5.14 @@ -13,6 +13,12 @@ CFLAGS  += -m32 -march=i686
    5.15  LDFLAGS := --oformat elf32-i386 
    5.16  endif
    5.17  
    5.18 +ifeq ($(debugger),y)
    5.19 +CFLAGS += -O2
    5.20 +else
    5.21 +CFLAGS += -O3 -fomit-frame-pointer
    5.22 +endif
    5.23 +
    5.24  ifeq ($(TARGET_SUBARCH),x86_64)
    5.25  CFLAGS  += -m64 -mno-red-zone -fpic -fno-reorder-blocks
    5.26  CFLAGS  += -fno-asynchronous-unwind-tables
     6.1 --- a/xen/arch/x86/pdb-linux.c	Fri Aug 06 11:53:45 2004 +0000
     6.2 +++ b/xen/arch/x86/pdb-linux.c	Fri Aug 06 12:20:20 2004 +0000
     6.3 @@ -10,8 +10,12 @@
     6.4   * linux & i386 dependent code. bleech.
     6.5   */
     6.6  
     6.7 +#include <xen/slab.h>
     6.8  #include <asm/pdb.h>
     6.9  
    6.10 +extern unsigned char pdb_x86_bkpt;
    6.11 +extern int pdb_x86_bkpt_length;
    6.12 +
    6.13  /* offset to the first instruction in the linux system call code
    6.14     where we can safely set a breakpoint */
    6.15  unsigned int pdb_linux_syscall_enter_bkpt_offset = 20;
    6.16 @@ -92,9 +96,25 @@ pdb_linux_syscall_exit_bkpt (struct pt_r
    6.17         debugger when re-entering user space */
    6.18      pdb_system_call_next_addr = *(unsigned long *)(regs->esp + 
    6.19  						 pdb_linux_syscall_eip_offset);
    6.20 -    pdb_linux_get_values (&pdb_system_call_leave_instr, 1, 
    6.21 -			  pdb_system_call_next_addr,
    6.22 -			  pdb_ctx->process, pdb_ctx->ptbr);
    6.23 -    pdb_linux_set_values ("cc", 1, pdb_system_call_next_addr,
    6.24 -			  pdb_ctx->process, pdb_ctx->ptbr);
    6.25 +
    6.26 +    /* set a breakpoint when we exit */
    6.27 +    {
    6.28 +        pdb_bwcpoint_p bwc;
    6.29 +
    6.30 +	bwc = (pdb_bwcpoint_p) xmalloc(sizeof(pdb_bwcpoint_t));
    6.31 +	if (!bwc)
    6.32 +	{
    6.33 +	    printk ("pdb error: can't allocate bwc %d\n", __LINE__);
    6.34 +	}
    6.35 +
    6.36 +	bwc->address = pdb_system_call_next_addr;
    6.37 +	bwc->length = 1;
    6.38 +	bwc->type = PDB_BP_SOFTWARE;
    6.39 +	bwc->user_type = PDB_BP_SOFTWARE;
    6.40 +	bwc->action = PDB_BWC_DELETE;
    6.41 +	bwc->comments = "pdb linux syscall exit";
    6.42 +	memcpy (&bwc->context, pdb_ctx, sizeof(pdb_context_t));
    6.43 +
    6.44 +	pdb_set_breakpoint(bwc);
    6.45 +    }
    6.46  }
     7.1 --- a/xen/arch/x86/pdb-stub.c	Fri Aug 06 11:53:45 2004 +0000
     7.2 +++ b/xen/arch/x86/pdb-stub.c	Fri Aug 06 12:20:20 2004 +0000
     7.3 @@ -22,39 +22,58 @@
     7.4  #include <xen/serial.h>
     7.5  #include <xen/softirq.h>
     7.6  
     7.7 -#define PDB_DEBUG_TRACE
     7.8 -#ifdef PDB_DEBUG_TRACE
     7.9 -#define TRC(_x) _x
    7.10 -#else
    7.11 -#define TRC(_x)
    7.12 -#endif
    7.13 +int pdb_trace = 1;                                 /* debugging the debugger */
    7.14  
    7.15  #define DEBUG_EXCEPTION     0x01
    7.16  #define BREAKPT_EXCEPTION   0x03
    7.17  #define PDB_LIVE_EXCEPTION  0x58
    7.18  #define KEYPRESS_EXCEPTION  0x88
    7.19  
    7.20 -#define BUFMAX 400
    7.21 -
    7.22  static const char hexchars[] = "0123456789abcdef";
    7.23  
    7.24 -static int remote_debug;
    7.25 -
    7.26  #define PDB_BUFMAX 1024
    7.27  static char pdb_in_buffer[PDB_BUFMAX];
    7.28  static char pdb_out_buffer[PDB_BUFMAX];
    7.29 -static char pdb_buffer[PDB_BUFMAX];
    7.30  static int  pdb_in_buffer_ptr;
    7.31  static unsigned char  pdb_in_checksum;
    7.32  static unsigned char  pdb_xmit_checksum;
    7.33  
    7.34 -struct pdb_context pdb_ctx;
    7.35 +void pdb_put_packet (unsigned char *buffer, int ack);
    7.36 +
    7.37 +pdb_context_t pdb_ctx;
    7.38  int pdb_continue_thread = 0;
    7.39  int pdb_general_thread = 0;
    7.40  
    7.41 -void pdb_put_packet (unsigned char *buffer, int ack);
    7.42 -void pdb_bkpt_check (u_char *buffer, int length,
    7.43 -		     unsigned long cr3, unsigned long addr);
    7.44 +
    7.45 +enum pdb_bwc_page_action
    7.46 +{
    7.47 +  PDB_BWC_PAGE_ACCESS_SET,
    7.48 +  PDB_BWC_PAGE_ACCESS_CLEAR,
    7.49 +  PDB_BWC_PAGE_WRITE_SET,
    7.50 +  PDB_BWC_PAGE_WRITE_CLEAR,
    7.51 +  PDB_BWC_PAGE_READ_SET,
    7.52 +  PDB_BWC_PAGE_READ_CLEAR,
    7.53 +};
    7.54 +static char *pdb_bwc_page_action_s[] =
    7.55 +  { "ac set", "ac clr", "wr set", "wr clr", "rd set", "rd cler" };
    7.56 +int pdb_bwc_page (int action, unsigned long addr, int length, 
    7.57 +		  pdb_context_p ctx, int offset, void *s);
    7.58 +
    7.59 +enum pdb_visit_page_action
    7.60 +{
    7.61 +  PDB_VISIT_PAGE_XEN_READ,
    7.62 +  PDB_VISIT_PAGE_XEN_WRITE,
    7.63 +  PDB_VISIT_PAGE_DOMAIN_READ,
    7.64 +  PDB_VISIT_PAGE_DOMAIN_WRITE,
    7.65 +  PDB_VISIT_PAGE_PROCESS_READ,
    7.66 +  PDB_VISIT_PAGE_PROCESS_WRITE,
    7.67 +};
    7.68 +static char *pdb_visit_page_action_s[] =
    7.69 +  { "xen read", "xen write", "domain read", "domain write", 
    7.70 +    "process read", "process write" };
    7.71 +
    7.72 +int pdb_visit_page (int action, unsigned long addr, int length,
    7.73 +                    pdb_context_p ctx, int offset, void *s);
    7.74  
    7.75  int pdb_initialized = 0;
    7.76  int pdb_page_fault_possible = 0;
    7.77 @@ -69,6 +88,12 @@ unsigned char pdb_system_call_leave_inst
    7.78  unsigned long pdb_system_call_next_addr = 0;         /* instr after int 0x80 */
    7.79  unsigned long pdb_system_call_eflags_addr = 0;      /* saved eflags on stack */
    7.80  
    7.81 +unsigned char pdb_x86_bkpt = 0xcc;
    7.82 +unsigned int  pdb_x86_bkpt_length = 1;
    7.83 +
    7.84 +/***********************************************************************/
    7.85 +/***********************************************************************/
    7.86 +
    7.87  static inline void pdb_put_char(unsigned char c)
    7.88  {
    7.89      serial_putc(pdb_serhnd, c);
    7.90 @@ -79,19 +104,146 @@ static inline unsigned char pdb_get_char
    7.91      return serial_getc(pdb_serhnd);
    7.92  }
    7.93  
    7.94 +/***********************************************************************/
    7.95 +/***********************************************************************/
    7.96 +
    7.97 +/*
    7.98 + * Prototype for function to process each page.  This function is called
    7.99 + * once per page.
   7.100 + *
   7.101 + * action  : function specific
   7.102 + * address : first byte of this page
   7.103 + * length  : number of bytes to process on this page
   7.104 + * offset  : number of bytes processed so far. can be used as
   7.105 + *           an index into data.
   7.106 + * data    : function specific.
   7.107 + */
   7.108 +
   7.109 +typedef int (pdb_invoke_ftype) (int action, unsigned long address, int length, 
   7.110 +				pdb_context_p ctx, int offset, void *data);
   7.111 +
   7.112 +typedef struct pdb_invoke_args
   7.113 +{
   7.114 +  pdb_context_p context;
   7.115 +  unsigned long address;
   7.116 +  int length;
   7.117 +  int action;
   7.118 +  void *data;
   7.119 +} pdb_invoke_args_t, * pdb_invoke_args_p;
   7.120 +
   7.121 +
   7.122 +/*
   7.123 + * call a particular function once per page given an address & length
   7.124 + */
   7.125 +
   7.126  int
   7.127 -get_char (char *addr)
   7.128 +pdb_invoke (pdb_invoke_ftype *function, pdb_invoke_args_p args)
   7.129  {
   7.130 -    return *addr;
   7.131 +  int remaining;
   7.132 +  int bytes = 0;
   7.133 +  int length = args->length;
   7.134 +  unsigned long address = args->address;
   7.135 +
   7.136 +  while ((remaining = (address + length - 1) - (address | (PAGE_SIZE - 1))) > 0)
   7.137 +  {
   7.138 +    bytes += (function)(args->action, address, length - remaining,
   7.139 +			args->context, address - args->address, args->data);
   7.140 +    length = remaining;
   7.141 +    address = (address | (PAGE_SIZE - 1)) + 1;
   7.142 +  }
   7.143 +  bytes += (function)(args->action, address, length,
   7.144 +                      args->context, address - args->address, args->data);
   7.145 +  return bytes;
   7.146 +}
   7.147 +
   7.148 +
   7.149 +/***********************************************************************/
   7.150 +/***********************************************************************/
   7.151 +
   7.152 +/* BWC List Support: breakpoints, watchpoints, and catchpoints */
   7.153 +
   7.154 +char *pdb_bwcpoint_type_s[] =                      /* enum pdb_bwcpoint_type */
   7.155 +  { "BP_SOFTWARE", "BP_HARDWARE", "WP_WRITE", "WP_READ", "WP_ACCESS" };
   7.156 +
   7.157 +char *pdb_bwcpoint_action_s[] =                  /* enum pdb_bwcpoint_action */
   7.158 +  { "UNKNOWN", "STOP", "DELETE" };
   7.159 +
   7.160 +int pdb_set_watchpoint (pdb_bwcpoint_p bwc); 
   7.161 +int pdb_clear_watchpoint (pdb_bwcpoint_p bwc);
   7.162 +
   7.163 +struct list_head pdb_bwc_list = LIST_HEAD_INIT(pdb_bwc_list);
   7.164 +
   7.165 +void
   7.166 +pdb_bwc_list_add (pdb_bwcpoint_p bwc)
   7.167 +{
   7.168 +    list_add_tail(&bwc->list, &pdb_bwc_list);
   7.169  }
   7.170  
   7.171  void
   7.172 -set_char (char *addr, int val)
   7.173 +pdb_bwc_list_remove (pdb_bwcpoint_p bwc)
   7.174 +{
   7.175 +    list_del(&bwc->list);
   7.176 +}
   7.177 +
   7.178 +pdb_bwcpoint_p
   7.179 +pdb_bwc_list_search (unsigned long address, int length, pdb_context_p ctx)
   7.180 +{
   7.181 +    struct list_head *ptr;
   7.182 +
   7.183 +    list_for_each(ptr, &pdb_bwc_list)
   7.184 +    {
   7.185 +        pdb_bwcpoint_p bwc = list_entry(ptr, pdb_bwcpoint_t, list);
   7.186 +
   7.187 +	if (bwc->address == address &&
   7.188 +	    bwc->length  == length)
   7.189 +	{
   7.190 +	    return bwc;
   7.191 +	}
   7.192 +    }
   7.193 +    return (pdb_bwcpoint_p) 0;
   7.194 +}
   7.195 +
   7.196 +pdb_bwcpoint_p
   7.197 +pdb_bwcpoint_search (unsigned long cr3, unsigned long address)
   7.198  {
   7.199 -    *addr = val;
   7.200 +    pdb_context_t ctx;
   7.201 +
   7.202 +    ctx.ptbr = cr3;
   7.203 +    return pdb_bwc_list_search(address, pdb_x86_bkpt_length, &ctx);
   7.204 +}
   7.205 +
   7.206 +void
   7.207 +pdb_bwc_print (pdb_bwcpoint_p bwc)
   7.208 +{
   7.209 +    printk ("addr:0x%08lx, len:0x%02x, type:0x%x %s, action:0x%x %s [%s]",
   7.210 +	    bwc->address, bwc->length,
   7.211 +	    bwc->type, pdb_bwcpoint_type_s[bwc->type],
   7.212 +	    bwc->action, pdb_bwcpoint_action_s[bwc->action], bwc->comments);
   7.213  }
   7.214  
   7.215  void
   7.216 +pdb_bwc_print_list ()
   7.217 +{
   7.218 +    struct list_head *ptr;
   7.219 +    int counter = 0;
   7.220 +
   7.221 +    list_for_each (ptr, &pdb_bwc_list)
   7.222 +    {
   7.223 +        pdb_bwcpoint_p bwc = list_entry(ptr, pdb_bwcpoint_t, list);
   7.224 +	printk ("  [%02d]  ", counter);   pdb_bwc_print(bwc);   printk ("\n");
   7.225 +	counter++;
   7.226 +    }
   7.227 +    
   7.228 +    if (counter == 0)
   7.229 +    {
   7.230 +        printk ("  empty list\n");
   7.231 +    }
   7.232 +}
   7.233 +
   7.234 +/***********************************************************************/
   7.235 +/***********************************************************************/
   7.236 +
   7.237 +void
   7.238  pdb_process_query (char *ptr)
   7.239  {
   7.240      if (strcmp(ptr, "C") == 0)
   7.241 @@ -100,82 +252,10 @@ pdb_process_query (char *ptr)
   7.242      }
   7.243      else if (strcmp(ptr, "fThreadInfo") == 0)
   7.244      {
   7.245 -#ifdef PDB_PAST
   7.246 -        struct domain *p;
   7.247 -        u_long flags;
   7.248 -#endif /* PDB_PAST */
   7.249 -
   7.250          int buf_idx = 0;
   7.251  
   7.252  	pdb_out_buffer[buf_idx++] = 'l';
   7.253  	pdb_out_buffer[buf_idx++] = 0;
   7.254 -
   7.255 -#ifdef PDB_PAST
   7.256 -	switch (pdb_level)
   7.257 -	{
   7.258 -	case PDB_LVL_XEN:                        /* return a list of domains */
   7.259 -	{
   7.260 -	    int count = 0;
   7.261 -
   7.262 -	    read_lock_irqsave (&tasklist_lock, flags);
   7.263 -
   7.264 -	    pdb_out_buffer[buf_idx++] = 'm';
   7.265 -	    for_each_domain ( p )
   7.266 -	    {
   7.267 -	        domid_t domain = p->domain + PDB_ID_OFFSET;
   7.268 -
   7.269 -		if (count > 0)
   7.270 -		{
   7.271 -		    pdb_out_buffer[buf_idx++] = ',';
   7.272 -		}
   7.273 -		if (domain > 15)
   7.274 -		{
   7.275 -		    pdb_out_buffer[buf_idx++] = hexchars[domain >> 4];
   7.276 -		}
   7.277 -		pdb_out_buffer[buf_idx++] = hexchars[domain % 16];
   7.278 -		count++;
   7.279 -	    }
   7.280 -	    pdb_out_buffer[buf_idx++] = 0;
   7.281 -
   7.282 -	    read_unlock_irqrestore(&tasklist_lock, flags);
   7.283 -	    break;
   7.284 -	}
   7.285 -	case PDB_LVL_GUESTOS:                  /* return a list of processes */
   7.286 -	{
   7.287 -	    int foobar[20];
   7.288 -	    int loop, total;
   7.289 -
   7.290 -                                                       /* this cr3 is wrong! */
   7.291 -	    total = pdb_linux_process_list(pdb_ctx[pdb_level].info_cr3,
   7.292 -					   foobar, 20);
   7.293 -
   7.294 -	    pdb_out_buffer[buf_idx++] = 'm';     
   7.295 -	    pdb_out_buffer[buf_idx++] = '1';              /* 1 is to go back */
   7.296 -	    for (loop = 0; loop < total; loop++)
   7.297 -	    {
   7.298 -	        int pid = foobar[loop] + PDB_ID_OFFSET;
   7.299 -
   7.300 -		pdb_out_buffer[buf_idx++] = ',';
   7.301 -		if (pid > 15)
   7.302 -		{
   7.303 -		    pdb_out_buffer[buf_idx++] = hexchars[pid >> 4];
   7.304 -		}
   7.305 -		pdb_out_buffer[buf_idx++] = hexchars[pid % 16];
   7.306 -	    }
   7.307 -	    pdb_out_buffer[buf_idx++] = 0;
   7.308 -	    break;
   7.309 -	}
   7.310 -	case PDB_LVL_PROCESS:                                     /* hmmm... */
   7.311 -	{
   7.312 -	    pdb_out_buffer[buf_idx++] = 'm';
   7.313 -	    pdb_out_buffer[buf_idx++] = '1';              /* 1 is to go back */
   7.314 -	    break;
   7.315 -	}
   7.316 -	default:
   7.317 -	    break;
   7.318 -	}
   7.319 -#endif /* PDB_PAST */
   7.320 -
   7.321      }
   7.322      else if (strcmp(ptr, "sThreadInfo") == 0)
   7.323      {
   7.324 @@ -195,22 +275,6 @@ pdb_process_query (char *ptr)
   7.325              mem2hex (message, pdb_out_buffer, strlen(message) + 1);
   7.326  	}
   7.327  
   7.328 -#ifdef PDB_PAST
   7.329 -        int thread = 0;
   7.330 -	char message[16];
   7.331 -	struct domain *p;
   7.332 -
   7.333 -	p = find_domain_by_id(pdb_ctx[pdb_level].info);
   7.334 -	strncpy (message, p->name, 16);
   7.335 -	put_domain(p);
   7.336 -
   7.337 -	ptr += 16;
   7.338 -        if (hexToInt (&ptr, &thread))
   7.339 -	{
   7.340 -            mem2hex ((char *)message, pdb_out_buffer, strlen(message) + 1);
   7.341 -	}
   7.342 -#endif /* PDB_PAST */
   7.343 -
   7.344  #ifdef PDB_FUTURE
   7.345        {
   7.346  	char string[task_struct_comm_length];
   7.347 @@ -220,7 +284,6 @@ pdb_process_query (char *ptr)
   7.348  	printk (" (%s)", string);
   7.349        }
   7.350  #endif /* PDB_FUTURE*/
   7.351 -
   7.352      }
   7.353      else if (strcmp(ptr, "Offsets") == 0)
   7.354      {
   7.355 @@ -237,7 +300,189 @@ pdb_process_query (char *ptr)
   7.356  }
   7.357  
   7.358  void
   7.359 -pdb_x86_to_gdb_regs (char *buffer, struct pt_regs *regs)
   7.360 +pdb_process_z (int onoff, char *ptr)
   7.361 +{
   7.362 +    int type = *(ptr++) - '0';
   7.363 +    int length;
   7.364 +    unsigned long addr;
   7.365 +    char *error = "E01";                                     /* syntax error */
   7.366 +
   7.367 +    /* try to read ',addr,length' */
   7.368 +    if (   *(ptr++) == ','
   7.369 +	&& hexToInt(&ptr, (int *)&addr)
   7.370 +	&& *(ptr++) == ','
   7.371 +	&& hexToInt(&ptr, &length))
   7.372 +    {
   7.373 +	error = "OK";
   7.374 +
   7.375 +	switch (type)
   7.376 +	{
   7.377 +	case PDB_BP_SOFTWARE:
   7.378 +	case PDB_BP_HARDWARE:
   7.379 +	{
   7.380 +	    if (onoff == 1)
   7.381 +	    {
   7.382 +	        pdb_bwcpoint_p bwc;
   7.383 +
   7.384 +		bwc = (pdb_bwcpoint_p) xmalloc(sizeof(pdb_bwcpoint_t));
   7.385 +		if (!bwc)
   7.386 +		{
   7.387 +		    printk ("pdb error: can't allocate bwc %d\n", __LINE__);
   7.388 +		    break;
   7.389 +		}
   7.390 +
   7.391 +		bwc->address = addr;
   7.392 +		bwc->length = pdb_x86_bkpt_length;
   7.393 +		bwc->type = PDB_BP_SOFTWARE;
   7.394 +		bwc->user_type = type;
   7.395 +		bwc->action = PDB_BWC_STOP;
   7.396 +		bwc->comments = "gdb breakpoint";
   7.397 +		memcpy(&bwc->context, &pdb_ctx, sizeof(pdb_context_t));
   7.398 +
   7.399 +		if (length != pdb_x86_bkpt_length)
   7.400 +		{
   7.401 +		    printk("pdb warning: x86 bkpt length should be 1\n");
   7.402 +		}
   7.403 +
   7.404 +		pdb_set_breakpoint(bwc);
   7.405 +	    }
   7.406 +	    else
   7.407 +	    {
   7.408 +	        pdb_clear_breakpoint(addr, &pdb_ctx);
   7.409 +	    }
   7.410 +	    break;
   7.411 +	}
   7.412 +	case PDB_WP_WRITE:
   7.413 +	case PDB_WP_READ:
   7.414 +	case PDB_WP_ACCESS:
   7.415 +	{
   7.416 +	    if (onoff == 1)
   7.417 +	    {
   7.418 +	        pdb_bwcpoint_p bwc;
   7.419 +
   7.420 +		bwc = (pdb_bwcpoint_p) xmalloc(sizeof(pdb_bwcpoint_t));
   7.421 +		if (!bwc)
   7.422 +		{
   7.423 +		    printk ("pdb error: can't allocate bwc %d\n", __LINE__);
   7.424 +		    break;
   7.425 +		}
   7.426 +
   7.427 +		bwc->address = addr;
   7.428 +		bwc->length = length;
   7.429 +		bwc->type = type;
   7.430 +		bwc->user_type = type;
   7.431 +		bwc->action = PDB_BWC_UNKNOWN;
   7.432 +		bwc->comments = "gdb writepoint";
   7.433 +		memcpy (&bwc->context, &pdb_ctx, sizeof(pdb_context_t));
   7.434 +
   7.435 +		pdb_set_watchpoint (bwc);
   7.436 +
   7.437 +		pdb_bwc_list_add (bwc);
   7.438 +	    }
   7.439 +	    else
   7.440 +	    {
   7.441 +	        pdb_bwcpoint_p bwc = pdb_bwc_list_search (addr, 1, &pdb_ctx);
   7.442 +
   7.443 +		if (bwc == 0)
   7.444 +		{
   7.445 +		    error = "E03";                   /* watchpoint not found */
   7.446 +		    break;
   7.447 +		}
   7.448 +
   7.449 +		pdb_clear_watchpoint (bwc);
   7.450 +		pdb_bwc_list_remove (bwc);
   7.451 +		xfree (bwc);
   7.452 +	    }
   7.453 +	    break;
   7.454 +	}
   7.455 +	default:
   7.456 +	{
   7.457 +	    printk ("pdb error: unknown Z command [%c]\n", type);
   7.458 +	    error = "E02";                                   /* syntax error */
   7.459 +	    break;
   7.460 +	}
   7.461 +	}
   7.462 +    }
   7.463 +
   7.464 +    if (error)                               /* return value, including okay */
   7.465 +    {
   7.466 +	strcpy (pdb_out_buffer, error);
   7.467 +    }
   7.468 +}
   7.469 +
   7.470 +void
   7.471 +pdb_process_pdb (char *ptr)
   7.472 +{
   7.473 +    unsigned long arg1, arg2;
   7.474 +    char *error = "E01";                                     /* syntax error */
   7.475 +    char command = *(ptr++);
   7.476 +
   7.477 +    switch (command)
   7.478 +    {
   7.479 +    case 'c':                                             /* set pdb context */
   7.480 +    case 'C':
   7.481 +    {
   7.482 +        /* try to read two hex arguments ':arg1,arg2 */
   7.483 +        if (   *(ptr++) == ':'
   7.484 +	    && hexToInt(&ptr, (int *)&arg1)
   7.485 +	    && *(ptr++) == ','
   7.486 +	    && hexToInt(&ptr, (int *)&arg2))
   7.487 +	{
   7.488 +	    printk ("pdb: set context: domain:0x%lx process:0x%lx\n", 
   7.489 +		    arg1, arg2);
   7.490 +	    error = "OK";
   7.491 +	}
   7.492 +
   7.493 +        pdb_ctx.domain  = arg1;
   7.494 +	pdb_ctx.process = arg2;
   7.495 +	pdb_ctx.valid   = 1;
   7.496 +	break;
   7.497 +    }
   7.498 +    case 't':                                          /* enable pdb tracing */
   7.499 +    case 'T':
   7.500 +    {
   7.501 +        /* read the trace level */
   7.502 +        if (   *(ptr++) == ':'
   7.503 +	    && hexToInt(&ptr, (int *)&pdb_trace))
   7.504 +	{
   7.505 +	    printk ("pdb: set trace level: 0x%x\n", pdb_trace);
   7.506 +	    error = "OK";
   7.507 +	}
   7.508 +	break;
   7.509 +    }
   7.510 +    case 'd':
   7.511 +    case 'D':                                              /* dump pdb state */
   7.512 +    {
   7.513 +        printk ("----------\n");
   7.514 +        printk ("pdb trace : %2d 0x%02x\n", pdb_trace, pdb_trace);
   7.515 +        printk ("pdb ctx domain  : %4d 0x%04x\n",
   7.516 +		pdb_ctx.domain, pdb_ctx.domain);
   7.517 +        printk ("        process : %4d 0x%04x\n",
   7.518 +		pdb_ctx.process, pdb_ctx.process);
   7.519 +        printk ("        sys call: %4d 0x%04x\n",
   7.520 +		pdb_ctx.system_call, pdb_ctx.system_call);
   7.521 +        printk ("bwc list:\n");
   7.522 +	pdb_bwc_print_list ();
   7.523 +        printk ("----------\n");
   7.524 +	error = "OK";
   7.525 +	break;
   7.526 +    }
   7.527 +    default:
   7.528 +    {
   7.529 +        printk ("pdb error: unknown pdb dot command [%c]\n", command);
   7.530 +	error = "E02";                                       /* syntax error */
   7.531 +	break;
   7.532 +    }
   7.533 +    }
   7.534 +
   7.535 +    if (error)                               /* return value, including okay */
   7.536 +    {
   7.537 +	strcpy (pdb_out_buffer, error);
   7.538 +    }
   7.539 +}
   7.540 +
   7.541 +void
   7.542 +pdb_read_regs (char *buffer, struct pt_regs *regs)
   7.543  {
   7.544      int idx = 0;
   7.545  
   7.546 @@ -276,7 +521,7 @@ pdb_x86_to_gdb_regs (char *buffer, struc
   7.547  
   7.548  /* at this point we allow any register to be changed, caveat emptor */
   7.549  void
   7.550 -pdb_gdb_to_x86_regs (struct pt_regs *regs, char *buffer)
   7.551 +pdb_write_regs (struct pt_regs *regs, char *buffer)
   7.552  {
   7.553      hex2mem(buffer, (char *)&regs->eax, sizeof(regs->eax));
   7.554      buffer += sizeof(regs->eax) * 2;
   7.555 @@ -320,7 +565,7 @@ pdb_process_command (char *ptr, struct p
   7.556      int ack = 1;                           /* wait for ack in pdb_put_packet */
   7.557      int go = 0;
   7.558  
   7.559 -    TRC(printf("pdb: [%s]\n", ptr));
   7.560 +    PDBTRC(1,printk("pdb: [%s]\n", ptr));
   7.561  
   7.562      pdb_out_buffer[0] = 0;
   7.563  
   7.564 @@ -386,8 +631,8 @@ pdb_process_command (char *ptr, struct p
   7.565  	}
   7.566  
   7.567  	pdb_ctx.valid = 0;
   7.568 -	TRC(printk ("pdb change context (dom:%d, proc:%d) now 0x%lx\n",
   7.569 -		    pdb_ctx.domain, pdb_ctx.process, pdb_ctx.ptbr));
   7.570 +	PDBTRC(1,printk ("pdb change context (dom:%d, proc:%d) now 0x%lx\n",
   7.571 +		      pdb_ctx.domain, pdb_ctx.process, pdb_ctx.ptbr));
   7.572      }
   7.573  
   7.574      switch (*ptr++)
   7.575 @@ -404,16 +649,13 @@ pdb_process_command (char *ptr, struct p
   7.576          if ( pdb_system_call_eflags_addr != 0 )
   7.577  	{
   7.578  	    unsigned long eflags;
   7.579 -	    char eflags_buf[sizeof(eflags)*2];       /* STUPID STUPID STUPID */
   7.580  
   7.581 -	    pdb_linux_get_values((u_char*)&eflags, sizeof(eflags), 
   7.582 -				 pdb_system_call_eflags_addr, 
   7.583 -				 pdb_ctx.process, pdb_ctx.ptbr);
   7.584 +	    /* this is always in a process context */
   7.585 +	    pdb_read_memory (pdb_system_call_eflags_addr, sizeof(eflags), 
   7.586 +			     (u_char *)&eflags, &pdb_ctx);
   7.587  	    eflags |= X86_EFLAGS_TF;
   7.588 -	    mem2hex ((u_char *)&eflags, eflags_buf, sizeof(eflags)); 
   7.589 -	    pdb_linux_set_values(eflags_buf, sizeof(eflags),
   7.590 -				 pdb_system_call_eflags_addr,
   7.591 -				 pdb_ctx.process, pdb_ctx.ptbr);
   7.592 +	    pdb_write_memory (pdb_system_call_eflags_addr, sizeof(eflags), 
   7.593 +			      (u_char *)&eflags, &pdb_ctx);
   7.594  	}
   7.595  
   7.596          regs->eflags |= X86_EFLAGS_TF;
   7.597 @@ -427,16 +669,13 @@ pdb_process_command (char *ptr, struct p
   7.598          if ( pdb_system_call_eflags_addr != 0 )
   7.599  	{
   7.600  	    unsigned long eflags;
   7.601 -	    char eflags_buf[sizeof(eflags)*2];       /* STUPID STUPID STUPID */
   7.602  
   7.603 -	    pdb_linux_get_values((u_char*)&eflags, sizeof(eflags), 
   7.604 -				 pdb_system_call_eflags_addr, 
   7.605 -				 pdb_ctx.process, pdb_ctx.ptbr);
   7.606 +	    /* this is always in a process context */
   7.607 +	    pdb_read_memory (pdb_system_call_eflags_addr, sizeof(eflags), 
   7.608 +			     (u_char *)&eflags, &pdb_ctx);
   7.609  	    eflags &= ~X86_EFLAGS_TF;
   7.610 -	    mem2hex ((u_char *)&eflags, eflags_buf, sizeof(eflags)); 
   7.611 -	    pdb_linux_set_values(eflags_buf, sizeof(eflags),
   7.612 -				 pdb_system_call_eflags_addr,
   7.613 -				 pdb_ctx.process, pdb_ctx.ptbr);
   7.614 +	    pdb_write_memory (pdb_system_call_eflags_addr, sizeof(eflags), 
   7.615 +			      (u_char *)&eflags, &pdb_ctx);
   7.616  	}
   7.617  
   7.618          regs->eflags &= ~X86_EFLAGS_TF;
   7.619 @@ -444,19 +683,18 @@ pdb_process_command (char *ptr, struct p
   7.620          /* not reached */
   7.621      }
   7.622      case 'd':
   7.623 -        remote_debug = !(remote_debug);                 /* toggle debug flag */
   7.624          break;
   7.625      case 'D':                                                      /* detach */
   7.626 -        return go;
   7.627 -        /* not reached */
   7.628 +        go = 1;
   7.629 +        break;
   7.630      case 'g':                       /* return the value of the CPU registers */
   7.631      {
   7.632 -        pdb_x86_to_gdb_regs (pdb_out_buffer, regs);
   7.633 +        pdb_read_regs (pdb_out_buffer, regs);
   7.634          break;
   7.635      }
   7.636      case 'G':              /* set the value of the CPU registers - return OK */
   7.637      {
   7.638 -        pdb_gdb_to_x86_regs (regs, ptr);
   7.639 +        pdb_write_regs (regs, ptr);
   7.640          break;
   7.641      }
   7.642      case 'H':
   7.643 @@ -503,37 +741,33 @@ pdb_process_command (char *ptr, struct p
   7.644      case 'm':
   7.645      {
   7.646          /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
   7.647 -        if (hexToInt (&ptr, (int *)&addr))
   7.648 -            if (*(ptr++) == ',')
   7.649 -                if (hexToInt (&ptr, &length))
   7.650 -                {
   7.651 -                    ptr = 0;
   7.652 +        if (   hexToInt (&ptr, (int *)&addr)
   7.653 +	    && *(ptr++) == ','
   7.654 +	    && hexToInt (&ptr, &length))
   7.655 +	{
   7.656 +	    ptr = 0;
   7.657 +
   7.658 +	    pdb_page_fault_possible = 2;
   7.659 +	    pdb_page_fault = 0;
   7.660  
   7.661 -		    pdb_page_fault_possible = 1;
   7.662 -		    pdb_page_fault = 0;
   7.663 -		    if (addr >= PAGE_OFFSET)
   7.664 -		    {
   7.665 -                        mem2hex ((char *) addr, pdb_out_buffer, length); 
   7.666 -		    }
   7.667 -		    else if (pdb_ctx.process != -1)
   7.668 -		    {
   7.669 -		        pdb_linux_get_values(pdb_buffer, length, addr, 
   7.670 -					     pdb_ctx.process, pdb_ctx.ptbr);
   7.671 -                        mem2hex (pdb_buffer, pdb_out_buffer, length); 
   7.672 -		    }
   7.673 -                    else
   7.674 -                    {
   7.675 -		        pdb_get_values (pdb_buffer, length, 
   7.676 -					pdb_ctx.ptbr, addr);
   7.677 -                        mem2hex (pdb_buffer, pdb_out_buffer, length);
   7.678 -                    }
   7.679 +	    {
   7.680 +	        u_char *buffer = (u_char *) xmalloc (length);
   7.681 +		if (!buffer)
   7.682 +		{
   7.683 +		    printk ("pdb error: xmalloc failure %d\n", __LINE__);
   7.684 +		    break;
   7.685 +		}
   7.686 +		pdb_read_memory (addr, length, buffer, &pdb_ctx);
   7.687 +		mem2hex (buffer, pdb_out_buffer, length); 
   7.688 +		xfree(buffer);
   7.689 +	    }
   7.690  
   7.691 -		    pdb_page_fault_possible = 0;
   7.692 -		    if (pdb_page_fault)
   7.693 -		    {
   7.694 -                        strcpy (pdb_out_buffer, "E03");
   7.695 -		    }
   7.696 -                }
   7.697 +	    pdb_page_fault_possible = 0;
   7.698 +	    if (pdb_page_fault)
   7.699 +	    {
   7.700 +	        strcpy (pdb_out_buffer, "E03");
   7.701 +	    }
   7.702 +	}
   7.703  	    
   7.704          if (ptr)
   7.705          {
   7.706 @@ -546,44 +780,39 @@ pdb_process_command (char *ptr, struct p
   7.707      case 'M':
   7.708      {
   7.709          /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
   7.710 -        if (hexToInt (&ptr, (int *)&addr))
   7.711 -            if (*(ptr++) == ',')
   7.712 -                if (hexToInt (&ptr, &length))
   7.713 -                    if (*(ptr++) == ':')
   7.714 -                    {
   7.715 +        if (   hexToInt (&ptr, (int *)&addr)
   7.716 +	    && *(ptr++) == ','
   7.717 +            && hexToInt (&ptr, &length)
   7.718 +	    && *(ptr++) == ':')
   7.719 +	{
   7.720 +	    pdb_page_fault_possible = 3;
   7.721 +	    pdb_page_fault = 0;
   7.722  
   7.723 -		        pdb_page_fault_possible = 1;
   7.724 -			pdb_page_fault = 0;
   7.725 -			if (addr >= PAGE_OFFSET)
   7.726 -			{
   7.727 -			    hex2mem (ptr, (char *)addr, length);
   7.728 -			    pdb_bkpt_check(ptr, length, pdb_ctx.ptbr, addr);
   7.729 -			}
   7.730 -			else if (pdb_ctx.process != -1)
   7.731 -			{
   7.732 -			    pdb_linux_set_values(ptr, length, addr,
   7.733 -						 pdb_ctx.process, 
   7.734 -						 pdb_ctx.ptbr);
   7.735 -			    pdb_bkpt_check(ptr, length, pdb_ctx.ptbr, addr);
   7.736 -			}
   7.737 -			else
   7.738 -			{
   7.739 -			    pdb_set_values (ptr, length,
   7.740 -					    pdb_ctx.ptbr, addr);
   7.741 -			    pdb_bkpt_check(ptr, length, pdb_ctx.ptbr, addr);
   7.742 -			}
   7.743 -			pdb_page_fault_possible = 0;
   7.744 -                        if (pdb_page_fault)
   7.745 -                        {
   7.746 -                            strcpy (pdb_out_buffer, "E03");
   7.747 -                        }
   7.748 -                        else
   7.749 -                        {
   7.750 -                            strcpy (pdb_out_buffer, "OK");
   7.751 -                        }
   7.752 +	    {
   7.753 +	        u_char *buffer = (u_char *) xmalloc (length);
   7.754 +		if (!buffer)
   7.755 +		{
   7.756 +		    printk ("pdb error: xmalloc failure %d\n", __LINE__);
   7.757 +		    break;
   7.758 +		}
   7.759 +	        hex2mem (ptr, buffer, length);
   7.760 +		pdb_write_memory (addr, length, buffer, &pdb_ctx);
   7.761 +		xfree(buffer);
   7.762 +	    }
   7.763  
   7.764 -                        ptr = 0;
   7.765 -                    }
   7.766 +	    pdb_page_fault_possible = 0;
   7.767 +	    if (pdb_page_fault)
   7.768 +	    {
   7.769 +	        strcpy (pdb_out_buffer, "E03");
   7.770 +	    }
   7.771 +	    else
   7.772 +	    {
   7.773 +	        strcpy (pdb_out_buffer, "OK");
   7.774 +	    }
   7.775 +
   7.776 +	    ptr = 0;
   7.777 +	}
   7.778 +
   7.779          if (ptr)
   7.780          {
   7.781              strcpy (pdb_out_buffer, "E02");
   7.782 @@ -597,59 +826,29 @@ pdb_process_command (char *ptr, struct p
   7.783          if (hexToInt (&ptr, &id))
   7.784          {
   7.785  	    strcpy (pdb_out_buffer, "E00");
   7.786 -
   7.787 -#ifdef PDB_PAST
   7.788 -
   7.789 -	    switch (pdb_level)                             /* previous level */
   7.790 -	    {
   7.791 -	        case PDB_LVL_XEN:
   7.792 -		{
   7.793 -		    struct domain *p;
   7.794 -		    id -= PDB_ID_OFFSET;
   7.795 -		    if ( (p = find_domain_by_id(id)) == NULL)
   7.796 -		        strcpy (pdb_out_buffer, "E00");
   7.797 -		    else
   7.798 -		        strcpy (pdb_out_buffer, "OK");
   7.799 -		    put_domain(p);
   7.800 -
   7.801 -		    pdb_level = PDB_LVL_GUESTOS;
   7.802 -		    pdb_ctx[pdb_level].ctrl = id;
   7.803 -		    pdb_ctx[pdb_level].info = id;
   7.804 -		    break;
   7.805 -		}
   7.806 -	        case PDB_LVL_GUESTOS:
   7.807 -		{
   7.808 -		    if (pdb_level == -1)
   7.809 -		    {
   7.810 -		        pdb_level = PDB_LVL_XEN;
   7.811 -		    }
   7.812 -		    else
   7.813 -		    {
   7.814 -		        pdb_level = PDB_LVL_PROCESS;
   7.815 -			pdb_ctx[pdb_level].ctrl = id;
   7.816 -			pdb_ctx[pdb_level].info = id;
   7.817 -		    }
   7.818 -		    break;
   7.819 -		}
   7.820 -	        case PDB_LVL_PROCESS:
   7.821 -		{
   7.822 -		    if (pdb_level == -1)
   7.823 -		    {
   7.824 -		        pdb_level = PDB_LVL_GUESTOS;
   7.825 -		    }
   7.826 -		    break;
   7.827 -		}
   7.828 -	        default:
   7.829 -		{
   7.830 -		    printk ("pdb internal error: invalid level [%d]\n", 
   7.831 -			    pdb_level);
   7.832 -		}
   7.833 -	    }
   7.834 -
   7.835 -#endif /* PDB_PAST */
   7.836          }
   7.837          break;
   7.838      }
   7.839 +    case 'Z':                                                         /* set */
   7.840 +    {
   7.841 +        pdb_process_z (1, ptr);
   7.842 +	break;
   7.843 +    }
   7.844 +    case 'z':                                                       /* clear */
   7.845 +    {
   7.846 +        pdb_process_z (0, ptr);
   7.847 +	break;
   7.848 +    }
   7.849 +    case '.':                                     /* pdb specific extensions */
   7.850 +    {
   7.851 +        pdb_process_pdb (ptr);
   7.852 +	break;
   7.853 +    }
   7.854 +    default:
   7.855 +    {
   7.856 +        PDBTRC(1,printk ("pdb warning: ignoring unknown command.\n"));
   7.857 +	break;
   7.858 +    }
   7.859      }
   7.860  
   7.861  exit:
   7.862 @@ -712,8 +911,8 @@ int pdb_serial_input(u_char c, struct pt
   7.863  	if (pdb_in_checksum != pdb_xmit_checksum) 
   7.864  	{
   7.865  	    pdb_put_char('-');                           /* checksum failure */
   7.866 -	    printk ("checksum failure [%s.%02x.%02x]\n", pdb_in_buffer,
   7.867 -		    pdb_in_checksum, pdb_xmit_checksum);
   7.868 +	    printk ("pdb error: checksum failure [%s.%02x.%02x]\n",
   7.869 +		    pdb_in_buffer, pdb_in_checksum, pdb_xmit_checksum);
   7.870  	}
   7.871  	else 
   7.872  	{
   7.873 @@ -738,6 +937,9 @@ int pdb_serial_input(u_char c, struct pt
   7.874      return out;
   7.875  }
   7.876  
   7.877 +/***********************************************************************/
   7.878 +/***********************************************************************/
   7.879 +
   7.880  int hex(char ch)
   7.881  {
   7.882      if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
   7.883 @@ -759,7 +961,8 @@ mem2hex (mem, buf, count)
   7.884  
   7.885      for (i = 0; i < count; i++)
   7.886      {
   7.887 -        ch = get_char (mem++);
   7.888 +        ch = *mem;
   7.889 +	mem ++;
   7.890          *buf++ = hexchars[ch >> 4];
   7.891          *buf++ = hexchars[ch % 16];
   7.892      }
   7.893 @@ -782,7 +985,8 @@ hex2mem (buf, mem, count)
   7.894      {
   7.895          ch = hex (*buf++) << 4;
   7.896          ch = ch + hex (*buf++);
   7.897 -        set_char (mem++, ch);
   7.898 +        *mem = ch;
   7.899 +	mem++;
   7.900      }
   7.901      return (mem);
   7.902  }
   7.903 @@ -826,150 +1030,153 @@ hexToInt (char **ptr, int *intValue)
   7.904  /***********************************************************************/
   7.905  /***********************************************************************/
   7.906  
   7.907 +/* READ / WRITE MEMORY */
   7.908 +int pdb_change_page (u_char *buffer, int length,
   7.909 +		     unsigned long cr3, unsigned long addr, int rw);
   7.910 +int pdb_visit_memory (unsigned long addr, int length, unsigned char *data,
   7.911 +		      pdb_context_p ctx, pdb_generic_action action);
   7.912  
   7.913 -/*
   7.914 - * Add a breakpoint to the list of known breakpoints.
   7.915 - * For now there should only be two or three breakpoints so
   7.916 - * we use a simple linked list.  In the future, maybe a red-black tree?
   7.917 - */
   7.918 -struct pdb_breakpoint breakpoints;
   7.919 +int 
   7.920 +pdb_read_memory (unsigned long addr, int length, unsigned char *data,
   7.921 +		 pdb_context_p ctx)
   7.922 +{
   7.923 +    return pdb_visit_memory (addr, length, data, ctx, __PDB_GET);
   7.924 +}
   7.925  
   7.926 -void pdb_bkpt_add (unsigned long cr3, unsigned long address)
   7.927 +int
   7.928 +pdb_write_memory (unsigned long addr, int length, unsigned char *data,
   7.929 +		  pdb_context_p ctx)
   7.930  {
   7.931 -    struct pdb_breakpoint *bkpt = xmalloc(sizeof(*bkpt));
   7.932 -    bkpt->cr3 = cr3;
   7.933 -    bkpt->address = address;
   7.934 -    list_add(&bkpt->list, &breakpoints.list);
   7.935 +    return pdb_visit_memory (addr, length, data, ctx, __PDB_SET);
   7.936  }
   7.937  
   7.938  /*
   7.939 - * Check to see of the breakpoint is in the list of known breakpoints 
   7.940 - * Return 1 if it has been set, NULL otherwise.
   7.941 + * either read or write a block of memory 
   7.942   */
   7.943 -struct pdb_breakpoint* pdb_bkpt_search (unsigned long cr3, 
   7.944 -					unsigned long address)
   7.945 +
   7.946 +int
   7.947 +pdb_visit_memory (unsigned long addr, int length, unsigned char *data,
   7.948 +		  pdb_context_p ctx, pdb_generic_action action)
   7.949  {
   7.950 -    struct list_head *list_entry;
   7.951 -    struct pdb_breakpoint *bkpt;
   7.952 +    int return_value;
   7.953 +    pdb_invoke_args_t args;
   7.954 +
   7.955 +    pdb_page_fault_possible = 4;
   7.956 +    pdb_page_fault = 0;
   7.957 +
   7.958 +    args.context = ctx;
   7.959 +    args.address = addr;
   7.960 +    args.length = length;
   7.961 +    args.data = data;
   7.962  
   7.963 -    list_for_each(list_entry, &breakpoints.list)
   7.964 +    if (addr >= PAGE_OFFSET)                                          /* Xen */
   7.965 +    {
   7.966 +        args.action = (action == __PDB_GET) ? PDB_VISIT_PAGE_XEN_READ
   7.967 +                                            : PDB_VISIT_PAGE_XEN_WRITE;
   7.968 +    }
   7.969 +    else if (pdb_ctx.process != -1)                               /* Process */
   7.970      {
   7.971 -        bkpt = list_entry(list_entry, struct pdb_breakpoint, list);
   7.972 -	if ( bkpt->cr3 == cr3 && bkpt->address == address )
   7.973 -            return bkpt;
   7.974 +        args.action = (action == __PDB_GET) ? PDB_VISIT_PAGE_PROCESS_READ
   7.975 +                                            : PDB_VISIT_PAGE_PROCESS_WRITE;
   7.976 +    }
   7.977 +    else                                                           /* Domain */
   7.978 +    {
   7.979 +        args.action = (action == __PDB_GET) ? PDB_VISIT_PAGE_DOMAIN_READ
   7.980 +                                            : PDB_VISIT_PAGE_DOMAIN_WRITE;
   7.981      }
   7.982  
   7.983 -    return NULL;
   7.984 -}
   7.985 -
   7.986 -/*
   7.987 - * Remove a breakpoint to the list of known breakpoints.
   7.988 - * Return 1 if the element was not found, otherwise 0.
   7.989 - */
   7.990 -int pdb_bkpt_remove (unsigned long cr3, unsigned long address)
   7.991 -{
   7.992 -    struct list_head *list_entry;
   7.993 -    struct pdb_breakpoint *bkpt;
   7.994 +    return_value = pdb_invoke (pdb_visit_page, &args);
   7.995  
   7.996 -    list_for_each(list_entry, &breakpoints.list)
   7.997 +    pdb_page_fault_possible = 0;
   7.998 +    if (pdb_page_fault || return_value < 0)
   7.999      {
  7.1000 -        bkpt = list_entry(list_entry, struct pdb_breakpoint, list);
  7.1001 -	if ( bkpt->cr3 == cr3 && bkpt->address == address )
  7.1002 -	{
  7.1003 -            list_del(&bkpt->list);
  7.1004 -            xfree(bkpt);
  7.1005 -            return 0;
  7.1006 -	}
  7.1007 +        strcpy (pdb_out_buffer, "E03");
  7.1008      }
  7.1009 -
  7.1010 -    return 1;
  7.1011 +  
  7.1012 +    return return_value;
  7.1013  }
  7.1014  
  7.1015  /*
  7.1016 - * Check to see if a memory write is really gdb setting a breakpoint
  7.1017 + * either read or write a single page
  7.1018   */
  7.1019 -void pdb_bkpt_check (u_char *buffer, int length,
  7.1020 -		     unsigned long cr3, unsigned long addr)
  7.1021 +
  7.1022 +int 
  7.1023 +pdb_visit_page (int action, unsigned long addr, int length, 
  7.1024 +		pdb_context_p ctx, int offset, void *data)
  7.1025  {
  7.1026 -    if (length == 1 && buffer[0] == 'c' && buffer[1] == 'c')
  7.1027 -    {
  7.1028 -        /* inserting a new breakpoint */
  7.1029 -        pdb_bkpt_add(cr3, addr);
  7.1030 -        TRC(printk("pdb breakpoint detected at 0x%lx:0x%lx\n", cr3, addr));
  7.1031 -    }
  7.1032 -    else if ( pdb_bkpt_remove(cr3, addr) == 0 )
  7.1033 -    {
  7.1034 -        /* removing a breakpoint */
  7.1035 -        TRC(printk("pdb breakpoint cleared at 0x%lx:0x%lx\n", cr3, addr));
  7.1036 -    }
  7.1037 +  int rval;
  7.1038 +  
  7.1039 +  PDBTRC(2,printk ("visit: %s [0x%08lx:%x] 0x%x (0x%p)\n",
  7.1040 +		   pdb_visit_page_action_s[action], 
  7.1041 +		   addr, length, offset, data));
  7.1042 +
  7.1043 +  switch (action)
  7.1044 +  {
  7.1045 +  case PDB_VISIT_PAGE_XEN_READ :
  7.1046 +  {
  7.1047 +      memcpy ((void *) data, (void *) addr, length);
  7.1048 +      rval = length;;
  7.1049 +      break;
  7.1050 +  }
  7.1051 +  case PDB_VISIT_PAGE_XEN_WRITE :
  7.1052 +  {
  7.1053 +      memcpy ((void *) addr, (void *) data, length);
  7.1054 +      rval = length;
  7.1055 +      break;
  7.1056 +  }
  7.1057 +  case PDB_VISIT_PAGE_DOMAIN_READ :
  7.1058 +  case PDB_VISIT_PAGE_DOMAIN_WRITE :
  7.1059 +  {
  7.1060 +      rval = pdb_change_page (data, length, ctx->ptbr, addr,
  7.1061 +               (action == PDB_VISIT_PAGE_DOMAIN_READ) ? __PDB_GET : __PDB_SET);
  7.1062 +      break;
  7.1063 +  }
  7.1064 +  case PDB_VISIT_PAGE_PROCESS_READ :
  7.1065 +  case PDB_VISIT_PAGE_PROCESS_WRITE :
  7.1066 +  {
  7.1067 +      u_char pdb_linux_visit_page(int pid, unsigned long cr3, unsigned long addr, int length, unsigned char *buffer, int action);
  7.1068 +
  7.1069 +      rval = pdb_linux_visit_page (ctx->process, ctx->ptbr, addr, length, data,
  7.1070 +              (action == PDB_VISIT_PAGE_PROCESS_READ) ? __PDB_GET : __PDB_SET);
  7.1071 +      break;
  7.1072 +  }
  7.1073 +  default :
  7.1074 +  {
  7.1075 +      printk ("pdb error: unknown visit page action [%d]\n", action);
  7.1076 +      break;
  7.1077 +  }
  7.1078 +  }
  7.1079 +
  7.1080 +  return 1;
  7.1081  }
  7.1082  
  7.1083 -/***********************************************************************/
  7.1084 -
  7.1085 -int pdb_change_values(u_char *buffer, int length,
  7.1086 -		      unsigned long cr3, unsigned long addr, int rw);
  7.1087 -int pdb_change_values_one_page(u_char *buffer, int length,
  7.1088 -			       unsigned long cr3, unsigned long addr, int rw);
  7.1089 -
  7.1090 -#define __PDB_GET_VAL 1
  7.1091 -#define __PDB_SET_VAL 2
  7.1092 +/**************************************/
  7.1093 +/**************************************/
  7.1094  
  7.1095 -/*
  7.1096 - * Set memory in a domain's address space
  7.1097 - * Set "length" bytes at "address" from "domain" to the values in "buffer".
  7.1098 - * Return the number of bytes set, 0 if there was a problem.
  7.1099 - */
  7.1100 +int
  7.1101 +pdb_read_page(u_char *buffer, int length,
  7.1102 +		unsigned long cr3, unsigned long addr)
  7.1103 +{
  7.1104 +    return pdb_change_page(buffer, length, cr3, addr, __PDB_GET);
  7.1105 +}
  7.1106  
  7.1107 -int pdb_set_values(u_char *buffer, int length,
  7.1108 -		   unsigned long cr3, unsigned long addr)
  7.1109 +int
  7.1110 +pdb_write_page(u_char *buffer, int length,
  7.1111 +	       unsigned long cr3, unsigned long addr)
  7.1112  {
  7.1113 -    int count = pdb_change_values(buffer, length, cr3, addr, __PDB_SET_VAL);
  7.1114 -    return count;
  7.1115 +    return pdb_change_page(buffer, length, cr3, addr, __PDB_SET);
  7.1116  }
  7.1117  
  7.1118  /*
  7.1119 - * Read memory from a domain's address space.
  7.1120 - * Fetch "length" bytes at "address" from "domain" into "buffer".
  7.1121 - * Return the number of bytes read, 0 if there was a problem.
  7.1122 - */
  7.1123 -
  7.1124 -int pdb_get_values(u_char *buffer, int length,
  7.1125 -		   unsigned long cr3, unsigned long addr)
  7.1126 -{
  7.1127 -  return pdb_change_values(buffer, length, cr3, addr, __PDB_GET_VAL);
  7.1128 -}
  7.1129 -
  7.1130 -/*
  7.1131 - * Read or write memory in an address space
  7.1132 - */
  7.1133 -int pdb_change_values(u_char *buffer, int length,
  7.1134 -		      unsigned long cr3, unsigned long addr, int rw)
  7.1135 -{
  7.1136 -    int remaining;                /* number of bytes to touch past this page */
  7.1137 -    int bytes = 0;
  7.1138 -
  7.1139 -    while ( (remaining = (addr + length - 1) - (addr | (PAGE_SIZE - 1))) > 0)
  7.1140 -    {
  7.1141 -        bytes += pdb_change_values_one_page(buffer, length - remaining, 
  7.1142 -					    cr3, addr, rw);
  7.1143 -	buffer = buffer + (2 * (length - remaining));
  7.1144 -	length = remaining;
  7.1145 -	addr = (addr | (PAGE_SIZE - 1)) + 1;
  7.1146 -    }
  7.1147 -
  7.1148 -    bytes += pdb_change_values_one_page(buffer, length, cr3, addr, rw);
  7.1149 -    return bytes;
  7.1150 -}
  7.1151 -
  7.1152 -/*
  7.1153 - * Change memory in a process' address space in one page
  7.1154 + * Change memory in one page of an address space.
  7.1155   * Read or write "length" bytes at "address" into/from "buffer"
  7.1156   * from the virtual address space referenced by "cr3".
  7.1157   * Return the number of bytes read, 0 if there was a problem.
  7.1158   */
  7.1159  
  7.1160 -int pdb_change_values_one_page(u_char *buffer, int length,
  7.1161 -			       unsigned long cr3, unsigned long addr, int rw)
  7.1162 +int
  7.1163 +pdb_change_page(u_char *buffer, int length,
  7.1164 +		unsigned long cr3, unsigned long addr, int rw)
  7.1165  {
  7.1166      l2_pgentry_t* l2_table = NULL;                         /* page directory */
  7.1167      l1_pgentry_t* l1_table = NULL;                             /* page table */
  7.1168 @@ -980,10 +1187,11 @@ int pdb_change_values_one_page(u_char *b
  7.1169      l2_table += l2_table_offset(addr);
  7.1170      if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 
  7.1171      {
  7.1172 -	if (pdb_page_fault_possible == 1)
  7.1173 +	if (pdb_page_fault_possible)
  7.1174  	{
  7.1175  	    pdb_page_fault = 1;
  7.1176 -	    TRC(printk("pdb: L2 error (0x%lx)\n", addr));
  7.1177 +	    PDBTRC2(1,printk("pdb: expected L2 error %d (0x%lx)\n", 
  7.1178 +			     pdb_page_fault_possible, addr));
  7.1179  	}
  7.1180  	else
  7.1181  	{
  7.1182 @@ -1021,7 +1229,7 @@ int pdb_change_values_one_page(u_char *b
  7.1183  	    if (pdb_page_fault_possible == 1)
  7.1184  	    {
  7.1185  	        pdb_page_fault = 1;
  7.1186 -		TRC(printk ("pdb: L1 error (0x%lx)\n", addr));
  7.1187 +		PDBTRC(1,printk ("pdb: L1 error (0x%lx)\n", addr));
  7.1188  	    }
  7.1189  	    else
  7.1190  	    {
  7.1191 @@ -1038,18 +1246,25 @@ int pdb_change_values_one_page(u_char *b
  7.1192  
  7.1193      switch (rw)
  7.1194      {
  7.1195 -    case __PDB_GET_VAL:                                              /* read */
  7.1196 +    case __PDB_GET:                                                  /* read */
  7.1197 +    {
  7.1198          memcpy (buffer, page, length);
  7.1199  	bytes = length;
  7.1200 +
  7.1201 +	break;
  7.1202 +    }
  7.1203 +    case __PDB_SET:                                                 /* write */
  7.1204 +    {
  7.1205 +        memcpy (page, buffer, length);
  7.1206 +	bytes = length;
  7.1207  	break;
  7.1208 -    case __PDB_SET_VAL:                                             /* write */
  7.1209 -        hex2mem (buffer, page, length);
  7.1210 -	bytes = length;
  7.1211 -	break;
  7.1212 +    }
  7.1213      default:                                                      /* unknown */
  7.1214 -        printk ("error: unknown RW flag: %d\n", rw);
  7.1215 +    {
  7.1216 +        printk ("pdb error: unknown RW flag: %d\n", rw);
  7.1217  	return 0;
  7.1218      }
  7.1219 +    }
  7.1220  
  7.1221      unmap_domain_mem((void *)page); 
  7.1222  exit1:
  7.1223 @@ -1061,9 +1276,149 @@ exit2:
  7.1224      return bytes;
  7.1225  }
  7.1226  
  7.1227 +
  7.1228 +/***********************************************************************/
  7.1229 +/***********************************************************************/
  7.1230 +
  7.1231 +/* BREAKPOINTS */
  7.1232 +
  7.1233 +int
  7.1234 +pdb_set_breakpoint (pdb_bwcpoint_p bwc)
  7.1235 +{
  7.1236 +    pdb_read_memory (bwc->address, pdb_x86_bkpt_length, 
  7.1237 +		     &bwc->original, &bwc->context);
  7.1238 +    pdb_write_memory (bwc->address, pdb_x86_bkpt_length, 
  7.1239 +		      &pdb_x86_bkpt, &bwc->context);
  7.1240 +
  7.1241 +    pdb_bwc_list_add (bwc);
  7.1242 +
  7.1243 +    return 0;
  7.1244 +}
  7.1245 +
  7.1246 +int
  7.1247 +pdb_clear_breakpoint (unsigned long address, pdb_context_p ctx)
  7.1248 +{
  7.1249 +    pdb_bwcpoint_p bwc = pdb_bwc_list_search(address, pdb_x86_bkpt_length,
  7.1250 +					     ctx);
  7.1251 +
  7.1252 +    if (bwc == 0)
  7.1253 +    {
  7.1254 +        printk("pdb error: unknown breakpoint 0x%lx\n", address);
  7.1255 +	return 0;
  7.1256 +    }
  7.1257 +
  7.1258 +    pdb_write_memory (address, pdb_x86_bkpt_length, &bwc->original, ctx);
  7.1259 +    pdb_bwc_list_remove (bwc);
  7.1260 +    xfree (bwc);
  7.1261 +
  7.1262 +    return 0;
  7.1263 +}
  7.1264 +
  7.1265 +/***********************************************************************/
  7.1266  /***********************************************************************/
  7.1267  
  7.1268 -void breakpoint(void);
  7.1269 +/* WATCHPOINTS */
  7.1270 +
  7.1271 +int pdb_process_watchpoint (pdb_bwcpoint_p bwc, pdb_generic_action action);
  7.1272 +
  7.1273 +int
  7.1274 +pdb_set_watchpoint (pdb_bwcpoint_p bwc)
  7.1275 +{
  7.1276 +    return pdb_process_watchpoint (bwc, __PDB_SET);
  7.1277 +}
  7.1278 +
  7.1279 +int
  7.1280 +pdb_clear_watchpoint (pdb_bwcpoint_p bwc)
  7.1281 +{
  7.1282 +    return pdb_process_watchpoint (bwc, __PDB_CLEAR);
  7.1283 +}
  7.1284 +
  7.1285 +/* set or clear watchpoint */
  7.1286 +int
  7.1287 +pdb_process_watchpoint (pdb_bwcpoint_p bwc, pdb_generic_action action)
  7.1288 +{
  7.1289 +    int return_value;
  7.1290 +    pdb_invoke_args_t args;
  7.1291 +
  7.1292 +    args.context = &bwc->context;
  7.1293 +    args.address = bwc->address;
  7.1294 +    args.length = bwc->length;
  7.1295 +    args.data = bwc;
  7.1296 +    switch (bwc->type)
  7.1297 +    {
  7.1298 +    case PDB_WP_WRITE :
  7.1299 +    {
  7.1300 +        args.action = (action == __PDB_SET) ? PDB_BWC_PAGE_WRITE_SET 
  7.1301 +                                            : PDB_BWC_PAGE_WRITE_CLEAR;
  7.1302 +	break;       
  7.1303 +    }
  7.1304 +    case PDB_WP_READ :
  7.1305 +    {
  7.1306 +        args.action = (action == __PDB_SET) ? PDB_BWC_PAGE_READ_SET 
  7.1307 +                                            : PDB_BWC_PAGE_READ_CLEAR;
  7.1308 +	break;       
  7.1309 +    }
  7.1310 +    case PDB_WP_ACCESS :
  7.1311 +    {
  7.1312 +        args.action = (action == __PDB_SET) ? PDB_BWC_PAGE_ACCESS_SET 
  7.1313 +                                            : PDB_BWC_PAGE_ACCESS_CLEAR;
  7.1314 +	break;       
  7.1315 +    }
  7.1316 +    default :
  7.1317 +    {
  7.1318 +        printk ("pdb error: incorrect watchpoint type [%d][%s]",
  7.1319 +		bwc->type, pdb_bwcpoint_type_s[bwc->type]);
  7.1320 +        break;
  7.1321 +    }
  7.1322 +    }
  7.1323 +
  7.1324 +    return_value = pdb_invoke (pdb_bwc_page, &args);
  7.1325 +
  7.1326 +    if (return_value < 0)
  7.1327 +    {
  7.1328 +         strcpy (pdb_out_buffer, "E03");
  7.1329 +    }
  7.1330 +
  7.1331 +    return return_value;
  7.1332 +}
  7.1333 +
  7.1334 +/*
  7.1335 + * set or clear watchpoint for a single page 
  7.1336 + */
  7.1337 +
  7.1338 +int 
  7.1339 +pdb_bwc_page (int action, unsigned long addr, int length, 
  7.1340 +	      pdb_context_p ctx, int offset, void *data)
  7.1341 +{
  7.1342 +    int rval = 0;
  7.1343 +
  7.1344 +    printk ("bwc: %s [0x%08lx:%x] 0x%x (0x%p)\n",
  7.1345 +	    pdb_bwc_page_action_s[action], addr, length, offset, data);
  7.1346 +
  7.1347 +    switch (action)
  7.1348 +    {
  7.1349 +    case PDB_BWC_PAGE_ACCESS_SET :
  7.1350 +    case PDB_BWC_PAGE_ACCESS_CLEAR : 
  7.1351 +    case PDB_BWC_PAGE_WRITE_SET :
  7.1352 +    case PDB_BWC_PAGE_WRITE_CLEAR :
  7.1353 +    case PDB_BWC_PAGE_READ_SET :
  7.1354 +    case PDB_BWC_PAGE_READ_CLEAR :
  7.1355 +    {
  7.1356 +        printk ("fill in the blank [%s:%d]\n", __FILE__, __LINE__);
  7.1357 +        break;
  7.1358 +    }
  7.1359 +    default :
  7.1360 +    {
  7.1361 +        printk ("pdb error: unknown bwc page action [%d]\n", action);
  7.1362 +	break;
  7.1363 +    }
  7.1364 +    }
  7.1365 +
  7.1366 +    return rval;
  7.1367 +}
  7.1368 +
  7.1369 +/***********************************************************************/
  7.1370 +/***********************************************************************/
  7.1371  
  7.1372  /* send the packet in buffer.  */
  7.1373  void pdb_put_packet (unsigned char *buffer, int ack)
  7.1374 @@ -1114,7 +1469,7 @@ void pdb_get_packet(char *buffer)
  7.1375  	count = 0;
  7.1376  	checksum = 0;
  7.1377  
  7.1378 -	while (count < BUFMAX)
  7.1379 +	while (count < PDB_BUFMAX)
  7.1380  	{
  7.1381  	    ch = pdb_get_char();
  7.1382  	    if (ch  == '#') break;
  7.1383 @@ -1132,10 +1487,11 @@ void pdb_get_packet(char *buffer)
  7.1384  	    if (xmitcsum == checksum)
  7.1385  	    {
  7.1386  	        pdb_put_char('+');
  7.1387 +
  7.1388 +#ifdef GDB_50_SUPPORT
  7.1389  		if (buffer[2] == ':')
  7.1390 -		{
  7.1391 -		    printk ("pdb: obsolete gdb packet (sequence ID)\n");
  7.1392 -		}
  7.1393 +		  { printk ("pdb: obsolete gdb packet (sequence ID)\n"); }
  7.1394 +#endif
  7.1395  	    }
  7.1396  	    else
  7.1397  	    {
  7.1398 @@ -1157,22 +1513,34 @@ int pdb_handle_exception(int exceptionVe
  7.1399  			 struct pt_regs *xen_regs)
  7.1400  {
  7.1401      int signal = 0;
  7.1402 -    struct pdb_breakpoint* bkpt;
  7.1403 +    struct pdb_bwcpoint* bkpt;
  7.1404      int watchdog_save;
  7.1405      unsigned long cr3;
  7.1406  
  7.1407      __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : );
  7.1408  
  7.1409 +PDBTRC(4,printk("pdb handle exception\n"));
  7.1410 +PDBTRC(4,printk("    cr3: 0x%lx\n", cr3));
  7.1411 +PDBTRC(4,printk("    eip: 0x%lx\n", xen_regs->eip));
  7.1412 +PDBTRC(4,printk("    except vector: 0x%x\n", exceptionVector));
  7.1413 +PDBTRC(4,printk("    xcs: 0x%x\n", xen_regs->xcs));
  7.1414 +PDBTRC(4,printk("    sys call next addr: 0x%lx\n", pdb_system_call_next_addr));
  7.1415 +PDBTRC(4,printk("    stepping: 0x%x\n", pdb_stepping));
  7.1416 +PDBTRC(4,printk("    system_call: 0x%x\n", pdb_system_call));
  7.1417 +
  7.1418      /* If the exception is an int3 from user space then pdb is only
  7.1419         interested if it re-wrote an instruction set the breakpoint.
  7.1420         This occurs when leaving a system call from a domain.
  7.1421      */
  7.1422 -    if ( exceptionVector == 3 &&
  7.1423 +    bkpt = pdb_bwcpoint_search(cr3, xen_regs->eip - 1);
  7.1424 +    if ( bkpt == NULL &&
  7.1425 +         exceptionVector == 3 &&
  7.1426  	 (xen_regs->xcs & 3) == 3 && 
  7.1427  	 xen_regs->eip != pdb_system_call_next_addr + 1)
  7.1428      {
  7.1429 -        TRC(printf("pdb: user bkpt (0x%x) at 0x%x:0x%lx:0x%lx\n", 
  7.1430 -		   exceptionVector, xen_regs->xcs & 3, cr3, xen_regs->eip));
  7.1431 +        PDBTRC(1,printk("pdb: user bkpt (0x%x) at 0x%x:0x%lx:0x%lx 0x%lx\n", 
  7.1432 +			exceptionVector, xen_regs->xcs & 3, cr3, 
  7.1433 +			xen_regs->eip, pdb_system_call_next_addr));
  7.1434  	return 1;
  7.1435      }
  7.1436  
  7.1437 @@ -1182,7 +1550,6 @@ int pdb_handle_exception(int exceptionVe
  7.1438       * the user didn't press the magic debug key, 
  7.1439       * then we don't handle the exception.
  7.1440       */
  7.1441 -    bkpt = pdb_bkpt_search(cr3, xen_regs->eip - 1);
  7.1442      if ( (bkpt == NULL) &&
  7.1443           !pdb_stepping && 
  7.1444  	 !pdb_system_call &&
  7.1445 @@ -1190,8 +1557,8 @@ int pdb_handle_exception(int exceptionVe
  7.1446  	 (exceptionVector != KEYPRESS_EXCEPTION) &&
  7.1447  	 xen_regs->eip < 0xc0000000)  /* Linux-specific for now! */
  7.1448      {
  7.1449 -        TRC(printf("pdb: user bkpt (0x%x) at 0x%lx:0x%lx\n", 
  7.1450 -		   exceptionVector, cr3, xen_regs->eip));
  7.1451 +        PDBTRC(1, printk("pdb: user bkpt (0x%x) at 0x%lx:0x%lx\n", 
  7.1452 +			 exceptionVector, cr3, xen_regs->eip));
  7.1453  	return 1;
  7.1454      }
  7.1455  
  7.1456 @@ -1222,28 +1589,23 @@ int pdb_handle_exception(int exceptionVe
  7.1457  	}
  7.1458      }
  7.1459  
  7.1460 -    if ( exceptionVector == BREAKPT_EXCEPTION && bkpt != NULL)
  7.1461 -    {
  7.1462 -        /* Executed Int3: replace breakpoint byte with real program byte. */
  7.1463 -        xen_regs->eip--;
  7.1464 -    }
  7.1465 -
  7.1466      /* returning to user space after a system call */
  7.1467      if ( xen_regs->eip == pdb_system_call_next_addr + 1)
  7.1468      {
  7.1469 -        u_char instr[2];                      /* REALLY REALLY REALLY STUPID */
  7.1470 -
  7.1471 -	mem2hex (&pdb_system_call_leave_instr, instr, sizeof(instr)); 
  7.1472 -
  7.1473 -	pdb_linux_set_values (instr, 1, pdb_system_call_next_addr,
  7.1474 -			      pdb_ctx.process, pdb_ctx.ptbr);
  7.1475 -
  7.1476 +        /* this is always in a process context */
  7.1477 +	 /*
  7.1478 +        pdb_write_memory (pdb_system_call_next_addr,
  7.1479 +			  sizeof(pdb_system_call_leave_instr),
  7.1480 +			  &pdb_system_call_leave_instr, &pdb_ctx);
  7.1481 +	 */
  7.1482 +        printk ("RETURNING TO USER SPACE AFTER SYSTEM CALL\n");
  7.1483 +	pdb_bwc_print_list();
  7.1484 +        pdb_clear_breakpoint(pdb_system_call_next_addr, &pdb_ctx);
  7.1485 +	pdb_bwc_print_list();
  7.1486 + 
  7.1487  	pdb_system_call_next_addr = 0;
  7.1488  	pdb_system_call_leave_instr = 0;
  7.1489  
  7.1490 -	/* manually rewind eip */
  7.1491 -	xen_regs->eip--;
  7.1492 -
  7.1493  	/* if the user doesn't care about breaking when returning 
  7.1494  	   to user space after a system call then we'll just ignore 
  7.1495  	   the exception */
  7.1496 @@ -1253,6 +1615,13 @@ int pdb_handle_exception(int exceptionVe
  7.1497  	}
  7.1498      }
  7.1499  
  7.1500 +
  7.1501 +    if ( exceptionVector == BREAKPT_EXCEPTION && bkpt != NULL)
  7.1502 +    {
  7.1503 +        /* Executed Int3: replace breakpoint byte with real program byte. */
  7.1504 +        xen_regs->eip--;
  7.1505 +    }
  7.1506 +
  7.1507      /* Generate a signal for GDB. */
  7.1508      switch ( exceptionVector )
  7.1509      {
  7.1510 @@ -1303,9 +1672,6 @@ void initialize_pdb()
  7.1511  {
  7.1512      extern char opt_pdb[];
  7.1513  
  7.1514 -    /* Certain state must be initialised even when PDB will not be used. */
  7.1515 -    memset((void *) &breakpoints, 0, sizeof(breakpoints));
  7.1516 -    INIT_LIST_HEAD(&breakpoints.list);
  7.1517      pdb_stepping = 0;
  7.1518  
  7.1519      if ( strcmp(opt_pdb, "none") == 0 )
  7.1520 @@ -1335,8 +1701,6 @@ void initialize_pdb()
  7.1521      pdb_initialized = 1;
  7.1522  }
  7.1523  
  7.1524 -void breakpoint(void)
  7.1525 -{
  7.1526 -    if ( pdb_initialized )
  7.1527 -        asm("int $3");
  7.1528 -}
  7.1529 +/***********************************************************************/
  7.1530 +/***********************************************************************/
  7.1531 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen/arch/x86/x86_32/xdb_trap.S	Fri Aug 06 12:20:20 2004 +0000
     8.3 @@ -0,0 +1,35 @@
     8.4 +.global trap_to_xendbg
     8.5 +.extern __trap_to_xendbg
     8.6 +	
     8.7 +#define SAVE_ALL_NOSEGREGS \
     8.8 +	pushw $0;  \
     8.9 +        pushw %gs; \
    8.10 +	pushw $0;  \
    8.11 +        pushw %fs; \
    8.12 +	pushw $0;  \
    8.13 +        pushw %es; \
    8.14 +	pushw $0;  \
    8.15 +        pushw %ds; \
    8.16 +        pushl %eax; \
    8.17 +        pushl %ebp; \
    8.18 +        pushl %edi; \
    8.19 +        pushl %esi; \
    8.20 +        pushl %edx; \
    8.21 +        pushl %ecx; \
    8.22 +        pushl %ebx;
    8.23 +
    8.24 +	// Save the register state and call __trap_to_xendbg 
    8.25 +trap_to_xendbg:
    8.26 +	pushw $0
    8.27 +	pushw %ss
    8.28 +	pushl %esp //We'll fix this up later, in __trap_to_xendbg, by adding 8
    8.29 +	pushf
    8.30 +	pushw $0
    8.31 +	pushw %cs
    8.32 +	pushl 16(%esp)
    8.33 +1:	pushl $0 		// Orig_eax
    8.34 +	SAVE_ALL_NOSEGREGS
    8.35 +	pushl %esp
    8.36 +	call __trap_to_xendbg
    8.37 +	add $72, %esp
    8.38 +	ret
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/arch/x86/xdb.c	Fri Aug 06 12:20:20 2004 +0000
     9.3 @@ -0,0 +1,355 @@
     9.4 +/* Simple hacked-up version of pdb for us in post-mortem debugging of
     9.5 +   Xen and domain 0. This should be a little cleaner, hopefully.  Note
     9.6 +   that we can't share a serial line with PDB. */
     9.7 +#include <xen/lib.h>
     9.8 +#include <asm/uaccess.h>
     9.9 +#include <xen/serial.h>
    9.10 +#include <asm/irq.h>
    9.11 +#include <xen/spinlock.h>
    9.12 +
    9.13 +/* Printk isn't particularly safe just after we've trapped to the
    9.14 +   debugger. so avoid it. */
    9.15 +#define dbg_printk(...)
    9.16 +
    9.17 +struct xendbg_context {
    9.18 +	int serhnd;
    9.19 +	u8 reply_csum;
    9.20 +	int currently_attached:1;
    9.21 +};
    9.22 +
    9.23 +static void
    9.24 +xendbg_put_char(u8 data, struct xendbg_context *ctx)
    9.25 +{
    9.26 +	ctx->reply_csum += data;
    9.27 +	serial_putc(ctx->serhnd, data);
    9.28 +}
    9.29 +
    9.30 +static u8
    9.31 +xendbg_get_char(struct xendbg_context *ctx)
    9.32 +{
    9.33 +	u8 ch;
    9.34 +	extern unsigned char __serial_getc(int handle);
    9.35 +	ch = __serial_getc(ctx->serhnd);
    9.36 +	return ch;
    9.37 +}
    9.38 +
    9.39 +static int
    9.40 +hex_char_val(unsigned char c)
    9.41 +{
    9.42 +	if (c >= '0' && c <= '9')
    9.43 +		return c - '0';
    9.44 +	else if (c >= 'a' && c <= 'f')
    9.45 +		return c - 'a' + 10;
    9.46 +	else if (c >= 'A' && c <= 'F')
    9.47 +		return c - 'A' + 10;
    9.48 +	else
    9.49 +		BUG();
    9.50 +	return -1;
    9.51 +}
    9.52 +
    9.53 +/* Receive a command.  Returns -1 on csum error, 0 otherwise. */
    9.54 +/* Does not acknowledge. */
    9.55 +static int
    9.56 +attempt_receive_packet(char *recv_buf, struct xendbg_context *ctx)
    9.57 +{
    9.58 +	int count;
    9.59 +	u8 csum;
    9.60 +	u8 received_csum;
    9.61 +	u8 ch;
    9.62 +
    9.63 +	/* Skip over everything up to the first '$' */
    9.64 +	while ((ch = xendbg_get_char(ctx)) != '$')
    9.65 +		;
    9.66 +	csum = 0;
    9.67 +	for (count = 0; count < 4096; count++) {
    9.68 +		ch = xendbg_get_char(ctx);
    9.69 +		if (ch == '#')
    9.70 +			break;
    9.71 +		recv_buf[count] = ch;
    9.72 +		csum += ch;
    9.73 +	}
    9.74 +	if (count == 4096) {
    9.75 +		dbg_printk("WARNING: GDB sent a stupidly big packet.\n");
    9.76 +		return -1;
    9.77 +	}
    9.78 +	recv_buf[count] = 0;
    9.79 +	received_csum = hex_char_val(xendbg_get_char(ctx)) * 16 +
    9.80 +		hex_char_val(xendbg_get_char(ctx));
    9.81 +	if (received_csum == csum) {
    9.82 +		return 0;
    9.83 +	} else {
    9.84 +		return -1;
    9.85 +	}
    9.86 +}
    9.87 +
    9.88 +/* Send a string of bytes to the debugger. */
    9.89 +static void
    9.90 +xendbg_send(const char *buf, int count, struct xendbg_context *ctx)
    9.91 +{
    9.92 +	int x;
    9.93 +	for (x = 0; x < count; x++)
    9.94 +		xendbg_put_char(buf[x], ctx);
    9.95 +}
    9.96 +
    9.97 +/* Receive a command, discarding up to ten packets with csum
    9.98 + * errors.  Acknowledges all received packets. */
    9.99 +static int
   9.100 +receive_command(char *recv_buf, struct xendbg_context *ctx)
   9.101 +{
   9.102 +	int r;
   9.103 +	int count;
   9.104 +
   9.105 +	count = 0;
   9.106 +	do {
   9.107 +		r = attempt_receive_packet(recv_buf, ctx);
   9.108 +		if (r < 0)
   9.109 +			xendbg_put_char('-', ctx);
   9.110 +		else
   9.111 +			xendbg_put_char('+', ctx);
   9.112 +		count++;
   9.113 +	} while (r < 0 && count < 10);
   9.114 +	return r;
   9.115 +}
   9.116 +
   9.117 +static void
   9.118 +xendbg_start_reply(struct xendbg_context *ctx)
   9.119 +{
   9.120 +	xendbg_put_char('$', ctx);
   9.121 +	ctx->reply_csum = 0;
   9.122 +}
   9.123 +
   9.124 +/* Return 0 if the reply was successfully received, !0 otherwise. */
   9.125 +static int
   9.126 +xendbg_finish_reply(struct xendbg_context *ctx)
   9.127 +{
   9.128 +	char ch;
   9.129 +	char buf[3];
   9.130 +
   9.131 +	sprintf(buf, "%.02x\n", ctx->reply_csum);
   9.132 +
   9.133 +	xendbg_put_char('#', ctx);
   9.134 +	xendbg_send(buf, 2, ctx);
   9.135 +
   9.136 +	ch = xendbg_get_char(ctx);
   9.137 +	if (ch == '+')
   9.138 +		return 0;
   9.139 +	else
   9.140 +		return 1;
   9.141 +}
   9.142 +
   9.143 +/* Swap the order of the bytes in a work. */
   9.144 +static inline unsigned
   9.145 +bswab32(unsigned val)
   9.146 +{
   9.147 +	return (((val >> 0) & 0xff) << 24) |
   9.148 +		(((val >> 8) & 0xff) << 16) |
   9.149 +		(((val >> 16) & 0xff) << 8) |
   9.150 +		(((val >> 24) & 0xff) << 0);
   9.151 +}
   9.152 +
   9.153 +static int
   9.154 +handle_memory_read_command(unsigned long addr, unsigned long length,
   9.155 +			   struct xendbg_context *ctx)
   9.156 +{
   9.157 +	int x;
   9.158 +	unsigned char val;
   9.159 +	int r;
   9.160 +	unsigned old_s_limit;
   9.161 +	char buf[2];
   9.162 +
   9.163 +	dbg_printk("Memory read starting at %lx, length %lx.\n", addr,
   9.164 +		   length);
   9.165 +	old_s_limit = current->addr_limit.seg;
   9.166 +	current->addr_limit.seg = ~0;
   9.167 +	xendbg_start_reply(ctx);
   9.168 +	for (x = 0; x < length; x++) {
   9.169 +		r = copy_from_user(&val, (void *)(addr + x), 1);
   9.170 +		if (r != 0) {
   9.171 +			dbg_printk("Error reading from %lx.\n", addr + x);
   9.172 +			break;
   9.173 +		}
   9.174 +		sprintf(buf, "%.02x", val);
   9.175 +		xendbg_send(buf, 2, ctx);
   9.176 +	}
   9.177 +	if (x == 0)
   9.178 +		xendbg_send("E05", 3, ctx);
   9.179 +	dbg_printk("Read done.\n");
   9.180 +	current->addr_limit.seg = old_s_limit;
   9.181 +	return xendbg_finish_reply(ctx);
   9.182 +}
   9.183 +
   9.184 +static int
   9.185 +xendbg_send_reply(const char *buf, struct xendbg_context *ctx)
   9.186 +{
   9.187 +	xendbg_start_reply(ctx);
   9.188 +	xendbg_send(buf, strlen(buf), ctx);
   9.189 +	return xendbg_finish_reply(ctx);
   9.190 +}
   9.191 +
   9.192 +static int
   9.193 +handle_register_read_command(struct pt_regs *regs, struct xendbg_context *ctx)
   9.194 +{
   9.195 +	char buf[121];
   9.196 +
   9.197 +	sprintf(buf,
   9.198 +		"%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x",
   9.199 +		bswab32(regs->eax),
   9.200 +		bswab32(regs->ecx),
   9.201 +		bswab32(regs->edx),
   9.202 +		bswab32(regs->ebx),
   9.203 +		bswab32(regs->esp),
   9.204 +		bswab32(regs->ebp),
   9.205 +		bswab32(regs->esi),
   9.206 +		bswab32(regs->edi),
   9.207 +		bswab32(regs->eip),
   9.208 +		bswab32(regs->eflags),
   9.209 +		bswab32(regs->xcs),
   9.210 +		bswab32(regs->xss),
   9.211 +		bswab32(regs->xes),
   9.212 +		bswab32(regs->xfs),
   9.213 +		bswab32(regs->xgs));
   9.214 +	return xendbg_send_reply(buf, ctx);
   9.215 +}
   9.216 +
   9.217 +static int
   9.218 +process_command(char *received_packet, struct pt_regs *regs,
   9.219 +		struct xendbg_context *ctx)
   9.220 +{
   9.221 +	char *ptr;
   9.222 +	unsigned long addr, length;
   9.223 +	int retry;
   9.224 +	int counter;
   9.225 +	int resume = 0;
   9.226 +
   9.227 +	/* Repeat until gdb acks the reply */
   9.228 +	counter = 0;
   9.229 +	do {
   9.230 +		switch (received_packet[0]) {
   9.231 +		case 'g': /* Read registers */
   9.232 +			retry = handle_register_read_command(regs, ctx);
   9.233 +			break;
   9.234 +		case 'm': /* Read memory */
   9.235 +			addr = simple_strtoul(received_packet + 1, &ptr, 16);
   9.236 +			if (ptr == received_packet + 1 ||
   9.237 +			    ptr[0] != ',') {
   9.238 +				xendbg_send_reply("E03", ctx);
   9.239 +				return 0;
   9.240 +			}
   9.241 +			length = simple_strtoul(ptr + 1, &ptr, 16);
   9.242 +			if (ptr[0] != 0) {
   9.243 +				xendbg_send_reply("E04", ctx);
   9.244 +				return 0;
   9.245 +			}
   9.246 +			retry =
   9.247 +				handle_memory_read_command(addr,
   9.248 +							   length,
   9.249 +							   ctx);
   9.250 +			break;
   9.251 +		case 'G': /* Write registers */
   9.252 +		case 'M': /* Write memory */
   9.253 +			retry = xendbg_send_reply("E02", ctx);
   9.254 +			break;
   9.255 +		case 'D':
   9.256 +			resume = 1;
   9.257 +			ctx->currently_attached = 0;
   9.258 +			retry = xendbg_send_reply("", ctx);
   9.259 +			break;
   9.260 +		case 'c': /* Resume at current address */
   9.261 +			ctx->currently_attached = 1;
   9.262 +			resume = 1;
   9.263 +			retry = 0;
   9.264 +			break;
   9.265 +		case 'Z': /* We need to claim to support these or gdb
   9.266 +			     won't let you continue the process. */
   9.267 +		case 'z':
   9.268 +			retry = xendbg_send_reply("OK", ctx);
   9.269 +			break;
   9.270 +
   9.271 +		case 's': /* Single step */
   9.272 +		case '?':
   9.273 +			retry = xendbg_send_reply("S01", ctx);
   9.274 +			break;
   9.275 +		default:
   9.276 +			retry = xendbg_send_reply("", ctx);
   9.277 +			break;
   9.278 +		}
   9.279 +		counter++;
   9.280 +	} while (retry == 1 && counter < 10);
   9.281 +	if (retry) {
   9.282 +		dbg_printk("WARNING: gdb disappeared when we were trying to send it a reply.\n");
   9.283 +		return 1;
   9.284 +	}
   9.285 +	return resume;
   9.286 +}
   9.287 +
   9.288 +static struct xendbg_context
   9.289 +xdb_ctx = {
   9.290 +	serhnd : -1
   9.291 +};
   9.292 +
   9.293 +void
   9.294 +__trap_to_xendbg(struct pt_regs *regs)
   9.295 +{
   9.296 +	int resume = 0;
   9.297 +	int r;
   9.298 +	static int xendbg_running;
   9.299 +	static char recv_buf[4096];
   9.300 +	unsigned flags;
   9.301 +
   9.302 +	if (xdb_ctx.serhnd < 0) {
   9.303 +		dbg_printk("Debugger not ready yet.\n");
   9.304 +		return;
   9.305 +	}
   9.306 +	/* We rely on our caller to ensure we're only on one processor
   9.307 +	 * at a time... We should probably panic here, but given that
   9.308 +	 * we're a debugger we should probably be a little tolerant of
   9.309 +	 * things going wrong. */
   9.310 +	if (xendbg_running) {
   9.311 +		dbg_printk("WARNING WARNING WARNING: Avoiding recursive xendbg.\n");
   9.312 +		return;
   9.313 +	}
   9.314 +	xendbg_running = 1;
   9.315 +
   9.316 +	/* Shouldn't really do this, but otherwise we stop for no
   9.317 +	   obvious reason, which is Bad */
   9.318 +	printk("Waiting for GDB to attach to XenDBG\n");
   9.319 +
   9.320 +	/* Try to make things a little more stable by disabling
   9.321 +	   interrupts while we're here. */
   9.322 +	local_irq_save(flags);
   9.323 +
   9.324 +	/* If gdb is already attached, tell it we've stopped again. */
   9.325 +	if (xdb_ctx.currently_attached) {
   9.326 +		do {
   9.327 +			r = xendbg_send_reply("S01", &xdb_ctx);
   9.328 +		} while (r != 0);
   9.329 +	}
   9.330 +
   9.331 +	while (resume == 0) {
   9.332 +		r = receive_command(recv_buf, &xdb_ctx);
   9.333 +		if (r < 0) {
   9.334 +			dbg_printk("GDB disappeared, trying to resume Xen...\n");
   9.335 +			resume = 1;
   9.336 +		} else
   9.337 +			resume = process_command(recv_buf, regs, &xdb_ctx);
   9.338 +	}
   9.339 +	xendbg_running = 0;
   9.340 +	local_irq_restore(flags);
   9.341 +}
   9.342 +
   9.343 +void
   9.344 +initialize_xendbg(void)
   9.345 +{
   9.346 +	extern char opt_xendbg[];
   9.347 +
   9.348 +	if (!strcmp(opt_xendbg, "none"))
   9.349 +		return;
   9.350 +	xdb_ctx.serhnd = parse_serial_handle(opt_xendbg);
   9.351 +	if (xdb_ctx.serhnd == -1)
   9.352 +		panic("Can't parse %s as XDB serial info.\n", opt_xendbg);
   9.353 +
   9.354 +	/* Acknowledge any spurious GDB packets. */
   9.355 +	xendbg_put_char('+', &xdb_ctx);
   9.356 +
   9.357 +	printk("Xendbg initialised.\n");
   9.358 +}
    10.1 --- a/xen/common/debug-linux.c	Fri Aug 06 11:53:45 2004 +0000
    10.2 +++ b/xen/common/debug-linux.c	Fri Aug 06 12:20:20 2004 +0000
    10.3 @@ -45,7 +45,7 @@ static inline unsigned long machine_to_p
    10.4                                              unsigned long machine)
    10.5  {
    10.6    unsigned long phys;
    10.7 -  pdb_get_values((u_char *) &phys, sizeof(phys), cr3,
    10.8 +  pdb_read_page((u_char *) &phys, sizeof(phys), cr3,
    10.9  		 (unsigned long) machine_to_phys_mapping + 
   10.10                   (machine >> PAGE_SHIFT) * 4);
   10.11    phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
   10.12 @@ -75,20 +75,20 @@ unsigned long pdb_linux_pid_task_struct 
   10.13    unsigned long task_struct_pid;
   10.14  
   10.15    /* find the task_struct of the given process */
   10.16 -  pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
   10.17 +  pdb_read_page((u_char *) &task_struct_p, sizeof(task_struct_p),
   10.18  		 cr3, pdb_pidhash_addr + pid_hashfn(pid) * 4);
   10.19  
   10.20    /* find the correct task struct */
   10.21    while (task_struct_p != (unsigned long)NULL)
   10.22    {
   10.23 -    pdb_get_values((u_char *) &task_struct_pid, sizeof(task_struct_pid),
   10.24 +    pdb_read_page((u_char *) &task_struct_pid, sizeof(task_struct_pid),
   10.25  		   cr3, task_struct_p + task_struct_pid_offset);
   10.26      if (task_struct_pid == pid)
   10.27      {
   10.28        break;
   10.29      }
   10.30  
   10.31 -    pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
   10.32 +    pdb_read_page((u_char *) &task_struct_p, sizeof(task_struct_p),
   10.33  		   cr3, task_struct_p + task_struct_pidhash_next_offset);
   10.34    }
   10.35    if (task_struct_p == (unsigned long) NULL)
   10.36 @@ -116,96 +116,59 @@ unsigned long pdb_linux_pid_ptbr (unsign
   10.37    }
   10.38  
   10.39    /* get the mm_struct within the task_struct */
   10.40 -  pdb_get_values((u_char *) &mm_p, sizeof(mm_p),
   10.41 +  pdb_read_page((u_char *) &mm_p, sizeof(mm_p),
   10.42  		 cr3, task_struct_p + task_struct_mm_offset);
   10.43    /* get the page global directory (cr3) within the mm_struct */
   10.44 -  pdb_get_values((u_char *) &pgd, sizeof(pgd),
   10.45 +  pdb_read_page((u_char *) &pgd, sizeof(pgd),
   10.46  		 cr3, mm_p + mm_struct_pgd_offset);
   10.47  
   10.48    return pgd;
   10.49  }
   10.50  
   10.51  
   10.52 -
   10.53 -/* read a byte from a process 
   10.54 - *
   10.55 - * in: pid: process id
   10.56 - *     cr3: ptbr for the process' domain
   10.57 - *     addr: address to read
   10.58 - */
   10.59 -
   10.60 -u_char pdb_linux_get_value(int pid, unsigned long cr3, unsigned long addr)
   10.61 -{
   10.62 -  u_char result = 0;
   10.63 -  unsigned long pgd;
   10.64 -  unsigned long l2tab, page;
   10.65 -
   10.66 -  /* get the process' pgd */
   10.67 -  pgd = pdb_linux_pid_ptbr(cr3, pid);
   10.68 -
   10.69 -  /* get the l2 table entry */
   10.70 -  pdb_get_values((u_char *) &l2tab, sizeof(l2tab),
   10.71 -		 cr3, pgd + (addr >> PGDIR_SHIFT) * 4);
   10.72 -  l2tab = (unsigned long)__va(machine_to_phys(cr3, l2tab) & PAGE_MASK);
   10.73 +/* read / write values from one page */
   10.74  
   10.75 -  /* get the page table entry */
   10.76 -  pdb_get_values((u_char *) &page, sizeof(page),
   10.77 -		 cr3, l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4);
   10.78 -  page = (unsigned long)__va(machine_to_phys(cr3, page) & PAGE_MASK);
   10.79 -
   10.80 -  /* get the byte */
   10.81 -  pdb_get_values((u_char *) &result, sizeof(result),
   10.82 -		 cr3, page + (addr & ~PAGE_MASK));
   10.83 -
   10.84 -  return result;
   10.85 -}
   10.86 -
   10.87 -void pdb_linux_get_values(char *buffer, int length, unsigned long address,
   10.88 -			  int pid, unsigned long cr3)
   10.89 +u_char 
   10.90 +pdb_linux_visit_page(int pid, unsigned long cr3, unsigned long addr,
   10.91 +		     int length, unsigned char *buffer, int action)
   10.92  {
   10.93 -    int loop;
   10.94 -
   10.95 -    /* yes, this can be optimized... a lot */
   10.96 -    for (loop = 0; loop < length; loop++)
   10.97 -    {
   10.98 -        buffer[loop] = pdb_linux_get_value(pid, cr3, address + loop);
   10.99 -    }
  10.100 -}
  10.101 -
  10.102 - 
  10.103 -void pdb_linux_set_value(int pid, unsigned long cr3, unsigned long addr,
  10.104 -			 u_char *value)
  10.105 -{
  10.106 +    u_char result = 0;
  10.107      unsigned long pgd;
  10.108      unsigned long l2tab, page;
  10.109 - 
  10.110 +
  10.111      /* get the process' pgd */
  10.112      pgd = pdb_linux_pid_ptbr(cr3, pid);
  10.113 - 
  10.114 +
  10.115      /* get the l2 table entry */
  10.116 -    pdb_get_values((u_char *) &l2tab, sizeof(l2tab),
  10.117 -		   cr3, pgd + (addr >> PGDIR_SHIFT) * 4);
  10.118 +    pdb_read_page((u_char *) &l2tab, sizeof(l2tab),
  10.119 +		  cr3, pgd + (addr >> PGDIR_SHIFT) * 4);
  10.120      l2tab = (unsigned long)__va(machine_to_phys(cr3, l2tab) & PAGE_MASK);
  10.121 - 
  10.122 +
  10.123      /* get the page table entry */
  10.124 -    pdb_get_values((u_char *) &page, sizeof(page),
  10.125 -		   cr3, l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4);
  10.126 +    pdb_read_page((u_char *) &page, sizeof(page),
  10.127 +		  cr3, l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4);
  10.128      page = (unsigned long)__va(machine_to_phys(cr3, page) & PAGE_MASK);
  10.129 - 
  10.130 -    /* set the byte */
  10.131 -    pdb_set_values(value, sizeof(u_char), cr3, page + (addr & ~PAGE_MASK));
  10.132 -}
  10.133 - 
  10.134 -void pdb_linux_set_values(char *buffer, int length, unsigned long address,
  10.135 -			  int pid, unsigned long cr3)
  10.136 -{
  10.137 -    int loop;
  10.138 - 
  10.139 -    /* it's difficult to imagine a more inefficient algorithm */
  10.140 -    for (loop = 0; loop < length; loop++)
  10.141 +
  10.142 +    switch (action)
  10.143 +    {
  10.144 +    case __PDB_GET :
  10.145 +    {
  10.146 +        pdb_read_page(buffer, length, cr3, page + (addr & ~PAGE_MASK));
  10.147 +        break;
  10.148 +    }
  10.149 +    case __PDB_SET :
  10.150      {
  10.151 -        pdb_linux_set_value(pid, cr3, address + loop, &buffer[loop * 2]);
  10.152 +        pdb_write_page(buffer, length, cr3, page + (addr & ~PAGE_MASK));
  10.153 +        break;
  10.154      }
  10.155 +    default :
  10.156 +    {
  10.157 +        printk ("pdb error: linux_visit_page unknown action [%d]\n", action);
  10.158 +	break;
  10.159 +    }
  10.160 +    }
  10.161 +
  10.162 +    return result;
  10.163  }
  10.164  
  10.165  /**********************************************************************/
  10.166 @@ -232,18 +195,18 @@ int pdb_linux_process_list (unsigned lon
  10.167    int count = 0;
  10.168  
  10.169    /* task_p = init_task->next_task  */
  10.170 -  pdb_get_values((u_char *) &task_p, sizeof(task_p),
  10.171 +  pdb_read_page((u_char *) &task_p, sizeof(task_p),
  10.172  		 cr3, pdb_init_task_union_addr + task_struct_next_task_offset);
  10.173    
  10.174    while (task_p != pdb_init_task_union_addr)
  10.175    {
  10.176 -      pdb_get_values((u_char *) &pid, sizeof(pid),
  10.177 +      pdb_read_page((u_char *) &pid, sizeof(pid),
  10.178  		     cr3, task_p + task_struct_pid_offset);
  10.179  
  10.180        array[count % max] = pid;
  10.181        count++;
  10.182  
  10.183 -      pdb_get_values((u_char *) &next_p, sizeof(next_p),
  10.184 +      pdb_read_page((u_char *) &next_p, sizeof(next_p),
  10.185  		     cr3, task_p + task_struct_next_task_offset);
  10.186        task_p = next_p;
  10.187    }
  10.188 @@ -260,7 +223,7 @@ void pdb_linux_process_details (unsigned
  10.189  
  10.190    task_struct_p = pdb_linux_pid_task_struct(cr3, pid);
  10.191  
  10.192 -  pdb_get_values((u_char *) buffer, task_struct_comm_length,
  10.193 +  pdb_read_page((u_char *) buffer, task_struct_comm_length,
  10.194  		 cr3, task_struct_p + task_struct_comm_offset);
  10.195    return;
  10.196  }
    11.1 --- a/xen/common/debug.c	Fri Aug 06 11:53:45 2004 +0000
    11.2 +++ b/xen/common/debug.c	Fri Aug 06 12:20:20 2004 +0000
    11.3 @@ -65,7 +65,7 @@ void pdb_do_debug (dom0_op_t *op)
    11.4          case 'r' :
    11.5          {
    11.6              int loop;
    11.7 -            u_char x;
    11.8 +            u_char x = 0;
    11.9  	    unsigned long cr3;
   11.10  	    struct domain *d;
   11.11  
   11.12 @@ -81,8 +81,8 @@ void pdb_do_debug (dom0_op_t *op)
   11.13                  {
   11.14                      printk ("\n%08x ", op->u.debug.in1 + loop);
   11.15                  }
   11.16 -                x = pdb_linux_get_value(op->u.debug.in3,
   11.17 -					cr3, op->u.debug.in1 + loop);
   11.18 +		/* x = pdb_linux_get_value(op->u.debug.in3,
   11.19 +		   cr3, op->u.debug.in1 + loop); */
   11.20                  printk (" %02x", x);
   11.21              }
   11.22              printk ("\n");
    12.1 --- a/xen/common/domain.c	Fri Aug 06 11:53:45 2004 +0000
    12.2 +++ b/xen/common/domain.c	Fri Aug 06 12:20:20 2004 +0000
    12.3 @@ -164,6 +164,8 @@ void domain_crash(void)
    12.4      BUG();
    12.5  }
    12.6  
    12.7 +extern void trap_to_xendbg(void);
    12.8 +
    12.9  void domain_shutdown(u8 reason)
   12.10  {
   12.11      struct domain *d;
   12.12 @@ -173,6 +175,8 @@ void domain_shutdown(u8 reason)
   12.13          extern void machine_restart(char *);
   12.14          extern void machine_halt(void);
   12.15  
   12.16 +	trap_to_xendbg();
   12.17 +
   12.18          if ( reason == 0 ) 
   12.19          {
   12.20              printk("Domain 0 halted: Our work here is done.\n");
    13.1 --- a/xen/common/kernel.c	Fri Aug 06 11:53:45 2004 +0000
    13.2 +++ b/xen/common/kernel.c	Fri Aug 06 12:20:20 2004 +0000
    13.3 @@ -64,6 +64,8 @@ int opt_ignorebiostables=0;
    13.4  int opt_watchdog=0;
    13.5  /* opt_pdb: Name of serial port for Xen pervasive debugger (and enable pdb) */
    13.6  unsigned char opt_pdb[10] = "none";
    13.7 +/* opt_pdb: Name of serial port for Xen debugger (and enable xendbg) */
    13.8 +unsigned char opt_xendbg[10] = "none";
    13.9  /* opt_tbuf_size: trace buffer size (in pages) */
   13.10  unsigned int opt_tbuf_size = 10;
   13.11  /* opt_sched: scheduler - default to Borrowed Virtual Time */
   13.12 @@ -124,10 +126,13 @@ static struct {
   13.13      { "xenheap_megabytes", OPT_UINT, V(opt_xenheap_megabytes) },
   13.14      { "nmi",               OPT_STR,  V(opt_nmi) },
   13.15      { "badpage",           OPT_STR,  V(opt_badpage) },
   13.16 +    { "xendbg",            OPT_STR,  V(opt_xendbg) },
   13.17      { NULL,                0,        NULL, 0 }
   13.18  };
   13.19  
   13.20  
   13.21 +void initialize_xendbg(void);
   13.22 +
   13.23  void cmain(multiboot_info_t *mbi)
   13.24  {
   13.25      struct domain *new_dom;
   13.26 @@ -186,6 +191,8 @@ void cmain(multiboot_info_t *mbi)
   13.27  
   13.28      init_console();
   13.29  
   13.30 +    initialize_xendbg();
   13.31 +
   13.32      /* HELLO WORLD --- start-of-day banner text. */
   13.33      printk(XEN_BANNER);
   13.34      printk(" http://www.cl.cam.ac.uk/netos/xen\n");
    14.1 --- a/xen/common/keyhandler.c	Fri Aug 06 11:53:45 2004 +0000
    14.2 +++ b/xen/common/keyhandler.c	Fri Aug 06 12:20:20 2004 +0000
    14.3 @@ -115,6 +115,15 @@ extern void perfc_reset(unsigned char ke
    14.4                          struct pt_regs *regs);
    14.5  #endif
    14.6  
    14.7 +void do_debug_key(unsigned char key, void *dev_id, struct pt_regs *regs)
    14.8 +{
    14.9 +    extern void trap_to_xendbg(void);
   14.10 +    trap_to_xendbg();
   14.11 +    asm volatile ("nop"); /* Prevent the compiler doing tail call
   14.12 +			     optimisation, as that confuses xendbg a
   14.13 +			     bit. */
   14.14 +}
   14.15 +
   14.16  void initialize_keytable(void)
   14.17  {
   14.18      add_key_handler('d', dump_registers, "dump registers"); 
   14.19 @@ -128,4 +137,5 @@ void initialize_keytable(void)
   14.20      add_key_handler('p', perfc_printall, "print performance counters"); 
   14.21      add_key_handler('P', perfc_reset,    "reset performance counters"); 
   14.22  #endif
   14.23 +    add_key_handler('%', do_debug_key,   "Trap to xendbg");
   14.24  }
    15.1 --- a/xen/drivers/char/console.c	Fri Aug 06 11:53:45 2004 +0000
    15.2 +++ b/xen/drivers/char/console.c	Fri Aug 06 12:20:20 2004 +0000
    15.3 @@ -451,6 +451,8 @@ void console_force_lock(void)
    15.4   * **************************************************************
    15.5   */
    15.6  
    15.7 +extern void trap_to_xendbg(void);
    15.8 +
    15.9  void panic(const char *fmt, ...)
   15.10  {
   15.11      va_list args;
   15.12 @@ -461,7 +463,9 @@ void panic(const char *fmt, ...)
   15.13      va_start(args, fmt);
   15.14      (void)vsnprintf(buf, sizeof(buf), fmt, args);
   15.15      va_end(args);
   15.16 -    
   15.17 +
   15.18 +    trap_to_xendbg();
   15.19 +
   15.20      /* Spit out multiline message in one go. */
   15.21      spin_lock_irqsave(&console_lock, flags);
   15.22      __putstr("\n****************************************\n");
    16.1 --- a/xen/drivers/char/serial.c	Fri Aug 06 11:53:45 2004 +0000
    16.2 +++ b/xen/drivers/char/serial.c	Fri Aug 06 12:20:20 2004 +0000
    16.3 @@ -420,6 +420,30 @@ static int byte_matches(int handle, unsi
    16.4      return 0;
    16.5  }
    16.6  
    16.7 +unsigned char __serial_getc(int handle)
    16.8 +{
    16.9 +    uart_t *uart = &com[handle & SERHND_IDX];
   16.10 +    unsigned char c;
   16.11 +
   16.12 +    /* disable_irq() may have raced execution of uart_rx(). */
   16.13 +    while ( uart->rxbufp != uart->rxbufc )
   16.14 +    {
   16.15 +        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
   16.16 +        if ( byte_matches(handle, &c) )
   16.17 +	  return c;
   16.18 +    }
   16.19 +
   16.20 +    /* We now wait for the UART to receive a suitable character. */
   16.21 +    do {
   16.22 +        while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
   16.23 +            barrier();
   16.24 +        c = inb(uart->io_base + RBR);
   16.25 +    }
   16.26 +    while ( !byte_matches(handle, &c) );
   16.27 +
   16.28 +    return c;
   16.29 +}
   16.30 +
   16.31  unsigned char serial_getc(int handle)
   16.32  {
   16.33      uart_t *uart = &com[handle & SERHND_IDX];
   16.34 @@ -434,26 +458,11 @@ unsigned char serial_getc(int handle)
   16.35          if ( byte_matches(handle, &c) )
   16.36              goto out;
   16.37      }
   16.38 -    
   16.39 +
   16.40      disable_irq(uart->irq);
   16.41 -    
   16.42 -    /* disable_irq() may have raced execution of uart_rx(). */
   16.43 -    while ( uart->rxbufp != uart->rxbufc )
   16.44 -    {
   16.45 -        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
   16.46 -        if ( byte_matches(handle, &c) )
   16.47 -            goto enable_and_out;
   16.48 -    }
   16.49  
   16.50 -    /* We now wait for the UART to receive a suitable character. */
   16.51 -    do {
   16.52 -        while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
   16.53 -            barrier();
   16.54 -        c = inb(uart->io_base + RBR);
   16.55 -    }
   16.56 -    while ( !byte_matches(handle, &c) );
   16.57 -    
   16.58 - enable_and_out:
   16.59 +    c = __serial_getc(handle);
   16.60 +
   16.61      enable_irq(uart->irq);
   16.62   out:
   16.63      spin_unlock_irqrestore(&uart->lock, flags);
    17.1 --- a/xen/include/asm-x86/pdb.h	Fri Aug 06 11:53:45 2004 +0000
    17.2 +++ b/xen/include/asm-x86/pdb.h	Fri Aug 06 12:20:20 2004 +0000
    17.3 @@ -26,11 +26,30 @@ extern int pdb_page_fault;
    17.4  
    17.5  extern void initialize_pdb(void);
    17.6  
    17.7 -/* Get/set values from generic debug interface. */
    17.8 -extern int pdb_set_values(u_char *buffer, int length,
    17.9 -                          unsigned long cr3, unsigned long addr);
   17.10 -extern int pdb_get_values(u_char *buffer, int length,
   17.11 -                          unsigned long cr3, unsigned long addr);
   17.12 +/*
   17.13 + * pdb debug context 
   17.14 + */
   17.15 +typedef struct pdb_context
   17.16 +{
   17.17 +    int valid;
   17.18 +    int domain;
   17.19 +    int process;
   17.20 +    int system_call;              /* 0x01 break on enter, 0x02 break on exit */
   17.21 +    unsigned long ptbr;
   17.22 +} pdb_context_t, *pdb_context_p;
   17.23 +
   17.24 +extern pdb_context_t pdb_ctx;
   17.25 +
   17.26 +/* read / write memory */
   17.27 +extern int pdb_read_memory (unsigned long addr, int length, 
   17.28 +			    unsigned char *data, pdb_context_p ctx);
   17.29 +extern int pdb_write_memory (unsigned long addr, int length, 
   17.30 +			     unsigned char *data, pdb_context_p ctx);
   17.31 +
   17.32 +extern int pdb_read_page (u_char *buffer, int length,
   17.33 +			  unsigned long cr3, unsigned long addr);
   17.34 +extern int pdb_write_page (u_char *buffer, int length,
   17.35 +			   unsigned long cr3, unsigned long addr);
   17.36  
   17.37  /* External entry points. */
   17.38  extern int pdb_handle_exception(int exceptionVector,
   17.39 @@ -38,29 +57,54 @@ extern int pdb_handle_exception(int exce
   17.40  extern int pdb_serial_input(u_char c, struct pt_regs *regs);
   17.41  extern void pdb_do_debug(dom0_op_t *op);
   17.42  
   17.43 -/* PDB Context. */
   17.44 -struct pdb_context
   17.45 +typedef enum pdb_generic_action
   17.46  {
   17.47 -    int valid;
   17.48 -    int domain;
   17.49 -    int process;
   17.50 -    int system_call;              /* 0x01 break on enter, 0x02 break on exit */
   17.51 -    unsigned long ptbr;
   17.52 +  __PDB_GET,
   17.53 +  __PDB_SET,
   17.54 +  __PDB_CLEAR
   17.55 +} pdb_generic_action;
   17.56 +
   17.57 +/*
   17.58 + * breakpoint, watchpoint, & catchpoint
   17.59 + * note: numbers must match GDB remote serial protocol Z command numbers
   17.60 + */
   17.61 +enum pdb_bwcpoint_type
   17.62 +{
   17.63 +  PDB_BP_SOFTWARE = 0,
   17.64 +  PDB_BP_HARDWARE = 1,
   17.65 +  PDB_WP_WRITE    = 2,
   17.66 +  PDB_WP_READ     = 3,
   17.67 +  PDB_WP_ACCESS   = 4
   17.68  };
   17.69 -extern struct pdb_context pdb_ctx;
   17.70  
   17.71 -/* Breakpoints. */
   17.72 -struct pdb_breakpoint
   17.73 +enum pdb_bwcpoint_action
   17.74 +{
   17.75 +  PDB_BWC_UNKNOWN = 0,                                            /* default */
   17.76 +  PDB_BWC_STOP,         /* stop execution and return control to the debugger */
   17.77 +  PDB_BWC_DELETE                                    /* delete the breakpoint */
   17.78 +};
   17.79 +
   17.80 +typedef struct pdb_bwcpoint
   17.81  {
   17.82 -    struct list_head list;
   17.83 -    unsigned long address;
   17.84 -    unsigned long cr3;
   17.85 -    domid_t domain;
   17.86 -};
   17.87 -extern void pdb_bkpt_add (unsigned long cr3, unsigned long address);
   17.88 -extern struct pdb_breakpoint* pdb_bkpt_search (unsigned long cr3, 
   17.89 -					       unsigned long address);
   17.90 -extern int pdb_bkpt_remove (unsigned long cr3, unsigned long address);
   17.91 +  struct list_head list;
   17.92 +  unsigned long address;
   17.93 +  int length;
   17.94 +  enum pdb_bwcpoint_type type;                            /* how implemented */
   17.95 +  enum pdb_bwcpoint_type user_type;                    /* what was requested */
   17.96 +  enum pdb_bwcpoint_action action;                         /* action to take */
   17.97 +  pdb_context_t context;
   17.98 +
   17.99 +  unsigned char original; /* original value for breakpoint, one byte for x86 */
  17.100 +  char *comments;                                                /* comments */
  17.101 +} pdb_bwcpoint_t, *pdb_bwcpoint_p;
  17.102 +
  17.103 +void pdb_bwc_list_add (pdb_bwcpoint_p bwc);
  17.104 +void pdb_bwc_list_remove (pdb_bwcpoint_p bwc);
  17.105 +pdb_bwcpoint_p pdb_bwcpoint_search (unsigned long cr3, unsigned long address);
  17.106 +
  17.107 +int pdb_set_breakpoint (pdb_bwcpoint_p bwc);
  17.108 +int pdb_clear_breakpoint (unsigned long address, pdb_context_p ctx);
  17.109 +
  17.110  
  17.111  /* Conversions. */
  17.112  extern int   hex (char);
  17.113 @@ -85,4 +129,10 @@ void pdb_linux_syscall_enter_bkpt (struc
  17.114  void pdb_linux_syscall_exit_bkpt (struct pt_regs *regs, 
  17.115  				  struct pdb_context *pdb_ctx);
  17.116  
  17.117 +/* tracing */
  17.118 +extern int pdb_trace;
  17.119 +#define PDBTRC(_lvl_, _blahblah_) if (_lvl_ & pdb_trace) {_blahblah_;}
  17.120 +#define PDBTRC2(_lvl_, _blahblah_) \
  17.121 +  if (_lvl_ & pdb_trace) {printk("[%s:%d]",__FILE__,__LINE__); _blahblah_;}
  17.122 +
  17.123  #endif  /* __PDB_H__ */