direct-io.hg

view tools/libxc/xc_ptrace.c @ 5216:3f244c5d2fe2

bitkeeper revision 1.1603 (429c25daAxv8CzKG49dW0khs2wyBew)

xc_ptrace_core.c, xc_ptrace.c:
SLES9 has a problem with it's <asm/elf.h> and other headers associated
with it. Since we are only using one thing from this (that we really
don't need) we can just stop including it.
http://bugzilla.xensource.com/cgi-bin/bugzilla/show_bug.cgi?id=34
Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue May 31 08:52:42 2005 +0000 (2005-05-31)
parents d16ae85cb89e
children 16e3155f3496
line source
1 #include <sys/ptrace.h>
2 #include <sys/wait.h>
3 #include "xc_private.h"
4 #include <time.h>
7 #define BSD_PAGE_MASK (PAGE_SIZE-1)
8 #define PG_FRAME (~((unsigned long)BSD_PAGE_MASK)
9 #define PDRSHIFT 22
10 #define PSL_T 0x00000100 /* trace enable bit */
12 #define VCPU 0 /* XXX */
14 /*
15 * long
16 * ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
17 */
20 int waitdomain(int domain, int *status, int options);
22 char * ptrace_names[] = {
23 "PTRACE_TRACEME",
24 "PTRACE_PEEKTEXT",
25 "PTRACE_PEEKDATA",
26 "PTRACE_PEEKUSER",
27 "PTRACE_POKETEXT",
28 "PTRACE_POKEDATA",
29 "PTRACE_POKEUSER",
30 "PTRACE_CONT",
31 "PTRACE_KILL",
32 "PTRACE_SINGLESTEP",
33 "PTRACE_INVALID",
34 "PTRACE_INVALID",
35 "PTRACE_GETREGS",
36 "PTRACE_SETREGS",
37 "PTRACE_GETFPREGS",
38 "PTRACE_SETFPREGS",
39 "PTRACE_ATTACH",
40 "PTRACE_DETACH",
41 "PTRACE_GETFPXREGS",
42 "PTRACE_SETFPXREGS",
43 "PTRACE_INVALID",
44 "PTRACE_INVALID",
45 "PTRACE_INVALID",
46 "PTRACE_INVALID",
47 "PTRACE_SYSCALL",
48 };
50 struct gdb_regs {
51 long ebx; /* 0 */
52 long ecx; /* 4 */
53 long edx; /* 8 */
54 long esi; /* 12 */
55 long edi; /* 16 */
56 long ebp; /* 20 */
57 long eax; /* 24 */
58 int xds; /* 28 */
59 int xes; /* 32 */
60 int xfs; /* 36 */
61 int xgs; /* 40 */
62 long orig_eax; /* 44 */
63 long eip; /* 48 */
64 int xcs; /* 52 */
65 long eflags; /* 56 */
66 long esp; /* 60 */
67 int xss; /* 64 */
68 };
70 #define FETCH_REGS(cpu) \
71 if (!regs_valid[cpu]) \
72 { \
73 int retval = xc_domain_get_vcpu_context(xc_handle, domid, cpu, &ctxt[cpu]); \
74 if (retval) \
75 goto error_out; \
76 cr3[cpu] = ctxt[cpu].pt_base; /* physical address */ \
77 regs_valid[cpu] = 1; \
78 } \
80 #define printval(x) printf("%s = %lx\n", #x, (long)x);
81 #define SET_PT_REGS(pt, xc) \
82 { \
83 pt.ebx = xc.ebx; \
84 pt.ecx = xc.ecx; \
85 pt.edx = xc.edx; \
86 pt.esi = xc.esi; \
87 pt.edi = xc.edi; \
88 pt.ebp = xc.ebp; \
89 pt.eax = xc.eax; \
90 pt.eip = xc.eip; \
91 pt.xcs = xc.cs; \
92 pt.eflags = xc.eflags; \
93 pt.esp = xc.esp; \
94 pt.xss = xc.ss; \
95 pt.xes = xc.es; \
96 pt.xds = xc.ds; \
97 pt.xfs = xc.fs; \
98 pt.xgs = xc.gs; \
99 }
101 #define SET_XC_REGS(pt, xc) \
102 { \
103 xc.ebx = pt->ebx; \
104 xc.ecx = pt->ecx; \
105 xc.edx = pt->edx; \
106 xc.esi = pt->esi; \
107 xc.edi = pt->edi; \
108 xc.ebp = pt->ebp; \
109 xc.eax = pt->eax; \
110 xc.eip = pt->eip; \
111 xc.cs = pt->xcs; \
112 xc.eflags = pt->eflags; \
113 xc.esp = pt->esp; \
114 xc.ss = pt->xss; \
115 xc.es = pt->xes; \
116 xc.ds = pt->xds; \
117 xc.fs = pt->xfs; \
118 xc.gs = pt->xgs; \
119 }
122 #define vtopdi(va) ((va) >> PDRSHIFT)
123 #define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
125 /* XXX application state */
128 static int xc_handle;
129 static long nr_pages = 0;
130 unsigned long *page_array = NULL;
131 static int regs_valid[MAX_VIRT_CPUS];
132 static unsigned long cr3[MAX_VIRT_CPUS];
133 static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
135 /* --------------------- */
137 static void *
138 map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm)
139 {
140 unsigned long pde, page;
141 unsigned long va = (unsigned long)guest_va;
142 long npgs = xc_get_tot_pages(xc_handle, domid);
144 static unsigned long cr3_phys[MAX_VIRT_CPUS];
145 static unsigned long *cr3_virt[MAX_VIRT_CPUS];
146 static unsigned long pde_phys[MAX_VIRT_CPUS];
147 static unsigned long *pde_virt[MAX_VIRT_CPUS];
148 static unsigned long page_phys[MAX_VIRT_CPUS];
149 static unsigned long *page_virt[MAX_VIRT_CPUS];
151 static int prev_perm[MAX_VIRT_CPUS];
153 if (nr_pages != npgs) {
154 if (nr_pages > 0)
155 free(page_array);
156 nr_pages = npgs;
157 if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
158 printf("Could not allocate memory\n");
159 goto error_out;
160 }
162 if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) {
163 printf("Could not get the page frame list\n");
164 goto error_out;
165 }
166 }
168 FETCH_REGS(cpu);
170 if (cr3[cpu] != cr3_phys[cpu])
171 {
172 cr3_phys[cpu] = cr3[cpu];
173 if (cr3_virt[cpu])
174 munmap(cr3_virt[cpu], PAGE_SIZE);
175 if ((cr3_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
176 PROT_READ,
177 cr3_phys[cpu] >> PAGE_SHIFT)) == NULL)
178 goto error_out;
179 }
180 if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */
181 goto error_out;
182 if (ctxt[cpu].flags & VGCF_VMX_GUEST)
183 pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
184 if (pde != pde_phys[cpu])
185 {
186 pde_phys[cpu] = pde;
187 if (pde_virt[cpu])
188 munmap(pde_virt[cpu], PAGE_SIZE);
189 if ((pde_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
190 PROT_READ,
191 pde_phys[cpu] >> PAGE_SHIFT)) == NULL)
192 goto error_out;
193 }
194 if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */
195 goto error_out;
196 if (ctxt[cpu].flags & VGCF_VMX_GUEST)
197 page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
198 if (page != page_phys[cpu] || perm != prev_perm[cpu])
199 {
200 page_phys[cpu] = page;
201 if (page_virt[cpu])
202 munmap(page_virt[cpu], PAGE_SIZE);
203 if ((page_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
204 perm,
205 page_phys[cpu] >> PAGE_SHIFT)) == NULL) {
206 printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va));
207 page_phys[cpu] = 0;
208 goto error_out;
209 }
210 prev_perm[cpu] = perm;
211 }
212 return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
214 error_out:
215 return 0;
216 }
218 int
219 xc_waitdomain(int domain, int *status, int options)
220 {
221 dom0_op_t op;
222 int retval;
223 struct timespec ts;
224 ts.tv_sec = 0;
225 ts.tv_nsec = 10*1000*1000;
227 if (!xc_handle)
228 if ((xc_handle = xc_interface_open()) < 0)
229 {
230 printf("xc_interface_open failed\n");
231 return -1;
232 }
233 op.cmd = DOM0_GETDOMAININFO;
234 op.u.getdomaininfo.domain = domain;
235 retry:
237 retval = do_dom0_op(xc_handle, &op);
238 if (retval || op.u.getdomaininfo.domain != domain) {
239 printf("getdomaininfo failed\n");
240 goto done;
241 }
242 *status = op.u.getdomaininfo.flags;
244 if (options & WNOHANG)
245 goto done;
248 if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)) {
249 nanosleep(&ts,NULL);
250 goto retry;
251 }
252 done:
253 return retval;
255 }
257 long
258 xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
259 {
260 dom0_op_t op;
261 int status = 0;
262 struct gdb_regs pt;
263 long retval = 0;
264 unsigned long *guest_va;
265 int cpu = VCPU;
266 void *addr = (char *)eaddr;
267 void *data = (char *)edata;
269 op.interface_version = DOM0_INTERFACE_VERSION;
271 if (!xc_handle)
272 if ((xc_handle = xc_interface_open()) < 0)
273 return -1;
274 #if 0
275 printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data);
276 #endif
277 switch (request) {
278 case PTRACE_PEEKTEXT:
279 case PTRACE_PEEKDATA:
280 if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ)) == NULL) {
281 status = EFAULT;
282 goto error_out;
283 }
285 retval = *guest_va;
286 break;
287 case PTRACE_POKETEXT:
288 case PTRACE_POKEDATA:
289 if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ|PROT_WRITE)) == NULL) {
290 status = EFAULT;
291 goto error_out;
292 }
294 *guest_va = (unsigned long)data;
295 break;
296 case PTRACE_GETREGS:
297 case PTRACE_GETFPREGS:
298 case PTRACE_GETFPXREGS:
299 FETCH_REGS(cpu);
301 if (request == PTRACE_GETREGS) {
302 SET_PT_REGS(pt, ctxt[cpu].user_regs);
303 memcpy(data, &pt, sizeof(struct gdb_regs));
304 } else if (request == PTRACE_GETFPREGS)
305 memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
306 else /*if (request == PTRACE_GETFPXREGS)*/
307 memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
308 break;
309 case PTRACE_SETREGS:
310 op.cmd = DOM0_SETDOMAININFO;
311 SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].user_regs);
312 op.u.setdomaininfo.domain = domid;
313 /* XXX need to understand multiple vcpus */
314 op.u.setdomaininfo.vcpu = cpu;
315 op.u.setdomaininfo.ctxt = &ctxt[cpu];
316 retval = do_dom0_op(xc_handle, &op);
317 if (retval)
318 goto error_out;
320 break;
321 case PTRACE_ATTACH:
322 op.cmd = DOM0_GETDOMAININFO;
323 op.u.getdomaininfo.domain = domid;
324 retval = do_dom0_op(xc_handle, &op);
325 if (retval || op.u.getdomaininfo.domain != domid) {
326 perror("dom0 op failed");
327 goto error_out;
328 }
329 if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) {
330 printf("domain currently paused\n");
331 goto error_out;
332 }
333 printf("domain not currently paused\n");
334 op.cmd = DOM0_PAUSEDOMAIN;
335 op.u.pausedomain.domain = domid;
336 retval = do_dom0_op(xc_handle, &op);
337 break;
338 case PTRACE_SINGLESTEP:
339 ctxt[VCPU].user_regs.eflags |= PSL_T;
340 op.cmd = DOM0_SETDOMAININFO;
341 op.u.setdomaininfo.domain = domid;
342 op.u.setdomaininfo.vcpu = 0;
343 op.u.setdomaininfo.ctxt = &ctxt[cpu];
344 retval = do_dom0_op(xc_handle, &op);
345 if (retval) {
346 perror("dom0 op failed");
347 goto error_out;
348 }
349 /* FALLTHROUGH */
350 case PTRACE_CONT:
351 case PTRACE_DETACH:
352 if (request != PTRACE_SINGLESTEP) {
353 FETCH_REGS(cpu);
354 /* Clear trace flag */
355 if (ctxt[cpu].user_regs.eflags & PSL_T) {
356 ctxt[cpu].user_regs.eflags &= ~PSL_T;
357 op.cmd = DOM0_SETDOMAININFO;
358 op.u.setdomaininfo.domain = domid;
359 op.u.setdomaininfo.vcpu = cpu;
360 op.u.setdomaininfo.ctxt = &ctxt[cpu];
361 retval = do_dom0_op(xc_handle, &op);
362 if (retval) {
363 perror("dom0 op failed");
364 goto error_out;
365 }
366 }
367 }
368 regs_valid[cpu] = 0;
369 op.cmd = DOM0_UNPAUSEDOMAIN;
370 op.u.unpausedomain.domain = domid > 0 ? domid : -domid;
371 retval = do_dom0_op(xc_handle, &op);
372 break;
373 case PTRACE_SETFPREGS:
374 case PTRACE_SETFPXREGS:
375 case PTRACE_PEEKUSER:
376 case PTRACE_POKEUSER:
377 case PTRACE_SYSCALL:
378 case PTRACE_KILL:
379 #ifdef DEBUG
380 printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
381 #endif
382 /* XXX not yet supported */
383 status = ENOSYS;
384 break;
385 case PTRACE_TRACEME:
386 printf("PTRACE_TRACEME is an invalid request under Xen\n");
387 status = EINVAL;
388 }
390 if (status) {
391 errno = status;
392 retval = -1;
393 }
394 error_out:
395 return retval;
396 }