ia64/xen-unstable
changeset 1229:9269207cff3f
bitkeeper revision 1.812.1.1 (40631008stsWqMpK0QGxpKbL8XGwTw)
cr3 changes
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);