direct-io.hg

view tools/xentrace/xenctx.c @ 11422:0419253c81de

Fix inverted sense of getRequiredAvailableMemory and
getRequiredInitialReservation on x86 HVM.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Sep 05 16:23:11 2006 +0100 (2006-09-05)
parents c974a6e3f517
children aa8ca06d209e
line source
1 /******************************************************************************
2 * tools/xentrace/xenctx.c
3 *
4 * Tool for dumping the cpu context
5 *
6 * Copyright (C) 2005 by Intel Corp
7 *
8 * Author: Arun Sharma <arun.sharma@intel.com>
9 * Date: February 2005
10 */
12 #include <time.h>
13 #include <stdlib.h>
14 #include <sys/mman.h>
15 #include <stdio.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <argp.h>
22 #include <signal.h>
23 #include <string.h>
24 #include <getopt.h>
26 #include "xenctrl.h"
28 int xc_handle = 0;
29 int domid = 0;
30 int frame_ptrs = 0;
31 int stack_trace = 0;
33 #if defined (__i386__)
34 #define FMT_SIZE_T "%08x"
35 #define STACK_POINTER(regs) (regs->esp)
36 #define FRAME_POINTER(regs) (regs->ebp)
37 #define INSTR_POINTER(regs) (regs->eip)
38 #define STACK_ROWS 4
39 #define STACK_COLS 8
40 #elif defined (__x86_64__)
41 #define FMT_SIZE_T "%016lx"
42 #define STACK_POINTER(regs) (regs->rsp)
43 #define FRAME_POINTER(regs) (regs->rbp)
44 #define INSTR_POINTER(regs) (regs->rip)
45 #define STACK_ROWS 4
46 #define STACK_COLS 4
47 #elif defined (__ia64__)
48 #define FMT_SIZE_T "%016lx"
49 #define STACK_POINTER(regs) (regs->r12)
50 #define FRAME_POINTER(regs) 0
51 #define INSTR_POINTER(regs) (regs->cr_iip)
52 #define STACK_ROWS 4
53 #define STACK_COLS 4
54 /* On ia64, we can't translate virtual address to physical address. */
55 #define NO_TRANSLATION
56 #endif
58 struct symbol {
59 size_t address;
60 char type;
61 char *name;
62 struct symbol *next;
63 } *symbol_table = NULL;
65 size_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage;
67 int is_kernel_text(size_t addr)
68 {
69 #if defined (__i386__)
70 if (symbol_table == NULL)
71 return (addr > 0xc000000);
72 #elif defined (__x86_64__)
73 if (symbol_table == NULL)
74 return (addr > 0xffffffff80000000UL);
75 #elif defined (__ia64__)
76 if (symbol_table == NULL)
77 return (addr > 0xa000000000000000UL);
78 #endif
80 if (addr >= kernel_stext &&
81 addr <= kernel_etext)
82 return 1;
83 if (addr >= kernel_hypercallpage &&
84 addr <= kernel_hypercallpage + 4096)
85 return 1;
86 if (addr >= kernel_sinittext &&
87 addr <= kernel_einittext)
88 return 1;
89 return 0;
90 }
92 void free_symbol(struct symbol *symbol)
93 {
94 if (symbol == NULL)
95 return;
96 if (symbol->name)
97 free(symbol->name);
98 free(symbol);
99 }
101 void insert_symbol(struct symbol *symbol)
102 {
103 static struct symbol *prev = NULL;
104 struct symbol *s = symbol_table;
106 if (s == NULL) {
107 symbol_table = symbol;
108 symbol->next = NULL;
109 return;
110 }
112 /* The System.map is usually already sorted... */
113 if (prev
114 && prev->address < symbol->address
115 && (!prev->next || prev->next->address > symbol->address)) {
116 s = prev;
117 } else {
118 /* ... otherwise do crappy/slow search for the correct place */
119 while(s && s->next && s->next->address < symbol->address)
120 s = s->next;
121 }
123 symbol->next = s->next;
124 s->next = symbol;
125 prev = symbol;
126 }
128 struct symbol *lookup_symbol(size_t address)
129 {
130 struct symbol *s = symbol_table;
132 while(s && s->next && s->next->address < address)
133 s = s->next;
135 if (s && s->address < address)
136 return s;
138 return NULL;
139 }
141 void print_symbol(size_t addr)
142 {
143 struct symbol *s;
145 if (!is_kernel_text(addr))
146 return;
148 s = lookup_symbol(addr);
150 if (s==NULL)
151 return;
153 if (addr==s->address)
154 printf("%s", s->name);
155 else
156 printf("%s+%#x", s->name, (unsigned int)(addr - s->address));
157 }
159 void read_symbol_table(const char *symtab)
160 {
161 char line[256];
162 char *p;
163 struct symbol *symbol;
164 FILE *f;
166 f = fopen(symtab, "r");
167 if(f == NULL) {
168 fprintf(stderr, "failed to open symbol table %s\n", symtab);
169 exit(-1);
170 }
172 while(!feof(f)) {
173 if(fgets(line,256,f)==NULL)
174 break;
176 symbol = malloc(sizeof(*symbol));
178 /* need more checks for syntax here... */
179 symbol->address = strtoull(line, &p, 16);
180 p++;
181 symbol->type = *p++;
182 p++;
184 /* in the future we should handle the module name
185 * being appended here, this would allow us to use
186 * /proc/kallsyms as our symbol table
187 */
188 if (p[strlen(p)-1] == '\n')
189 p[strlen(p)-1] = '\0';
190 symbol->name = strdup(p);
192 insert_symbol(symbol);
194 if (strcmp(symbol->name, "_stext") == 0)
195 kernel_stext = symbol->address;
196 else if (strcmp(symbol->name, "_etext") == 0)
197 kernel_etext = symbol->address;
198 else if (strcmp(symbol->name, "_sinittext") == 0)
199 kernel_sinittext = symbol->address;
200 else if (strcmp(symbol->name, "_einittext") == 0)
201 kernel_einittext = symbol->address;
202 else if (strcmp(symbol->name, "hypercall_page") == 0)
203 kernel_hypercallpage = symbol->address;
204 }
206 fclose(f);
207 }
209 #ifdef __i386__
210 void print_ctx(vcpu_guest_context_t *ctx1)
211 {
212 struct cpu_user_regs *regs = &ctx1->user_regs;
214 printf("eip: %08x ", regs->eip);
215 print_symbol(regs->eip);
216 printf("\n");
218 printf("esp: %08x\n", regs->esp);
220 printf("eax: %08x\t", regs->eax);
221 printf("ebx: %08x\t", regs->ebx);
222 printf("ecx: %08x\t", regs->ecx);
223 printf("edx: %08x\n", regs->edx);
225 printf("esi: %08x\t", regs->esi);
226 printf("edi: %08x\t", regs->edi);
227 printf("ebp: %08x\n", regs->ebp);
229 printf(" cs: %08x\t", regs->cs);
230 printf(" ds: %08x\t", regs->ds);
231 printf(" fs: %08x\t", regs->fs);
232 printf(" gs: %08x\n", regs->gs);
234 }
235 #elif defined(__x86_64__)
236 void print_ctx(vcpu_guest_context_t *ctx1)
237 {
238 struct cpu_user_regs *regs = &ctx1->user_regs;
240 printf("rip: %08lx ", regs->rip);
241 print_symbol(regs->rip);
242 printf("\n");
243 printf("rsp: %08lx\n", regs->rsp);
245 printf("rax: %08lx\t", regs->rax);
246 printf("rbx: %08lx\t", regs->rbx);
247 printf("rcx: %08lx\t", regs->rcx);
248 printf("rdx: %08lx\n", regs->rdx);
250 printf("rsi: %08lx\t", regs->rsi);
251 printf("rdi: %08lx\t", regs->rdi);
252 printf("rbp: %08lx\n", regs->rbp);
254 printf(" r8: %08lx\t", regs->r8);
255 printf(" r9: %08lx\t", regs->r9);
256 printf("r10: %08lx\t", regs->r10);
257 printf("r11: %08lx\n", regs->r11);
259 printf("r12: %08lx\t", regs->r12);
260 printf("r13: %08lx\t", regs->r13);
261 printf("r14: %08lx\t", regs->r14);
262 printf("r15: %08lx\n", regs->r15);
264 printf(" cs: %08x\t", regs->cs);
265 printf(" ds: %08x\t", regs->ds);
266 printf(" fs: %08x\t", regs->fs);
267 printf(" gs: %08x\n", regs->gs);
269 }
270 #elif defined(__ia64__)
271 void print_ctx(vcpu_guest_context_t *ctx1)
272 {
273 struct cpu_user_regs *regs = &ctx1->user_regs;
275 printf("iip: %016lx ", regs->cr_iip);
276 print_symbol(regs->cr_iip);
277 printf("\n");
278 printf("psr: %016lu ", regs->cr_ipsr);
279 printf(" b0: %016lx\n", regs->b0);
281 printf(" r1: %016lx\n", regs->r1);
282 printf(" r2: %016lx ", regs->r2);
283 printf(" r3: %016lx\n", regs->r3);
284 printf(" r4: %016lx ", regs->r4);
285 printf(" r5: %016lx\n", regs->r5);
286 printf(" r6: %016lx ", regs->r6);
287 printf(" r7: %016lx\n", regs->r7);
288 printf(" r8: %016lx ", regs->r8);
289 printf(" r9: %016lx\n", regs->r9);
290 printf(" r10: %016lx ", regs->r10);
291 printf(" r11: %016lx\n", regs->r11);
292 printf(" sp: %016lx ", regs->r12);
293 printf(" tp: %016lx\n", regs->r13);
294 printf(" r14: %016lx ", regs->r14);
295 printf(" r15: %016lx\n", regs->r15);
296 printf(" r16: %016lx ", regs->r16);
297 printf(" r17: %016lx\n", regs->r17);
298 printf(" r18: %016lx ", regs->r18);
299 printf(" r19: %016lx\n", regs->r19);
300 printf(" r20: %016lx ", regs->r20);
301 printf(" r21: %016lx\n", regs->r21);
302 printf(" r22: %016lx ", regs->r22);
303 printf(" r23: %016lx\n", regs->r23);
304 printf(" r24: %016lx ", regs->r24);
305 printf(" r25: %016lx\n", regs->r25);
306 printf(" r26: %016lx ", regs->r26);
307 printf(" r27: %016lx\n", regs->r27);
308 printf(" r28: %016lx ", regs->r28);
309 printf(" r29: %016lx\n", regs->r29);
310 printf(" r30: %016lx ", regs->r30);
311 printf(" r31: %016lx\n", regs->r31);
313 }
314 #endif
316 #ifndef NO_TRANSLATION
317 void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt)
318 {
319 static unsigned long previous_mfn = 0;
320 static void *mapped = NULL;
322 unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt);
323 unsigned long offset = virt & ~XC_PAGE_MASK;
325 if (mapped && mfn == previous_mfn)
326 goto out;
328 if (mapped)
329 munmap(mapped, XC_PAGE_SIZE);
331 previous_mfn = mfn;
333 mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn);
335 if (mapped == NULL) {
336 fprintf(stderr, "failed to map page.\n");
337 exit(-1);
338 }
340 out:
341 return (void *)(mapped + offset);
342 }
344 void print_stack(vcpu_guest_context_t *ctx, int vcpu)
345 {
346 struct cpu_user_regs *regs = &ctx->user_regs;
347 size_t stack = STACK_POINTER(regs);
348 size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE;
349 size_t frame;
350 size_t instr;
351 size_t *p;
352 int i;
354 printf("\n");
355 printf("Stack:\n");
356 for (i=1; i<STACK_ROWS+1 && stack < stack_limit; i++) {
357 while(stack < stack_limit && stack < STACK_POINTER(regs) + i*STACK_COLS*sizeof(stack)) {
358 p = map_page(ctx, vcpu, stack);
359 printf(" " FMT_SIZE_T, *p);
360 stack += sizeof(stack);
361 }
362 printf("\n");
363 }
364 printf("\n");
366 printf("Code:\n");
367 instr = INSTR_POINTER(regs) - 21;
368 for(i=0; i<32; i++) {
369 unsigned char *c = map_page(ctx, vcpu, instr+i);
370 if (instr+i == INSTR_POINTER(regs))
371 printf("<%02x> ", *c);
372 else
373 printf("%02x ", *c);
374 }
375 printf("\n");
377 printf("\n");
379 if(stack_trace)
380 printf("Stack Trace:\n");
381 else
382 printf("Call Trace:\n");
383 printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ', INSTR_POINTER(regs));
385 print_symbol(INSTR_POINTER(regs));
386 printf(" <--\n");
387 if (frame_ptrs) {
388 stack = STACK_POINTER(regs);
389 frame = FRAME_POINTER(regs);
390 while(frame && stack < stack_limit) {
391 if (stack_trace) {
392 while (stack < frame) {
393 p = map_page(ctx, vcpu, stack);
394 printf("| " FMT_SIZE_T " ", *p);
395 printf("\n");
396 stack += sizeof(*p);
397 }
398 } else {
399 stack = frame;
400 }
402 p = map_page(ctx, vcpu, stack);
403 frame = *p;
404 if (stack_trace)
405 printf("|-- " FMT_SIZE_T "\n", *p);
406 stack += sizeof(*p);
408 if (frame) {
409 p = map_page(ctx, vcpu, stack);
410 printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p);
411 print_symbol(*p);
412 printf("\n");
413 stack += sizeof(*p);
414 }
415 }
416 } else {
417 stack = STACK_POINTER(regs);
418 while(stack < stack_limit) {
419 p = map_page(ctx, vcpu, stack);
420 if (is_kernel_text(*p)) {
421 printf(" [<" FMT_SIZE_T ">] ", *p);
422 print_symbol(*p);
423 printf("\n");
424 } else if (stack_trace) {
425 printf(" " FMT_SIZE_T "\n", *p);
426 }
427 stack += sizeof(*p);
428 }
429 }
430 }
431 #else
432 #define print_stack(ctx, vcpu)
433 #endif
435 void dump_ctx(int vcpu)
436 {
437 int ret;
438 vcpu_guest_context_t ctx;
440 xc_handle = xc_interface_open(); /* for accessing control interface */
442 ret = xc_domain_pause(xc_handle, domid);
443 if (ret < 0) {
444 perror("xc_domain_pause");
445 exit(-1);
446 }
448 ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx);
449 if (ret < 0) {
450 xc_domain_unpause(xc_handle, domid);
451 perror("xc_vcpu_getcontext");
452 exit(-1);
453 }
455 print_ctx(&ctx);
456 if (is_kernel_text(INSTR_POINTER((&ctx.user_regs))))
457 print_stack(&ctx, vcpu);
459 ret = xc_domain_unpause(xc_handle, domid);
460 if (ret < 0) {
461 perror("xc_domain_unpause");
462 exit(-1);
463 }
465 xc_interface_close(xc_handle);
466 if (ret < 0) {
467 perror("xc_interface_close");
468 exit(-1);
469 }
470 }
472 void usage(void)
473 {
474 printf("usage:\n\n");
476 printf(" xenctx [options] <DOMAIN> [VCPU]\n\n");
478 printf("options:\n");
479 printf(" -f, --frame-pointers\n");
480 printf(" assume the kernel was compiled with\n");
481 printf(" frame pointers.\n");
482 printf(" -s SYMTAB, --symbol-table=SYMTAB\n");
483 printf(" read symbol table from SYMTAB.\n");
484 printf(" --stack-trace print a complete stack trace.\n");
485 }
487 int main(int argc, char **argv)
488 {
489 int ch;
490 const char *sopts = "fs:h";
491 const struct option lopts[] = {
492 {"stack-trace", 0, NULL, 'S'},
493 {"symbol-table", 1, NULL, 's'},
494 {"frame-pointers", 0, NULL, 'f'},
495 {"help", 0, NULL, 'h'},
496 {0, 0, 0, 0}
497 };
498 const char *symbol_table = NULL;
500 int vcpu = 0;
502 while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
503 switch(ch) {
504 case 'f':
505 frame_ptrs = 1;
506 break;
507 case 's':
508 symbol_table = optarg;
509 break;
510 case 'S':
511 stack_trace = 1;
512 break;
513 case 'h':
514 usage();
515 exit(-1);
516 case '?':
517 fprintf(stderr, "%s --help for more options\n", argv[0]);
518 exit(-1);
519 }
520 }
522 argv += optind; argc -= optind;
524 if (argc < 1 || argc > 2) {
525 printf("usage: xenctx [options] <domid> <optional vcpu>\n");
526 exit(-1);
527 }
529 domid = atoi(argv[0]);
530 if (domid==0) {
531 fprintf(stderr, "cannot trace dom0\n");
532 exit(-1);
533 }
535 if (argc == 2)
536 vcpu = atoi(argv[1]);
538 if (symbol_table)
539 read_symbol_table(symbol_table);
541 dump_ctx(vcpu);
543 return 0;
544 }
546 /*
547 * Local variables:
548 * mode: C
549 * c-set-style: "BSD"
550 * c-basic-offset: 4
551 * tab-width: 4
552 * indent-tabs-mode: nil
553 * End:
554 */