ia64/xen-unstable

changeset 1229:9269207cff3f

bitkeeper revision 1.812.1.1 (40631008stsWqMpK0QGxpKbL8XGwTw)

cr3 changes
author ach61@labyrinth.cl.cam.ac.uk
date Thu Mar 25 16:59:52 2004 +0000 (2004-03-25)
parents 6deb5c07e776
children bf27b8aaeb2f
files xen/arch/i386/pdb-stub.c xen/common/debug-linux.c xen/common/debug.c xen/include/asm-i386/pdb.h
line diff
     1.1 --- a/xen/arch/i386/pdb-stub.c	Fri Mar 19 14:49:10 2004 +0000
     1.2 +++ b/xen/arch/i386/pdb-stub.c	Thu Mar 25 16:59:52 2004 +0000
     1.3 @@ -1,15 +1,38 @@
     1.4 +
     1.5 +/*
     1.6 + * pervasive debugger
     1.7 + *
     1.8 + * alex ho
     1.9 + * 2004
    1.10 + * university of cambridge computer laboratory
    1.11 + */
    1.12 +
    1.13  #include <xeno/lib.h>
    1.14  #include <xeno/sched.h>
    1.15  #include <asm-i386/ptrace.h>
    1.16  #include <xeno/keyhandler.h> 
    1.17  #include <asm/apic.h>
    1.18 +#include <asm/domain_page.h>                           /* [un]map_domain_mem */
    1.19 +#include <asm/processor.h>
    1.20  #include <asm/pdb.h>
    1.21  #include <xeno/list.h>
    1.22  #include <xeno/serial.h>
    1.23  
    1.24 +#define DEBUG_TRACE
    1.25 +#ifdef DEBUG_TRACE
    1.26 +#define TRC(_x) _x
    1.27 +#else
    1.28 +#define TRC(_x)
    1.29 +#endif
    1.30 +
    1.31 +#define DEBUG_EXCEPTION     0x01
    1.32 +#define BREAKPT_EXCEPTION   0x03
    1.33 +#define PDB_LIVE_EXCEPTION  0x58
    1.34 +#define KEYPRESS_EXCEPTION  0x88
    1.35 +
    1.36  #define BUFMAX 400
    1.37  
    1.38 -#define PDB_DOMAIN_OFFSET 2              /* all domains are positive numbers */
    1.39 +#define PDB_ID_OFFSET 2        /* all threads & domains are positive numbers */
    1.40  
    1.41  static const char hexchars[]="0123456789abcdef";
    1.42  
    1.43 @@ -23,14 +46,24 @@ static int  pdb_in_buffer_ptr;
    1.44  static unsigned char  pdb_in_checksum;
    1.45  static unsigned char  pdb_xmit_checksum;
    1.46  
    1.47 -static int pdb_ctrl_thread = -1;
    1.48 -static int pdb_info_thread = -1;
    1.49 -static int pdb_stepping = 0;
    1.50 +struct pdb_ctx_element
    1.51 +{
    1.52 +    int ctrl;
    1.53 +    int info;
    1.54 +    unsigned long ctrl_cr3;
    1.55 +    unsigned long info_cr3;
    1.56 +};
    1.57 +
    1.58 +#define pdb_ctx_count 3
    1.59 +enum pdb_levels {PDB_LVL_XEN = 0, PDB_LVL_GUESTOS, PDB_LVL_PROCESS};
    1.60 +struct pdb_ctx_element pdb_ctx[pdb_ctx_count];
    1.61 +int pdb_level = PDB_LVL_XEN;
    1.62  
    1.63  void pdb_put_packet (unsigned char *buffer, int ack);
    1.64  
    1.65  int pdb_initialized = 0;
    1.66 -static int pdb_serhnd      = -1;
    1.67 +static int pdb_serhnd = -1;
    1.68 +static int pdb_stepping = 0;
    1.69  
    1.70  static inline void pdb_put_char(unsigned char c)
    1.71  {
    1.72 @@ -75,46 +108,136 @@ pdb_process_query (char *ptr)
    1.73      {
    1.74          struct task_struct *p;
    1.75          u_long flags;
    1.76 -	int count = 0, buf_idx = 0;
    1.77 +	int buf_idx = 0;
    1.78 +
    1.79 +	{                                                /* case pdb_lvl_xen */
    1.80 +	    int count = 0;
    1.81  
    1.82 -        read_lock_irqsave (&tasklist_lock, flags);
    1.83 +	    read_lock_irqsave (&tasklist_lock, flags);
    1.84 +
    1.85 +	    pdb_out_buffer[buf_idx++] = 'm';
    1.86 +	    for_each_domain ( p )
    1.87 +	    {
    1.88 +	        domid_t domain = p->domain + PDB_ID_OFFSET;
    1.89  
    1.90 -	pdb_out_buffer[buf_idx++] = 'm';
    1.91 -        for_each_domain ( p )
    1.92 +		if (count > 0)
    1.93 +		{
    1.94 +		    pdb_out_buffer[buf_idx++] = ',';
    1.95 +		}
    1.96 +		if (domain > 15)
    1.97 +		{
    1.98 +		    pdb_out_buffer[buf_idx++] = hexchars[domain >> 4];
    1.99 +		}
   1.100 +		pdb_out_buffer[buf_idx++] = hexchars[domain % 16];
   1.101 +		count++;
   1.102 +	    }
   1.103 +	    pdb_out_buffer[buf_idx++] = 0;
   1.104 +
   1.105 +	    read_unlock_irqrestore(&tasklist_lock, flags);
   1.106 +	}
   1.107 +
   1.108 +#ifdef PDB_FUTURE
   1.109 +
   1.110 +	switch (pdb_level)
   1.111  	{
   1.112 -	    domid_t domain = p->domain + PDB_DOMAIN_OFFSET;
   1.113 +	case PDB_LVL_XEN:                        /* return a list of domains */
   1.114 +	{
   1.115 +	    int count = 0;
   1.116 +
   1.117 +	    read_lock_irqsave (&tasklist_lock, flags);
   1.118 +
   1.119 +	    pdb_out_buffer[buf_idx++] = 'm';
   1.120 +	    for_each_domain ( p )
   1.121 +	    {
   1.122 +	        domid_t domain = p->domain + PDB_ID_OFFSET;
   1.123  
   1.124 -	    if (count > 0)
   1.125 -	        pdb_out_buffer[buf_idx++] = ',';
   1.126 -	    /*
   1.127 -              if (domain < 0)
   1.128 -              {   pdb_out_buffer[buf_idx++] = '-'; domain = domain * -1; }
   1.129 -	    */
   1.130 -	    if (domain > 15)
   1.131 +		if (count > 0)
   1.132 +		{
   1.133 +		    pdb_out_buffer[buf_idx++] = ',';
   1.134 +		}
   1.135 +		if (domain > 15)
   1.136 +		{
   1.137 +		    pdb_out_buffer[buf_idx++] = hexchars[domain >> 4];
   1.138 +		}
   1.139 +		pdb_out_buffer[buf_idx++] = hexchars[domain % 16];
   1.140 +		count++;
   1.141 +	    }
   1.142 +	    pdb_out_buffer[buf_idx++] = 0;
   1.143 +
   1.144 +	    read_unlock_irqrestore(&tasklist_lock, flags);
   1.145 +	    break;
   1.146 +	}
   1.147 +	case PDB_LVL_GUESTOS:                  /* return a list of processes */
   1.148 +	{
   1.149 +	    int foobar[20];
   1.150 +	    int loop, total;
   1.151 +
   1.152 +	    /* *** BUG: this cr3 is wrong wrong wrong */
   1.153 +	    total = pdb_linux_process_list(pdb_ctx[pdb_level].info_cr3,
   1.154 +					   foobar, 20);
   1.155 +
   1.156 +	    pdb_out_buffer[buf_idx++] = 'm';     
   1.157 +	    pdb_out_buffer[buf_idx++] = '1';              /* 1 is to go back */
   1.158 +	    for (loop = 0; loop < total; loop++)
   1.159  	    {
   1.160 -	        pdb_out_buffer[buf_idx++] = hexchars[domain >> 4];
   1.161 +	        int pid = foobar[loop] + PDB_ID_OFFSET;
   1.162 +
   1.163 +		pdb_out_buffer[buf_idx++] = ',';
   1.164 +		if (pid > 15)
   1.165 +		{
   1.166 +		    pdb_out_buffer[buf_idx++] = hexchars[pid >> 4];
   1.167 +		}
   1.168 +		pdb_out_buffer[buf_idx++] = hexchars[pid % 16];
   1.169  	    }
   1.170 -	    pdb_out_buffer[buf_idx++] = hexchars[domain % 16];
   1.171 -	    count++;
   1.172 +	    pdb_out_buffer[buf_idx++] = 0;
   1.173 +	    break;
   1.174  	}
   1.175 -	pdb_out_buffer[buf_idx++] = 'l';
   1.176 -	pdb_out_buffer[buf_idx++] = 0;
   1.177 +	case PDB_LVL_PROCESS:                                     /* hmmm... */
   1.178 +	{
   1.179 +	    pdb_out_buffer[buf_idx++] = 'm';
   1.180 +	    pdb_out_buffer[buf_idx++] = '1';              /* 1 is to go back */
   1.181 +	    break;
   1.182 +	}
   1.183 +	default:
   1.184 +	    break;
   1.185 +	}
   1.186  
   1.187 -        read_unlock_irqrestore(&tasklist_lock, flags);
   1.188 +#endif /* PDB_FUTURE */
   1.189 +
   1.190      }
   1.191      else if (strcmp(ptr, "sThreadInfo") == 0)
   1.192      {
   1.193 +        int buf_idx = 0;
   1.194 +
   1.195 +	pdb_out_buffer[buf_idx++] = 'l';
   1.196 +	pdb_out_buffer[buf_idx++] = 0;
   1.197      }
   1.198      else if (strncmp(ptr, "ThreadExtraInfo,", 16) == 0)
   1.199      {
   1.200          int thread = 0;
   1.201 -	char *message = "whatever!";
   1.202 +	char message[16];
   1.203 +	struct task_struct *p;
   1.204 +
   1.205 +	p = find_domain_by_id(pdb_ctx[pdb_level].info);
   1.206 +	strncpy (message, p->name, 16);
   1.207 +	put_task_struct(p);
   1.208  
   1.209  	ptr += 16;
   1.210          if (hexToInt (&ptr, &thread))
   1.211  	{
   1.212              mem2hex ((char *)message, pdb_out_buffer, strlen(message) + 1);
   1.213  	}
   1.214 +
   1.215 +#ifdef PDB_FUTURE
   1.216 +      {
   1.217 +	char string[task_struct_comm_length];
   1.218 +
   1.219 +	string[0] = 0;
   1.220 +	pdb_linux_process_details (cr3, pid, string);
   1.221 +	printk (" (%s)", string);
   1.222 +      }
   1.223 +#endif /* PDB_FUTURE*/
   1.224 +
   1.225      }
   1.226      else if (strcmp(ptr, "Offsets") == 0)
   1.227      {
   1.228 @@ -206,18 +329,43 @@ pdb_gdb_to_x86_regs (struct pt_regs *reg
   1.229  }
   1.230  
   1.231  int
   1.232 -pdb_process_command (char *ptr, struct pt_regs *regs)
   1.233 +pdb_process_command (char *ptr, struct pt_regs *regs, unsigned long cr3,
   1.234 +		     int sigval)
   1.235  {
   1.236 -    int sigval = 10;
   1.237      int length;
   1.238      unsigned long addr;
   1.239      int ack = 1;                           /* wait for ack in pdb_put_packet */
   1.240      int go = 0;
   1.241  
   1.242 -    DPRINTK("pdb: [%s]\n", ptr);
   1.243 +    TRC(printf("pdb: [%s]\n", ptr));
   1.244  
   1.245      pdb_out_buffer[0] = 0;
   1.246  
   1.247 +    if (pdb_ctx[pdb_level].ctrl_cr3 == 0 &&
   1.248 +	pdb_ctx[pdb_level].ctrl >= 0)
   1.249 +    {
   1.250 +        struct task_struct *p;
   1.251 +
   1.252 +	p = find_domain_by_id(pdb_ctx[pdb_level].ctrl);
   1.253 +	pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.pagetable);
   1.254 +	put_task_struct(p);
   1.255 +	printk ("PROCESS: PDB SET CONTROL DOMAIN TO 0x%lx 0x%x\n",
   1.256 +		pdb_ctx[pdb_level].ctrl_cr3, 
   1.257 +		pdb_ctx[pdb_level].ctrl);
   1.258 +    }
   1.259 +    if (pdb_ctx[pdb_level].info_cr3 == 0 &&
   1.260 +	pdb_ctx[pdb_level].info >= 0)
   1.261 +    {
   1.262 +        struct task_struct *p;
   1.263 +
   1.264 +	p = find_domain_by_id(pdb_ctx[pdb_level].info);
   1.265 +	pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.pagetable);
   1.266 +	put_task_struct(p);
   1.267 +	printk ("PROCESS: PDB SET INFO DOMAIN TO 0x%lx 0x%x\n",
   1.268 +		pdb_ctx[pdb_level].info_cr3, 
   1.269 +		pdb_ctx[pdb_level].info);
   1.270 +    }
   1.271 +
   1.272      switch (*ptr++)
   1.273      {
   1.274      case '?':
   1.275 @@ -228,15 +376,14 @@ pdb_process_command (char *ptr, struct p
   1.276          break;
   1.277      case 'S':                                            /* step with signal */
   1.278      case 's':                                                        /* step */
   1.279 -        regs->eflags |= 0x100;
   1.280 +        regs->eflags |= X86_EFLAGS_TF;
   1.281          pdb_stepping = 1;
   1.282          return 1;                                        
   1.283          /* not reached */
   1.284      case 'C':                                        /* continue with signal */
   1.285      case 'c':                                                    /* continue */
   1.286 -        regs->eflags &= ~0x100;
   1.287 -        /* jump out before replying to gdb */
   1.288 -        return 1;
   1.289 +        regs->eflags &= ~X86_EFLAGS_TF;
   1.290 +        return 1;                         /* jump out before replying to gdb */
   1.291          /* not reached */
   1.292      case 'd':
   1.293          remote_debug = !(remote_debug);                 /* toggle debug flag */
   1.294 @@ -301,19 +448,40 @@ pdb_process_command (char *ptr, struct p
   1.295      {
   1.296          int thread;
   1.297          char *next = &ptr[1];
   1.298 +
   1.299          if (hexToInt (&next, &thread))
   1.300          {
   1.301              if (thread > 0)
   1.302              {
   1.303 -                thread = thread - PDB_DOMAIN_OFFSET;
   1.304 +                thread = thread - PDB_ID_OFFSET;
   1.305              }
   1.306              if (*ptr == 'c')
   1.307              {
   1.308 -                pdb_ctrl_thread = thread;
   1.309 +	        pdb_ctx[pdb_level].ctrl = thread;
   1.310 +
   1.311 +		if (thread > 0)
   1.312 +		{
   1.313 +		    struct task_struct *p = find_domain_by_id(thread);
   1.314 +		    pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.pagetable);
   1.315 +		    put_task_struct(p);
   1.316 +		    printk ("PDB SET CONTROL DOMAIN TO 0x%lx 0x%x\n",
   1.317 +			    pdb_ctx[pdb_level].ctrl_cr3,
   1.318 +			    pdb_ctx[pdb_level].ctrl);
   1.319 +		}
   1.320              }
   1.321              else if (*ptr == 'g')
   1.322              {
   1.323 -                pdb_info_thread = thread;
   1.324 +	        pdb_ctx[pdb_level].info = thread;
   1.325 +
   1.326 +		if (thread > 0)
   1.327 +		{
   1.328 +		    struct task_struct *p = find_domain_by_id(thread);
   1.329 +		    pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.pagetable);
   1.330 +		    put_task_struct(p);
   1.331 +		    printk ("PDB SET INFO DOMAIN TO 0x%lx 0x%x\n",
   1.332 +			    pdb_ctx[pdb_level].info_cr3,
   1.333 +			    pdb_ctx[pdb_level].info);
   1.334 +		}
   1.335              }
   1.336              else
   1.337              {
   1.338 @@ -349,9 +517,10 @@ pdb_process_command (char *ptr, struct p
   1.339                      ptr = 0;
   1.340                      mem_err = 0;
   1.341  
   1.342 -                    if (pdb_info_thread >= 0)
   1.343 +                    if (pdb_ctx[pdb_level].info >= 0)
   1.344                      {
   1.345 -                        pdb_get_values(pdb_info_thread, pdb_buffer, addr, length);
   1.346 +		        pdb_get_values(pdb_buffer, length,
   1.347 +				       pdb_ctx[pdb_level].info_cr3, addr);
   1.348                          mem2hex (pdb_buffer, pdb_out_buffer, length);
   1.349                      }
   1.350                      else
   1.351 @@ -380,8 +549,9 @@ pdb_process_command (char *ptr, struct p
   1.352                      {
   1.353                          mem_err = 0;
   1.354  
   1.355 -                        pdb_set_values(pdb_info_thread, 
   1.356 -                                       ptr, addr, length);
   1.357 +                        /* pdb_set_values(ptr, length, cr3, addr); */
   1.358 +                        pdb_set_values(ptr, length, 
   1.359 +				       pdb_ctx[pdb_level].info_cr3, addr);
   1.360  
   1.361                          if (mem_err)
   1.362                          {
   1.363 @@ -402,20 +572,73 @@ pdb_process_command (char *ptr, struct p
   1.364      }
   1.365      case 'T':
   1.366      {
   1.367 -        int thread;
   1.368 -        if (hexToInt (&ptr, &thread))
   1.369 +        int id;
   1.370 +
   1.371 +        if (hexToInt (&ptr, &id))
   1.372          {
   1.373 -	    struct task_struct *p;
   1.374 -            thread -= PDB_DOMAIN_OFFSET;
   1.375 -            if ( (p = find_domain_by_id(thread)) == NULL)
   1.376 -                strcpy (pdb_out_buffer, "E00");
   1.377 -            else
   1.378 -                strcpy (pdb_out_buffer, "OK");
   1.379 -            put_task_struct(p);
   1.380 +	        {                                        /* case pdb_lvl_xen */
   1.381 +		    struct task_struct *p;
   1.382 +		    id -= PDB_ID_OFFSET;
   1.383 +		    if ( (p = find_domain_by_id(id)) == NULL)
   1.384 +		        strcpy (pdb_out_buffer, "E00");
   1.385 +		    else
   1.386 +		        strcpy (pdb_out_buffer, "OK");
   1.387 +		    put_task_struct(p);
   1.388 +		}
   1.389 +
   1.390 +#ifdef PDB_FUTURE
   1.391 +
   1.392 +	    switch (pdb_level)                             /* previous level */
   1.393 +	    {
   1.394 +	        case PDB_LVL_XEN:
   1.395 +		{
   1.396 +		    struct task_struct *p;
   1.397 +		    id -= PDB_ID_OFFSET;
   1.398 +		    if ( (p = find_domain_by_id(id)) == NULL)
   1.399 +		        strcpy (pdb_out_buffer, "E00");
   1.400 +		    else
   1.401 +		        strcpy (pdb_out_buffer, "OK");
   1.402 +		    put_task_struct(p);
   1.403 +
   1.404 +		    pdb_level = PDB_LVL_GUESTOS;
   1.405 +		    pdb_ctx[pdb_level].ctrl = id;
   1.406 +		    pdb_ctx[pdb_level].info = id;
   1.407 +		    break;
   1.408 +		}
   1.409 +	        case PDB_LVL_GUESTOS:
   1.410 +		{
   1.411 +		    if (pdb_level == -1)
   1.412 +		    {
   1.413 +		        pdb_level = PDB_LVL_XEN;
   1.414 +		    }
   1.415 +		    else
   1.416 +		    {
   1.417 +		        pdb_level = PDB_LVL_PROCESS;
   1.418 +			pdb_ctx[pdb_level].ctrl = id;
   1.419 +			pdb_ctx[pdb_level].info = id;
   1.420 +		    }
   1.421 +		    break;
   1.422 +		}
   1.423 +	        case PDB_LVL_PROCESS:
   1.424 +		{
   1.425 +		    if (pdb_level == -1)
   1.426 +		    {
   1.427 +		        pdb_level = PDB_LVL_GUESTOS;
   1.428 +		    }
   1.429 +		    break;
   1.430 +		}
   1.431 +	        default:
   1.432 +		{
   1.433 +		    printk ("pdb internal error: invalid level [%d]\n", 
   1.434 +			    pdb_level);
   1.435 +		}
   1.436 +	    }
   1.437 +
   1.438 +#endif /* PDB_FUTURE */
   1.439          }
   1.440          break;
   1.441      }
   1.442 -    }                                                          /* switch */
   1.443 +    }
   1.444  
   1.445      /* reply to the request */
   1.446      pdb_put_packet (pdb_out_buffer, ack);
   1.447 @@ -436,6 +659,9 @@ int pdb_serial_input(u_char c, struct pt
   1.448  {
   1.449      int out = 1;
   1.450      int loop, count;
   1.451 +    unsigned long cr3;
   1.452 +
   1.453 +    __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : );
   1.454  
   1.455      switch (pdb_debug_state)
   1.456      {
   1.457 @@ -489,7 +715,8 @@ int pdb_serial_input(u_char c, struct pt
   1.458  		    pdb_in_buffer[loop - 3] = pdb_in_buffer[loop];
   1.459  	    }
   1.460  
   1.461 -	    pdb_process_command (pdb_in_buffer, regs);
   1.462 +	    pdb_process_command (pdb_in_buffer, regs, cr3,
   1.463 +				 PDB_LIVE_EXCEPTION);
   1.464  	}
   1.465  	pdb_debug_state = 0;
   1.466  	break;
   1.467 @@ -594,18 +821,20 @@ hexToInt (char **ptr, int *intValue)
   1.468   */
   1.469  struct pdb_breakpoint breakpoints;
   1.470  
   1.471 -void pdb_bkpt_add (unsigned long address)
   1.472 +void pdb_bkpt_add (unsigned long cr3, unsigned long address)
   1.473  {
   1.474      struct pdb_breakpoint *bkpt = kmalloc(sizeof(*bkpt), GFP_KERNEL);
   1.475 +    bkpt->cr3 = cr3;
   1.476      bkpt->address = address;
   1.477      list_add(&bkpt->list, &breakpoints.list);
   1.478  }
   1.479  
   1.480  /*
   1.481   * Check to see of the breakpoint is in the list of known breakpoints 
   1.482 - * Return 1 if it has been set, 0 otherwise.
   1.483 + * Return 1 if it has been set, NULL otherwise.
   1.484   */
   1.485 -struct pdb_breakpoint* pdb_bkpt_search (unsigned long address)
   1.486 +struct pdb_breakpoint* pdb_bkpt_search (unsigned long cr3, 
   1.487 +					unsigned long address)
   1.488  {
   1.489      struct list_head *list_entry;
   1.490      struct pdb_breakpoint *bkpt;
   1.491 @@ -613,7 +842,7 @@ struct pdb_breakpoint* pdb_bkpt_search (
   1.492      list_for_each(list_entry, &breakpoints.list)
   1.493      {
   1.494          bkpt = list_entry(list_entry, struct pdb_breakpoint, list);
   1.495 -	if ( bkpt->address == address )
   1.496 +	if ( bkpt->cr3 == cr3 && bkpt->address == address )
   1.497              return bkpt;
   1.498      }
   1.499  
   1.500 @@ -624,7 +853,7 @@ struct pdb_breakpoint* pdb_bkpt_search (
   1.501   * Remove a breakpoint to the list of known breakpoints.
   1.502   * Return 1 if the element was not found, otherwise 0.
   1.503   */
   1.504 -int pdb_bkpt_remove (unsigned long address)
   1.505 +int pdb_bkpt_remove (unsigned long cr3, unsigned long address)
   1.506  {
   1.507      struct list_head *list_entry;
   1.508      struct pdb_breakpoint *bkpt;
   1.509 @@ -632,7 +861,7 @@ int pdb_bkpt_remove (unsigned long addre
   1.510      list_for_each(list_entry, &breakpoints.list)
   1.511      {
   1.512          bkpt = list_entry(list_entry, struct pdb_breakpoint, list);
   1.513 -	if ( bkpt->address == address )
   1.514 +	if ( bkpt->cr3 == cr3 && bkpt->address == address )
   1.515  	{
   1.516              list_del(&bkpt->list);
   1.517              kfree(bkpt);
   1.518 @@ -643,6 +872,166 @@ int pdb_bkpt_remove (unsigned long addre
   1.519      return 1;
   1.520  }
   1.521  
   1.522 +/*
   1.523 + * Check to see if a memory write is really gdb setting a breakpoint
   1.524 + */
   1.525 +void pdb_bkpt_check (u_char *buffer, int length,
   1.526 +		     unsigned long cr3, unsigned long addr)
   1.527 +{
   1.528 +    if (length == 1 && buffer[0] == 'c' && buffer[1] == 'c')
   1.529 +    {
   1.530 +        /* inserting a new breakpoint */
   1.531 +        pdb_bkpt_add(cr3, addr);
   1.532 +        TRC(printk("pdb breakpoint detected at 0x%lx:0x%lx\n", cr3, addr));
   1.533 +    }
   1.534 +    else if ( pdb_bkpt_remove(cr3, addr) == 0 )
   1.535 +    {
   1.536 +        /* removing a breakpoint */
   1.537 +        TRC(printk("pdb breakpoint cleared at 0x%lx:0x%lx\n", cr3, addr));
   1.538 +    }
   1.539 +}
   1.540 +
   1.541 +/***********************************************************************/
   1.542 +
   1.543 +int pdb_change_values(u_char *buffer, int length,
   1.544 +		      unsigned long cr3, unsigned long addr, int rw);
   1.545 +int pdb_change_values_one_page(u_char *buffer, int length,
   1.546 +			       unsigned long cr3, unsigned long addr, int rw);
   1.547 +
   1.548 +#define __PDB_GET_VAL 1
   1.549 +#define __PDB_SET_VAL 2
   1.550 +
   1.551 +/*
   1.552 + * Set memory in a domain's address space
   1.553 + * Set "length" bytes at "address" from "domain" to the values in "buffer".
   1.554 + * Return the number of bytes set, 0 if there was a problem.
   1.555 + */
   1.556 +
   1.557 +int pdb_set_values(u_char *buffer, int length,
   1.558 +		   unsigned long cr3, unsigned long addr)
   1.559 +{
   1.560 +    int count = pdb_change_values(buffer, length, cr3, addr, __PDB_SET_VAL);
   1.561 +    pdb_bkpt_check(buffer, length, cr3, addr);
   1.562 +    return count;
   1.563 +}
   1.564 +
   1.565 +/*
   1.566 + * Read memory from a domain's address space.
   1.567 + * Fetch "length" bytes at "address" from "domain" into "buffer".
   1.568 + * Return the number of bytes read, 0 if there was a problem.
   1.569 + */
   1.570 +
   1.571 +int pdb_get_values(u_char *buffer, int length,
   1.572 +		   unsigned long cr3, unsigned long addr)
   1.573 +{
   1.574 +  return pdb_change_values(buffer, length, cr3, addr, __PDB_GET_VAL);
   1.575 +}
   1.576 +
   1.577 +/*
   1.578 + * Read or write memory in an address space
   1.579 + */
   1.580 +int pdb_change_values(u_char *buffer, int length,
   1.581 +		      unsigned long cr3, unsigned long addr, int rw)
   1.582 +{
   1.583 +    int remaining;                /* number of bytes to touch past this page */
   1.584 +    int bytes = 0;
   1.585 +
   1.586 +    while ( (remaining = (addr + length - 1) - (addr | (PAGE_SIZE - 1))) > 0)
   1.587 +    {
   1.588 +        bytes += pdb_change_values_one_page(buffer, length - remaining, 
   1.589 +					    cr3, addr, rw);
   1.590 +	buffer = buffer + (2 * (length - remaining));
   1.591 +	length = remaining;
   1.592 +	addr = (addr | (PAGE_SIZE - 1)) + 1;
   1.593 +    }
   1.594 +
   1.595 +    bytes += pdb_change_values_one_page(buffer, length, cr3, addr, rw);
   1.596 +    return bytes;
   1.597 +}
   1.598 +
   1.599 +/*
   1.600 + * Change memory in a process' address space in one page
   1.601 + * Read or write "length" bytes at "address" into/from "buffer"
   1.602 + * from the virtual address space referenced by "cr3".
   1.603 + * Return the number of bytes read, 0 if there was a problem.
   1.604 + */
   1.605 +
   1.606 +int pdb_change_values_one_page(u_char *buffer, int length,
   1.607 +			       unsigned long cr3, unsigned long addr, int rw)
   1.608 +{
   1.609 +    l2_pgentry_t* l2_table = NULL;
   1.610 +    l1_pgentry_t* l1_table = NULL;
   1.611 +    u_char *page;
   1.612 +    int bytes = 0;
   1.613 +
   1.614 +    l2_table = map_domain_mem(cr3); 
   1.615 +    l2_table += l2_table_offset(addr);
   1.616 +    if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 
   1.617 +    {
   1.618 +        struct task_struct *p = find_domain_by_id(0);
   1.619 +	printk ("cr3: 0x%lx    dom0cr3:  0x%lx\n", 
   1.620 +		cr3, pagetable_val(p->mm.pagetable));
   1.621 +	put_task_struct(p);
   1.622 +
   1.623 +	printk ("L2:0x%p (0x%lx) \n", l2_table, l2_pgentry_val(*l2_table));
   1.624 +	goto exit2;
   1.625 +    }
   1.626 +
   1.627 +    if (l2_pgentry_val(*l2_table) & _PAGE_PSE)
   1.628 +    {
   1.629 +#define PSE_PAGE_SHIFT           L2_PAGETABLE_SHIFT
   1.630 +#define PSE_PAGE_SIZE	         (1UL << PSE_PAGE_SHIFT)
   1.631 +#define PSE_PAGE_MASK	         (~(PSE_PAGE_SIZE-1))
   1.632 +
   1.633 +#define L1_PAGE_BITS ( (ENTRIES_PER_L1_PAGETABLE - 1) << L1_PAGETABLE_SHIFT )
   1.634 +
   1.635 +#define pse_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PSE_PAGE_MASK)
   1.636 +
   1.637 +        page = map_domain_mem(pse_pgentry_to_phys(*l2_table) +    /* 10 bits */
   1.638 +			      (addr & L1_PAGE_BITS));             /* 10 bits */
   1.639 +	page += addr & (PAGE_SIZE - 1);                           /* 12 bits */
   1.640 +    }
   1.641 +    else
   1.642 +    {
   1.643 +        l1_table = map_domain_mem(l2_pgentry_to_phys(*l2_table));
   1.644 +	l1_table += l1_table_offset(addr); 
   1.645 +	if (!(l1_pgentry_val(*l1_table) & _PAGE_PRESENT))
   1.646 +	{
   1.647 +	    printk ("L2:0x%p (0x%lx) L1:0x%p (0x%lx)\n", 
   1.648 +		    l2_table, l2_pgentry_val(*l2_table),
   1.649 +		    l1_table, l1_pgentry_val(*l1_table));
   1.650 +	    goto exit1;
   1.651 +	}
   1.652 +
   1.653 +	page = map_domain_mem(l1_pgentry_to_phys(*l1_table));
   1.654 +	page += addr & (PAGE_SIZE - 1);
   1.655 +    }
   1.656 +
   1.657 +    switch (rw)
   1.658 +    {
   1.659 +    case __PDB_GET_VAL:                                              /* read */
   1.660 +        memcpy (buffer, page, length);
   1.661 +	bytes = length;
   1.662 +	break;
   1.663 +    case __PDB_SET_VAL:                                         /* write */
   1.664 +        hex2mem (buffer, page, length);
   1.665 +	bytes = length;
   1.666 +	break;
   1.667 +    default:                                                  /* unknown */
   1.668 +        printk ("error: unknown RW flag: %d\n", rw);
   1.669 +	return 0;
   1.670 +    }
   1.671 +
   1.672 +    unmap_domain_mem((void *)page); 
   1.673 +exit1:
   1.674 +    if (l1_table != NULL)
   1.675 +        unmap_domain_mem((void *)l1_table);
   1.676 +exit2:
   1.677 +    unmap_domain_mem((void *)l2_table);
   1.678 +
   1.679 +    return bytes;
   1.680 +}
   1.681 +
   1.682  /***********************************************************************/
   1.683  
   1.684  void breakpoint(void);
   1.685 @@ -716,7 +1105,7 @@ void pdb_get_packet(char *buffer)
   1.686  	        pdb_put_char('+');
   1.687  		if (buffer[2] == ':')
   1.688  		{
   1.689 -		    printk ("gdb packet found with sequence ID\n");
   1.690 +		    printk ("pdb: obsolete gdb packet (sequence ID)\n");
   1.691  		}
   1.692  	    }
   1.693  	    else
   1.694 @@ -735,38 +1124,40 @@ void pdb_get_packet(char *buffer)
   1.695   * be propagated to the guest os.
   1.696   */
   1.697  
   1.698 -#define DEBUG_EXCEPTION     0x01
   1.699 -#define BREAKPT_EXCEPTION   0x03
   1.700 -#define KEYPRESS_EXCEPTION  0x88
   1.701 -
   1.702  int pdb_handle_exception(int exceptionVector,
   1.703  			 struct pt_regs *xen_regs)
   1.704  {
   1.705      int signal = 0;
   1.706 +    struct pdb_breakpoint* bkpt;
   1.707      int watchdog_save;
   1.708 +    unsigned long cr3;
   1.709 +
   1.710 +    __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : );
   1.711  
   1.712      /*
   1.713       * If PDB didn't set the breakpoint, is not single stepping, and the user
   1.714       * didn't press the magic debug key, then we don't handle the exception.
   1.715       */
   1.716 -    if ( (pdb_bkpt_search(xen_regs->eip - 1) == NULL) &&
   1.717 -         !pdb_stepping && (exceptionVector != KEYPRESS_EXCEPTION) )
   1.718 +    bkpt = pdb_bkpt_search(cr3, xen_regs->eip - 1);
   1.719 +    if ( (bkpt == NULL) &&
   1.720 +         !pdb_stepping && (exceptionVector != KEYPRESS_EXCEPTION) &&
   1.721 +	 xen_regs->eip < 0xc0000000)                   /* xenolinux for now! */
   1.722      {
   1.723 -        DPRINTK("pdb: external breakpoint at 0x%lx\n", xen_regs->eip);
   1.724 +        TRC(printf("pdb: user bkpt at 0x%lx:0x%lx\n", cr3, xen_regs->eip));
   1.725  	return 1;
   1.726      }
   1.727  
   1.728 -    printk("pdb_handle_exception [0x%x][0x%lx]\n",
   1.729 -           exceptionVector, xen_regs->eip);
   1.730 +    printk("pdb_handle_exception [0x%x][0x%lx:0x%lx]\n",
   1.731 +           exceptionVector, cr3, xen_regs->eip);
   1.732  
   1.733      if ( pdb_stepping )
   1.734      {
   1.735          /* Stepped one instruction; now return to normal execution. */
   1.736 -        xen_regs->eflags &= ~0x100;
   1.737 +        xen_regs->eflags &= ~X86_EFLAGS_TF;
   1.738          pdb_stepping = 0;
   1.739      }
   1.740  
   1.741 -    if ( exceptionVector == BREAKPT_EXCEPTION )
   1.742 +    if ( exceptionVector == BREAKPT_EXCEPTION && bkpt != NULL)
   1.743      {
   1.744          /* Executed Int3: replace breakpoint byte with real program byte. */
   1.745          xen_regs->eip--;
   1.746 @@ -800,7 +1191,7 @@ int pdb_handle_exception(int exceptionVe
   1.747          pdb_out_buffer[0] = 0;
   1.748  	pdb_get_packet(pdb_in_buffer);
   1.749      }
   1.750 -    while ( pdb_process_command(pdb_in_buffer, xen_regs) == 0 );
   1.751 +    while ( pdb_process_command(pdb_in_buffer, xen_regs, cr3, signal) == 0 );
   1.752  
   1.753      watchdog_on = watchdog_save;
   1.754  
   1.755 @@ -816,9 +1207,10 @@ void pdb_key_pressed(u_char key, void *d
   1.756  void initialize_pdb()
   1.757  {
   1.758      extern char opt_pdb[];
   1.759 +    int loop;
   1.760  
   1.761      /* Certain state must be initialised even when PDB will not be used. */
   1.762 -    breakpoints.address = 0;
   1.763 +    memset((void *) &breakpoints, 0, sizeof(breakpoints));
   1.764      INIT_LIST_HEAD(&breakpoints.list);
   1.765      pdb_stepping = 0;
   1.766  
   1.767 @@ -827,14 +1219,22 @@ void initialize_pdb()
   1.768  
   1.769      if ( (pdb_serhnd = parse_serial_handle(opt_pdb)) == -1 )
   1.770      {
   1.771 -        printk("Failed to initialise PDB on port %s\n", opt_pdb);
   1.772 +        printk("error: failed to initialize PDB on port %s\n", opt_pdb);
   1.773          return;
   1.774      }
   1.775  
   1.776 -    printk("Initialised pervasive debugger (PDB) on port %s\n", opt_pdb);
   1.777 +    for (loop = 0; loop < pdb_ctx_count; loop++)
   1.778 +    {
   1.779 +        pdb_ctx[loop].ctrl = -1;
   1.780 +	pdb_ctx[loop].info = -1;
   1.781 +        pdb_ctx[loop].ctrl_cr3 = 0;
   1.782 +	pdb_ctx[loop].info_cr3 = 0;
   1.783 +    }
   1.784 +
   1.785 +    printk("Initialized pervasive debugger (PDB) on port %s\n", opt_pdb);
   1.786  
   1.787      /* Acknowledge any spurious GDB packets. */
   1.788 -    serial_putc(pdb_serhnd, '+');
   1.789 +    pdb_put_char('+');
   1.790  
   1.791      add_key_handler('D', pdb_key_pressed, "enter pervasive debugger");
   1.792  
     2.1 --- a/xen/common/debug-linux.c	Fri Mar 19 14:49:10 2004 +0000
     2.2 +++ b/xen/common/debug-linux.c	Thu Mar 25 16:59:52 2004 +0000
     2.3 @@ -31,95 +31,160 @@
     2.4  #define L1_PAGE_BITS ( (ENTRIES_PER_L1_PAGETABLE - 1) << PAGE_SHIFT )
     2.5  
     2.6  
     2.7 +void pdb_linux_process_details (unsigned long cr3, int pid, char *buffer);
     2.8 +
     2.9 +
    2.10  /* adapted from asm-xeno/page.h */
    2.11 -static inline unsigned long machine_to_phys(domid_t domain, 
    2.12 +static inline unsigned long machine_to_phys(unsigned long cr3,
    2.13                                              unsigned long machine)
    2.14  {
    2.15    unsigned long phys;
    2.16 -  pdb_get_values(domain, (u_char *) &phys,
    2.17 +  pdb_get_values((u_char *) &phys, sizeof(phys), cr3,
    2.18  		 (unsigned long) machine_to_phys_mapping + 
    2.19 -                 (machine >> PAGE_SHIFT) * 4,
    2.20 -		 sizeof(phys));
    2.21 +                 (machine >> PAGE_SHIFT) * 4);
    2.22    phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
    2.23    return phys;
    2.24  }
    2.25  
    2.26  
    2.27 -#define pidhash_addr 0xc018f260UL
    2.28 -
    2.29 -#define task_struct_mm_offset  0x2c
    2.30 -#define task_struct_pid_offset 0x7c
    2.31 -#define task_struct_pidhash_next_offset 0xb0
    2.32 -#define mm_struct_pgd_offset   0x0c
    2.33 +#define pidhash_addr         0xc01971e0UL
    2.34 +#define init_task_union_addr 0xc0182000UL
    2.35  
    2.36 -/*
    2.37 -  static inline struct task_struct *find_task_by_pid(int pid)
    2.38 -  {
    2.39 -    struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)];
    2.40 +#define task_struct_mm_offset        0x2c
    2.41 +#define task_struct_next_task_offset 0x48
    2.42 +#define task_struct_pid_offset       0x7c
    2.43 +#define task_struct_pidhash_next_offset 0xb0
    2.44 +#define task_struct_comm_offset      0x23e
    2.45 +#define task_struct_comm_length      0x10
    2.46  
    2.47 -    for(p = *htable; p && p->pid != pid; p = p->pidhash_next) ;
    2.48 -    return p;
    2.49 -  }
    2.50 -*/
    2.51 +#define mm_struct_pgd_offset         0x0c
    2.52  
    2.53  /* read a byte from a process */
    2.54 -u_char pdb_linux_get_value(domid_t domain, int pid, unsigned long addr)
    2.55 +u_char pdb_linux_get_value(int pid, unsigned long cr3, unsigned long addr)
    2.56  {
    2.57    u_char result = 0;
    2.58    unsigned long task_struct_p, mm_p, pgd, task_struct_pid;
    2.59    unsigned long l2tab, page;
    2.60  
    2.61    /* find the task_struct of the given process */
    2.62 -  pdb_get_values(domain, (u_char *) &task_struct_p, 
    2.63 -		 pidhash_addr + pid_hashfn(pid) * 4,
    2.64 -		 sizeof(task_struct_p));
    2.65 +  pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
    2.66 +		 cr3, pidhash_addr + pid_hashfn(pid) * 4);
    2.67  
    2.68    /* find the correct task struct */
    2.69    while (task_struct_p != (unsigned long)NULL)
    2.70    {
    2.71 -    pdb_get_values(domain, (u_char *) &task_struct_pid, 
    2.72 -		   task_struct_p + task_struct_pid_offset,
    2.73 -		   sizeof(task_struct_pid));
    2.74 +    pdb_get_values((u_char *) &task_struct_pid, sizeof(task_struct_pid),
    2.75 +		   cr3, task_struct_p + task_struct_pid_offset);
    2.76      if (task_struct_pid == pid)
    2.77      {
    2.78        break;
    2.79      }
    2.80      
    2.81 -    pdb_get_values(domain, (u_char *) &task_struct_p, 
    2.82 -		   task_struct_p + task_struct_pidhash_next_offset,
    2.83 -		   sizeof(task_struct_p));
    2.84 +    pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
    2.85 +		   cr3, task_struct_p + task_struct_pidhash_next_offset);
    2.86    }
    2.87    if (task_struct_p == (unsigned long)NULL)
    2.88    {
    2.89      /* oops */
    2.90 -    printk ("error: couldn't find process 0x%x in domain %llu\n", pid, domain);
    2.91 +    printk ("error: pdb couldn't find process 0x%x\n", pid);
    2.92      return 0;
    2.93    }
    2.94  
    2.95    /* get the mm_struct within the task_struct */
    2.96 -  pdb_get_values(domain, (u_char *) &mm_p, 
    2.97 -		 task_struct_p + task_struct_mm_offset,
    2.98 -		 sizeof(mm_p));
    2.99 +  pdb_get_values((u_char *) &mm_p, sizeof(mm_p),
   2.100 +		 cr3, task_struct_p + task_struct_mm_offset);
   2.101    /* get the page global directory (cr3) within the mm_struct */
   2.102 -  pdb_get_values(domain, (u_char *) &pgd, 
   2.103 -		 mm_p + mm_struct_pgd_offset,
   2.104 -		 sizeof(pgd));
   2.105 +  pdb_get_values((u_char *) &pgd, sizeof(pgd),
   2.106 +		 cr3, mm_p + mm_struct_pgd_offset);
   2.107  
   2.108    /* get the l2 table entry */
   2.109 -  pdb_get_values(domain, (u_char *) &l2tab, 
   2.110 -		 pgd + (addr >> PGDIR_SHIFT) * 4,
   2.111 -		 sizeof(l2tab));
   2.112 -  l2tab = (unsigned long)__va(machine_to_phys(domain, l2tab) & PAGE_MASK);
   2.113 +  pdb_get_values((u_char *) &l2tab, sizeof(l2tab),
   2.114 +		 cr3, pgd + (addr >> PGDIR_SHIFT) * 4);
   2.115 +  l2tab = (unsigned long)__va(machine_to_phys(cr3, l2tab) & PAGE_MASK);
   2.116  
   2.117    /* get the page table entry */
   2.118 -  pdb_get_values(domain, (u_char *) &page,
   2.119 -		 l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4,
   2.120 -		 sizeof(page));
   2.121 -  page = (unsigned long)__va(machine_to_phys(domain, page) & PAGE_MASK);
   2.122 +  pdb_get_values((u_char *) &page, sizeof(page),
   2.123 +		 cr3, l2tab + ((addr & L1_PAGE_BITS) >> PAGE_SHIFT) * 4);
   2.124 +  page = (unsigned long)__va(machine_to_phys(cr3, page) & PAGE_MASK);
   2.125  
   2.126    /* get the byte */
   2.127 -  pdb_get_values(domain, (u_char *) &result, page + (addr & ~PAGE_MASK),
   2.128 -		 sizeof(result));
   2.129 +  pdb_get_values((u_char *) &result, sizeof(result),
   2.130 +		 cr3, page + (addr & ~PAGE_MASK));
   2.131  
   2.132    return result;
   2.133  }
   2.134 +
   2.135 +/* return 1 if is the virtual address is in the operating system's
   2.136 +   address space, else 0 */
   2.137 +int pdb_linux_address_space (unsigned long addr)
   2.138 +{
   2.139 +    return (addr > PAGE_OFFSET);
   2.140 +}
   2.141 +
   2.142 +/* get a list of at most "max" processes
   2.143 + * return: number of threads found
   2.144 + *
   2.145 + *   init_task -> init_task_union.task
   2.146 + *   while (next_task != init_task) {}
   2.147 + */
   2.148 +int pdb_linux_process_list (unsigned long cr3, int array[], int max)
   2.149 +{
   2.150 +  unsigned long task_p, next_p;
   2.151 +  int pid;
   2.152 +  int count = 0;
   2.153 +
   2.154 +  /* task_p = init_task->next_task  */
   2.155 +  pdb_get_values((u_char *) &task_p, sizeof(task_p),
   2.156 +		 cr3, init_task_union_addr + task_struct_next_task_offset);
   2.157 +  
   2.158 +  while (task_p != init_task_union_addr)
   2.159 +  {
   2.160 +      pdb_get_values((u_char *) &pid, sizeof(pid),
   2.161 +		     cr3, task_p + task_struct_pid_offset);
   2.162 +
   2.163 +      array[count % max] = pid;
   2.164 +      count++;
   2.165 +
   2.166 +      pdb_get_values((u_char *) &next_p, sizeof(next_p),
   2.167 +		     cr3, task_p + task_struct_next_task_offset);
   2.168 +      task_p = next_p;
   2.169 +  }
   2.170 +
   2.171 +  return count;
   2.172 +}
   2.173 +
   2.174 +/* get additional details about a particular process:
   2.175 + */
   2.176 +void pdb_linux_process_details (unsigned long cr3, int pid, char *buffer)
   2.177 +{
   2.178 +  unsigned long task_struct_p, task_struct_pid;
   2.179 +
   2.180 +  /* find the task_struct of the given process */
   2.181 +  pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
   2.182 +		 cr3, pidhash_addr + pid_hashfn(pid) * 4);
   2.183 +
   2.184 +  /* find the correct task struct */
   2.185 +  while (task_struct_p != (unsigned long)NULL)
   2.186 +  {
   2.187 +    pdb_get_values((u_char *) &task_struct_pid, sizeof(task_struct_pid),
   2.188 +		   cr3, task_struct_p + task_struct_pid_offset);
   2.189 +    if (task_struct_pid == pid)
   2.190 +    {
   2.191 +      break;
   2.192 +    }
   2.193 +
   2.194 +    pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
   2.195 +		   cr3, task_struct_p + task_struct_pidhash_next_offset);
   2.196 +  }
   2.197 +  if (task_struct_p == (unsigned long)NULL)
   2.198 +  {
   2.199 +    /* oops */
   2.200 +    printk ("error: pdb couldn't find process 0x%x\n", pid);
   2.201 +    return;
   2.202 +  }
   2.203 +
   2.204 +  pdb_get_values((u_char *) buffer, task_struct_comm_length,
   2.205 +		 cr3, task_struct_p + task_struct_comm_offset);
   2.206 +  return;
   2.207 +}
   2.208 +
     3.1 --- a/xen/common/debug.c	Fri Mar 19 14:49:10 2004 +0000
     3.2 +++ b/xen/common/debug.c	Thu Mar 25 16:59:52 2004 +0000
     3.3 @@ -11,7 +11,6 @@
     3.4  #include <xeno/sched.h>
     3.5  #include <xeno/event.h>
     3.6  #include <asm/page.h>
     3.7 -#include <asm/domain_page.h>                           /* [un]map_domain_mem */
     3.8  #include <asm/pdb.h>
     3.9  
    3.10  #undef DEBUG_TRACE
    3.11 @@ -23,144 +22,8 @@
    3.12  
    3.13  /****************************************************************************/
    3.14  
    3.15 -extern int pdb_change_values(domid_t domain, 
    3.16 -                             u_char *buffer, unsigned long addr,
    3.17 -                             int length, int rw);
    3.18 -extern u_char pdb_linux_get_value(domid_t domain, int pid, unsigned long addr);
    3.19 -
    3.20 -/*
    3.21 - * Set memory in a domain's address space
    3.22 - * Set "length" bytes at "address" from "domain" to the values in "buffer".
    3.23 - * Return the number of bytes set, 0 if there was a problem.
    3.24 - *
    3.25 - * THIS WILL BECOME A MACRO
    3.26 - */
    3.27 -
    3.28 -int pdb_set_values(domid_t domain, 
    3.29 -                   u_char *buffer, unsigned long addr, int length)
    3.30 -{
    3.31 -    int count = pdb_change_values(domain, buffer, addr, length, 2);
    3.32 -
    3.33 -    /* this is a bit x86 specific at the moment... */
    3.34 -    if (length == 1 && buffer[0] == 'c' && buffer[1] == 'c')
    3.35 -    {
    3.36 -        /* inserting a new breakpoint */
    3.37 -        pdb_bkpt_add(addr);
    3.38 -        TRC(printk("pdb breakpoint detected at 0x%lx\n", addr));
    3.39 -    }
    3.40 -    else if ( pdb_bkpt_remove(addr) == 0 )
    3.41 -    {
    3.42 -        /* removing a breakpoint */
    3.43 -        TRC(printk("pdb breakpoint cleared at 0x%lx\n", addr));
    3.44 -    }
    3.45 -
    3.46 -    return count;
    3.47 -}
    3.48 -
    3.49 -/*
    3.50 - * Read memory from a domain's address space.
    3.51 - * Fetch "length" bytes at "address" from "domain" into "buffer".
    3.52 - * Return the number of bytes read, 0 if there was a problem.
    3.53 - *
    3.54 - * THIS WILL BECOME A MACRO
    3.55 - */
    3.56 -
    3.57 -int pdb_get_values(domid_t domain, 
    3.58 -                   u_char *buffer, unsigned long addr, int length)
    3.59 -{
    3.60 -    return pdb_change_values(domain, buffer, addr, length, 1);
    3.61 -}
    3.62 -
    3.63 -/*
    3.64 - * Change memory in  a domain's address space.
    3.65 - * Read or write "length" bytes at "address" from "domain" into/from "buffer".
    3.66 - * Return the number of bytes read, 0 if there was a problem.
    3.67 - * RW: 1 = read, 2 = write
    3.68 - */
    3.69 -
    3.70 -int pdb_change_values(domid_t domain, u_char *buffer, unsigned long addr,
    3.71 -                      int length, int rw)
    3.72 -{
    3.73 -    struct task_struct *p;
    3.74 -    l2_pgentry_t* l2_table = NULL;
    3.75 -    l1_pgentry_t* l1_table = NULL;
    3.76 -    u_char *page;
    3.77 -    int bytes = 0;
    3.78 -
    3.79 -    p = find_domain_by_id(domain);
    3.80 -
    3.81 -    if ((addr >> PAGE_SHIFT) == ((addr + length - 1) >> PAGE_SHIFT))
    3.82 -    {
    3.83 -        l2_table = map_domain_mem(pagetable_val(p->mm.pagetable));
    3.84 -	l2_table += l2_table_offset(addr);
    3.85 -	if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 
    3.86 -	{
    3.87 -	    printk ("L2:0x%p (0x%lx) \n", l2_table, l2_pgentry_val(*l2_table));
    3.88 -	    goto exit2;
    3.89 -	}
    3.90 -
    3.91 -	if (l2_pgentry_val(*l2_table) & _PAGE_PSE)
    3.92 -	{
    3.93 -#define PSE_PAGE_SHIFT           L2_PAGETABLE_SHIFT
    3.94 -#define PSE_PAGE_SIZE	         (1UL << PSE_PAGE_SHIFT)
    3.95 -#define PSE_PAGE_MASK	         (~(PSE_PAGE_SIZE-1))
    3.96 -
    3.97 -#define L1_PAGE_BITS ( (ENTRIES_PER_L1_PAGETABLE - 1) << L1_PAGETABLE_SHIFT )
    3.98 -
    3.99 -#define pse_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PSE_PAGE_MASK)
   3.100 -
   3.101 -	    page = map_domain_mem(pse_pgentry_to_phys(*l2_table) +/* 10 bits */
   3.102 -				  (addr & L1_PAGE_BITS));         /* 10 bits */
   3.103 -	    page += addr & (PAGE_SIZE - 1);                       /* 12 bits */
   3.104 -	}
   3.105 -	else
   3.106 -	{
   3.107 -	    l1_table = map_domain_mem(l2_pgentry_to_phys(*l2_table));
   3.108 -	    l1_table += l1_table_offset(addr); 
   3.109 -	    if (!(l1_pgentry_val(*l1_table) & _PAGE_PRESENT))
   3.110 -	    {
   3.111 -	        printk ("L2:0x%p (0x%lx) L1:0x%p (0x%lx)\n", 
   3.112 -			l2_table, l2_pgentry_val(*l2_table),
   3.113 -			l1_table, l1_pgentry_val(*l1_table));
   3.114 -		goto exit1;
   3.115 -	    }
   3.116 -
   3.117 -	    page = map_domain_mem(l1_pgentry_to_phys(*l1_table));
   3.118 -	    page += addr & (PAGE_SIZE - 1);
   3.119 -	}
   3.120 -
   3.121 -	switch (rw)
   3.122 -	{
   3.123 -	case 1:                                                      /* read */
   3.124 -	    memcpy (buffer, page, length);
   3.125 -	    bytes = length;
   3.126 -	    break;
   3.127 -	case 2:                                                     /* write */
   3.128 -	    hex2mem (buffer, page, length);
   3.129 -	    bytes = length;
   3.130 -	    break;
   3.131 -	default:                                                  /* unknown */
   3.132 -	    printk ("error: unknown RW flag: %d\n", rw);
   3.133 -	    return 0;
   3.134 -	}
   3.135 -
   3.136 -	unmap_domain_mem((void *)page); 
   3.137 -    exit1:
   3.138 -	if (l1_table != NULL)
   3.139 -	    unmap_domain_mem((void *)l1_table);
   3.140 -    exit2:
   3.141 -	unmap_domain_mem((void *)l2_table);
   3.142 -    }
   3.143 -    else
   3.144 -    {
   3.145 -        /* read spans pages. need to recurse */
   3.146 -        printk ("pdb memory SPAN! addr:0x%lx l: %x\n", addr, length);
   3.147 -    }
   3.148 -
   3.149 -    put_task_struct(p);
   3.150 -    return bytes;
   3.151 -}
   3.152 -
   3.153 +extern u_char pdb_linux_get_value(int pid, unsigned long cr3, 
   3.154 +				  unsigned long addr);
   3.155  
   3.156  /*
   3.157   * interactively call pervasive debugger from a privileged domain
   3.158 @@ -206,6 +69,11 @@ void pdb_do_debug (dom0_op_t *op)
   3.159          {
   3.160              int loop;
   3.161              u_char x;
   3.162 +	    unsigned long cr3;
   3.163 +	    struct task_struct *p;
   3.164 +
   3.165 +	    p = find_domain_by_id(op->u.debug.domain);
   3.166 +	    cr3 = pagetable_val(p->mm.pagetable);
   3.167  
   3.168              for (loop = 0; loop < op->u.debug.in2; loop++)         /* length */
   3.169              { 
   3.170 @@ -213,15 +81,14 @@ void pdb_do_debug (dom0_op_t *op)
   3.171                  {
   3.172                      printk ("\n%08x ", op->u.debug.in1 + loop);
   3.173                  }
   3.174 -                x = pdb_linux_get_value(op->u.debug.domain,        /* domain */
   3.175 -					op->u.debug.in3,             /* pid */
   3.176 -					op->u.debug.in1 + loop);     /* addr */
   3.177 +                x = pdb_linux_get_value(op->u.debug.in3,
   3.178 +					cr3, op->u.debug.in1 + loop);
   3.179                  printk (" %02x", x);
   3.180              }
   3.181              printk ("\n");
   3.182 +	    put_task_struct(p);
   3.183              break;
   3.184          }
   3.185 -
   3.186          case 's' :
   3.187  	{
   3.188  	    unsigned long cpu_mask;
     4.1 --- a/xen/include/asm-i386/pdb.h	Fri Mar 19 14:49:10 2004 +0000
     4.2 +++ b/xen/include/asm-i386/pdb.h	Thu Mar 25 16:59:52 2004 +0000
     4.3 @@ -13,6 +13,7 @@
     4.4  
     4.5  #include <asm/ptrace.h>
     4.6  #include <xeno/list.h>
     4.7 +#include <hypervisor-ifs/hypervisor-if.h>                   /* for domain id */
     4.8  
     4.9  extern int pdb_initialized;
    4.10  extern int pdb_com_port;
    4.11 @@ -21,10 +22,10 @@ extern int pdb_high_bit;
    4.12  extern void initialize_pdb(void);
    4.13  
    4.14  /* Get/set values from generic debug interface. */
    4.15 -extern int pdb_set_values(domid_t domain, u_char *buffer, 
    4.16 -                          unsigned long addr, int length);
    4.17 -extern int pdb_get_values(domid_t domain, u_char *buffer,
    4.18 -                          unsigned long addr, int length);
    4.19 +extern int pdb_set_values(u_char *buffer, int length,
    4.20 +                          unsigned long cr3, unsigned long addr);
    4.21 +extern int pdb_get_values(u_char *buffer, int length,
    4.22 +                          unsigned long cr3, unsigned long addr);
    4.23  
    4.24  /* External entry points. */
    4.25  extern int pdb_handle_exception(int exceptionVector,
    4.26 @@ -37,10 +38,13 @@ struct pdb_breakpoint
    4.27  {
    4.28      struct list_head list;
    4.29      unsigned long address;
    4.30 +    unsigned long cr3;
    4.31 +    domid_t domain;
    4.32  };
    4.33 -extern void pdb_bkpt_add (unsigned long address);
    4.34 -extern struct pdb_breakpoint* pdb_bkpt_search (unsigned long address);
    4.35 -extern int pdb_bkpt_remove (unsigned long address);
    4.36 +extern void pdb_bkpt_add (unsigned long cr3, unsigned long address);
    4.37 +extern struct pdb_breakpoint* pdb_bkpt_search (unsigned long cr3, 
    4.38 +					       unsigned long address);
    4.39 +extern int pdb_bkpt_remove (unsigned long cr3, unsigned long address);
    4.40  
    4.41  /* Conversions. */
    4.42  extern int   hex (char);