ia64/xen-unstable
changeset 1231:d1172efb8a1e
bitkeeper revision 1.825.3.2 (40631c64DS7cItyYKH3CeHEBO7EJGA)
merge
merge
author | ach61@labyrinth.cl.cam.ac.uk |
---|---|
date | Thu Mar 25 17:52:36 2004 +0000 (2004-03-25) |
parents | ee97ff34e170 bf27b8aaeb2f |
children | 916d919c54b7 |
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 Thu Mar 25 15:16:57 2004 +0000 1.2 +++ b/xen/arch/i386/pdb-stub.c Thu Mar 25 17:52:36 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 <xen/lib.h> 1.14 #include <xen/sched.h> 1.15 #include <asm-i386/ptrace.h> 1.16 #include <xen/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 <xen/list.h> 1.22 #include <xen/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,49 @@ 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 + if (p->mm.shadow_mode) 1.254 + pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.shadow_table); 1.255 + else 1.256 + pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.pagetable); 1.257 + put_task_struct(p); 1.258 + printk ("PROCESS: PDB SET CONTROL DOMAIN TO 0x%lx 0x%x\n", 1.259 + pdb_ctx[pdb_level].ctrl_cr3, 1.260 + pdb_ctx[pdb_level].ctrl); 1.261 + } 1.262 + if (pdb_ctx[pdb_level].info_cr3 == 0 && 1.263 + pdb_ctx[pdb_level].info >= 0) 1.264 + { 1.265 + struct task_struct *p; 1.266 + 1.267 + p = find_domain_by_id(pdb_ctx[pdb_level].info); 1.268 + if (p->mm.shadow_mode) 1.269 + pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.shadow_table); 1.270 + else 1.271 + pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.pagetable); 1.272 + put_task_struct(p); 1.273 + printk ("PROCESS: PDB SET INFO DOMAIN TO 0x%lx 0x%x\n", 1.274 + pdb_ctx[pdb_level].info_cr3, 1.275 + pdb_ctx[pdb_level].info); 1.276 + } 1.277 + 1.278 switch (*ptr++) 1.279 { 1.280 case '?': 1.281 @@ -228,15 +382,14 @@ pdb_process_command (char *ptr, struct p 1.282 break; 1.283 case 'S': /* step with signal */ 1.284 case 's': /* step */ 1.285 - regs->eflags |= 0x100; 1.286 + regs->eflags |= X86_EFLAGS_TF; 1.287 pdb_stepping = 1; 1.288 return 1; 1.289 /* not reached */ 1.290 case 'C': /* continue with signal */ 1.291 case 'c': /* continue */ 1.292 - regs->eflags &= ~0x100; 1.293 - /* jump out before replying to gdb */ 1.294 - return 1; 1.295 + regs->eflags &= ~X86_EFLAGS_TF; 1.296 + return 1; /* jump out before replying to gdb */ 1.297 /* not reached */ 1.298 case 'd': 1.299 remote_debug = !(remote_debug); /* toggle debug flag */ 1.300 @@ -301,19 +454,46 @@ pdb_process_command (char *ptr, struct p 1.301 { 1.302 int thread; 1.303 char *next = &ptr[1]; 1.304 + 1.305 if (hexToInt (&next, &thread)) 1.306 { 1.307 if (thread > 0) 1.308 { 1.309 - thread = thread - PDB_DOMAIN_OFFSET; 1.310 + thread = thread - PDB_ID_OFFSET; 1.311 } 1.312 if (*ptr == 'c') 1.313 { 1.314 - pdb_ctrl_thread = thread; 1.315 + pdb_ctx[pdb_level].ctrl = thread; 1.316 + 1.317 + if (thread > 0) 1.318 + { 1.319 + struct task_struct *p = find_domain_by_id(thread); 1.320 + if (p->mm.shadow_mode) 1.321 + pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.shadow_table); 1.322 + else 1.323 + pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.pagetable); 1.324 + put_task_struct(p); 1.325 + printk ("PDB SET CONTROL DOMAIN TO 0x%lx 0x%x\n", 1.326 + pdb_ctx[pdb_level].ctrl_cr3, 1.327 + pdb_ctx[pdb_level].ctrl); 1.328 + } 1.329 } 1.330 else if (*ptr == 'g') 1.331 { 1.332 - pdb_info_thread = thread; 1.333 + pdb_ctx[pdb_level].info = thread; 1.334 + 1.335 + if (thread > 0) 1.336 + { 1.337 + struct task_struct *p = find_domain_by_id(thread); 1.338 + if (p->mm.shadow_mode) 1.339 + pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.shadow_table); 1.340 + else 1.341 + pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.pagetable); 1.342 + put_task_struct(p); 1.343 + printk ("PDB SET INFO DOMAIN TO 0x%lx 0x%x\n", 1.344 + pdb_ctx[pdb_level].info_cr3, 1.345 + pdb_ctx[pdb_level].info); 1.346 + } 1.347 } 1.348 else 1.349 { 1.350 @@ -349,9 +529,10 @@ pdb_process_command (char *ptr, struct p 1.351 ptr = 0; 1.352 mem_err = 0; 1.353 1.354 - if (pdb_info_thread >= 0) 1.355 + if (pdb_ctx[pdb_level].info >= 0) 1.356 { 1.357 - pdb_get_values(pdb_info_thread, pdb_buffer, addr, length); 1.358 + pdb_get_values(pdb_buffer, length, 1.359 + pdb_ctx[pdb_level].info_cr3, addr); 1.360 mem2hex (pdb_buffer, pdb_out_buffer, length); 1.361 } 1.362 else 1.363 @@ -380,8 +561,9 @@ pdb_process_command (char *ptr, struct p 1.364 { 1.365 mem_err = 0; 1.366 1.367 - pdb_set_values(pdb_info_thread, 1.368 - ptr, addr, length); 1.369 + /* pdb_set_values(ptr, length, cr3, addr); */ 1.370 + pdb_set_values(ptr, length, 1.371 + pdb_ctx[pdb_level].info_cr3, addr); 1.372 1.373 if (mem_err) 1.374 { 1.375 @@ -402,20 +584,73 @@ pdb_process_command (char *ptr, struct p 1.376 } 1.377 case 'T': 1.378 { 1.379 - int thread; 1.380 - if (hexToInt (&ptr, &thread)) 1.381 + int id; 1.382 + 1.383 + if (hexToInt (&ptr, &id)) 1.384 { 1.385 - struct task_struct *p; 1.386 - thread -= PDB_DOMAIN_OFFSET; 1.387 - if ( (p = find_domain_by_id(thread)) == NULL) 1.388 - strcpy (pdb_out_buffer, "E00"); 1.389 - else 1.390 - strcpy (pdb_out_buffer, "OK"); 1.391 - put_task_struct(p); 1.392 + { /* case pdb_lvl_xen */ 1.393 + struct task_struct *p; 1.394 + id -= PDB_ID_OFFSET; 1.395 + if ( (p = find_domain_by_id(id)) == NULL) 1.396 + strcpy (pdb_out_buffer, "E00"); 1.397 + else 1.398 + strcpy (pdb_out_buffer, "OK"); 1.399 + put_task_struct(p); 1.400 + } 1.401 + 1.402 +#ifdef PDB_FUTURE 1.403 + 1.404 + switch (pdb_level) /* previous level */ 1.405 + { 1.406 + case PDB_LVL_XEN: 1.407 + { 1.408 + struct task_struct *p; 1.409 + id -= PDB_ID_OFFSET; 1.410 + if ( (p = find_domain_by_id(id)) == NULL) 1.411 + strcpy (pdb_out_buffer, "E00"); 1.412 + else 1.413 + strcpy (pdb_out_buffer, "OK"); 1.414 + put_task_struct(p); 1.415 + 1.416 + pdb_level = PDB_LVL_GUESTOS; 1.417 + pdb_ctx[pdb_level].ctrl = id; 1.418 + pdb_ctx[pdb_level].info = id; 1.419 + break; 1.420 + } 1.421 + case PDB_LVL_GUESTOS: 1.422 + { 1.423 + if (pdb_level == -1) 1.424 + { 1.425 + pdb_level = PDB_LVL_XEN; 1.426 + } 1.427 + else 1.428 + { 1.429 + pdb_level = PDB_LVL_PROCESS; 1.430 + pdb_ctx[pdb_level].ctrl = id; 1.431 + pdb_ctx[pdb_level].info = id; 1.432 + } 1.433 + break; 1.434 + } 1.435 + case PDB_LVL_PROCESS: 1.436 + { 1.437 + if (pdb_level == -1) 1.438 + { 1.439 + pdb_level = PDB_LVL_GUESTOS; 1.440 + } 1.441 + break; 1.442 + } 1.443 + default: 1.444 + { 1.445 + printk ("pdb internal error: invalid level [%d]\n", 1.446 + pdb_level); 1.447 + } 1.448 + } 1.449 + 1.450 +#endif /* PDB_FUTURE */ 1.451 } 1.452 break; 1.453 } 1.454 - } /* switch */ 1.455 + } 1.456 1.457 /* reply to the request */ 1.458 pdb_put_packet (pdb_out_buffer, ack); 1.459 @@ -436,6 +671,9 @@ int pdb_serial_input(u_char c, struct pt 1.460 { 1.461 int out = 1; 1.462 int loop, count; 1.463 + unsigned long cr3; 1.464 + 1.465 + __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : ); 1.466 1.467 switch (pdb_debug_state) 1.468 { 1.469 @@ -489,7 +727,8 @@ int pdb_serial_input(u_char c, struct pt 1.470 pdb_in_buffer[loop - 3] = pdb_in_buffer[loop]; 1.471 } 1.472 1.473 - pdb_process_command (pdb_in_buffer, regs); 1.474 + pdb_process_command (pdb_in_buffer, regs, cr3, 1.475 + PDB_LIVE_EXCEPTION); 1.476 } 1.477 pdb_debug_state = 0; 1.478 break; 1.479 @@ -594,18 +833,20 @@ hexToInt (char **ptr, int *intValue) 1.480 */ 1.481 struct pdb_breakpoint breakpoints; 1.482 1.483 -void pdb_bkpt_add (unsigned long address) 1.484 +void pdb_bkpt_add (unsigned long cr3, unsigned long address) 1.485 { 1.486 struct pdb_breakpoint *bkpt = kmalloc(sizeof(*bkpt), GFP_KERNEL); 1.487 + bkpt->cr3 = cr3; 1.488 bkpt->address = address; 1.489 list_add(&bkpt->list, &breakpoints.list); 1.490 } 1.491 1.492 /* 1.493 * Check to see of the breakpoint is in the list of known breakpoints 1.494 - * Return 1 if it has been set, 0 otherwise. 1.495 + * Return 1 if it has been set, NULL otherwise. 1.496 */ 1.497 -struct pdb_breakpoint* pdb_bkpt_search (unsigned long address) 1.498 +struct pdb_breakpoint* pdb_bkpt_search (unsigned long cr3, 1.499 + unsigned long address) 1.500 { 1.501 struct list_head *list_entry; 1.502 struct pdb_breakpoint *bkpt; 1.503 @@ -613,7 +854,7 @@ struct pdb_breakpoint* pdb_bkpt_search ( 1.504 list_for_each(list_entry, &breakpoints.list) 1.505 { 1.506 bkpt = list_entry(list_entry, struct pdb_breakpoint, list); 1.507 - if ( bkpt->address == address ) 1.508 + if ( bkpt->cr3 == cr3 && bkpt->address == address ) 1.509 return bkpt; 1.510 } 1.511 1.512 @@ -624,7 +865,7 @@ struct pdb_breakpoint* pdb_bkpt_search ( 1.513 * Remove a breakpoint to the list of known breakpoints. 1.514 * Return 1 if the element was not found, otherwise 0. 1.515 */ 1.516 -int pdb_bkpt_remove (unsigned long address) 1.517 +int pdb_bkpt_remove (unsigned long cr3, unsigned long address) 1.518 { 1.519 struct list_head *list_entry; 1.520 struct pdb_breakpoint *bkpt; 1.521 @@ -632,7 +873,7 @@ int pdb_bkpt_remove (unsigned long addre 1.522 list_for_each(list_entry, &breakpoints.list) 1.523 { 1.524 bkpt = list_entry(list_entry, struct pdb_breakpoint, list); 1.525 - if ( bkpt->address == address ) 1.526 + if ( bkpt->cr3 == cr3 && bkpt->address == address ) 1.527 { 1.528 list_del(&bkpt->list); 1.529 kfree(bkpt); 1.530 @@ -643,6 +884,167 @@ int pdb_bkpt_remove (unsigned long addre 1.531 return 1; 1.532 } 1.533 1.534 +/* 1.535 + * Check to see if a memory write is really gdb setting a breakpoint 1.536 + */ 1.537 +void pdb_bkpt_check (u_char *buffer, int length, 1.538 + unsigned long cr3, unsigned long addr) 1.539 +{ 1.540 + if (length == 1 && buffer[0] == 'c' && buffer[1] == 'c') 1.541 + { 1.542 + /* inserting a new breakpoint */ 1.543 + pdb_bkpt_add(cr3, addr); 1.544 + TRC(printk("pdb breakpoint detected at 0x%lx:0x%lx\n", cr3, addr)); 1.545 + } 1.546 + else if ( pdb_bkpt_remove(cr3, addr) == 0 ) 1.547 + { 1.548 + /* removing a breakpoint */ 1.549 + TRC(printk("pdb breakpoint cleared at 0x%lx:0x%lx\n", cr3, addr)); 1.550 + } 1.551 +} 1.552 + 1.553 +/***********************************************************************/ 1.554 + 1.555 +int pdb_change_values(u_char *buffer, int length, 1.556 + unsigned long cr3, unsigned long addr, int rw); 1.557 +int pdb_change_values_one_page(u_char *buffer, int length, 1.558 + unsigned long cr3, unsigned long addr, int rw); 1.559 + 1.560 +#define __PDB_GET_VAL 1 1.561 +#define __PDB_SET_VAL 2 1.562 + 1.563 +/* 1.564 + * Set memory in a domain's address space 1.565 + * Set "length" bytes at "address" from "domain" to the values in "buffer". 1.566 + * Return the number of bytes set, 0 if there was a problem. 1.567 + */ 1.568 + 1.569 +int pdb_set_values(u_char *buffer, int length, 1.570 + unsigned long cr3, unsigned long addr) 1.571 +{ 1.572 + int count = pdb_change_values(buffer, length, cr3, addr, __PDB_SET_VAL); 1.573 + pdb_bkpt_check(buffer, length, cr3, addr); 1.574 + return count; 1.575 +} 1.576 + 1.577 +/* 1.578 + * Read memory from a domain's address space. 1.579 + * Fetch "length" bytes at "address" from "domain" into "buffer". 1.580 + * Return the number of bytes read, 0 if there was a problem. 1.581 + */ 1.582 + 1.583 +int pdb_get_values(u_char *buffer, int length, 1.584 + unsigned long cr3, unsigned long addr) 1.585 +{ 1.586 + return pdb_change_values(buffer, length, cr3, addr, __PDB_GET_VAL); 1.587 +} 1.588 + 1.589 +/* 1.590 + * Read or write memory in an address space 1.591 + */ 1.592 +int pdb_change_values(u_char *buffer, int length, 1.593 + unsigned long cr3, unsigned long addr, int rw) 1.594 +{ 1.595 + int remaining; /* number of bytes to touch past this page */ 1.596 + int bytes = 0; 1.597 + 1.598 + while ( (remaining = (addr + length - 1) - (addr | (PAGE_SIZE - 1))) > 0) 1.599 + { 1.600 + bytes += pdb_change_values_one_page(buffer, length - remaining, 1.601 + cr3, addr, rw); 1.602 + buffer = buffer + (2 * (length - remaining)); 1.603 + length = remaining; 1.604 + addr = (addr | (PAGE_SIZE - 1)) + 1; 1.605 + } 1.606 + 1.607 + bytes += pdb_change_values_one_page(buffer, length, cr3, addr, rw); 1.608 + return bytes; 1.609 +} 1.610 + 1.611 +/* 1.612 + * Change memory in a process' address space in one page 1.613 + * Read or write "length" bytes at "address" into/from "buffer" 1.614 + * from the virtual address space referenced by "cr3". 1.615 + * Return the number of bytes read, 0 if there was a problem. 1.616 + */ 1.617 + 1.618 +int pdb_change_values_one_page(u_char *buffer, int length, 1.619 + unsigned long cr3, unsigned long addr, int rw) 1.620 +{ 1.621 + l2_pgentry_t* l2_table = NULL; 1.622 + l1_pgentry_t* l1_table = NULL; 1.623 + u_char *page; 1.624 + int bytes = 0; 1.625 + 1.626 + l2_table = map_domain_mem(cr3); 1.627 + l2_table += l2_table_offset(addr); 1.628 + if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 1.629 + { 1.630 + struct task_struct *p = find_domain_by_id(0); 1.631 + printk ("cr3: 0x%lx dom0cr3: 0x%lx\n", cr3, 1.632 + p->mm.shadow_mode ? pagetable_val(p->mm.shadow_table) 1.633 + : pagetable_val(p->mm.pagetable)); 1.634 + put_task_struct(p); 1.635 + 1.636 + printk ("L2:0x%p (0x%lx) \n", l2_table, l2_pgentry_val(*l2_table)); 1.637 + goto exit2; 1.638 + } 1.639 + 1.640 + if (l2_pgentry_val(*l2_table) & _PAGE_PSE) 1.641 + { 1.642 +#define PSE_PAGE_SHIFT L2_PAGETABLE_SHIFT 1.643 +#define PSE_PAGE_SIZE (1UL << PSE_PAGE_SHIFT) 1.644 +#define PSE_PAGE_MASK (~(PSE_PAGE_SIZE-1)) 1.645 + 1.646 +#define L1_PAGE_BITS ( (ENTRIES_PER_L1_PAGETABLE - 1) << L1_PAGETABLE_SHIFT ) 1.647 + 1.648 +#define pse_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PSE_PAGE_MASK) 1.649 + 1.650 + page = map_domain_mem(pse_pgentry_to_phys(*l2_table) + /* 10 bits */ 1.651 + (addr & L1_PAGE_BITS)); /* 10 bits */ 1.652 + page += addr & (PAGE_SIZE - 1); /* 12 bits */ 1.653 + } 1.654 + else 1.655 + { 1.656 + l1_table = map_domain_mem(l2_pgentry_to_phys(*l2_table)); 1.657 + l1_table += l1_table_offset(addr); 1.658 + if (!(l1_pgentry_val(*l1_table) & _PAGE_PRESENT)) 1.659 + { 1.660 + printk ("L2:0x%p (0x%lx) L1:0x%p (0x%lx)\n", 1.661 + l2_table, l2_pgentry_val(*l2_table), 1.662 + l1_table, l1_pgentry_val(*l1_table)); 1.663 + goto exit1; 1.664 + } 1.665 + 1.666 + page = map_domain_mem(l1_pgentry_to_phys(*l1_table)); 1.667 + page += addr & (PAGE_SIZE - 1); 1.668 + } 1.669 + 1.670 + switch (rw) 1.671 + { 1.672 + case __PDB_GET_VAL: /* read */ 1.673 + memcpy (buffer, page, length); 1.674 + bytes = length; 1.675 + break; 1.676 + case __PDB_SET_VAL: /* write */ 1.677 + hex2mem (buffer, page, length); 1.678 + bytes = length; 1.679 + break; 1.680 + default: /* unknown */ 1.681 + printk ("error: unknown RW flag: %d\n", rw); 1.682 + return 0; 1.683 + } 1.684 + 1.685 + unmap_domain_mem((void *)page); 1.686 +exit1: 1.687 + if (l1_table != NULL) 1.688 + unmap_domain_mem((void *)l1_table); 1.689 +exit2: 1.690 + unmap_domain_mem((void *)l2_table); 1.691 + 1.692 + return bytes; 1.693 +} 1.694 + 1.695 /***********************************************************************/ 1.696 1.697 void breakpoint(void); 1.698 @@ -716,7 +1118,7 @@ void pdb_get_packet(char *buffer) 1.699 pdb_put_char('+'); 1.700 if (buffer[2] == ':') 1.701 { 1.702 - printk ("gdb packet found with sequence ID\n"); 1.703 + printk ("pdb: obsolete gdb packet (sequence ID)\n"); 1.704 } 1.705 } 1.706 else 1.707 @@ -735,38 +1137,40 @@ void pdb_get_packet(char *buffer) 1.708 * be propagated to the guest os. 1.709 */ 1.710 1.711 -#define DEBUG_EXCEPTION 0x01 1.712 -#define BREAKPT_EXCEPTION 0x03 1.713 -#define KEYPRESS_EXCEPTION 0x88 1.714 - 1.715 int pdb_handle_exception(int exceptionVector, 1.716 struct pt_regs *xen_regs) 1.717 { 1.718 int signal = 0; 1.719 + struct pdb_breakpoint* bkpt; 1.720 int watchdog_save; 1.721 + unsigned long cr3; 1.722 + 1.723 + __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : ); 1.724 1.725 /* 1.726 * If PDB didn't set the breakpoint, is not single stepping, and the user 1.727 * didn't press the magic debug key, then we don't handle the exception. 1.728 */ 1.729 - if ( (pdb_bkpt_search(xen_regs->eip - 1) == NULL) && 1.730 - !pdb_stepping && (exceptionVector != KEYPRESS_EXCEPTION) ) 1.731 + bkpt = pdb_bkpt_search(cr3, xen_regs->eip - 1); 1.732 + if ( (bkpt == NULL) && 1.733 + !pdb_stepping && (exceptionVector != KEYPRESS_EXCEPTION) && 1.734 + xen_regs->eip < 0xc0000000) /* xenolinux for now! */ 1.735 { 1.736 - DPRINTK("pdb: external breakpoint at 0x%lx\n", xen_regs->eip); 1.737 + TRC(printf("pdb: user bkpt at 0x%lx:0x%lx\n", cr3, xen_regs->eip)); 1.738 return 1; 1.739 } 1.740 1.741 - printk("pdb_handle_exception [0x%x][0x%lx]\n", 1.742 - exceptionVector, xen_regs->eip); 1.743 + printk("pdb_handle_exception [0x%x][0x%lx:0x%lx]\n", 1.744 + exceptionVector, cr3, xen_regs->eip); 1.745 1.746 if ( pdb_stepping ) 1.747 { 1.748 /* Stepped one instruction; now return to normal execution. */ 1.749 - xen_regs->eflags &= ~0x100; 1.750 + xen_regs->eflags &= ~X86_EFLAGS_TF; 1.751 pdb_stepping = 0; 1.752 } 1.753 1.754 - if ( exceptionVector == BREAKPT_EXCEPTION ) 1.755 + if ( exceptionVector == BREAKPT_EXCEPTION && bkpt != NULL) 1.756 { 1.757 /* Executed Int3: replace breakpoint byte with real program byte. */ 1.758 xen_regs->eip--; 1.759 @@ -800,7 +1204,7 @@ int pdb_handle_exception(int exceptionVe 1.760 pdb_out_buffer[0] = 0; 1.761 pdb_get_packet(pdb_in_buffer); 1.762 } 1.763 - while ( pdb_process_command(pdb_in_buffer, xen_regs) == 0 ); 1.764 + while ( pdb_process_command(pdb_in_buffer, xen_regs, cr3, signal) == 0 ); 1.765 1.766 watchdog_on = watchdog_save; 1.767 1.768 @@ -816,9 +1220,10 @@ void pdb_key_pressed(u_char key, void *d 1.769 void initialize_pdb() 1.770 { 1.771 extern char opt_pdb[]; 1.772 + int loop; 1.773 1.774 /* Certain state must be initialised even when PDB will not be used. */ 1.775 - breakpoints.address = 0; 1.776 + memset((void *) &breakpoints, 0, sizeof(breakpoints)); 1.777 INIT_LIST_HEAD(&breakpoints.list); 1.778 pdb_stepping = 0; 1.779 1.780 @@ -827,14 +1232,22 @@ void initialize_pdb() 1.781 1.782 if ( (pdb_serhnd = parse_serial_handle(opt_pdb)) == -1 ) 1.783 { 1.784 - printk("Failed to initialise PDB on port %s\n", opt_pdb); 1.785 + printk("error: failed to initialize PDB on port %s\n", opt_pdb); 1.786 return; 1.787 } 1.788 1.789 - printk("Initialised pervasive debugger (PDB) on port %s\n", opt_pdb); 1.790 + for (loop = 0; loop < pdb_ctx_count; loop++) 1.791 + { 1.792 + pdb_ctx[loop].ctrl = -1; 1.793 + pdb_ctx[loop].info = -1; 1.794 + pdb_ctx[loop].ctrl_cr3 = 0; 1.795 + pdb_ctx[loop].info_cr3 = 0; 1.796 + } 1.797 + 1.798 + printk("Initialized pervasive debugger (PDB) on port %s\n", opt_pdb); 1.799 1.800 /* Acknowledge any spurious GDB packets. */ 1.801 - serial_putc(pdb_serhnd, '+'); 1.802 + pdb_put_char('+'); 1.803 1.804 add_key_handler('D', pdb_key_pressed, "enter pervasive debugger"); 1.805
2.1 --- a/xen/common/debug-linux.c Thu Mar 25 15:16:57 2004 +0000 2.2 +++ b/xen/common/debug-linux.c Thu Mar 25 17:52:36 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-xen/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 Thu Mar 25 15:16:57 2004 +0000 3.2 +++ b/xen/common/debug.c Thu Mar 25 17:52:36 2004 +0000 3.3 @@ -11,7 +11,6 @@ 3.4 #include <xen/sched.h> 3.5 #include <xen/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,148 +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 - if (p->mm.shadow_mode ) 3.84 - l2_table = map_domain_mem(pagetable_val(p->mm.shadow_table)); 3.85 - else 3.86 - l2_table = map_domain_mem(pagetable_val(p->mm.pagetable)); 3.87 - 3.88 - l2_table += l2_table_offset(addr); 3.89 - if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 3.90 - { 3.91 - printk ("L2:0x%p (0x%lx) \n", l2_table, l2_pgentry_val(*l2_table)); 3.92 - goto exit2; 3.93 - } 3.94 - 3.95 - if (l2_pgentry_val(*l2_table) & _PAGE_PSE) 3.96 - { 3.97 -#define PSE_PAGE_SHIFT L2_PAGETABLE_SHIFT 3.98 -#define PSE_PAGE_SIZE (1UL << PSE_PAGE_SHIFT) 3.99 -#define PSE_PAGE_MASK (~(PSE_PAGE_SIZE-1)) 3.100 - 3.101 -#define L1_PAGE_BITS ( (ENTRIES_PER_L1_PAGETABLE - 1) << L1_PAGETABLE_SHIFT ) 3.102 - 3.103 -#define pse_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PSE_PAGE_MASK) 3.104 - 3.105 - page = map_domain_mem(pse_pgentry_to_phys(*l2_table) +/* 10 bits */ 3.106 - (addr & L1_PAGE_BITS)); /* 10 bits */ 3.107 - page += addr & (PAGE_SIZE - 1); /* 12 bits */ 3.108 - } 3.109 - else 3.110 - { 3.111 - l1_table = map_domain_mem(l2_pgentry_to_phys(*l2_table)); 3.112 - l1_table += l1_table_offset(addr); 3.113 - if (!(l1_pgentry_val(*l1_table) & _PAGE_PRESENT)) 3.114 - { 3.115 - printk ("L2:0x%p (0x%lx) L1:0x%p (0x%lx)\n", 3.116 - l2_table, l2_pgentry_val(*l2_table), 3.117 - l1_table, l1_pgentry_val(*l1_table)); 3.118 - goto exit1; 3.119 - } 3.120 - 3.121 - page = map_domain_mem(l1_pgentry_to_phys(*l1_table)); 3.122 - page += addr & (PAGE_SIZE - 1); 3.123 - } 3.124 - 3.125 - switch (rw) 3.126 - { 3.127 - case 1: /* read */ 3.128 - memcpy (buffer, page, length); 3.129 - bytes = length; 3.130 - break; 3.131 - case 2: /* write */ 3.132 - hex2mem (buffer, page, length); 3.133 - bytes = length; 3.134 - break; 3.135 - default: /* unknown */ 3.136 - printk ("error: unknown RW flag: %d\n", rw); 3.137 - return 0; 3.138 - } 3.139 - 3.140 - unmap_domain_mem((void *)page); 3.141 - exit1: 3.142 - if (l1_table != NULL) 3.143 - unmap_domain_mem((void *)l1_table); 3.144 - exit2: 3.145 - unmap_domain_mem((void *)l2_table); 3.146 - } 3.147 - else 3.148 - { 3.149 - /* read spans pages. need to recurse */ 3.150 - printk ("pdb memory SPAN! addr:0x%lx l: %x\n", addr, length); 3.151 - } 3.152 - 3.153 - put_task_struct(p); 3.154 - return bytes; 3.155 -} 3.156 - 3.157 +extern u_char pdb_linux_get_value(int pid, unsigned long cr3, 3.158 + unsigned long addr); 3.159 3.160 /* 3.161 * interactively call pervasive debugger from a privileged domain 3.162 @@ -210,6 +69,14 @@ void pdb_do_debug (dom0_op_t *op) 3.163 { 3.164 int loop; 3.165 u_char x; 3.166 + unsigned long cr3; 3.167 + struct task_struct *p; 3.168 + 3.169 + p = find_domain_by_id(op->u.debug.domain); 3.170 + if (p->mm.shadow_mode) 3.171 + cr3 = pagetable_val(p->mm.shadow_table); 3.172 + else 3.173 + cr3 = pagetable_val(p->mm.pagetable); 3.174 3.175 for (loop = 0; loop < op->u.debug.in2; loop++) /* length */ 3.176 { 3.177 @@ -217,15 +84,14 @@ void pdb_do_debug (dom0_op_t *op) 3.178 { 3.179 printk ("\n%08x ", op->u.debug.in1 + loop); 3.180 } 3.181 - x = pdb_linux_get_value(op->u.debug.domain, /* domain */ 3.182 - op->u.debug.in3, /* pid */ 3.183 - op->u.debug.in1 + loop); /* addr */ 3.184 + x = pdb_linux_get_value(op->u.debug.in3, 3.185 + cr3, op->u.debug.in1 + loop); 3.186 printk (" %02x", x); 3.187 } 3.188 printk ("\n"); 3.189 + put_task_struct(p); 3.190 break; 3.191 } 3.192 - 3.193 case 's' : 3.194 { 3.195 struct task_struct * p = find_domain_by_id(op->u.debug.domain); 3.196 @@ -233,7 +99,9 @@ void pdb_do_debug (dom0_op_t *op) 3.197 if (p != NULL) 3.198 { 3.199 if (p->state != TASK_STOPPED) 3.200 - send_guest_virq(p, VIRQ_STOP); 3.201 + { 3.202 + send_guest_virq(p, VIRQ_STOP); 3.203 + } 3.204 put_task_struct(p); 3.205 } 3.206 else
4.1 --- a/xen/include/asm-i386/pdb.h Thu Mar 25 15:16:57 2004 +0000 4.2 +++ b/xen/include/asm-i386/pdb.h Thu Mar 25 17:52:36 2004 +0000 4.3 @@ -13,6 +13,7 @@ 4.4 4.5 #include <asm/ptrace.h> 4.6 #include <xen/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);