debuggers.hg
changeset 4605:793cb54d3745
bitkeeper revision 1.1321 (42642eb1DhlDvDKcX1gTZhvys-xHJQ)
fix single-stepping
make persistent context per-cpu
Signed-off-by: Kip Macy <kmacy@fsmware.com>
Signed-off-by: ian@xensource.com
fix single-stepping
make persistent context per-cpu
Signed-off-by: Kip Macy <kmacy@fsmware.com>
Signed-off-by: ian@xensource.com
author | iap10@freefall.cl.cam.ac.uk |
---|---|
date | Mon Apr 18 22:03:29 2005 +0000 (2005-04-18) |
parents | 7edc9d4fa41e |
children | 756991cc6c70 |
files | tools/libxc/xc_ptrace.c |
line diff
1.1 --- a/tools/libxc/xc_ptrace.c Mon Apr 18 21:59:54 2005 +0000 1.2 +++ b/tools/libxc/xc_ptrace.c Mon Apr 18 22:03:29 2005 +0000 1.3 @@ -10,6 +10,7 @@ 1.4 #define PDRSHIFT 22 1.5 #define PSL_T 0x00000100 /* trace enable bit */ 1.6 1.7 +#define VCPU 0 /* XXX */ 1.8 1.9 /* 1.10 * long 1.11 @@ -67,6 +68,17 @@ struct gdb_regs { 1.12 long esp; /* 60 */ 1.13 int xss; /* 64 */ 1.14 }; 1.15 + 1.16 +#define FETCH_REGS(cpu) \ 1.17 + if (!regs_valid[cpu]) \ 1.18 + { \ 1.19 + int retval = xc_domain_getfullinfo(xc_handle, domid, cpu, NULL, &ctxt[cpu]); \ 1.20 + if (retval) \ 1.21 + goto error_out; \ 1.22 + cr3[cpu] = ctxt[cpu].pt_base; \ 1.23 + regs_valid[cpu] = 1; \ 1.24 + } \ 1.25 + 1.26 #define printval(x) printf("%s = %lx\n", #x, (long)x); 1.27 #define SET_PT_REGS(pt, xc) \ 1.28 { \ 1.29 @@ -115,74 +127,70 @@ struct gdb_regs { 1.30 /* XXX application state */ 1.31 1.32 1.33 -static int xc_handle; 1.34 -static int regs_valid; 1.35 -static unsigned long cr3; 1.36 -static full_execution_context_t ctxt; 1.37 +static int xc_handle; 1.38 +static int regs_valid[MAX_VIRT_CPUS]; 1.39 +static unsigned long cr3[MAX_VIRT_CPUS]; 1.40 +static full_execution_context_t ctxt[MAX_VIRT_CPUS]; 1.41 + 1.42 1.43 /* --------------------- */ 1.44 1.45 static void * 1.46 -map_domain_va(unsigned long domid, void * guest_va, int perm) 1.47 +map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm) 1.48 { 1.49 unsigned long pde, page; 1.50 unsigned long va = (unsigned long)guest_va; 1.51 1.52 - static unsigned long cr3_phys; 1.53 - static unsigned long *cr3_virt; 1.54 - static unsigned long pde_phys; 1.55 - static unsigned long *pde_virt; 1.56 - static unsigned long page_phys; 1.57 - static unsigned long *page_virt; 1.58 + static unsigned long cr3_phys[MAX_VIRT_CPUS]; 1.59 + static unsigned long *cr3_virt[MAX_VIRT_CPUS]; 1.60 + static unsigned long pde_phys[MAX_VIRT_CPUS]; 1.61 + static unsigned long *pde_virt[MAX_VIRT_CPUS]; 1.62 + static unsigned long page_phys[MAX_VIRT_CPUS]; 1.63 + static unsigned long *page_virt[MAX_VIRT_CPUS]; 1.64 1.65 - static int prev_perm; 1.66 - if (!regs_valid) 1.67 + static int prev_perm[MAX_VIRT_CPUS]; 1.68 + 1.69 + FETCH_REGS(cpu); 1.70 + 1.71 + if (cr3[cpu] != cr3_phys[cpu]) 1.72 { 1.73 - int retval = xc_domain_getfullinfo(xc_handle, domid, 0, NULL, &ctxt); 1.74 - if (retval) 1.75 - goto error_out; 1.76 - cr3 = ctxt.pt_base; 1.77 - regs_valid = 1; 1.78 - } 1.79 - if (cr3 != cr3_phys) 1.80 - { 1.81 - cr3_phys = cr3; 1.82 - if (cr3_virt) 1.83 - munmap(cr3_virt, PAGE_SIZE); 1.84 - if ((cr3_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 1.85 + cr3_phys[cpu] = cr3[cpu]; 1.86 + if (cr3_virt[cpu]) 1.87 + munmap(cr3_virt[cpu], PAGE_SIZE); 1.88 + if ((cr3_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 1.89 PROT_READ, 1.90 - cr3_phys >> PAGE_SHIFT)) == NULL) 1.91 + cr3_phys[cpu] >> PAGE_SHIFT)) == NULL) 1.92 goto error_out; 1.93 } 1.94 - if ((pde = cr3_virt[vtopdi(va)]) == 0) 1.95 + if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) 1.96 goto error_out; 1.97 - if (pde != pde_phys) 1.98 + if (pde != pde_phys[cpu]) 1.99 { 1.100 - pde_phys = pde; 1.101 - if (pde_virt) 1.102 - munmap(pde_virt, PAGE_SIZE); 1.103 - if ((pde_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 1.104 + pde_phys[cpu] = pde; 1.105 + if (pde_virt[cpu]) 1.106 + munmap(pde_virt[cpu], PAGE_SIZE); 1.107 + if ((pde_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 1.108 PROT_READ, 1.109 - pde_phys >> PAGE_SHIFT)) == NULL) 1.110 + pde_phys[cpu] >> PAGE_SHIFT)) == NULL) 1.111 goto error_out; 1.112 } 1.113 - if ((page = pde_virt[vtopti(va)]) == 0) 1.114 + if ((page = pde_virt[cpu][vtopti(va)]) == 0) 1.115 goto error_out; 1.116 - if (page != page_phys || perm != prev_perm) 1.117 + if (page != page_phys[cpu] || perm != prev_perm[cpu]) 1.118 { 1.119 - page_phys = page; 1.120 - if (page_virt) 1.121 - munmap(page_virt, PAGE_SIZE); 1.122 - if ((page_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 1.123 - perm, 1.124 - page_phys >> PAGE_SHIFT)) == NULL) { 1.125 - printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3, pde, page, vtopti(va)); 1.126 - page_phys = 0; 1.127 + page_phys[cpu] = page; 1.128 + if (page_virt[cpu]) 1.129 + munmap(page_virt[cpu], PAGE_SIZE); 1.130 + if ((page_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 1.131 + perm, 1.132 + page_phys[cpu] >> PAGE_SHIFT)) == NULL) { 1.133 + printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va)); 1.134 + page_phys[cpu] = 0; 1.135 goto error_out; 1.136 } 1.137 - prev_perm = perm; 1.138 + prev_perm[cpu] = perm; 1.139 } 1.140 - return (void *)(((unsigned long)page_virt) | (va & BSD_PAGE_MASK)); 1.141 + return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); 1.142 1.143 error_out: 1.144 return 0; 1.145 @@ -231,14 +239,14 @@ waitdomain(int domain, int *status, int 1.146 } 1.147 1.148 long 1.149 -xc_ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data) 1.150 +xc_ptrace(enum __ptrace_request request, pid_t domid, void *addr, void *data) 1.151 { 1.152 - dom0_op_t op; 1.153 - int status = 0; 1.154 - xc_domaininfo_t info; 1.155 + dom0_op_t op; 1.156 + int status = 0; 1.157 struct gdb_regs pt; 1.158 - long retval = 0; 1.159 - unsigned long *guest_va; 1.160 + long retval = 0; 1.161 + unsigned long *guest_va; 1.162 + int cpu = VCPU; 1.163 1.164 op.interface_version = DOM0_INTERFACE_VERSION; 1.165 1.166 @@ -246,23 +254,23 @@ xc_ptrace(enum __ptrace_request request, 1.167 if ((xc_handle = xc_interface_open()) < 0) 1.168 return -1; 1.169 #if 0 1.170 - printf("%20s %d, %p, %p \n", ptrace_names[request], pid, addr, data); 1.171 + printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data); 1.172 #endif 1.173 switch (request) { 1.174 case PTRACE_PEEKTEXT: 1.175 case PTRACE_PEEKDATA: 1.176 - if ((guest_va = (unsigned long *)map_domain_va(pid, addr, PROT_READ)) == NULL) { 1.177 + if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ)) == NULL) { 1.178 status = EFAULT; 1.179 - goto done; 1.180 + goto error_out; 1.181 } 1.182 1.183 retval = *guest_va; 1.184 break; 1.185 case PTRACE_POKETEXT: 1.186 case PTRACE_POKEDATA: 1.187 - if ((guest_va = (unsigned long *)map_domain_va(pid, addr, PROT_READ|PROT_WRITE)) == NULL) { 1.188 + if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ|PROT_WRITE)) == NULL) { 1.189 status = EFAULT; 1.190 - goto done; 1.191 + goto error_out; 1.192 } 1.193 1.194 *guest_va = (unsigned long)data; 1.195 @@ -270,70 +278,79 @@ xc_ptrace(enum __ptrace_request request, 1.196 case PTRACE_GETREGS: 1.197 case PTRACE_GETFPREGS: 1.198 case PTRACE_GETFPXREGS: 1.199 - /* XXX hard-coding UP */ 1.200 - retval = xc_domain_getfullinfo(xc_handle, pid, 0, &info, &ctxt); 1.201 + FETCH_REGS(cpu); 1.202 1.203 - if (retval) { 1.204 - printf("getfullinfo failed\n"); 1.205 - goto done; 1.206 - } 1.207 if (request == PTRACE_GETREGS) { 1.208 - SET_PT_REGS(pt, ctxt.cpu_ctxt); 1.209 + SET_PT_REGS(pt, ctxt[cpu].cpu_ctxt); 1.210 memcpy(data, &pt, sizeof(elf_gregset_t)); 1.211 } else if (request == PTRACE_GETFPREGS) 1.212 - memcpy(data, &ctxt.fpu_ctxt, sizeof(ctxt.fpu_ctxt)); 1.213 + memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt)); 1.214 else /*if (request == PTRACE_GETFPXREGS)*/ 1.215 - memcpy(data, &ctxt.fpu_ctxt, sizeof(ctxt.fpu_ctxt)); 1.216 - cr3 = ctxt.pt_base; 1.217 - regs_valid = 1; 1.218 + memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt)); 1.219 break; 1.220 case PTRACE_SETREGS: 1.221 op.cmd = DOM0_SETDOMAININFO; 1.222 - SET_XC_REGS(((struct gdb_regs *)data), ctxt.cpu_ctxt); 1.223 - op.u.setdomaininfo.domain = pid; 1.224 + SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].cpu_ctxt); 1.225 + op.u.setdomaininfo.domain = domid; 1.226 /* XXX need to understand multiple exec_domains */ 1.227 - op.u.setdomaininfo.exec_domain = 0; 1.228 - op.u.setdomaininfo.ctxt = &ctxt; 1.229 + op.u.setdomaininfo.exec_domain = cpu; 1.230 + op.u.setdomaininfo.ctxt = &ctxt[cpu]; 1.231 retval = do_dom0_op(xc_handle, &op); 1.232 if (retval) 1.233 - goto done; 1.234 + goto error_out; 1.235 1.236 break; 1.237 case PTRACE_ATTACH: 1.238 op.cmd = DOM0_GETDOMAININFO; 1.239 - op.u.getdomaininfo.domain = pid; 1.240 + op.u.getdomaininfo.domain = domid; 1.241 op.u.getdomaininfo.exec_domain = 0; 1.242 - op.u.getdomaininfo.ctxt = &ctxt; 1.243 + op.u.getdomaininfo.ctxt = NULL; 1.244 retval = do_dom0_op(xc_handle, &op); 1.245 if (retval) { 1.246 perror("dom0 op failed"); 1.247 - goto done; 1.248 + goto error_out; 1.249 } 1.250 if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) { 1.251 printf("domain currently paused\n"); 1.252 - goto done; 1.253 + goto error_out; 1.254 } 1.255 printf("domain not currently paused\n"); 1.256 op.cmd = DOM0_PAUSEDOMAIN; 1.257 - op.u.pausedomain.domain = pid; 1.258 + op.u.pausedomain.domain = domid; 1.259 retval = do_dom0_op(xc_handle, &op); 1.260 break; 1.261 case PTRACE_SINGLESTEP: 1.262 - ctxt.cpu_ctxt.eflags |= PSL_T; 1.263 + ctxt[VCPU].cpu_ctxt.eflags |= PSL_T; 1.264 op.cmd = DOM0_SETDOMAININFO; 1.265 - op.u.setdomaininfo.domain = pid; 1.266 + op.u.setdomaininfo.domain = domid; 1.267 op.u.setdomaininfo.exec_domain = 0; 1.268 - op.u.setdomaininfo.ctxt = &ctxt; 1.269 + op.u.setdomaininfo.ctxt = &ctxt[cpu]; 1.270 retval = do_dom0_op(xc_handle, &op); 1.271 if (retval) { 1.272 perror("dom0 op failed"); 1.273 - goto done; 1.274 + goto error_out; 1.275 } 1.276 case PTRACE_CONT: 1.277 case PTRACE_DETACH: 1.278 - regs_valid = 0; 1.279 + if (request != PTRACE_SINGLESTEP) { 1.280 + FETCH_REGS(cpu); 1.281 + /* Clear trace flag */ 1.282 + if (ctxt[cpu].cpu_ctxt.eflags & PSL_T) { 1.283 + ctxt[cpu].cpu_ctxt.eflags &= ~PSL_T; 1.284 + op.cmd = DOM0_SETDOMAININFO; 1.285 + op.u.setdomaininfo.domain = domid; 1.286 + op.u.setdomaininfo.exec_domain = cpu; 1.287 + op.u.setdomaininfo.ctxt = &ctxt[cpu]; 1.288 + retval = do_dom0_op(xc_handle, &op); 1.289 + if (retval) { 1.290 + perror("dom0 op failed"); 1.291 + goto error_out; 1.292 + } 1.293 + } 1.294 + } 1.295 + regs_valid[cpu] = 0; 1.296 op.cmd = DOM0_UNPAUSEDOMAIN; 1.297 - op.u.unpausedomain.domain = pid > 0 ? pid : -pid; 1.298 + op.u.unpausedomain.domain = domid > 0 ? domid : -domid; 1.299 retval = do_dom0_op(xc_handle, &op); 1.300 break; 1.301 case PTRACE_SETFPREGS: 1.302 @@ -357,6 +374,6 @@ xc_ptrace(enum __ptrace_request request, 1.303 errno = status; 1.304 retval = -1; 1.305 } 1.306 - done: 1.307 + error_out: 1.308 return retval; 1.309 }