ia64/xen-unstable

changeset 1964:57bae9faf165

bitkeeper revision 1.1108.1.38 (4107dff0CY0QB61rmGjAYX7oYF1dzA)

Merge
author ach61@labyrinth.cl.cam.ac.uk
date Wed Jul 28 17:18:40 2004 +0000 (2004-07-28)
parents 2cf5a0ee2c00 bffcca8408ce
children 6e4a18835d0d
files xen/arch/x86/pdb-linux.c xen/arch/x86/pdb-stub.c xen/common/debug-linux.c xen/common/debug.c xen/include/asm-x86/pdb.h
line diff
     1.1 --- a/xen/arch/x86/pdb-linux.c	Wed Jul 28 16:11:25 2004 +0000
     1.2 +++ b/xen/arch/x86/pdb-linux.c	Wed Jul 28 17:18:40 2004 +0000
     1.3 @@ -10,8 +10,12 @@
     1.4   * linux & i386 dependent code. bleech.
     1.5   */
     1.6  
     1.7 +#include <xen/slab.h>
     1.8  #include <asm/pdb.h>
     1.9  
    1.10 +extern unsigned char pdb_x86_bkpt;
    1.11 +extern int pdb_x86_bkpt_length;
    1.12 +
    1.13  /* offset to the first instruction in the linux system call code
    1.14     where we can safely set a breakpoint */
    1.15  unsigned int pdb_linux_syscall_enter_bkpt_offset = 20;
    1.16 @@ -92,9 +96,25 @@ pdb_linux_syscall_exit_bkpt (struct pt_r
    1.17         debugger when re-entering user space */
    1.18      pdb_system_call_next_addr = *(unsigned long *)(regs->esp + 
    1.19  						 pdb_linux_syscall_eip_offset);
    1.20 -    pdb_linux_get_values (&pdb_system_call_leave_instr, 1, 
    1.21 -			  pdb_system_call_next_addr,
    1.22 -			  pdb_ctx->process, pdb_ctx->ptbr);
    1.23 -    pdb_linux_set_values ("cc", 1, pdb_system_call_next_addr,
    1.24 -			  pdb_ctx->process, pdb_ctx->ptbr);
    1.25 +
    1.26 +    /* set a breakpoint when we exit */
    1.27 +    {
    1.28 +        pdb_bwcpoint_p bwc = (pdb_bwcpoint_p) kmalloc(sizeof(pdb_bwcpoint_t));
    1.29 +
    1.30 +	bwc->address = pdb_system_call_next_addr;
    1.31 +	bwc->length = 1;
    1.32 +	bwc->type = PDB_BP_SOFTWARE;
    1.33 +	bwc->user_type = PDB_BP_SOFTWARE;
    1.34 +	bwc->original = pdb_system_call_leave_instr;
    1.35 +	memcpy (&bwc->context, pdb_ctx, sizeof(pdb_context_t));
    1.36 +
    1.37 +	/* this is always in a process context */
    1.38 +	pdb_read_memory (pdb_system_call_next_addr, 1, 
    1.39 +			 &pdb_system_call_leave_instr,
    1.40 +			 (pdb_context_p) pdb_ctx);
    1.41 +	pdb_write_memory (pdb_system_call_next_addr, pdb_x86_bkpt_length,
    1.42 +			  &pdb_x86_bkpt, (pdb_context_p) pdb_ctx);
    1.43 +
    1.44 +	pdb_bwc_list_add (bwc);
    1.45 +    }
    1.46  }
     2.1 --- a/xen/arch/x86/pdb-stub.c	Wed Jul 28 16:11:25 2004 +0000
     2.2 +++ b/xen/arch/x86/pdb-stub.c	Wed Jul 28 17:18:40 2004 +0000
     2.3 @@ -22,39 +22,57 @@
     2.4  #include <xen/serial.h>
     2.5  #include <xen/softirq.h>
     2.6  
     2.7 -#define PDB_DEBUG_TRACE
     2.8 -#ifdef PDB_DEBUG_TRACE
     2.9 -#define TRC(_x) _x
    2.10 -#else
    2.11 -#define TRC(_x)
    2.12 -#endif
    2.13 +int pdb_trace = 1;                                 /* debugging the debugger */
    2.14  
    2.15  #define DEBUG_EXCEPTION     0x01
    2.16  #define BREAKPT_EXCEPTION   0x03
    2.17  #define PDB_LIVE_EXCEPTION  0x58
    2.18  #define KEYPRESS_EXCEPTION  0x88
    2.19  
    2.20 -#define BUFMAX 400
    2.21 -
    2.22  static const char hexchars[] = "0123456789abcdef";
    2.23  
    2.24 -static int remote_debug;
    2.25 -
    2.26  #define PDB_BUFMAX 1024
    2.27  static char pdb_in_buffer[PDB_BUFMAX];
    2.28  static char pdb_out_buffer[PDB_BUFMAX];
    2.29 -static char pdb_buffer[PDB_BUFMAX];
    2.30  static int  pdb_in_buffer_ptr;
    2.31  static unsigned char  pdb_in_checksum;
    2.32  static unsigned char  pdb_xmit_checksum;
    2.33  
    2.34 -struct pdb_context pdb_ctx;
    2.35 +void pdb_put_packet (unsigned char *buffer, int ack);
    2.36 +
    2.37 +pdb_context_t pdb_ctx;
    2.38  int pdb_continue_thread = 0;
    2.39  int pdb_general_thread = 0;
    2.40  
    2.41 -void pdb_put_packet (unsigned char *buffer, int ack);
    2.42 -void pdb_bkpt_check (u_char *buffer, int length,
    2.43 -		     unsigned long cr3, unsigned long addr);
    2.44 +
    2.45 +enum pdb_bwc_page_action
    2.46 +{
    2.47 +  PDB_BWC_PAGE_ACCESS_SET,
    2.48 +  PDB_BWC_PAGE_ACCESS_CLEAR,
    2.49 +  PDB_BWC_PAGE_WRITE_SET,
    2.50 +  PDB_BWC_PAGE_WRITE_CLEAR,
    2.51 +  PDB_BWC_PAGE_READ_SET,
    2.52 +  PDB_BWC_PAGE_READ_CLEAR,
    2.53 +};
    2.54 +static char *pdb_bwc_page_action_s[] =
    2.55 +  { "ac set", "ac clr", "wr set", "wr clr", "rd set", "rd cler" };
    2.56 +int pdb_bwc_page (int action, unsigned long addr, int length, 
    2.57 +		  pdb_context_p ctx, int offset, void *s);
    2.58 +
    2.59 +enum pdb_visit_page_action
    2.60 +{
    2.61 +  PDB_VISIT_PAGE_XEN_READ,
    2.62 +  PDB_VISIT_PAGE_XEN_WRITE,
    2.63 +  PDB_VISIT_PAGE_DOMAIN_READ,
    2.64 +  PDB_VISIT_PAGE_DOMAIN_WRITE,
    2.65 +  PDB_VISIT_PAGE_PROCESS_READ,
    2.66 +  PDB_VISIT_PAGE_PROCESS_WRITE,
    2.67 +};
    2.68 +static char *pdb_visit_page_action_s[] =
    2.69 +  { "xen rd", "xen wr", "dom rd", "dom wr", "proc rd", "proc wr" };
    2.70 +
    2.71 +int pdb_visit_page (int action, unsigned long addr, int length,
    2.72 +                    pdb_context_p ctx, int offset, void *s);
    2.73  
    2.74  int pdb_initialized = 0;
    2.75  int pdb_page_fault_possible = 0;
    2.76 @@ -69,6 +87,12 @@ unsigned char pdb_system_call_leave_inst
    2.77  unsigned long pdb_system_call_next_addr = 0;         /* instr after int 0x80 */
    2.78  unsigned long pdb_system_call_eflags_addr = 0;      /* saved eflags on stack */
    2.79  
    2.80 +unsigned char pdb_x86_bkpt = 0xcc;
    2.81 +unsigned int  pdb_x86_bkpt_length = 1;
    2.82 +
    2.83 +/***********************************************************************/
    2.84 +/***********************************************************************/
    2.85 +
    2.86  static inline void pdb_put_char(unsigned char c)
    2.87  {
    2.88      serial_putc(pdb_serhnd, c);
    2.89 @@ -79,19 +103,137 @@ static inline unsigned char pdb_get_char
    2.90      return serial_getc(pdb_serhnd);
    2.91  }
    2.92  
    2.93 +/***********************************************************************/
    2.94 +/***********************************************************************/
    2.95 +
    2.96 +/*
    2.97 + * Prototype for function to process each page.  This function is called
    2.98 + * once per page.
    2.99 + *
   2.100 + * action  : function specific
   2.101 + * address : first byte of this page
   2.102 + * length  : number of bytes to process on this page
   2.103 + * offset  : number of bytes processed so far. can be used as
   2.104 + *           an index into data.
   2.105 + * data    : function specific.
   2.106 + */
   2.107 +
   2.108 +typedef int (pdb_invoke_ftype) (int action, unsigned long address, int length, 
   2.109 +				pdb_context_p ctx, int offset, void *data);
   2.110 +
   2.111 +typedef struct pdb_invoke_args
   2.112 +{
   2.113 +  pdb_context_p context;
   2.114 +  unsigned long address;
   2.115 +  int length;
   2.116 +  int action;
   2.117 +  void *data;
   2.118 +} pdb_invoke_args_t, * pdb_invoke_args_p;
   2.119 +
   2.120 +
   2.121 +/*
   2.122 + * call a particular function once per page given an address & length
   2.123 + */
   2.124 +
   2.125  int
   2.126 -get_char (char *addr)
   2.127 +pdb_invoke(pdb_invoke_ftype *function, pdb_invoke_args_p args)
   2.128  {
   2.129 -    return *addr;
   2.130 +  int remaining;
   2.131 +  int bytes = 0;
   2.132 +  int length = args->length;
   2.133 +  unsigned long address = args->address;
   2.134 +
   2.135 +  while ((remaining = (address + length - 1) - (address | (PAGE_SIZE - 1))) > 0)
   2.136 +  {
   2.137 +    bytes += (function)(args->action, address, length - remaining,
   2.138 +			args->context, address - args->address, args->data);
   2.139 +    length = remaining;
   2.140 +    address = (address | (PAGE_SIZE - 1)) + 1;
   2.141 +  }
   2.142 +  bytes += (function)(args->action, address, length,
   2.143 +                      args->context, address - args->address, args->data);
   2.144 +  return bytes;
   2.145 +}
   2.146 +
   2.147 +
   2.148 +/***********************************************************************/
   2.149 +/***********************************************************************/
   2.150 +
   2.151 +/* BWC List Support: breakpoints, watchpoints, and catchpoints */
   2.152 +
   2.153 +char *pdb_bwcpoint_type_s[] =                      /* enum pdb_bwcpoint_type */
   2.154 +  { "BP_SOFTWARE", "BP_HARDWARE", "WP_WRITE", "WP_READ", "WP_ACCESS" };
   2.155 +
   2.156 +int pdb_set_watchpoint (pdb_bwcpoint_p bwc); 
   2.157 +int pdb_clear_watchpoint (pdb_bwcpoint_p bwc);
   2.158 +
   2.159 +struct list_head pdb_bwc_list = LIST_HEAD_INIT(pdb_bwc_list);
   2.160 +
   2.161 +void
   2.162 +pdb_bwc_list_add (pdb_bwcpoint_p bwc)
   2.163 +{
   2.164 +  list_add_tail(&bwc->list, &pdb_bwc_list);
   2.165  }
   2.166  
   2.167  void
   2.168 -set_char (char *addr, int val)
   2.169 +pdb_bwc_list_remove (pdb_bwcpoint_p bwc)
   2.170 +{
   2.171 +  list_del(&bwc->list);
   2.172 +}
   2.173 +
   2.174 +pdb_bwcpoint_p
   2.175 +pdb_bwc_list_search (unsigned long address, int length, pdb_context_p ctx)
   2.176 +{
   2.177 +  struct list_head *ptr;
   2.178 +
   2.179 +  list_for_each (ptr, &pdb_bwc_list)
   2.180 +  {
   2.181 +    pdb_bwcpoint_p bwc = list_entry(ptr, pdb_bwcpoint_t, list);
   2.182 +
   2.183 +    if (bwc->address == address &&
   2.184 +        bwc->length  == length)
   2.185 +    {
   2.186 +      return bwc;
   2.187 +    }
   2.188 +  }
   2.189 +  return (pdb_bwcpoint_p) 0;
   2.190 +}
   2.191 +
   2.192 +pdb_bwcpoint_p
   2.193 +pdb_bwcpoint_search (unsigned long cr3, unsigned long address)
   2.194  {
   2.195 -    *addr = val;
   2.196 +  pdb_context_t ctx;
   2.197 +
   2.198 +  ctx.ptbr = cr3;
   2.199 +  return pdb_bwc_list_search (address, pdb_x86_bkpt_length, &ctx);
   2.200 +}
   2.201 +
   2.202 +void
   2.203 +pdb_bwc_print (pdb_bwcpoint_p bwc)
   2.204 +{
   2.205 +    printk ("address: 0x%08lx, length: 0x%02x, type: 0x%x %s", 
   2.206 +	    bwc->address, bwc->length,
   2.207 +	    bwc->type, pdb_bwcpoint_type_s[bwc->type]);
   2.208  }
   2.209  
   2.210  void
   2.211 +pdb_bwc_print_list ()
   2.212 +{
   2.213 +  struct list_head *ptr;
   2.214 +  int counter = 0;
   2.215 +
   2.216 +  list_for_each (ptr, &pdb_bwc_list)
   2.217 +  {
   2.218 +    pdb_bwcpoint_p bwc = list_entry(ptr, pdb_bwcpoint_t, list);
   2.219 +    printk ("  [%02d]  ", counter);   pdb_bwc_print(bwc);   printk ("\n");
   2.220 +    counter++;
   2.221 +  }
   2.222 +}
   2.223 +
   2.224 +/***********************************************************************/
   2.225 +/***********************************************************************/
   2.226 +
   2.227 +void
   2.228  pdb_process_query (char *ptr)
   2.229  {
   2.230      if (strcmp(ptr, "C") == 0)
   2.231 @@ -100,82 +242,10 @@ pdb_process_query (char *ptr)
   2.232      }
   2.233      else if (strcmp(ptr, "fThreadInfo") == 0)
   2.234      {
   2.235 -#ifdef PDB_PAST
   2.236 -        struct domain *p;
   2.237 -        u_long flags;
   2.238 -#endif /* PDB_PAST */
   2.239 -
   2.240          int buf_idx = 0;
   2.241  
   2.242  	pdb_out_buffer[buf_idx++] = 'l';
   2.243  	pdb_out_buffer[buf_idx++] = 0;
   2.244 -
   2.245 -#ifdef PDB_PAST
   2.246 -	switch (pdb_level)
   2.247 -	{
   2.248 -	case PDB_LVL_XEN:                        /* return a list of domains */
   2.249 -	{
   2.250 -	    int count = 0;
   2.251 -
   2.252 -	    read_lock_irqsave (&tasklist_lock, flags);
   2.253 -
   2.254 -	    pdb_out_buffer[buf_idx++] = 'm';
   2.255 -	    for_each_domain ( p )
   2.256 -	    {
   2.257 -	        domid_t domain = p->domain + PDB_ID_OFFSET;
   2.258 -
   2.259 -		if (count > 0)
   2.260 -		{
   2.261 -		    pdb_out_buffer[buf_idx++] = ',';
   2.262 -		}
   2.263 -		if (domain > 15)
   2.264 -		{
   2.265 -		    pdb_out_buffer[buf_idx++] = hexchars[domain >> 4];
   2.266 -		}
   2.267 -		pdb_out_buffer[buf_idx++] = hexchars[domain % 16];
   2.268 -		count++;
   2.269 -	    }
   2.270 -	    pdb_out_buffer[buf_idx++] = 0;
   2.271 -
   2.272 -	    read_unlock_irqrestore(&tasklist_lock, flags);
   2.273 -	    break;
   2.274 -	}
   2.275 -	case PDB_LVL_GUESTOS:                  /* return a list of processes */
   2.276 -	{
   2.277 -	    int foobar[20];
   2.278 -	    int loop, total;
   2.279 -
   2.280 -                                                       /* this cr3 is wrong! */
   2.281 -	    total = pdb_linux_process_list(pdb_ctx[pdb_level].info_cr3,
   2.282 -					   foobar, 20);
   2.283 -
   2.284 -	    pdb_out_buffer[buf_idx++] = 'm';     
   2.285 -	    pdb_out_buffer[buf_idx++] = '1';              /* 1 is to go back */
   2.286 -	    for (loop = 0; loop < total; loop++)
   2.287 -	    {
   2.288 -	        int pid = foobar[loop] + PDB_ID_OFFSET;
   2.289 -
   2.290 -		pdb_out_buffer[buf_idx++] = ',';
   2.291 -		if (pid > 15)
   2.292 -		{
   2.293 -		    pdb_out_buffer[buf_idx++] = hexchars[pid >> 4];
   2.294 -		}
   2.295 -		pdb_out_buffer[buf_idx++] = hexchars[pid % 16];
   2.296 -	    }
   2.297 -	    pdb_out_buffer[buf_idx++] = 0;
   2.298 -	    break;
   2.299 -	}
   2.300 -	case PDB_LVL_PROCESS:                                     /* hmmm... */
   2.301 -	{
   2.302 -	    pdb_out_buffer[buf_idx++] = 'm';
   2.303 -	    pdb_out_buffer[buf_idx++] = '1';              /* 1 is to go back */
   2.304 -	    break;
   2.305 -	}
   2.306 -	default:
   2.307 -	    break;
   2.308 -	}
   2.309 -#endif /* PDB_PAST */
   2.310 -
   2.311      }
   2.312      else if (strcmp(ptr, "sThreadInfo") == 0)
   2.313      {
   2.314 @@ -195,22 +265,6 @@ pdb_process_query (char *ptr)
   2.315              mem2hex (message, pdb_out_buffer, strlen(message) + 1);
   2.316  	}
   2.317  
   2.318 -#ifdef PDB_PAST
   2.319 -        int thread = 0;
   2.320 -	char message[16];
   2.321 -	struct domain *p;
   2.322 -
   2.323 -	p = find_domain_by_id(pdb_ctx[pdb_level].info);
   2.324 -	strncpy (message, p->name, 16);
   2.325 -	put_domain(p);
   2.326 -
   2.327 -	ptr += 16;
   2.328 -        if (hexToInt (&ptr, &thread))
   2.329 -	{
   2.330 -            mem2hex ((char *)message, pdb_out_buffer, strlen(message) + 1);
   2.331 -	}
   2.332 -#endif /* PDB_PAST */
   2.333 -
   2.334  #ifdef PDB_FUTURE
   2.335        {
   2.336  	char string[task_struct_comm_length];
   2.337 @@ -220,7 +274,6 @@ pdb_process_query (char *ptr)
   2.338  	printk (" (%s)", string);
   2.339        }
   2.340  #endif /* PDB_FUTURE*/
   2.341 -
   2.342      }
   2.343      else if (strcmp(ptr, "Offsets") == 0)
   2.344      {
   2.345 @@ -237,7 +290,182 @@ pdb_process_query (char *ptr)
   2.346  }
   2.347  
   2.348  void
   2.349 -pdb_x86_to_gdb_regs (char *buffer, struct pt_regs *regs)
   2.350 +pdb_process_z (int onoff, char *ptr)
   2.351 +{
   2.352 +    int type = *(ptr++) - '0';
   2.353 +    int length;
   2.354 +    unsigned long addr;
   2.355 +    char *error = "E01";                                     /* syntax error */
   2.356 +
   2.357 +    /* try to read ',addr,length' */
   2.358 +    if (   *(ptr++) == ','
   2.359 +	&& hexToInt(&ptr, (int *)&addr)
   2.360 +	&& *(ptr++) == ','
   2.361 +	&& hexToInt(&ptr, &length))
   2.362 +    {
   2.363 +	error = "OK";
   2.364 +
   2.365 +	switch (type)
   2.366 +	{
   2.367 +	case PDB_BP_SOFTWARE:
   2.368 +	case PDB_BP_HARDWARE:
   2.369 +	{
   2.370 +	    if (onoff == 1)
   2.371 +	    {
   2.372 +	        pdb_bwcpoint_p bwc = (pdb_bwcpoint_p) kmalloc(sizeof(pdb_bwcpoint_t));
   2.373 +
   2.374 +		bwc->address = addr;
   2.375 +		bwc->length = pdb_x86_bkpt_length;
   2.376 +		bwc->type = PDB_BP_SOFTWARE;
   2.377 +		bwc->user_type = type;
   2.378 +		memcpy (&bwc->context, &pdb_ctx, sizeof(pdb_context_t));
   2.379 +
   2.380 +		if (length != pdb_x86_bkpt_length)
   2.381 +		{
   2.382 +		    printk("pdb warning: x86 bkpt length should be 1\n");
   2.383 +		}
   2.384 +
   2.385 +		pdb_set_breakpoint (bwc);
   2.386 +	    }
   2.387 +	    else
   2.388 +	    {
   2.389 +	        pdb_clear_breakpoint (addr, pdb_x86_bkpt_length, &pdb_ctx);
   2.390 +	        pdb_bwcpoint_p bwc = pdb_bwc_list_search (addr, 1, &pdb_ctx);
   2.391 +
   2.392 +		if (bwc == 0)
   2.393 +		{
   2.394 +		    error = "E03";                   /* breakpoint not found */
   2.395 +		    break;
   2.396 +		}
   2.397 +
   2.398 +		pdb_write_memory (addr, 1, &bwc->original, &pdb_ctx);
   2.399 +
   2.400 +		pdb_bwc_list_remove (bwc);
   2.401 +	    }
   2.402 +	    break;
   2.403 +	}
   2.404 +	case PDB_WP_WRITE:
   2.405 +	case PDB_WP_READ:
   2.406 +	case PDB_WP_ACCESS:
   2.407 +	{
   2.408 +	    if (onoff == 1)
   2.409 +	    {
   2.410 +	        pdb_bwcpoint_p bwc = (pdb_bwcpoint_p) kmalloc(sizeof(pdb_bwcpoint_t));
   2.411 +
   2.412 +		bwc->address = addr;
   2.413 +		bwc->length = length;
   2.414 +		bwc->type = type;
   2.415 +		bwc->user_type = type;
   2.416 +		memcpy (&bwc->context, &pdb_ctx, sizeof(pdb_context_t));
   2.417 +
   2.418 +		pdb_set_watchpoint (bwc);
   2.419 +
   2.420 +		pdb_bwc_list_add (bwc);
   2.421 +	    }
   2.422 +	    else
   2.423 +	    {
   2.424 +	        pdb_bwcpoint_p bwc = pdb_bwc_list_search (addr, 1, &pdb_ctx);
   2.425 +
   2.426 +		if (bwc == 0)
   2.427 +		{
   2.428 +		    error = "E03";                   /* watchpoint not found */
   2.429 +		    break;
   2.430 +		}
   2.431 +
   2.432 +		pdb_clear_watchpoint (bwc);
   2.433 +
   2.434 +		pdb_bwc_list_remove (bwc);
   2.435 +	    }
   2.436 +	    break;
   2.437 +	}
   2.438 +	default:
   2.439 +	{
   2.440 +	    printk ("pdb error: unknown Z command [%c]\n", type);
   2.441 +	    error = "E02";                                   /* syntax error */
   2.442 +	    break;
   2.443 +	}
   2.444 +	}
   2.445 +    }
   2.446 +
   2.447 +    if (error)                               /* return value, including okay */
   2.448 +    {
   2.449 +	strcpy (pdb_out_buffer, error);
   2.450 +    }
   2.451 +}
   2.452 +
   2.453 +void
   2.454 +pdb_process_pdb (char *ptr)
   2.455 +{
   2.456 +    unsigned long arg1, arg2;
   2.457 +    char *error = "E01";                                     /* syntax error */
   2.458 +    char command = *(ptr++);
   2.459 +
   2.460 +    switch (command)
   2.461 +    {
   2.462 +    case 'c':                                             /* set pdb context */
   2.463 +    case 'C':
   2.464 +    {
   2.465 +        /* try to read two hex arguments ':arg1,arg2 */
   2.466 +        if (   *(ptr++) == ':'
   2.467 +	    && hexToInt(&ptr, (int *)&arg1)
   2.468 +	    && *(ptr++) == ','
   2.469 +	    && hexToInt(&ptr, (int *)&arg2))
   2.470 +	{
   2.471 +	    printk ("pdb: set context: domain:0x%lx process:0x%lx\n", 
   2.472 +		    arg1, arg2);
   2.473 +	    error = "OK";
   2.474 +	}
   2.475 +
   2.476 +        pdb_ctx.domain  = arg1;
   2.477 +	pdb_ctx.process = arg2;
   2.478 +	pdb_ctx.valid   = 1;
   2.479 +	break;
   2.480 +    }
   2.481 +    case 't':                                          /* enable pdb tracing */
   2.482 +    case 'T':
   2.483 +    {
   2.484 +        /* read the trace level */
   2.485 +        if (   *(ptr++) == ':'
   2.486 +	    && hexToInt(&ptr, (int *)&pdb_trace))
   2.487 +	{
   2.488 +	    printk ("pdb: set trace level: 0x%x\n", pdb_trace);
   2.489 +	    error = "OK";
   2.490 +	}
   2.491 +	break;
   2.492 +    }
   2.493 +    case 'd':
   2.494 +    case 'D':                                              /* dump pdb state */
   2.495 +    {
   2.496 +        printk ("----------\n");
   2.497 +        printk ("pdb trace : %2d 0x%02x\n", pdb_trace, pdb_trace);
   2.498 +        printk ("pdb ctx domain  : %4d 0x%04x\n",
   2.499 +		pdb_ctx.domain, pdb_ctx.domain);
   2.500 +        printk ("        process : %4d 0x%04x\n",
   2.501 +		pdb_ctx.process, pdb_ctx.process);
   2.502 +        printk ("        sys call: %4d 0x%04x\n",
   2.503 +		pdb_ctx.system_call, pdb_ctx.system_call);
   2.504 +        printk ("bwc list:\n");
   2.505 +	pdb_bwc_print_list ();
   2.506 +        printk ("----------\n");
   2.507 +	error = "OK";
   2.508 +	break;
   2.509 +    }
   2.510 +    default:
   2.511 +    {
   2.512 +        printk ("pdb error: unknown pdb dot command [%c]\n", command);
   2.513 +	error = "E02";                                       /* syntax error */
   2.514 +	break;
   2.515 +    }
   2.516 +    }
   2.517 +
   2.518 +    if (error)                               /* return value, including okay */
   2.519 +    {
   2.520 +	strcpy (pdb_out_buffer, error);
   2.521 +    }
   2.522 +}
   2.523 +
   2.524 +void
   2.525 +pdb_read_regs (char *buffer, struct pt_regs *regs)
   2.526  {
   2.527      int idx = 0;
   2.528  
   2.529 @@ -276,7 +504,7 @@ pdb_x86_to_gdb_regs (char *buffer, struc
   2.530  
   2.531  /* at this point we allow any register to be changed, caveat emptor */
   2.532  void
   2.533 -pdb_gdb_to_x86_regs (struct pt_regs *regs, char *buffer)
   2.534 +pdb_write_regs (struct pt_regs *regs, char *buffer)
   2.535  {
   2.536      hex2mem(buffer, (char *)&regs->eax, sizeof(regs->eax));
   2.537      buffer += sizeof(regs->eax) * 2;
   2.538 @@ -320,7 +548,7 @@ pdb_process_command (char *ptr, struct p
   2.539      int ack = 1;                           /* wait for ack in pdb_put_packet */
   2.540      int go = 0;
   2.541  
   2.542 -    TRC(printf("pdb: [%s]\n", ptr));
   2.543 +    PDBTRC(1,printk("pdb: [%s]\n", ptr));
   2.544  
   2.545      pdb_out_buffer[0] = 0;
   2.546  
   2.547 @@ -386,8 +614,8 @@ pdb_process_command (char *ptr, struct p
   2.548  	}
   2.549  
   2.550  	pdb_ctx.valid = 0;
   2.551 -	TRC(printk ("pdb change context (dom:%d, proc:%d) now 0x%lx\n",
   2.552 -		    pdb_ctx.domain, pdb_ctx.process, pdb_ctx.ptbr));
   2.553 +	PDBTRC(1,printk ("pdb change context (dom:%d, proc:%d) now 0x%lx\n",
   2.554 +		      pdb_ctx.domain, pdb_ctx.process, pdb_ctx.ptbr));
   2.555      }
   2.556  
   2.557      switch (*ptr++)
   2.558 @@ -404,16 +632,13 @@ pdb_process_command (char *ptr, struct p
   2.559          if ( pdb_system_call_eflags_addr != 0 )
   2.560  	{
   2.561  	    unsigned long eflags;
   2.562 -	    char eflags_buf[sizeof(eflags)*2];       /* STUPID STUPID STUPID */
   2.563  
   2.564 -	    pdb_linux_get_values((u_char*)&eflags, sizeof(eflags), 
   2.565 -				 pdb_system_call_eflags_addr, 
   2.566 -				 pdb_ctx.process, pdb_ctx.ptbr);
   2.567 +	    /* this is always in a process context */
   2.568 +	    pdb_read_memory (pdb_system_call_eflags_addr, sizeof(eflags), 
   2.569 +			     (u_char *)&eflags, &pdb_ctx);
   2.570  	    eflags |= X86_EFLAGS_TF;
   2.571 -	    mem2hex ((u_char *)&eflags, eflags_buf, sizeof(eflags)); 
   2.572 -	    pdb_linux_set_values(eflags_buf, sizeof(eflags),
   2.573 -				 pdb_system_call_eflags_addr,
   2.574 -				 pdb_ctx.process, pdb_ctx.ptbr);
   2.575 +	    pdb_write_memory (pdb_system_call_eflags_addr, sizeof(eflags), 
   2.576 +			      (u_char *)&eflags, &pdb_ctx);
   2.577  	}
   2.578  
   2.579          regs->eflags |= X86_EFLAGS_TF;
   2.580 @@ -427,16 +652,13 @@ pdb_process_command (char *ptr, struct p
   2.581          if ( pdb_system_call_eflags_addr != 0 )
   2.582  	{
   2.583  	    unsigned long eflags;
   2.584 -	    char eflags_buf[sizeof(eflags)*2];       /* STUPID STUPID STUPID */
   2.585  
   2.586 -	    pdb_linux_get_values((u_char*)&eflags, sizeof(eflags), 
   2.587 -				 pdb_system_call_eflags_addr, 
   2.588 -				 pdb_ctx.process, pdb_ctx.ptbr);
   2.589 +	    /* this is always in a process context */
   2.590 +	    pdb_read_memory (pdb_system_call_eflags_addr, sizeof(eflags), 
   2.591 +			     (u_char *)&eflags, &pdb_ctx);
   2.592  	    eflags &= ~X86_EFLAGS_TF;
   2.593 -	    mem2hex ((u_char *)&eflags, eflags_buf, sizeof(eflags)); 
   2.594 -	    pdb_linux_set_values(eflags_buf, sizeof(eflags),
   2.595 -				 pdb_system_call_eflags_addr,
   2.596 -				 pdb_ctx.process, pdb_ctx.ptbr);
   2.597 +	    pdb_write_memory (pdb_system_call_eflags_addr, sizeof(eflags), 
   2.598 +			      (u_char *)&eflags, &pdb_ctx);
   2.599  	}
   2.600  
   2.601          regs->eflags &= ~X86_EFLAGS_TF;
   2.602 @@ -444,19 +666,18 @@ pdb_process_command (char *ptr, struct p
   2.603          /* not reached */
   2.604      }
   2.605      case 'd':
   2.606 -        remote_debug = !(remote_debug);                 /* toggle debug flag */
   2.607          break;
   2.608      case 'D':                                                      /* detach */
   2.609 -        return go;
   2.610 -        /* not reached */
   2.611 +        go = 1;
   2.612 +        break;
   2.613      case 'g':                       /* return the value of the CPU registers */
   2.614      {
   2.615 -        pdb_x86_to_gdb_regs (pdb_out_buffer, regs);
   2.616 +        pdb_read_regs (pdb_out_buffer, regs);
   2.617          break;
   2.618      }
   2.619      case 'G':              /* set the value of the CPU registers - return OK */
   2.620      {
   2.621 -        pdb_gdb_to_x86_regs (regs, ptr);
   2.622 +        pdb_write_regs (regs, ptr);
   2.623          break;
   2.624      }
   2.625      case 'H':
   2.626 @@ -509,24 +730,20 @@ pdb_process_command (char *ptr, struct p
   2.627                  {
   2.628                      ptr = 0;
   2.629  
   2.630 -		    pdb_page_fault_possible = 1;
   2.631 +		    pdb_page_fault_possible = 2;
   2.632  		    pdb_page_fault = 0;
   2.633 -		    if (addr >= PAGE_OFFSET)
   2.634 -		    {
   2.635 -                        mem2hex ((char *) addr, pdb_out_buffer, length); 
   2.636 -		    }
   2.637 -		    else if (pdb_ctx.process != -1)
   2.638 -		    {
   2.639 -		        pdb_linux_get_values(pdb_buffer, length, addr, 
   2.640 -					     pdb_ctx.process, pdb_ctx.ptbr);
   2.641 -                        mem2hex (pdb_buffer, pdb_out_buffer, length); 
   2.642 -		    }
   2.643 -                    else
   2.644 -                    {
   2.645 -		        pdb_get_values (pdb_buffer, length, 
   2.646 -					pdb_ctx.ptbr, addr);
   2.647 -                        mem2hex (pdb_buffer, pdb_out_buffer, length);
   2.648 -                    }
   2.649 +
   2.650 +	    {
   2.651 +	        u_char *buffer = (u_char *) kmalloc (length);
   2.652 +		if (!buffer)
   2.653 +		{
   2.654 +		    printk ("pdb error: kmalloc failure\n");
   2.655 +		    break;
   2.656 +		}
   2.657 +		pdb_read_memory (addr, length, buffer, &pdb_ctx);
   2.658 +		mem2hex (buffer, pdb_out_buffer, length); 
   2.659 +		kfree(buffer);
   2.660 +	    }
   2.661  
   2.662  		    pdb_page_fault_possible = 0;
   2.663  		    if (pdb_page_fault)
   2.664 @@ -546,44 +763,39 @@ pdb_process_command (char *ptr, struct p
   2.665      case 'M':
   2.666      {
   2.667          /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
   2.668 -        if (hexToInt (&ptr, (int *)&addr))
   2.669 -            if (*(ptr++) == ',')
   2.670 -                if (hexToInt (&ptr, &length))
   2.671 -                    if (*(ptr++) == ':')
   2.672 -                    {
   2.673 +        if (   hexToInt (&ptr, (int *)&addr)
   2.674 +	    && *(ptr++) == ','
   2.675 +            && hexToInt (&ptr, &length)
   2.676 +	    && *(ptr++) == ':')
   2.677 +	{
   2.678 +	    pdb_page_fault_possible = 3;
   2.679 +	    pdb_page_fault = 0;
   2.680  
   2.681 -		        pdb_page_fault_possible = 1;
   2.682 -			pdb_page_fault = 0;
   2.683 -			if (addr >= PAGE_OFFSET)
   2.684 -			{
   2.685 -			    hex2mem (ptr, (char *)addr, length);
   2.686 -			    pdb_bkpt_check(ptr, length, pdb_ctx.ptbr, addr);
   2.687 -			}
   2.688 -			else if (pdb_ctx.process != -1)
   2.689 -			{
   2.690 -			    pdb_linux_set_values(ptr, length, addr,
   2.691 -						 pdb_ctx.process, 
   2.692 -						 pdb_ctx.ptbr);
   2.693 -			    pdb_bkpt_check(ptr, length, pdb_ctx.ptbr, addr);
   2.694 -			}
   2.695 -			else
   2.696 -			{
   2.697 -			    pdb_set_values (ptr, length,
   2.698 -					    pdb_ctx.ptbr, addr);
   2.699 -			    pdb_bkpt_check(ptr, length, pdb_ctx.ptbr, addr);
   2.700 -			}
   2.701 -			pdb_page_fault_possible = 0;
   2.702 -                        if (pdb_page_fault)
   2.703 -                        {
   2.704 -                            strcpy (pdb_out_buffer, "E03");
   2.705 -                        }
   2.706 -                        else
   2.707 -                        {
   2.708 -                            strcpy (pdb_out_buffer, "OK");
   2.709 -                        }
   2.710 +	    {
   2.711 +	        u_char *buffer = (u_char *) kmalloc (length);
   2.712 +		if (!buffer)
   2.713 +		{
   2.714 +		    printk ("pdb error: kmalloc failure\n");
   2.715 +		    break;
   2.716 +		}
   2.717 +	        hex2mem (ptr, buffer, length);
   2.718 +		pdb_write_memory (addr, length, buffer, &pdb_ctx);
   2.719 +		kfree(buffer);
   2.720 +	    }
   2.721  
   2.722 -                        ptr = 0;
   2.723 -                    }
   2.724 +	    pdb_page_fault_possible = 0;
   2.725 +	    if (pdb_page_fault)
   2.726 +	    {
   2.727 +	        strcpy (pdb_out_buffer, "E03");
   2.728 +	    }
   2.729 +	    else
   2.730 +	    {
   2.731 +	        strcpy (pdb_out_buffer, "OK");
   2.732 +	    }
   2.733 +
   2.734 +	    ptr = 0;
   2.735 +	}
   2.736 +
   2.737          if (ptr)
   2.738          {
   2.739              strcpy (pdb_out_buffer, "E02");
   2.740 @@ -597,59 +809,29 @@ pdb_process_command (char *ptr, struct p
   2.741          if (hexToInt (&ptr, &id))
   2.742          {
   2.743  	    strcpy (pdb_out_buffer, "E00");
   2.744 -
   2.745 -#ifdef PDB_PAST
   2.746 -
   2.747 -	    switch (pdb_level)                             /* previous level */
   2.748 -	    {
   2.749 -	        case PDB_LVL_XEN:
   2.750 -		{
   2.751 -		    struct domain *p;
   2.752 -		    id -= PDB_ID_OFFSET;
   2.753 -		    if ( (p = find_domain_by_id(id)) == NULL)
   2.754 -		        strcpy (pdb_out_buffer, "E00");
   2.755 -		    else
   2.756 -		        strcpy (pdb_out_buffer, "OK");
   2.757 -		    put_domain(p);
   2.758 -
   2.759 -		    pdb_level = PDB_LVL_GUESTOS;
   2.760 -		    pdb_ctx[pdb_level].ctrl = id;
   2.761 -		    pdb_ctx[pdb_level].info = id;
   2.762 -		    break;
   2.763 -		}
   2.764 -	        case PDB_LVL_GUESTOS:
   2.765 -		{
   2.766 -		    if (pdb_level == -1)
   2.767 -		    {
   2.768 -		        pdb_level = PDB_LVL_XEN;
   2.769 -		    }
   2.770 -		    else
   2.771 -		    {
   2.772 -		        pdb_level = PDB_LVL_PROCESS;
   2.773 -			pdb_ctx[pdb_level].ctrl = id;
   2.774 -			pdb_ctx[pdb_level].info = id;
   2.775 -		    }
   2.776 -		    break;
   2.777 -		}
   2.778 -	        case PDB_LVL_PROCESS:
   2.779 -		{
   2.780 -		    if (pdb_level == -1)
   2.781 -		    {
   2.782 -		        pdb_level = PDB_LVL_GUESTOS;
   2.783 -		    }
   2.784 -		    break;
   2.785 -		}
   2.786 -	        default:
   2.787 -		{
   2.788 -		    printk ("pdb internal error: invalid level [%d]\n", 
   2.789 -			    pdb_level);
   2.790 -		}
   2.791 -	    }
   2.792 -
   2.793 -#endif /* PDB_PAST */
   2.794          }
   2.795          break;
   2.796      }
   2.797 +    case 'Z':                                                         /* set */
   2.798 +    {
   2.799 +        pdb_process_z (1, ptr);
   2.800 +	break;
   2.801 +    }
   2.802 +    case 'z':                                                       /* clear */
   2.803 +    {
   2.804 +        pdb_process_z (0, ptr);
   2.805 +	break;
   2.806 +    }
   2.807 +    case '.':                                     /* pdb specific extensions */
   2.808 +    {
   2.809 +        pdb_process_pdb (ptr);
   2.810 +	break;
   2.811 +    }
   2.812 +    default:
   2.813 +    {
   2.814 +        PDBTRC(1,printk ("pdb warning: ignoring unknown command.\n"));
   2.815 +	break;
   2.816 +    }
   2.817      }
   2.818  
   2.819  exit:
   2.820 @@ -712,8 +894,8 @@ int pdb_serial_input(u_char c, struct pt
   2.821  	if (pdb_in_checksum != pdb_xmit_checksum) 
   2.822  	{
   2.823  	    pdb_put_char('-');                           /* checksum failure */
   2.824 -	    printk ("checksum failure [%s.%02x.%02x]\n", pdb_in_buffer,
   2.825 -		    pdb_in_checksum, pdb_xmit_checksum);
   2.826 +	    printk ("pdb error: checksum failure [%s.%02x.%02x]\n",
   2.827 +		    pdb_in_buffer, pdb_in_checksum, pdb_xmit_checksum);
   2.828  	}
   2.829  	else 
   2.830  	{
   2.831 @@ -738,6 +920,9 @@ int pdb_serial_input(u_char c, struct pt
   2.832      return out;
   2.833  }
   2.834  
   2.835 +/***********************************************************************/
   2.836 +/***********************************************************************/
   2.837 +
   2.838  int hex(char ch)
   2.839  {
   2.840      if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
   2.841 @@ -759,7 +944,8 @@ mem2hex (mem, buf, count)
   2.842  
   2.843      for (i = 0; i < count; i++)
   2.844      {
   2.845 -        ch = get_char (mem++);
   2.846 +        ch = *mem;
   2.847 +	mem ++;
   2.848          *buf++ = hexchars[ch >> 4];
   2.849          *buf++ = hexchars[ch % 16];
   2.850      }
   2.851 @@ -782,7 +968,8 @@ hex2mem (buf, mem, count)
   2.852      {
   2.853          ch = hex (*buf++) << 4;
   2.854          ch = ch + hex (*buf++);
   2.855 -        set_char (mem++, ch);
   2.856 +        *mem = ch;
   2.857 +	mem++;
   2.858      }
   2.859      return (mem);
   2.860  }
   2.861 @@ -826,150 +1013,153 @@ hexToInt (char **ptr, int *intValue)
   2.862  /***********************************************************************/
   2.863  /***********************************************************************/
   2.864  
   2.865 +/* READ / WRITE MEMORY */
   2.866 +int pdb_change_page (u_char *buffer, int length,
   2.867 +		     unsigned long cr3, unsigned long addr, int rw);
   2.868 +int pdb_visit_memory (unsigned long addr, int length, unsigned char *data,
   2.869 +		      pdb_context_p ctx, pdb_generic_action action);
   2.870  
   2.871 -/*
   2.872 - * Add a breakpoint to the list of known breakpoints.
   2.873 - * For now there should only be two or three breakpoints so
   2.874 - * we use a simple linked list.  In the future, maybe a red-black tree?
   2.875 - */
   2.876 -struct pdb_breakpoint breakpoints;
   2.877 +int 
   2.878 +pdb_read_memory (unsigned long addr, int length, unsigned char *data,
   2.879 +		 pdb_context_p ctx)
   2.880 +{
   2.881 +    return pdb_visit_memory (addr, length, data, ctx, __PDB_GET);
   2.882 +}
   2.883  
   2.884 -void pdb_bkpt_add (unsigned long cr3, unsigned long address)
   2.885 +int
   2.886 +pdb_write_memory (unsigned long addr, int length, unsigned char *data,
   2.887 +		  pdb_context_p ctx)
   2.888  {
   2.889 -    struct pdb_breakpoint *bkpt = xmalloc(sizeof(*bkpt));
   2.890 -    bkpt->cr3 = cr3;
   2.891 -    bkpt->address = address;
   2.892 -    list_add(&bkpt->list, &breakpoints.list);
   2.893 +    return pdb_visit_memory (addr, length, data, ctx, __PDB_SET);
   2.894  }
   2.895  
   2.896  /*
   2.897 - * Check to see of the breakpoint is in the list of known breakpoints 
   2.898 - * Return 1 if it has been set, NULL otherwise.
   2.899 + * either read or write a block of memory 
   2.900   */
   2.901 -struct pdb_breakpoint* pdb_bkpt_search (unsigned long cr3, 
   2.902 -					unsigned long address)
   2.903 +
   2.904 +int
   2.905 +pdb_visit_memory (unsigned long addr, int length, unsigned char *data,
   2.906 +		  pdb_context_p ctx, pdb_generic_action action)
   2.907  {
   2.908 -    struct list_head *list_entry;
   2.909 -    struct pdb_breakpoint *bkpt;
   2.910 +    int return_value;
   2.911 +    pdb_invoke_args_t args;
   2.912 +
   2.913 +    pdb_page_fault_possible = 4;
   2.914 +    pdb_page_fault = 0;
   2.915 +
   2.916 +    args.context = ctx;
   2.917 +    args.address = addr;
   2.918 +    args.length = length;
   2.919 +    args.data = data;
   2.920  
   2.921 -    list_for_each(list_entry, &breakpoints.list)
   2.922 +    if (addr >= PAGE_OFFSET)                                          /* Xen */
   2.923 +    {
   2.924 +        args.action = (action == __PDB_GET) ? PDB_VISIT_PAGE_XEN_READ
   2.925 +                                            : PDB_VISIT_PAGE_XEN_WRITE;
   2.926 +    }
   2.927 +    else if (pdb_ctx.process != -1)                               /* Process */
   2.928      {
   2.929 -        bkpt = list_entry(list_entry, struct pdb_breakpoint, list);
   2.930 -	if ( bkpt->cr3 == cr3 && bkpt->address == address )
   2.931 -            return bkpt;
   2.932 +        args.action = (action == __PDB_GET) ? PDB_VISIT_PAGE_PROCESS_READ
   2.933 +                                            : PDB_VISIT_PAGE_PROCESS_WRITE;
   2.934 +    }
   2.935 +    else                                                           /* Domain */
   2.936 +    {
   2.937 +        args.action = (action == __PDB_GET) ? PDB_VISIT_PAGE_DOMAIN_READ
   2.938 +                                            : PDB_VISIT_PAGE_DOMAIN_WRITE;
   2.939      }
   2.940  
   2.941 -    return NULL;
   2.942 -}
   2.943 -
   2.944 -/*
   2.945 - * Remove a breakpoint to the list of known breakpoints.
   2.946 - * Return 1 if the element was not found, otherwise 0.
   2.947 - */
   2.948 -int pdb_bkpt_remove (unsigned long cr3, unsigned long address)
   2.949 -{
   2.950 -    struct list_head *list_entry;
   2.951 -    struct pdb_breakpoint *bkpt;
   2.952 +    return_value = pdb_invoke (pdb_visit_page, &args);
   2.953  
   2.954 -    list_for_each(list_entry, &breakpoints.list)
   2.955 +    pdb_page_fault_possible = 0;
   2.956 +    if (pdb_page_fault || return_value < 0)
   2.957      {
   2.958 -        bkpt = list_entry(list_entry, struct pdb_breakpoint, list);
   2.959 -	if ( bkpt->cr3 == cr3 && bkpt->address == address )
   2.960 -	{
   2.961 -            list_del(&bkpt->list);
   2.962 -            xfree(bkpt);
   2.963 -            return 0;
   2.964 -	}
   2.965 +        strcpy (pdb_out_buffer, "E03");
   2.966      }
   2.967 -
   2.968 -    return 1;
   2.969 +  
   2.970 +    return return_value;
   2.971  }
   2.972  
   2.973  /*
   2.974 - * Check to see if a memory write is really gdb setting a breakpoint
   2.975 + * either read or write a single page
   2.976   */
   2.977 -void pdb_bkpt_check (u_char *buffer, int length,
   2.978 -		     unsigned long cr3, unsigned long addr)
   2.979 +
   2.980 +int 
   2.981 +pdb_visit_page (int action, unsigned long addr, int length, 
   2.982 +		pdb_context_p ctx, int offset, void *data)
   2.983  {
   2.984 -    if (length == 1 && buffer[0] == 'c' && buffer[1] == 'c')
   2.985 -    {
   2.986 -        /* inserting a new breakpoint */
   2.987 -        pdb_bkpt_add(cr3, addr);
   2.988 -        TRC(printk("pdb breakpoint detected at 0x%lx:0x%lx\n", cr3, addr));
   2.989 -    }
   2.990 -    else if ( pdb_bkpt_remove(cr3, addr) == 0 )
   2.991 -    {
   2.992 -        /* removing a breakpoint */
   2.993 -        TRC(printk("pdb breakpoint cleared at 0x%lx:0x%lx\n", cr3, addr));
   2.994 -    }
   2.995 +  int rval;
   2.996 +  
   2.997 +  PDBTRC(2,printk ("visit: %s [0x%08lx:%x] 0x%x (0x%p)\n",
   2.998 +		   pdb_visit_page_action_s[action], 
   2.999 +		   addr, length, offset, data));
  2.1000 +
  2.1001 +  switch (action)
  2.1002 +  {
  2.1003 +  case PDB_VISIT_PAGE_XEN_READ :
  2.1004 +  {
  2.1005 +      memcpy ((void *) data, (void *) addr, length);
  2.1006 +      rval = length;;
  2.1007 +      break;
  2.1008 +  }
  2.1009 +  case PDB_VISIT_PAGE_XEN_WRITE :
  2.1010 +  {
  2.1011 +      memcpy ((void *) addr, (void *) data, length);
  2.1012 +      rval = length;
  2.1013 +      break;
  2.1014 +  }
  2.1015 +  case PDB_VISIT_PAGE_DOMAIN_READ :
  2.1016 +  case PDB_VISIT_PAGE_DOMAIN_WRITE :
  2.1017 +  {
  2.1018 +      rval = pdb_change_page (data, length, ctx->ptbr, addr,
  2.1019 +               (action == PDB_VISIT_PAGE_DOMAIN_READ) ? __PDB_GET : __PDB_SET);
  2.1020 +      break;
  2.1021 +  }
  2.1022 +  case PDB_VISIT_PAGE_PROCESS_READ :
  2.1023 +  case PDB_VISIT_PAGE_PROCESS_WRITE :
  2.1024 +  {
  2.1025 +      u_char pdb_linux_visit_page(int pid, unsigned long cr3, unsigned long addr, int length, unsigned char *buffer, int action);
  2.1026 +
  2.1027 +      rval = pdb_linux_visit_page (ctx->process, ctx->ptbr, addr, length, data,
  2.1028 +              (action == PDB_VISIT_PAGE_PROCESS_READ) ? __PDB_GET : __PDB_SET);
  2.1029 +      break;
  2.1030 +  }
  2.1031 +  default :
  2.1032 +  {
  2.1033 +      printk ("pdb error: unknown visit page action [%d]\n", action);
  2.1034 +      break;
  2.1035 +  }
  2.1036 +  }
  2.1037 +
  2.1038 +  return 1;
  2.1039  }
  2.1040  
  2.1041 -/***********************************************************************/
  2.1042 -
  2.1043 -int pdb_change_values(u_char *buffer, int length,
  2.1044 -		      unsigned long cr3, unsigned long addr, int rw);
  2.1045 -int pdb_change_values_one_page(u_char *buffer, int length,
  2.1046 -			       unsigned long cr3, unsigned long addr, int rw);
  2.1047 -
  2.1048 -#define __PDB_GET_VAL 1
  2.1049 -#define __PDB_SET_VAL 2
  2.1050 +/**************************************/
  2.1051 +/**************************************/
  2.1052  
  2.1053 -/*
  2.1054 - * Set memory in a domain's address space
  2.1055 - * Set "length" bytes at "address" from "domain" to the values in "buffer".
  2.1056 - * Return the number of bytes set, 0 if there was a problem.
  2.1057 - */
  2.1058 +int
  2.1059 +pdb_read_page(u_char *buffer, int length,
  2.1060 +		unsigned long cr3, unsigned long addr)
  2.1061 +{
  2.1062 +    return pdb_change_page(buffer, length, cr3, addr, __PDB_GET);
  2.1063 +}
  2.1064  
  2.1065 -int pdb_set_values(u_char *buffer, int length,
  2.1066 -		   unsigned long cr3, unsigned long addr)
  2.1067 +int
  2.1068 +pdb_write_page(u_char *buffer, int length,
  2.1069 +	       unsigned long cr3, unsigned long addr)
  2.1070  {
  2.1071 -    int count = pdb_change_values(buffer, length, cr3, addr, __PDB_SET_VAL);
  2.1072 -    return count;
  2.1073 +    return pdb_change_page(buffer, length, cr3, addr, __PDB_SET);
  2.1074  }
  2.1075  
  2.1076  /*
  2.1077 - * Read memory from a domain's address space.
  2.1078 - * Fetch "length" bytes at "address" from "domain" into "buffer".
  2.1079 - * Return the number of bytes read, 0 if there was a problem.
  2.1080 - */
  2.1081 -
  2.1082 -int pdb_get_values(u_char *buffer, int length,
  2.1083 -		   unsigned long cr3, unsigned long addr)
  2.1084 -{
  2.1085 -  return pdb_change_values(buffer, length, cr3, addr, __PDB_GET_VAL);
  2.1086 -}
  2.1087 -
  2.1088 -/*
  2.1089 - * Read or write memory in an address space
  2.1090 - */
  2.1091 -int pdb_change_values(u_char *buffer, int length,
  2.1092 -		      unsigned long cr3, unsigned long addr, int rw)
  2.1093 -{
  2.1094 -    int remaining;                /* number of bytes to touch past this page */
  2.1095 -    int bytes = 0;
  2.1096 -
  2.1097 -    while ( (remaining = (addr + length - 1) - (addr | (PAGE_SIZE - 1))) > 0)
  2.1098 -    {
  2.1099 -        bytes += pdb_change_values_one_page(buffer, length - remaining, 
  2.1100 -					    cr3, addr, rw);
  2.1101 -	buffer = buffer + (2 * (length - remaining));
  2.1102 -	length = remaining;
  2.1103 -	addr = (addr | (PAGE_SIZE - 1)) + 1;
  2.1104 -    }
  2.1105 -
  2.1106 -    bytes += pdb_change_values_one_page(buffer, length, cr3, addr, rw);
  2.1107 -    return bytes;
  2.1108 -}
  2.1109 -
  2.1110 -/*
  2.1111 - * Change memory in a process' address space in one page
  2.1112 + * Change memory in one page of an address space.
  2.1113   * Read or write "length" bytes at "address" into/from "buffer"
  2.1114   * from the virtual address space referenced by "cr3".
  2.1115   * Return the number of bytes read, 0 if there was a problem.
  2.1116   */
  2.1117  
  2.1118 -int pdb_change_values_one_page(u_char *buffer, int length,
  2.1119 -			       unsigned long cr3, unsigned long addr, int rw)
  2.1120 +int
  2.1121 +pdb_change_page(u_char *buffer, int length,
  2.1122 +		unsigned long cr3, unsigned long addr, int rw)
  2.1123  {
  2.1124      l2_pgentry_t* l2_table = NULL;                         /* page directory */
  2.1125      l1_pgentry_t* l1_table = NULL;                             /* page table */
  2.1126 @@ -980,10 +1170,11 @@ int pdb_change_values_one_page(u_char *b
  2.1127      l2_table += l2_table_offset(addr);
  2.1128      if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 
  2.1129      {
  2.1130 -	if (pdb_page_fault_possible == 1)
  2.1131 +	if (pdb_page_fault_possible)
  2.1132  	{
  2.1133  	    pdb_page_fault = 1;
  2.1134 -	    TRC(printk("pdb: L2 error (0x%lx)\n", addr));
  2.1135 +	    PDBTRC2(1,printk("pdb: expected L2 error %d (0x%lx)\n", 
  2.1136 +			     pdb_page_fault_possible, addr));
  2.1137  	}
  2.1138  	else
  2.1139  	{
  2.1140 @@ -1021,7 +1212,7 @@ int pdb_change_values_one_page(u_char *b
  2.1141  	    if (pdb_page_fault_possible == 1)
  2.1142  	    {
  2.1143  	        pdb_page_fault = 1;
  2.1144 -		TRC(printk ("pdb: L1 error (0x%lx)\n", addr));
  2.1145 +		PDBTRC(1,printk ("pdb: L1 error (0x%lx)\n", addr));
  2.1146  	    }
  2.1147  	    else
  2.1148  	    {
  2.1149 @@ -1038,18 +1229,25 @@ int pdb_change_values_one_page(u_char *b
  2.1150  
  2.1151      switch (rw)
  2.1152      {
  2.1153 -    case __PDB_GET_VAL:                                              /* read */
  2.1154 +    case __PDB_GET:                                                  /* read */
  2.1155 +    {
  2.1156          memcpy (buffer, page, length);
  2.1157  	bytes = length;
  2.1158 +
  2.1159 +	break;
  2.1160 +    }
  2.1161 +    case __PDB_SET:                                                 /* write */
  2.1162 +    {
  2.1163 +        memcpy (page, buffer, length);
  2.1164 +	bytes = length;
  2.1165  	break;
  2.1166 -    case __PDB_SET_VAL:                                             /* write */
  2.1167 -        hex2mem (buffer, page, length);
  2.1168 -	bytes = length;
  2.1169 -	break;
  2.1170 +    }
  2.1171      default:                                                      /* unknown */
  2.1172 -        printk ("error: unknown RW flag: %d\n", rw);
  2.1173 +    {
  2.1174 +        printk ("pdb error: unknown RW flag: %d\n", rw);
  2.1175  	return 0;
  2.1176      }
  2.1177 +    }
  2.1178  
  2.1179      unmap_domain_mem((void *)page); 
  2.1180  exit1:
  2.1181 @@ -1061,9 +1259,146 @@ exit2:
  2.1182      return bytes;
  2.1183  }
  2.1184  
  2.1185 +
  2.1186 +/***********************************************************************/
  2.1187 +/***********************************************************************/
  2.1188 +
  2.1189 +/* BREAKPOINTS */
  2.1190 +
  2.1191 +int
  2.1192 +pdb_set_breakpoint (pdb_bwcpoint_p bwc)
  2.1193 +{
  2.1194 +    pdb_read_memory (bwc->address, 1, &bwc->original, &bwc->context);
  2.1195 +    pdb_write_memory (bwc->address, 1, &pdb_x86_bkpt, &bwc->context);
  2.1196 +
  2.1197 +    pdb_bwc_list_add (bwc);
  2.1198 +
  2.1199 +    return 0;
  2.1200 +}
  2.1201 +
  2.1202 +int
  2.1203 +pdb_clear_breakpoint (unsigned long address, int length, pdb_context_p ctx)
  2.1204 +{
  2.1205 +    int error = 0;
  2.1206 +    pdb_bwcpoint_p bwc = pdb_bwc_list_search (address, 1, &pdb_ctx);
  2.1207 +
  2.1208 +    if (bwc == 0)
  2.1209 +    {
  2.1210 +      error = 3;                                     /* breakpoint not found */
  2.1211 +    }
  2.1212 +
  2.1213 +    pdb_write_memory (address, 1, &bwc->original, &pdb_ctx);
  2.1214 +    
  2.1215 +    pdb_bwc_list_remove (bwc);
  2.1216 +
  2.1217 +    return error;
  2.1218 +}
  2.1219 +
  2.1220 +/***********************************************************************/
  2.1221  /***********************************************************************/
  2.1222  
  2.1223 -void breakpoint(void);
  2.1224 +/* WATCHPOINTS */
  2.1225 +
  2.1226 +int pdb_process_watchpoint (pdb_bwcpoint_p bwc, pdb_generic_action action);
  2.1227 +
  2.1228 +int
  2.1229 +pdb_set_watchpoint (pdb_bwcpoint_p bwc)
  2.1230 +{
  2.1231 +    return pdb_process_watchpoint (bwc, __PDB_SET);
  2.1232 +}
  2.1233 +
  2.1234 +int
  2.1235 +pdb_clear_watchpoint (pdb_bwcpoint_p bwc)
  2.1236 +{
  2.1237 +    return pdb_process_watchpoint (bwc, __PDB_CLEAR);
  2.1238 +}
  2.1239 +
  2.1240 +/* set or clear watchpoint */
  2.1241 +int
  2.1242 +pdb_process_watchpoint (pdb_bwcpoint_p bwc, pdb_generic_action action)
  2.1243 +{
  2.1244 +    int return_value;
  2.1245 +    pdb_invoke_args_t args;
  2.1246 +
  2.1247 +    args.context = &bwc->context;
  2.1248 +    args.address = bwc->address;
  2.1249 +    args.length = bwc->length;
  2.1250 +    args.data = bwc;
  2.1251 +    switch (bwc->type)
  2.1252 +    {
  2.1253 +    case PDB_WP_WRITE :
  2.1254 +    {
  2.1255 +        args.action = (action == __PDB_SET) ? PDB_BWC_PAGE_WRITE_SET 
  2.1256 +                                            : PDB_BWC_PAGE_WRITE_CLEAR;
  2.1257 +	break;       
  2.1258 +    }
  2.1259 +    case PDB_WP_READ :
  2.1260 +    {
  2.1261 +        args.action = (action == __PDB_SET) ? PDB_BWC_PAGE_READ_SET 
  2.1262 +                                            : PDB_BWC_PAGE_READ_CLEAR;
  2.1263 +	break;       
  2.1264 +    }
  2.1265 +    case PDB_WP_ACCESS :
  2.1266 +    {
  2.1267 +        args.action = (action == __PDB_SET) ? PDB_BWC_PAGE_ACCESS_SET 
  2.1268 +                                            : PDB_BWC_PAGE_ACCESS_CLEAR;
  2.1269 +	break;       
  2.1270 +    }
  2.1271 +    default :
  2.1272 +    {
  2.1273 +        printk ("pdb error: incorrect watchpoint type [%d][%s]",
  2.1274 +		bwc->type, pdb_bwcpoint_type_s[bwc->type]);
  2.1275 +        break;
  2.1276 +    }
  2.1277 +    }
  2.1278 +
  2.1279 +    return_value = pdb_invoke (pdb_bwc_page, &args);
  2.1280 +
  2.1281 +    if (return_value < 0)
  2.1282 +    {
  2.1283 +         strcpy (pdb_out_buffer, "E03");
  2.1284 +    }
  2.1285 +
  2.1286 +    return return_value;
  2.1287 +}
  2.1288 +
  2.1289 +/*
  2.1290 + * set or clear watchpoint for a single page 
  2.1291 + */
  2.1292 +
  2.1293 +int 
  2.1294 +pdb_bwc_page (int action, unsigned long addr, int length, 
  2.1295 +	      pdb_context_p ctx, int offset, void *data)
  2.1296 +{
  2.1297 +    int rval = 0;
  2.1298 +
  2.1299 +    printk ("bwc: %s [0x%08lx:%x] 0x%x (0x%p)\n",
  2.1300 +	    pdb_bwc_page_action_s[action], addr, length, offset, data);
  2.1301 +
  2.1302 +    switch (action)
  2.1303 +    {
  2.1304 +    case PDB_BWC_PAGE_ACCESS_SET :
  2.1305 +    case PDB_BWC_PAGE_ACCESS_CLEAR : 
  2.1306 +    case PDB_BWC_PAGE_WRITE_SET :
  2.1307 +    case PDB_BWC_PAGE_WRITE_CLEAR :
  2.1308 +    case PDB_BWC_PAGE_READ_SET :
  2.1309 +    case PDB_BWC_PAGE_READ_CLEAR :
  2.1310 +    {
  2.1311 +        printk ("fill in the blank [%s:%d]\n", __FILE__, __LINE__);
  2.1312 +        break;
  2.1313 +    }
  2.1314 +    default :
  2.1315 +    {
  2.1316 +        printk ("pdb error: unknown bwc page action [%d]\n", action);
  2.1317 +	break;
  2.1318 +    }
  2.1319 +    }
  2.1320 +
  2.1321 +    return rval;
  2.1322 +}
  2.1323 +
  2.1324 +/***********************************************************************/
  2.1325 +/***********************************************************************/
  2.1326  
  2.1327  /* send the packet in buffer.  */
  2.1328  void pdb_put_packet (unsigned char *buffer, int ack)
  2.1329 @@ -1114,7 +1449,7 @@ void pdb_get_packet(char *buffer)
  2.1330  	count = 0;
  2.1331  	checksum = 0;
  2.1332  
  2.1333 -	while (count < BUFMAX)
  2.1334 +	while (count < PDB_BUFMAX)
  2.1335  	{
  2.1336  	    ch = pdb_get_char();
  2.1337  	    if (ch  == '#') break;
  2.1338 @@ -1132,10 +1467,11 @@ void pdb_get_packet(char *buffer)
  2.1339  	    if (xmitcsum == checksum)
  2.1340  	    {
  2.1341  	        pdb_put_char('+');
  2.1342 +
  2.1343 +#ifdef GDB_50_SUPPORT
  2.1344  		if (buffer[2] == ':')
  2.1345 -		{
  2.1346 -		    printk ("pdb: obsolete gdb packet (sequence ID)\n");
  2.1347 -		}
  2.1348 +		  { printk ("pdb: obsolete gdb packet (sequence ID)\n"); }
  2.1349 +#endif
  2.1350  	    }
  2.1351  	    else
  2.1352  	    {
  2.1353 @@ -1157,22 +1493,34 @@ int pdb_handle_exception(int exceptionVe
  2.1354  			 struct pt_regs *xen_regs)
  2.1355  {
  2.1356      int signal = 0;
  2.1357 -    struct pdb_breakpoint* bkpt;
  2.1358 +    struct pdb_bwcpoint* bkpt;
  2.1359      int watchdog_save;
  2.1360      unsigned long cr3;
  2.1361  
  2.1362      __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : );
  2.1363  
  2.1364 +PDBTRC(4,printk("pdb handle exception\n"));
  2.1365 +PDBTRC(4,printk("    cr3: 0x%lx\n", cr3));
  2.1366 +PDBTRC(4,printk("    eip: 0x%lx\n", xen_regs->eip));
  2.1367 +PDBTRC(4,printk("    except vector: 0x%x\n", exceptionVector));
  2.1368 +PDBTRC(4,printk("    xcs: 0x%x\n", xen_regs->xcs));
  2.1369 +PDBTRC(4,printk("    sys call next addr: 0x%lx\n", pdb_system_call_next_addr));
  2.1370 +PDBTRC(4,printk("    stepping: 0x%x\n", pdb_stepping));
  2.1371 +PDBTRC(4,printk("    system_call: 0x%x\n", pdb_system_call));
  2.1372 +
  2.1373      /* If the exception is an int3 from user space then pdb is only
  2.1374         interested if it re-wrote an instruction set the breakpoint.
  2.1375         This occurs when leaving a system call from a domain.
  2.1376      */
  2.1377 -    if ( exceptionVector == 3 &&
  2.1378 +    bkpt = pdb_bwcpoint_search(cr3, xen_regs->eip - 1);
  2.1379 +    if ( bkpt == NULL &&
  2.1380 +         exceptionVector == 3 &&
  2.1381  	 (xen_regs->xcs & 3) == 3 && 
  2.1382  	 xen_regs->eip != pdb_system_call_next_addr + 1)
  2.1383      {
  2.1384 -        TRC(printf("pdb: user bkpt (0x%x) at 0x%x:0x%lx:0x%lx\n", 
  2.1385 -		   exceptionVector, xen_regs->xcs & 3, cr3, xen_regs->eip));
  2.1386 +        PDBTRC(1,printk("pdb: user bkpt (0x%x) at 0x%x:0x%lx:0x%lx 0x%lx\n", 
  2.1387 +			exceptionVector, xen_regs->xcs & 3, cr3, 
  2.1388 +			xen_regs->eip, pdb_system_call_next_addr));
  2.1389  	return 1;
  2.1390      }
  2.1391  
  2.1392 @@ -1182,7 +1530,6 @@ int pdb_handle_exception(int exceptionVe
  2.1393       * the user didn't press the magic debug key, 
  2.1394       * then we don't handle the exception.
  2.1395       */
  2.1396 -    bkpt = pdb_bkpt_search(cr3, xen_regs->eip - 1);
  2.1397      if ( (bkpt == NULL) &&
  2.1398           !pdb_stepping && 
  2.1399  	 !pdb_system_call &&
  2.1400 @@ -1190,8 +1537,8 @@ int pdb_handle_exception(int exceptionVe
  2.1401  	 (exceptionVector != KEYPRESS_EXCEPTION) &&
  2.1402  	 xen_regs->eip < 0xc0000000)  /* Linux-specific for now! */
  2.1403      {
  2.1404 -        TRC(printf("pdb: user bkpt (0x%x) at 0x%lx:0x%lx\n", 
  2.1405 -		   exceptionVector, cr3, xen_regs->eip));
  2.1406 +        PDBTRC(1,printk("pdb: user bkpt (0x%x) at 0x%lx:0x%lx\n", 
  2.1407 +		     exceptionVector, cr3, xen_regs->eip));
  2.1408  	return 1;
  2.1409      }
  2.1410  
  2.1411 @@ -1222,22 +1569,23 @@ int pdb_handle_exception(int exceptionVe
  2.1412  	}
  2.1413      }
  2.1414  
  2.1415 -    if ( exceptionVector == BREAKPT_EXCEPTION && bkpt != NULL)
  2.1416 -    {
  2.1417 -        /* Executed Int3: replace breakpoint byte with real program byte. */
  2.1418 -        xen_regs->eip--;
  2.1419 -    }
  2.1420 -
  2.1421      /* returning to user space after a system call */
  2.1422      if ( xen_regs->eip == pdb_system_call_next_addr + 1)
  2.1423      {
  2.1424 -        u_char instr[2];                      /* REALLY REALLY REALLY STUPID */
  2.1425 -
  2.1426 -	mem2hex (&pdb_system_call_leave_instr, instr, sizeof(instr)); 
  2.1427 +	 printk("BUG ******** \n");
  2.1428 +         printk("BUG return to user space bug\n");
  2.1429 +	 printk("BUG ******** \n");
  2.1430  
  2.1431 -	pdb_linux_set_values (instr, 1, pdb_system_call_next_addr,
  2.1432 -			      pdb_ctx.process, pdb_ctx.ptbr);
  2.1433 +        /*
  2.1434 +	 * BUG: remember to delete the breakpoint!!!
  2.1435 +	 *       
  2.1436 +	 */
  2.1437  
  2.1438 +        /* this is always in a process context */
  2.1439 +        pdb_write_memory (pdb_system_call_next_addr,
  2.1440 +			  sizeof(pdb_system_call_leave_instr),
  2.1441 +			  &pdb_system_call_leave_instr, &pdb_ctx);
  2.1442 + 
  2.1443  	pdb_system_call_next_addr = 0;
  2.1444  	pdb_system_call_leave_instr = 0;
  2.1445  
  2.1446 @@ -1253,6 +1601,13 @@ int pdb_handle_exception(int exceptionVe
  2.1447  	}
  2.1448      }
  2.1449  
  2.1450 +
  2.1451 +    if ( exceptionVector == BREAKPT_EXCEPTION && bkpt != NULL)
  2.1452 +    {
  2.1453 +        /* Executed Int3: replace breakpoint byte with real program byte. */
  2.1454 +        xen_regs->eip--;
  2.1455 +    }
  2.1456 +
  2.1457      /* Generate a signal for GDB. */
  2.1458      switch ( exceptionVector )
  2.1459      {
  2.1460 @@ -1303,9 +1658,6 @@ void initialize_pdb()
  2.1461  {
  2.1462      extern char opt_pdb[];
  2.1463  
  2.1464 -    /* Certain state must be initialised even when PDB will not be used. */
  2.1465 -    memset((void *) &breakpoints, 0, sizeof(breakpoints));
  2.1466 -    INIT_LIST_HEAD(&breakpoints.list);
  2.1467      pdb_stepping = 0;
  2.1468  
  2.1469      if ( strcmp(opt_pdb, "none") == 0 )
  2.1470 @@ -1335,8 +1687,6 @@ void initialize_pdb()
  2.1471      pdb_initialized = 1;
  2.1472  }
  2.1473  
  2.1474 -void breakpoint(void)
  2.1475 -{
  2.1476 -    if ( pdb_initialized )
  2.1477 -        asm("int $3");
  2.1478 -}
  2.1479 +/***********************************************************************/
  2.1480 +/***********************************************************************/
  2.1481 +
     3.1 --- a/xen/common/debug-linux.c	Wed Jul 28 16:11:25 2004 +0000
     3.2 +++ b/xen/common/debug-linux.c	Wed Jul 28 17:18:40 2004 +0000
     3.3 @@ -45,7 +45,7 @@ static inline unsigned long machine_to_p
     3.4                                              unsigned long machine)
     3.5  {
     3.6    unsigned long phys;
     3.7 -  pdb_get_values((u_char *) &phys, sizeof(phys), cr3,
     3.8 +  pdb_read_page((u_char *) &phys, sizeof(phys), cr3,
     3.9  		 (unsigned long) machine_to_phys_mapping + 
    3.10                   (machine >> PAGE_SHIFT) * 4);
    3.11    phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
    3.12 @@ -75,20 +75,20 @@ unsigned long pdb_linux_pid_task_struct 
    3.13    unsigned long task_struct_pid;
    3.14  
    3.15    /* find the task_struct of the given process */
    3.16 -  pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
    3.17 +  pdb_read_page((u_char *) &task_struct_p, sizeof(task_struct_p),
    3.18  		 cr3, pdb_pidhash_addr + pid_hashfn(pid) * 4);
    3.19  
    3.20    /* find the correct task struct */
    3.21    while (task_struct_p != (unsigned long)NULL)
    3.22    {
    3.23 -    pdb_get_values((u_char *) &task_struct_pid, sizeof(task_struct_pid),
    3.24 +    pdb_read_page((u_char *) &task_struct_pid, sizeof(task_struct_pid),
    3.25  		   cr3, task_struct_p + task_struct_pid_offset);
    3.26      if (task_struct_pid == pid)
    3.27      {
    3.28        break;
    3.29      }
    3.30  
    3.31 -    pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
    3.32 +    pdb_read_page((u_char *) &task_struct_p, sizeof(task_struct_p),
    3.33  		   cr3, task_struct_p + task_struct_pidhash_next_offset);
    3.34    }
    3.35    if (task_struct_p == (unsigned long) NULL)
    3.36 @@ -116,96 +116,59 @@ unsigned long pdb_linux_pid_ptbr (unsign
    3.37    }
    3.38  
    3.39    /* get the mm_struct within the task_struct */
    3.40 -  pdb_get_values((u_char *) &mm_p, sizeof(mm_p),
    3.41 +  pdb_read_page((u_char *) &mm_p, sizeof(mm_p),
    3.42  		 cr3, task_struct_p + task_struct_mm_offset);
    3.43    /* get the page global directory (cr3) within the mm_struct */
    3.44 -  pdb_get_values((u_char *) &pgd, sizeof(pgd),
    3.45 +  pdb_read_page((u_char *) &pgd, sizeof(pgd),
    3.46  		 cr3, mm_p + mm_struct_pgd_offset);
    3.47  
    3.48    return pgd;
    3.49  }
    3.50  
    3.51  
    3.52 -
    3.53 -/* read a byte from a process 
    3.54 - *
    3.55 - * in: pid: process id
    3.56 - *     cr3: ptbr for the process' domain
    3.57 - *     addr: address to read
    3.58 - */
    3.59 -
    3.60 -u_char pdb_linux_get_value(int pid, unsigned long cr3, unsigned long addr)
    3.61 -{
    3.62 -  u_char result = 0;
    3.63 -  unsigned long pgd;
    3.64 -  unsigned long l2tab, page;
    3.65 -
    3.66 -  /* get the process' pgd */
    3.67 -  pgd = pdb_linux_pid_ptbr(cr3, pid);
    3.68 -
    3.69 -  /* get the l2 table entry */
    3.70 -  pdb_get_values((u_char *) &l2tab, sizeof(l2tab),
    3.71 -		 cr3, pgd + (addr >> PGDIR_SHIFT) * 4);
    3.72 -  l2tab = (unsigned long)__va(machine_to_phys(cr3, l2tab) & PAGE_MASK);
    3.73 +/* read / write values from one page */
    3.74  
    3.75 -  /* get the page table entry */
    3.76 -  pdb_get_values((u_char *) &page, sizeof(page),
    3.77 -		 cr3, l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4);
    3.78 -  page = (unsigned long)__va(machine_to_phys(cr3, page) & PAGE_MASK);
    3.79 -
    3.80 -  /* get the byte */
    3.81 -  pdb_get_values((u_char *) &result, sizeof(result),
    3.82 -		 cr3, page + (addr & ~PAGE_MASK));
    3.83 -
    3.84 -  return result;
    3.85 -}
    3.86 -
    3.87 -void pdb_linux_get_values(char *buffer, int length, unsigned long address,
    3.88 -			  int pid, unsigned long cr3)
    3.89 +u_char 
    3.90 +pdb_linux_visit_page(int pid, unsigned long cr3, unsigned long addr,
    3.91 +		     int length, unsigned char *buffer, int action)
    3.92  {
    3.93 -    int loop;
    3.94 -
    3.95 -    /* yes, this can be optimized... a lot */
    3.96 -    for (loop = 0; loop < length; loop++)
    3.97 -    {
    3.98 -        buffer[loop] = pdb_linux_get_value(pid, cr3, address + loop);
    3.99 -    }
   3.100 -}
   3.101 -
   3.102 - 
   3.103 -void pdb_linux_set_value(int pid, unsigned long cr3, unsigned long addr,
   3.104 -			 u_char *value)
   3.105 -{
   3.106 +    u_char result = 0;
   3.107      unsigned long pgd;
   3.108      unsigned long l2tab, page;
   3.109 - 
   3.110 +
   3.111      /* get the process' pgd */
   3.112      pgd = pdb_linux_pid_ptbr(cr3, pid);
   3.113 - 
   3.114 +
   3.115      /* get the l2 table entry */
   3.116 -    pdb_get_values((u_char *) &l2tab, sizeof(l2tab),
   3.117 -		   cr3, pgd + (addr >> PGDIR_SHIFT) * 4);
   3.118 +    pdb_read_page((u_char *) &l2tab, sizeof(l2tab),
   3.119 +		  cr3, pgd + (addr >> PGDIR_SHIFT) * 4);
   3.120      l2tab = (unsigned long)__va(machine_to_phys(cr3, l2tab) & PAGE_MASK);
   3.121 - 
   3.122 +
   3.123      /* get the page table entry */
   3.124 -    pdb_get_values((u_char *) &page, sizeof(page),
   3.125 -		   cr3, l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4);
   3.126 +    pdb_read_page((u_char *) &page, sizeof(page),
   3.127 +		  cr3, l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4);
   3.128      page = (unsigned long)__va(machine_to_phys(cr3, page) & PAGE_MASK);
   3.129 - 
   3.130 -    /* set the byte */
   3.131 -    pdb_set_values(value, sizeof(u_char), cr3, page + (addr & ~PAGE_MASK));
   3.132 -}
   3.133 - 
   3.134 -void pdb_linux_set_values(char *buffer, int length, unsigned long address,
   3.135 -			  int pid, unsigned long cr3)
   3.136 -{
   3.137 -    int loop;
   3.138 - 
   3.139 -    /* it's difficult to imagine a more inefficient algorithm */
   3.140 -    for (loop = 0; loop < length; loop++)
   3.141 +
   3.142 +    switch (action)
   3.143 +    {
   3.144 +    case __PDB_GET :
   3.145 +    {
   3.146 +        pdb_read_page(buffer, length, cr3, page + (addr & ~PAGE_MASK));
   3.147 +        break;
   3.148 +    }
   3.149 +    case __PDB_SET :
   3.150      {
   3.151 -        pdb_linux_set_value(pid, cr3, address + loop, &buffer[loop * 2]);
   3.152 +        pdb_write_page(buffer, length, cr3, page + (addr & ~PAGE_MASK));
   3.153 +        break;
   3.154      }
   3.155 +    default :
   3.156 +    {
   3.157 +        printk ("pdb error: linux_visit_page unknown action [%d]\n", action);
   3.158 +	break;
   3.159 +    }
   3.160 +    }
   3.161 +
   3.162 +    return result;
   3.163  }
   3.164  
   3.165  /**********************************************************************/
   3.166 @@ -232,18 +195,18 @@ int pdb_linux_process_list (unsigned lon
   3.167    int count = 0;
   3.168  
   3.169    /* task_p = init_task->next_task  */
   3.170 -  pdb_get_values((u_char *) &task_p, sizeof(task_p),
   3.171 +  pdb_read_page((u_char *) &task_p, sizeof(task_p),
   3.172  		 cr3, pdb_init_task_union_addr + task_struct_next_task_offset);
   3.173    
   3.174    while (task_p != pdb_init_task_union_addr)
   3.175    {
   3.176 -      pdb_get_values((u_char *) &pid, sizeof(pid),
   3.177 +      pdb_read_page((u_char *) &pid, sizeof(pid),
   3.178  		     cr3, task_p + task_struct_pid_offset);
   3.179  
   3.180        array[count % max] = pid;
   3.181        count++;
   3.182  
   3.183 -      pdb_get_values((u_char *) &next_p, sizeof(next_p),
   3.184 +      pdb_read_page((u_char *) &next_p, sizeof(next_p),
   3.185  		     cr3, task_p + task_struct_next_task_offset);
   3.186        task_p = next_p;
   3.187    }
   3.188 @@ -260,7 +223,7 @@ void pdb_linux_process_details (unsigned
   3.189  
   3.190    task_struct_p = pdb_linux_pid_task_struct(cr3, pid);
   3.191  
   3.192 -  pdb_get_values((u_char *) buffer, task_struct_comm_length,
   3.193 +  pdb_read_page((u_char *) buffer, task_struct_comm_length,
   3.194  		 cr3, task_struct_p + task_struct_comm_offset);
   3.195    return;
   3.196  }
     4.1 --- a/xen/common/debug.c	Wed Jul 28 16:11:25 2004 +0000
     4.2 +++ b/xen/common/debug.c	Wed Jul 28 17:18:40 2004 +0000
     4.3 @@ -65,7 +65,7 @@ void pdb_do_debug (dom0_op_t *op)
     4.4          case 'r' :
     4.5          {
     4.6              int loop;
     4.7 -            u_char x;
     4.8 +            u_char x = 0;
     4.9  	    unsigned long cr3;
    4.10  	    struct domain *d;
    4.11  
    4.12 @@ -81,8 +81,8 @@ void pdb_do_debug (dom0_op_t *op)
    4.13                  {
    4.14                      printk ("\n%08x ", op->u.debug.in1 + loop);
    4.15                  }
    4.16 -                x = pdb_linux_get_value(op->u.debug.in3,
    4.17 -					cr3, op->u.debug.in1 + loop);
    4.18 +		/* x = pdb_linux_get_value(op->u.debug.in3,
    4.19 +		   cr3, op->u.debug.in1 + loop); */
    4.20                  printk (" %02x", x);
    4.21              }
    4.22              printk ("\n");
     5.1 --- a/xen/include/asm-x86/pdb.h	Wed Jul 28 16:11:25 2004 +0000
     5.2 +++ b/xen/include/asm-x86/pdb.h	Wed Jul 28 17:18:40 2004 +0000
     5.3 @@ -26,11 +26,30 @@ extern int pdb_page_fault;
     5.4  
     5.5  extern void initialize_pdb(void);
     5.6  
     5.7 -/* Get/set values from generic debug interface. */
     5.8 -extern int pdb_set_values(u_char *buffer, int length,
     5.9 -                          unsigned long cr3, unsigned long addr);
    5.10 -extern int pdb_get_values(u_char *buffer, int length,
    5.11 -                          unsigned long cr3, unsigned long addr);
    5.12 +/*
    5.13 + * pdb debug context 
    5.14 + */
    5.15 +typedef struct pdb_context
    5.16 +{
    5.17 +    int valid;
    5.18 +    int domain;
    5.19 +    int process;
    5.20 +    int system_call;              /* 0x01 break on enter, 0x02 break on exit */
    5.21 +    unsigned long ptbr;
    5.22 +} pdb_context_t, *pdb_context_p;
    5.23 +
    5.24 +extern pdb_context_t pdb_ctx;
    5.25 +
    5.26 +/* read / write memory */
    5.27 +extern int pdb_read_memory (unsigned long addr, int length, 
    5.28 +			    unsigned char *data, pdb_context_p ctx);
    5.29 +extern int pdb_write_memory (unsigned long addr, int length, 
    5.30 +			     unsigned char *data, pdb_context_p ctx);
    5.31 +
    5.32 +extern int pdb_read_page (u_char *buffer, int length,
    5.33 +			  unsigned long cr3, unsigned long addr);
    5.34 +extern int pdb_write_page (u_char *buffer, int length,
    5.35 +			   unsigned long cr3, unsigned long addr);
    5.36  
    5.37  /* External entry points. */
    5.38  extern int pdb_handle_exception(int exceptionVector,
    5.39 @@ -38,29 +57,47 @@ extern int pdb_handle_exception(int exce
    5.40  extern int pdb_serial_input(u_char c, struct pt_regs *regs);
    5.41  extern void pdb_do_debug(dom0_op_t *op);
    5.42  
    5.43 -/* PDB Context. */
    5.44 -struct pdb_context
    5.45 +typedef enum pdb_generic_action
    5.46  {
    5.47 -    int valid;
    5.48 -    int domain;
    5.49 -    int process;
    5.50 -    int system_call;              /* 0x01 break on enter, 0x02 break on exit */
    5.51 -    unsigned long ptbr;
    5.52 +  __PDB_GET,
    5.53 +  __PDB_SET,
    5.54 +  __PDB_CLEAR
    5.55 +} pdb_generic_action;
    5.56 +
    5.57 +/*
    5.58 + * breakpoint, watchpoint, & catchpoint
    5.59 + * note: numbers must match GDB remote serial protocol Z command numbers
    5.60 + */
    5.61 +enum pdb_bwcpoint_type
    5.62 +{
    5.63 +  PDB_BP_SOFTWARE = 0,
    5.64 +  PDB_BP_HARDWARE = 1,
    5.65 +  PDB_WP_WRITE    = 2,
    5.66 +  PDB_WP_READ     = 3,
    5.67 +  PDB_WP_ACCESS   = 4
    5.68  };
    5.69 -extern struct pdb_context pdb_ctx;
    5.70  
    5.71 -/* Breakpoints. */
    5.72 -struct pdb_breakpoint
    5.73 +typedef struct pdb_bwcpoint
    5.74  {
    5.75 -    struct list_head list;
    5.76 -    unsigned long address;
    5.77 -    unsigned long cr3;
    5.78 -    domid_t domain;
    5.79 -};
    5.80 -extern void pdb_bkpt_add (unsigned long cr3, unsigned long address);
    5.81 -extern struct pdb_breakpoint* pdb_bkpt_search (unsigned long cr3, 
    5.82 -					       unsigned long address);
    5.83 -extern int pdb_bkpt_remove (unsigned long cr3, unsigned long address);
    5.84 +  struct list_head list;
    5.85 +  unsigned long address;
    5.86 +  int length;
    5.87 +  enum pdb_bwcpoint_type type;                            /* how implemented */
    5.88 +  enum pdb_bwcpoint_type user_type;                    /* what was requested */
    5.89 +  pdb_context_t context;
    5.90 +
    5.91 +  /* original value for breakpoint, one byte for x86 */
    5.92 +  unsigned char original;
    5.93 +} pdb_bwcpoint_t, *pdb_bwcpoint_p;
    5.94 +
    5.95 +void pdb_bwc_list_add (pdb_bwcpoint_p bwc);
    5.96 +void pdb_bwc_list_remove (pdb_bwcpoint_p bwc);
    5.97 +pdb_bwcpoint_p pdb_bwcpoint_search (unsigned long cr3, unsigned long address);
    5.98 +
    5.99 +int pdb_set_breakpoint (pdb_bwcpoint_p bwc);
   5.100 +int pdb_clear_breakpoint (unsigned long address, int length, 
   5.101 +			  pdb_context_p ctx);
   5.102 +
   5.103  
   5.104  /* Conversions. */
   5.105  extern int   hex (char);
   5.106 @@ -85,4 +122,10 @@ void pdb_linux_syscall_enter_bkpt (struc
   5.107  void pdb_linux_syscall_exit_bkpt (struct pt_regs *regs, 
   5.108  				  struct pdb_context *pdb_ctx);
   5.109  
   5.110 +/* tracing */
   5.111 +extern int pdb_trace;
   5.112 +#define PDBTRC(_lvl_, _blahblah_) if (_lvl_ & pdb_trace) {_blahblah_;}
   5.113 +#define PDBTRC2(_lvl_, _blahblah_) \
   5.114 +  if (_lvl_ & pdb_trace) {printk("[%s:%d]",__FILE__,__LINE__); _blahblah_;}
   5.115 +
   5.116  #endif  /* __PDB_H__ */