ia64/xen-unstable

view tools/debugger/xenitp/xenitp.c @ 16086:e7ae19321560

ia64: Fix help message of xenitp.
Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
author Keir Fraser <keir@xensource.com>
date Wed Oct 10 13:17:42 2007 +0100 (2007-10-10)
parents 9f2b83a34453
children 1e27eb0c9f22
line source
1 /* tools/debugger/xenitp.c - A low-level debugger.
3 Based on xenctxt.c, but heavily modified.
4 Copyright 2007 Tristan Gingold <tgingold@free.fr>
6 Xenitp is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 Xenitp is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
20 #include <time.h>
21 #include <stdlib.h>
22 #include <sys/mman.h>
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <argp.h>
30 #include <signal.h>
31 #include <string.h>
32 #include <getopt.h>
34 #include "xenctrl.h"
35 #include <xen/sys/privcmd.h>
36 #include "dis-asm.h"
38 #ifdef __HYPERVISOR_ia64_debug_op
39 #define HAVE_DEBUG_OP
40 #endif
42 static int xc_handle = 0;
43 static int domid = 0;
44 static vcpu_guest_context_t *cur_ctx;
45 static int cur_vcpu;
47 #define PSR_BN (1UL << 44)
48 #define PSR_SS (1UL << 40)
49 #define PSR_DB (1UL << 24)
50 #define PSR_TB (1UL << 26)
51 #define PSR_DD (1UL << 39)
52 #define PSR_ID (1UL << 37)
53 #define PSR_IT (1UL << 36)
54 #define PSR_DT (1UL << 17)
55 #define PSR_RI_SHIFT 41
56 #define CFM_SOF_MASK 0x3f
58 int virt_to_phys (int is_inst, unsigned long vaddr, unsigned long *paddr);
60 static inline unsigned int ctx_slot (vcpu_guest_context_t *ctx)
61 {
62 return (ctx->regs.psr >> PSR_RI_SHIFT) & 3;
63 }
65 unsigned char *
66 target_map_memory (unsigned long paddr)
67 {
68 static unsigned long cur_page = (unsigned long)-1;
69 static unsigned char *cur_map = NULL;
71 if ((paddr >> XC_PAGE_SHIFT) != cur_page) {
72 if (cur_map) {
73 munmap (cur_map, XC_PAGE_SIZE);
74 cur_map = NULL;
75 }
76 cur_page = paddr >> XC_PAGE_SHIFT;
77 cur_map = xc_map_foreign_range (xc_handle, domid, XC_PAGE_SIZE,
78 PROT_READ, cur_page);
79 if (cur_map == NULL) {
80 perror ("cannot map page");
81 cur_page = -1;
82 return NULL;
83 }
84 }
85 return cur_map + (paddr & (XC_PAGE_SIZE - 1));
86 }
88 /* Get LENGTH bytes from info's buffer, at target address memaddr.
89 Transfer them to myaddr. */
90 int
91 target_read_memory (bfd_vma memaddr, bfd_byte *myaddr,
92 unsigned int length, struct disassemble_info *info)
93 {
94 int i;
95 unsigned long paddr;
97 if (cur_ctx->regs.psr & PSR_IT) {
98 if (virt_to_phys (1, memaddr, &paddr) != 0)
99 return EIO;
100 }
101 else {
102 /* Clear UC. */
103 paddr = memaddr & ~(1UL << 63);
104 }
106 for (i = 0; i < length; i++) {
107 unsigned char *p = target_map_memory (paddr + i);
109 if (p == NULL)
110 return EIO;
111 myaddr[i] = *p;
112 }
113 return 0;
114 }
116 /* Print an error message. We can assume that this is in response to
117 an error return from buffer_read_memory. */
118 void
119 perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
120 {
121 if (status != EIO)
122 /* Can't happen. */
123 (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
124 else
125 /* Actually, address between memaddr and memaddr + len was
126 out of bounds. */
127 (*info->fprintf_func) (info->stream,
128 "Address 0x%" PRIx64 " is out of bounds.\n",
129 memaddr);
130 }
132 /* This could be in a separate file, to save miniscule amounts of space
133 in statically linked executables. */
135 /* Just print the address is hex. This is included for completeness even
136 though both GDB and objdump provide their own (to print symbolic
137 addresses). */
139 void
140 generic_print_address (bfd_vma addr, struct disassemble_info *info)
141 {
142 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
143 }
145 /* Just return the given address. */
147 int
148 generic_symbol_at_address (bfd_vma addr, struct disassemble_info * info)
149 {
150 return 1;
151 }
153 bfd_boolean
154 generic_symbol_is_valid (asymbol * sym ATTRIBUTE_UNUSED,
155 struct disassemble_info *info ATTRIBUTE_UNUSED)
156 {
157 return 1;
158 }
160 bfd_vma bfd_getl32 (const bfd_byte *addr)
161 {
162 unsigned long v;
164 v = (unsigned long) addr[0];
165 v |= (unsigned long) addr[1] << 8;
166 v |= (unsigned long) addr[2] << 16;
167 v |= (unsigned long) addr[3] << 24;
169 return (bfd_vma) v;
170 }
172 bfd_vma bfd_getl64 (const bfd_byte *addr)
173 {
174 unsigned long v;
176 v = (unsigned long) addr[0];
177 v |= (unsigned long) addr[1] << 8;
178 v |= (unsigned long) addr[2] << 16;
179 v |= (unsigned long) addr[3] << 24;
180 v |= (unsigned long) addr[4] << 32;
181 v |= (unsigned long) addr[5] << 40;
182 v |= (unsigned long) addr[6] << 48;
183 v |= (unsigned long) addr[7] << 56;
185 return (bfd_vma) v;
186 }
188 bfd_vma bfd_getb32 (const bfd_byte *addr)
189 {
190 unsigned long v;
192 v = (unsigned long) addr[0] << 24;
193 v |= (unsigned long) addr[1] << 16;
194 v |= (unsigned long) addr[2] << 8;
195 v |= (unsigned long) addr[3];
197 return (bfd_vma) v;
198 }
200 bfd_vma bfd_getl16 (const bfd_byte *addr)
201 {
202 unsigned long v;
204 v = (unsigned long) addr[0];
205 v |= (unsigned long) addr[1] << 8;
207 return (bfd_vma) v;
208 }
210 bfd_vma bfd_getb16 (const bfd_byte *addr)
211 {
212 unsigned long v;
214 v = (unsigned long) addr[0] << 24;
215 v |= (unsigned long) addr[1] << 16;
217 return (bfd_vma) v;
218 }
220 void
221 init_disassemble_info (struct disassemble_info *info, void *stream,
222 fprintf_ftype fprintf_func)
223 {
224 memset (info, 0, sizeof (*info));
226 info->flavour = bfd_target_unknown_flavour;
227 info->arch = bfd_arch_unknown;
228 info->endian = BFD_ENDIAN_UNKNOWN;
229 info->octets_per_byte = 1;
230 info->fprintf_func = fprintf_func;
231 info->stream = stream;
232 info->read_memory_func = target_read_memory;
233 info->memory_error_func = perror_memory;
234 info->print_address_func = generic_print_address;
235 info->symbol_at_address_func = generic_symbol_at_address;
236 info->symbol_is_valid = generic_symbol_is_valid;
237 info->display_endian = BFD_ENDIAN_UNKNOWN;
238 }
241 void target_disas (FILE *out, unsigned long code, unsigned long size)
242 {
243 unsigned long pc;
244 int count;
245 struct disassemble_info disasm_info;
247 INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
249 disasm_info.read_memory_func = target_read_memory;
250 #if 0
251 disasm_info.buffer = NULL;
252 disasm_info.buffer_vma = (unsigned long)code;
253 disasm_info.buffer_length = size;
254 #endif
256 disasm_info.endian = BFD_ENDIAN_LITTLE;
257 disasm_info.mach = 0; //bfd_mach_ia64;
259 for (pc = code; pc < code + size; pc += count) {
260 int slot = (pc & 0x0f) / 6;
261 fprintf (out, "0x%016lx+%d:%c ", pc & ~0x0fUL, slot,
262 ((pc & ~0x0fUL) == cur_ctx->regs.ip
263 && slot == ctx_slot (cur_ctx)) ? '*' : ' ');
265 count = print_insn_ia64 (pc, &disasm_info);
267 #if 0
268 {
269 int i;
270 uint8_t b;
272 fprintf (out, " {");
273 for (i = 0; i < count; i++) {
274 target_read_memory (pc + i, &b, 1, &disasm_info);
275 fprintf (out, " %02x", b);
276 }
277 fprintf (out, " }");
278 }
279 #endif
280 fprintf (out, "\n");
281 if (count < 0)
282 break;
283 }
284 }
287 #define PTE_ED_SHIFT 52
288 #define PTE_ED_MASK 1
289 #define PTE_PPN_SHIFT 12
290 #define PTE_PPN_MASK 0x3fffffffff
291 #define PTE_AR_SHIFT 9
292 #define PTE_AR_MASK 7
293 #define PTE_PL_SHIFT 7
294 #define PTE_PL_MASK 3
295 #define PTE_D_SHIFT 6
296 #define PTE_D_MASK 1
297 #define PTE_A_SHIFT 5
298 #define PTE_A_MASK 1
299 #define PTE_MA_SHIFT 2
300 #define PTE_MA_MASK 7
301 #define PTE_P_SHIFT 0
302 #define PTE_P_MASK 1
303 #define ITIR_KEY_SHIFT 8
304 #define ITIR_KEY_MASK 0xffffff
305 #define ITIR_PS_SHIFT 2
306 #define ITIR_PS_MASK 0x3f
307 #define ITIR_PS_MIN 12
308 #define ITIR_PS_MAX 28
309 #define RR_RID_SHIFT 8
310 #define RR_RID_MASK 0xffffff
311 #define RR_PS_SHIFT 2
312 #define RR_PS_MASK 0x3f
313 #define RR_VE_MASK 1
315 static const char *get_ps (int ps_val)
316 {
317 static const char ps[][5] = {" 4K", " 8K", " 16K", " ",
318 " 64K", " ", "256K", " ",
319 " 1M", " ", " 4M", " ",
320 " 16M", " ", " 64M", " ",
321 "256M"};
322 return ((ps_val >= ITIR_PS_MIN && ps_val <= ITIR_PS_MAX) ?
323 ps[ps_val - ITIR_PS_MIN] : " ");
325 }
327 static void print_a_tr (int i, const struct ia64_tr_entry *tr)
328 {
329 int ps_val, ma_val;
330 unsigned long pa;
332 static const char ma[][4] = {"WB ", " ", " ", " ",
333 "UC ", "UCE", "WC ", "Nat"};
335 ps_val = tr->itir >> ITIR_PS_SHIFT & ITIR_PS_MASK;
336 ma_val = tr->pte >> PTE_MA_SHIFT & PTE_MA_MASK;
337 pa = (tr->pte >> PTE_PPN_SHIFT & PTE_PPN_MASK) << PTE_PPN_SHIFT;
338 pa = (pa >> ps_val) << ps_val;
339 printf (" [%2d] %ld %06lx %016lx %013lx %02d %s %ld %ld %ld %ld "
340 "%ld %d %s %06lx\n", i,
341 tr->pte >> PTE_P_SHIFT & PTE_P_MASK,
342 tr->rid >> RR_RID_SHIFT & RR_RID_MASK,
343 tr->vadr, pa, ps_val, get_ps (ps_val),
344 tr->pte >> PTE_ED_SHIFT & PTE_ED_MASK,
345 tr->pte >> PTE_PL_SHIFT & PTE_PL_MASK,
346 tr->pte >> PTE_AR_SHIFT & PTE_AR_MASK,
347 tr->pte >> PTE_A_SHIFT & PTE_A_MASK,
348 tr->pte >> PTE_D_SHIFT & PTE_D_MASK,
349 ma_val, ma[ma_val],
350 tr->itir >> ITIR_KEY_SHIFT & ITIR_KEY_MASK);
351 }
353 void print_ctx (vcpu_guest_context_t *ctx)
354 {
355 struct vcpu_guest_context_regs *regs = &ctx->regs;
356 int i;
357 unsigned int rbs_size, cfm_sof;
359 rbs_size = (regs->ar.bsp - regs->ar.bspstore) / 8;
360 cfm_sof = (regs->cfm & CFM_SOF_MASK);
361 printf ("bspstore: %016lx bsp: %016lx rbs_size=%d, sof=%d\n",
362 regs->ar.bspstore, regs->ar.bsp, rbs_size, cfm_sof);
364 for (i = 0; i < cfm_sof; i++) {
365 int off = cfm_sof - i;
366 unsigned int rbs_off =
367 (((62 - ((rbs_size + regs->rbs_voff) % 64) + off)) / 63) + off;
368 if (rbs_off > rbs_size)
369 break;
370 printf (" r%02d: %016lx%s", 32 + i,
371 regs->rbs[rbs_size - rbs_off],
372 (i % 3) != 2 ? " " : "\n");
373 }
374 if ((i % 3) != 0)
375 printf ("\n");
377 printf ("\n");
378 printf (" r1: %016lx ", regs->r[1]);
379 printf (" r2: %016lx ", regs->r[2]);
380 printf (" r3: %016lx\n", regs->r[3]);
381 printf (" r4: %016lx ", regs->r[4]);
382 printf (" r5: %016lx ", regs->r[5]);
383 printf (" r6: %016lx\n", regs->r[6]);
384 printf (" r7: %016lx ", regs->r[7]);
385 printf (" r8: %016lx ", regs->r[8]);
386 printf (" r9: %016lx\n", regs->r[9]);
387 printf (" r10: %016lx ", regs->r[10]);
388 printf (" r11: %016lx ", regs->r[11]);
389 printf (" sp: %016lx\n", regs->r[12]);
390 printf (" tp: %016lx ", regs->r[13]);
391 printf (" r14: %016lx ", regs->r[14]);
392 printf (" r15: %016lx\n", regs->r[15]);
393 printf (" r16: %016lx ", regs->r[16]);
394 printf (" r17: %016lx ", regs->r[17]);
395 printf (" r18: %016lx\n", regs->r[18]);
396 printf (" r19: %016lx ", regs->r[19]);
397 printf (" r20: %016lx ", regs->r[20]);
398 printf (" r21: %016lx\n", regs->r[21]);
399 printf (" r22: %016lx ", regs->r[22]);
400 printf (" r23: %016lx ", regs->r[23]);
401 printf (" r24: %016lx\n", regs->r[24]);
402 printf (" r25: %016lx ", regs->r[25]);
403 printf (" r26: %016lx ", regs->r[26]);
404 printf (" r27: %016lx\n", regs->r[27]);
405 printf (" r28: %016lx ", regs->r[28]);
406 printf (" r29: %016lx ", regs->r[29]);
407 printf (" r30: %016lx\n", regs->r[30]);
408 printf (" r31: %016lx ", regs->r[31]);
409 printf (" ");
410 printf (" b0: %016lx\n", regs->b[0]);
412 printf ("\n");
413 printf (" psr: %016lx ", regs->psr);
414 printf (" cfm: %016lx ", regs->cfm);
415 printf (" pr: %016lx\n", regs->pr);
417 printf ("\n");
418 printf (" ip: %016lx+%d", regs->ip, (int)(regs->psr >> PSR_RI_SHIFT) & 3);
419 printf ("\n");
420 target_disas (stdout, regs->ip, 16);
421 }
423 void print_br (vcpu_guest_context_t *ctx)
424 {
425 struct vcpu_guest_context_regs *regs = &ctx->regs;
427 printf (" b0: %016lx ", regs->b[0]);
428 printf (" b1: %016lx ", regs->b[1]);
429 printf (" b2: %016lx\n", regs->b[2]);
430 printf (" b3: %016lx ", regs->b[3]);
431 printf (" b4: %016lx ", regs->b[4]);
432 printf (" b5: %016lx\n", regs->b[5]);
433 printf (" b6: %016lx ", regs->b[6]);
434 printf (" b7: %016lx\n", regs->b[7]);
435 }
437 void print_regs (vcpu_guest_context_t *ctx)
438 {
439 struct vcpu_guest_context_regs *regs = &ctx->regs;
441 printf (" r1: %016lx ", regs->r[1]);
442 printf (" r2: %016lx ", regs->r[2]);
443 printf (" r3: %016lx\n", regs->r[3]);
444 printf (" r4: %016lx ", regs->r[4]);
445 printf (" r5: %016lx ", regs->r[5]);
446 printf (" r6: %016lx\n", regs->r[6]);
447 printf (" r7: %016lx ", regs->r[7]);
448 printf (" r8: %016lx ", regs->r[8]);
449 printf (" r9: %016lx\n", regs->r[9]);
450 printf (" r10: %016lx ", regs->r[10]);
451 printf (" r11: %016lx ", regs->r[11]);
452 printf (" sp: %016lx\n", regs->r[12]);
453 printf (" tp: %016lx ", regs->r[13]);
454 printf (" r14: %016lx ", regs->r[14]);
455 printf (" r15: %016lx\n", regs->r[15]);
457 printf (" Bank %d (current) Bank %d\n",
458 (regs->psr & PSR_BN) ? 1 : 0, (regs->psr & PSR_BN) ? 0 : 1);
459 printf ("16:%016lx ", regs->r[16]);
460 printf ("17:%016lx ", regs->r[17]);
461 printf ("16:%016lx ", regs->bank[0]);
462 printf ("17:%016lx\n", regs->bank[1]);
463 printf ("18:%016lx ", regs->r[18]);
464 printf ("19:%016lx ", regs->r[19]);
465 printf ("18:%016lx ", regs->bank[2]);
466 printf ("19:%016lx\n", regs->bank[3]);
467 printf ("20:%016lx ", regs->r[20]);
468 printf ("21:%016lx ", regs->r[21]);
469 printf ("20:%016lx ", regs->bank[4]);
470 printf ("21:%016lx\n", regs->bank[5]);
471 printf ("22:%016lx ", regs->r[22]);
472 printf ("23:%016lx ", regs->r[23]);
473 printf ("22:%016lx ", regs->bank[6]);
474 printf ("23:%016lx\n", regs->bank[7]);
475 printf ("24:%016lx ", regs->r[24]);
476 printf ("25:%016lx ", regs->r[25]);
477 printf ("24:%016lx ", regs->bank[8]);
478 printf ("25:%016lx\n", regs->bank[9]);
479 printf ("26:%016lx ", regs->r[26]);
480 printf ("27:%016lx ", regs->r[27]);
481 printf ("26:%016lx ", regs->bank[10]);
482 printf ("27:%016lx\n", regs->bank[11]);
483 printf ("28:%016lx ", regs->r[28]);
484 printf ("29:%016lx ", regs->r[29]);
485 printf ("28:%016lx ", regs->bank[12]);
486 printf ("29:%016lx\n", regs->bank[13]);
487 printf ("30:%016lx ", regs->r[30]);
488 printf ("31:%016lx ", regs->r[31]);
489 printf ("30:%016lx ", regs->bank[14]);
490 printf ("31:%016lx\n", regs->bank[15]);
491 printf ("\n");
492 }
494 void print_cr (vcpu_guest_context_t *ctx)
495 {
496 struct vcpu_guest_context_regs *regs = &ctx->regs;
498 printf (" dcr: %016lx ", regs->cr.dcr);
499 printf (" itm: %016lx ", regs->cr.itm);
500 printf (" iva: %016lx\n", regs->cr.iva);
501 printf (" pta: %016lx ", regs->cr.pta);
502 printf (" ipsr: %016lx ", regs->cr.ipsr);
503 printf (" isr: %016lx\n", regs->cr.isr);
504 printf (" iip: %016lx ", regs->cr.iip);
505 printf (" ifa: %016lx ", regs->cr.ifa);
506 printf (" itir: %016lx\n", regs->cr.itir);
507 printf (" iipa: %016lx ", regs->cr.iipa);
508 printf (" ifs: %016lx ", regs->cr.ifs);
509 printf (" iim: %016lx\n", regs->cr.iim);
510 printf (" iha: %016lx ", regs->cr.iha);
511 printf (" lid: %016lx ", regs->cr.lid);
512 printf (" ivr: %016lx\n", regs->cr.ivr);
513 printf (" tpr: %016lx ", regs->cr.tpr);
514 printf (" eoi: %016lx ", regs->cr.eoi);
515 printf (" irr0: %016lx\n", regs->cr.irr[0]);
516 printf (" irr1: %016lx ", regs->cr.irr[1]);
517 printf (" irr2: %016lx ", regs->cr.irr[2]);
518 printf (" irr3: %016lx\n", regs->cr.irr[3]);
519 printf (" itv: %016lx ", regs->cr.itv);
520 printf (" pmv: %016lx ", regs->cr.pmv);
521 printf (" cmcv: %016lx\n", regs->cr.cmcv);
522 printf (" lrr0: %016lx ", regs->cr.lrr0);
523 printf (" lrr1: %016lx ", regs->cr.lrr1);
524 printf (" ev_cb:%016lx\n", ctx->event_callback_ip);
525 }
527 void print_ar (vcpu_guest_context_t *ctx)
528 {
529 struct vcpu_guest_context_regs *regs = &ctx->regs;
531 printf (" kr0: %016lx ", regs->ar.kr[0]);
532 printf (" kr1: %016lx ", regs->ar.kr[1]);
533 printf (" kr2: %016lx\n", regs->ar.kr[2]);
534 printf (" kr3: %016lx ", regs->ar.kr[3]);
535 printf (" kr4: %016lx ", regs->ar.kr[4]);
536 printf (" kr5: %016lx\n", regs->ar.kr[5]);
537 printf (" kr6: %016lx ", regs->ar.kr[6]);
538 printf (" kr7: %016lx ", regs->ar.kr[7]);
539 printf (" rsc: %016lx\n", regs->ar.rsc);
540 printf (" bsp: %016lx ", regs->ar.bsp);
541 printf (" bsps: %016lx ", regs->ar.bspstore);
542 printf (" rnat: %016lx\n", regs->ar.rnat);
543 printf (" csd: %016lx ", regs->ar.csd);
544 printf (" ccv: %016lx ", regs->ar.ccv);
545 printf (" unat: %016lx\n", regs->ar.unat);
546 printf (" fpsr: %016lx ", regs->ar.fpsr);
547 printf (" itc: %016lx\n", regs->ar.itc);
548 printf (" pfs: %016lx ", regs->ar.pfs);
549 printf (" lc: %016lx ", regs->ar.lc);
550 printf (" ec: %016lx\n", regs->ar.ec);
551 }
553 void print_a_rr (int num, unsigned long rr)
554 {
555 int ps_val = (rr >> RR_PS_SHIFT) & RR_PS_MASK;
557 printf (" [%d] %06lx %02x %s %ld\n",
558 num, (rr >> RR_RID_SHIFT) & RR_RID_MASK,
559 ps_val, get_ps (ps_val), rr & RR_VE_MASK);
560 }
562 void print_rr (vcpu_guest_context_t *ctx)
563 {
564 struct vcpu_guest_context_regs *regs = &ctx->regs;
565 int i;
567 printf (" rr: rid ps ve\n");
568 for (i = 0; i < 8; i++)
569 print_a_rr (i, regs->rr[i]);
570 }
572 void print_db (vcpu_guest_context_t *ctx)
573 {
574 struct vcpu_guest_context_regs *regs = &ctx->regs;
575 int i;
577 for (i = 0; i < 7; i += 2)
578 printf (" ibr[%d]: %016lx ibr[%d]: %016lx\n",
579 i, regs->ibr[i], i + 1, regs->ibr[i + 1]);
580 printf ("\n");
581 for (i = 0; i < 7; i += 2)
582 printf (" dbr[%d]: %016lx dbr[%d]: %016lx\n",
583 i, regs->dbr[i], i + 1, regs->dbr[i + 1]);
584 }
586 struct bit_descr {
587 const char *name;
588 unsigned char sz;
589 };
591 const struct bit_descr psr_bits[] =
592 {
593 {"", 1 }, {"be", 1 }, {"up", 1 }, {"ac", 1 },
594 {"mfl", 1 }, {"mfh", 1 }, {"", 7 },
595 {"ic", 1 }, {"i", 1 }, {"pk", 1 },
596 {"", 1 }, {"dt", 1 }, {"dfl", 1 }, {"dfh", 1 },
597 {"sp", 1 }, {"pp", 1 }, {"di", 1 }, {"si", 1 },
598 {"db", 1 }, {"lp", 1 }, {"tb", 1 }, {"rt", 1 },
599 {"", 4 },
600 {"cpl", 2 }, {"is", 1 }, {"mc", 1 },
601 {"it", 1 }, {"id", 1 }, {"da", 1 }, {"dd", 1 },
602 {"ss", 1 }, {"ri", 2 }, {"ed", 1 },
603 {"bn", 1 }, {"ia", 1 }, {"vm", 1 },
604 {NULL, 0 }
605 };
607 void print_bits (const struct bit_descr *desc, unsigned long val)
608 {
609 const struct bit_descr *d;
610 unsigned int off;
612 /* Reverse order. */
613 for (d = desc, off = 0; d->name; d++)
614 off += d->sz;
616 d--;
618 while (1) {
619 off -= d->sz;
620 if (*d->name) {
621 if (d->sz != 1 || ((val >> off) & 1))
622 printf (" %s", d->name);
623 if (d->sz != 1)
624 printf ("=%lx", (val >> off) & ((1 << d->sz) - 1));
625 }
626 if (d == desc)
627 break;
628 d--;
629 }
630 }
632 void print_tr (vcpu_guest_context_t *ctx)
633 {
634 struct vcpu_tr_regs *tr = &ctx->regs.tr;
635 int i;
637 printf ("\n itr: P rid va pa ps ed pl "
638 "ar a d ma key\n");
640 for (i = 0; i < sizeof (tr->itrs) / sizeof (tr->itrs[0]); i++)
641 print_a_tr (i, &tr->itrs[i]);
643 printf ("\n dtr: P rid va pa ps ed pl "
644 "ar a d ma key\n");
646 for (i = 0; i < sizeof (tr->dtrs) / sizeof (tr->dtrs[0]); i++)
647 print_a_tr (i, &tr->dtrs[i]);
648 }
650 int lock_pages (void *addr, size_t len);
651 void unlock_pages (void *addr, size_t len);
652 int do_xen_hypercall (int xc_handle, privcmd_hypercall_t *hypercall);
654 #ifdef HAVE_DEBUG_OP
655 static int do_ia64_debug_op (int xc_handle,
656 unsigned long cmd, unsigned long domain,
657 xen_ia64_debug_op_t *op)
658 {
659 int ret = -1;
660 privcmd_hypercall_t hypercall;
662 hypercall.op = __HYPERVISOR_ia64_debug_op;
663 hypercall.arg[0] = cmd;
664 hypercall.arg[1] = domain;
665 hypercall.arg[2] = (unsigned long)op;
667 if (lock_pages (op, sizeof (*op)) != 0) {
668 perror ("Could not lock memory for Xen hypercall");
669 goto out1;
670 }
672 ret = do_xen_hypercall (xc_handle, &hypercall);
673 if (ret < 0) {
674 if (errno == EACCES)
675 fprintf (stderr,"domctl operation failed -- need to "
676 "rebuild the user-space tool set?\n");
677 }
679 unlock_pages (op, sizeof (*op));
681 out1:
682 return ret;
683 }
684 #endif
686 static volatile int ctrl_c_hit;
688 void ctrl_c_handler (int sig)
689 {
690 fflush (stdout);
691 ctrl_c_hit = 1;
692 }
694 int wait_domain (int vcpu, vcpu_guest_context_t *ctx)
695 {
696 struct timespec ts;
697 xc_dominfo_t dominfo;
698 int ret;
699 int cnt = 0;
701 ts.tv_sec = 0;
702 ts.tv_nsec = 10*1000*1000;
704 ret = xc_domain_unpause (xc_handle, domid);
705 if (ret < 0)
706 perror ("xc_domain_unpause");
708 ctrl_c_hit = 0;
710 while (1) {
711 ret = xc_domain_getinfo (xc_handle, domid, 1, &dominfo);
712 if (ret < 0)
713 perror ("xc_domain_getinfo");
715 if (dominfo.paused)
716 break;
718 if (ctrl_c_hit) {
719 /* Force pause. */
720 ret = xc_domain_pause (xc_handle, domid);
721 if (ret < 0)
722 perror ("xc_domain_pause");
724 break;
725 }
727 printf ("%c\b", "/-\\|"[(cnt++) % 4]);
728 fflush (stdout);
729 nanosleep (&ts, NULL);
730 }
731 return xc_vcpu_getcontext (xc_handle, domid, vcpu, ctx);
732 }
734 int virt_to_phys (int is_inst, unsigned long vaddr, unsigned long *paddr)
735 {
736 struct vcpu_tr_regs *trs = &cur_ctx->regs.tr;
737 struct ia64_tr_entry *tr;
738 int i;
739 int num;
741 /* Search in tr. */
742 if (is_inst) {
743 tr = trs->itrs;
744 num = sizeof (trs->itrs) / sizeof (trs->itrs[0]);
745 }
746 else {
747 tr = trs->dtrs;
748 num = sizeof (trs->dtrs) / sizeof (trs->dtrs[0]);
749 }
750 for (i = 0; i < num; i++, tr++) {
751 int ps_val = (tr->itir >> ITIR_PS_SHIFT) & ITIR_PS_MASK;
752 unsigned long ps_mask = (-1L) << ps_val;
754 if ((tr->vadr & ps_mask) == (vaddr & ps_mask)) {
755 *paddr = ((tr->pte & (PTE_PPN_MASK << PTE_PPN_SHIFT)) & ps_mask) |
756 (vaddr & ~ps_mask);
757 return 0;
758 }
759 }
760 return -1;
761 }
763 unsigned long *
764 get_reg_addr (const char *name)
765 {
766 if (strcmp (name, "ip") == 0)
767 return &cur_ctx->regs.ip;
768 else if (strcmp (name, "psr") == 0)
769 return &cur_ctx->regs.psr;
770 else if (strcmp (name, "iip") == 0)
771 return &cur_ctx->regs.cr.iip;
772 else if (strcmp (name, "b0") == 0)
773 return &cur_ctx->regs.b[0];
774 else
775 return 0;
776 }
778 enum prio_expr {EXPR_BASE, EXPR_SUM, EXPR_LOGIC, EXPR_PROD};
780 int parse_expr (char **buf, unsigned long *res, enum prio_expr prio);
782 int next_char (char **buf)
783 {
784 char *b;
786 b = *buf;
787 while (isspace ((unsigned char)*b))
788 b++;
789 *buf = b;
790 return *b;
791 }
793 int parse_unary (char **buf, unsigned long *res)
794 {
795 char c;
797 c = next_char (buf);
798 switch (c) {
799 case '0' ... '9':
800 {
801 char *e;
802 *res = strtoul (*buf, &e, 0);
803 if (e == *buf) {
804 printf ("bad literal\n");
805 return -1;
806 }
807 *buf = e;
808 }
809 break;
810 case '+':
811 (*buf)++;
812 return parse_unary (buf, res);
813 case '$':
814 {
815 char *b;
816 char *e;
817 char c;
818 unsigned long *reg;
819 int len;
821 b = *buf;
822 e = b + 1;
824 while ((*e >= 'a' && *e <= 'z') ||
825 (*e >= 'A' && *e <= 'Z') ||
826 (*e >= '0' && *e <= '9') ||
827 (*e == '_' || *e == '.'))
828 e++;
830 if (b == e) {
831 printf ("identifier missing after '$'\n");
832 return -1;
833 }
835 b++;
836 len = e - b;
838 c = b[len];
839 b[len] = 0;
840 reg = get_reg_addr (b);
841 b[len] = c;
843 if (reg != NULL)
844 *res = *reg;
845 else if (strncmp (b, "d2p", len) == 0 ||
846 strncmp (b, "i2p", len) == 0) {
847 unsigned long vaddr;
849 *buf = e;
850 if (parse_unary (buf, &vaddr) != 0)
851 return -1;
852 if (virt_to_phys (*b == 'i', vaddr, res) != 0) {
853 printf ("cannot find vaddr %016lx in tr\n", vaddr);
854 return -1;
855 }
856 return 0;
857 }
858 else {
859 printf ("unknown symbol\n");
860 return -1;
861 }
862 *buf = e;
863 }
864 break;
865 case '(':
866 (*buf)++;
867 if (parse_expr (buf, res, EXPR_BASE) != 0)
868 return -1;
870 if (next_char (buf) != ')') {
871 printf ("missing ')'\n");
872 return -1;
873 }
874 else
875 (*buf)++;
876 break;
877 default:
878 printf ("unknown operand '%c' in expression\n", c);
879 return -1;
880 }
882 return 0;
883 }
885 int parse_expr (char **buf, unsigned long *res, enum prio_expr prio)
886 {
887 unsigned long val = 0;
888 unsigned long val1;
889 char c;
891 if (parse_unary (buf, &val) != 0)
892 return -1;
894 while (1) {
895 c = next_char (buf);
896 switch (c) {
897 case '+':
898 case '-':
899 if (prio > EXPR_SUM)
900 return 0;
901 (*buf)++;
902 if (parse_expr (buf, &val1, EXPR_SUM) < 0)
903 return -1;
904 if (c == '+')
905 val += val1;
906 else
907 val -= val1;
908 break;
909 case '*':
910 if (prio > EXPR_PROD)
911 return 0;
913 (*buf)++;
914 if (parse_expr (buf, &val1, EXPR_SUM) < 0)
915 return -1;
917 val *= val1;
918 break;
919 default:
920 *res = val;
921 return 0;
922 }
923 }
924 }
926 char *parse_arg (char **buf)
927 {
928 char *res;
929 char *b = *buf;
931 /* Eat leading spaces. */
932 while (isspace ((unsigned char)*b))
933 b++;
935 res = b;
936 while (*b && !isspace ((unsigned char)*b))
937 b++;
939 /* Set the NUL terminator. */
940 if (*b)
941 *b++ = 0;
943 *buf = b;
944 return res;
945 }
947 vcpu_guest_context_t vcpu_ctx[MAX_VIRT_CPUS];
949 int vcpu_setcontext (int vcpu)
950 {
951 int ret;
953 ret = xc_vcpu_setcontext (xc_handle, domid, vcpu, &vcpu_ctx[vcpu]);
954 if (ret < 0)
955 perror ("xc_vcpu_setcontext");
957 return ret;
958 }
960 struct command_desc
961 {
962 const char *name;
963 const char *help;
964 int (*cmd)(char *line);
965 };
967 static int
968 cmd_registers (char *line)
969 {
970 print_ctx (cur_ctx);
971 return 0;
972 }
974 static int
975 cmd_sstep (char *line)
976 {
977 if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB)) != PSR_SS) {
978 cur_ctx->regs.psr |= PSR_SS;
979 cur_ctx->regs.psr &= ~PSR_TB;
980 if (vcpu_setcontext (cur_vcpu) < 0)
981 return -1;
982 }
984 if (wait_domain (cur_vcpu, cur_ctx) < 0) {
985 perror ("wait_domain");
986 return -1;
987 }
989 print_ctx (cur_ctx);
991 return 0;
992 }
994 static int
995 cmd_go (char *line)
996 {
997 unsigned long n = 1;
999 if (*line != 0) {
1000 if (parse_expr (&line, &n, 0) < 0)
1001 return -1;
1003 while (n > 0) {
1004 /* Set psr.dd and psr.id to skip over current breakpoint. */
1005 if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB | PSR_DB)) != 0) {
1006 cur_ctx->regs.psr &= ~(PSR_SS | PSR_TB);
1007 cur_ctx->regs.psr |= PSR_DD | PSR_ID;
1008 if (vcpu_setcontext (cur_vcpu) < 0)
1009 return -1;
1012 if (wait_domain (cur_vcpu, cur_ctx) < 0) {
1013 perror ("wait_domain");
1014 return -1;
1016 print_ctx (cur_ctx);
1017 n--;
1020 return 0;
1023 static int
1024 cmd_cb (char *line)
1026 if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB)) != PSR_TB) {
1027 cur_ctx->regs.psr &= ~PSR_SS;
1028 cur_ctx->regs.psr |= PSR_TB;
1029 if (vcpu_setcontext (cur_vcpu) < 0)
1030 return -1;
1033 if (wait_domain (cur_vcpu, cur_ctx) < 0) {
1034 perror ("wait_domain");
1035 return -1;
1038 print_ctx (cur_ctx);
1040 return 0;
1043 static int
1044 cmd_quit (char *line)
1046 return -2;
1049 static int
1050 cmd_echo (char *line)
1052 printf ("%s", line);
1053 return 0;
1056 static int
1057 cmd_disassemble (char *args)
1059 static unsigned long addr;
1060 unsigned long end_addr = addr + 16;
1062 if (*args != 0) {
1063 if (parse_expr (&args, &addr, 0) < 0)
1064 return -1;
1065 if (*args != 0) {
1066 if (parse_expr (&args, &end_addr, 0) < 0)
1067 return -1;
1069 else
1070 end_addr = addr + 16;
1072 target_disas (stdout, addr, end_addr - addr);
1073 addr = end_addr;
1074 return 0;
1078 static int
1079 cmd_break (char *args)
1081 unsigned long addr;
1082 int i;
1084 for (i = 0; i < 4; i++)
1085 if (cur_ctx->regs.ibr[2 * i] == 0 && cur_ctx->regs.ibr[2 * i + 1] == 0)
1086 break;
1088 if (i == 4) {
1089 printf ("no availabe break points\n");
1090 return -1;
1093 if (parse_expr (&args, &addr, 0) < 0)
1094 return -1;
1096 cur_ctx->regs.ibr[2 * i] = addr;
1097 cur_ctx->regs.ibr[2 * i + 1] = 0x87fffffffffffff0UL;
1098 cur_ctx->regs.psr |= PSR_DB;
1100 return vcpu_setcontext (cur_vcpu);
1103 static int
1104 cmd_watch (char *args)
1106 unsigned long addr;
1107 unsigned long mask;
1108 int i;
1110 for (i = 0; i < 4; i++)
1111 if (cur_ctx->regs.dbr[2 * i] == 0 && cur_ctx->regs.dbr[2 * i + 1] == 0)
1112 break;
1114 if (i == 4) {
1115 printf ("no availabe watch points\n");
1116 return -1;
1119 if (parse_expr (&args, &addr, 0) < 0)
1120 return -1;
1122 if (parse_expr (&args, &mask, 0) < 0)
1123 mask = 3;
1125 cur_ctx->regs.dbr[2 * i] = addr;
1126 cur_ctx->regs.dbr[2 * i + 1] = ~((1UL << mask) - 1) | (0xc7UL << 56);
1127 cur_ctx->regs.psr |= PSR_DB;
1129 return vcpu_setcontext (cur_vcpu);
1132 static int
1133 cmd_delete (char *args)
1135 unsigned long num;
1137 if (parse_expr (&args, &num, 0) < 0)
1138 return -1;
1140 if (num < 4) {
1141 cur_ctx->regs.ibr[2 * num] = 0;
1142 cur_ctx->regs.ibr[2 * num + 1] = 0;
1144 else if (num < 8) {
1145 num -= 4;
1146 cur_ctx->regs.dbr[2 * num] = 0;
1147 cur_ctx->regs.dbr[2 * num + 1] = 0;
1149 else {
1150 printf ("breakpoint out of range\n");
1151 return -1;
1154 cur_ctx->regs.psr |= PSR_DB;
1156 return vcpu_setcontext (cur_vcpu);
1159 static int
1160 cmd_disable (char *args)
1162 unsigned long num;
1164 if (parse_expr (&args, &num, 0) < 0)
1165 return -1;
1167 if (num >= 4) {
1168 printf ("breakpoint out of range\n");
1169 return -1;
1172 cur_ctx->regs.ibr[2 * num + 1] &= ~(1UL << 63);
1174 return vcpu_setcontext (cur_vcpu);
1177 static int
1178 cmd_enable (char *args)
1180 unsigned long num;
1182 if (parse_expr (&args, &num, 0) < 0)
1183 return -1;
1185 if (num >= 4) {
1186 printf ("breakpoint out of range\n");
1187 return -1;
1190 cur_ctx->regs.ibr[2 * num + 1] |= 1UL << 63;
1192 return vcpu_setcontext (cur_vcpu);
1195 static int
1196 cmd_print (char *args)
1198 unsigned long addr;
1200 if (parse_expr (&args, &addr, 0) < 0)
1201 return -1;
1203 printf ("res: 0x%016lx = %ld\n", addr, addr);
1205 return 0;
1208 struct bit_xlat {
1209 unsigned int bit;
1210 const char *name;
1211 };
1213 static const struct bit_xlat debug_flags[] = {
1214 { XEN_IA64_DEBUG_ON_KERN_SSTEP, "sstep" },
1215 { XEN_IA64_DEBUG_ON_KERN_DEBUG, "debug" },
1216 { XEN_IA64_DEBUG_ON_KERN_TBRANCH, "tbranch" },
1217 { XEN_IA64_DEBUG_ON_EXTINT, "extint" },
1218 { XEN_IA64_DEBUG_ON_EXCEPT, "except" },
1219 { XEN_IA64_DEBUG_ON_EVENT, "event" },
1220 { XEN_IA64_DEBUG_ON_PRIVOP, "privop" },
1221 { XEN_IA64_DEBUG_ON_PAL, "pal" },
1222 { XEN_IA64_DEBUG_ON_SAL, "sal" },
1223 { XEN_IA64_DEBUG_ON_EFI, "efi" },
1224 { XEN_IA64_DEBUG_ON_RFI, "rfi" },
1225 { XEN_IA64_DEBUG_ON_MMU, "mmu" },
1226 { XEN_IA64_DEBUG_ON_BAD_MPA, "mpa" },
1227 { XEN_IA64_DEBUG_FORCE_SS, "ss" },
1228 { XEN_IA64_DEBUG_FORCE_DB, "db" },
1229 { XEN_IA64_DEBUG_ON_TR, "tr" },
1230 { XEN_IA64_DEBUG_ON_TC, "tc" },
1231 /* { XEN_IA64_DEBUG_ON_KEYS, "keys" }, */
1232 { 0, NULL }
1233 };
1235 static int
1236 cmd_disp (char *arg)
1238 if (strcmp (arg, "br") == 0)
1239 print_br (cur_ctx);
1240 else if (strcmp (arg, "regs") == 0)
1241 print_regs (cur_ctx);
1242 else if (strcmp (arg, "cr") == 0)
1243 print_cr (cur_ctx);
1244 else if (strcmp (arg, "ar") == 0)
1245 print_ar (cur_ctx);
1246 else if (strcmp (arg, "tr") == 0)
1247 print_tr (cur_ctx);
1248 else if (strcmp (arg, "rr") == 0)
1249 print_rr (cur_ctx);
1250 else if (strcmp (arg, "db") == 0)
1251 print_db (cur_ctx);
1252 else if (strcmp (arg, "psr") == 0) {
1253 printf ("psr:");
1254 print_bits (psr_bits, cur_ctx->regs.psr);
1255 printf ("\n");
1257 else if (strcmp (arg, "ipsr") == 0) {
1258 printf ("ipsr:");
1259 print_bits (psr_bits, cur_ctx->regs.cr.ipsr);
1260 printf ("\n");
1262 else if (strcmp (arg, "break") == 0) {
1263 int i;
1265 for (i = 0; i < 4; i++)
1266 if (cur_ctx->regs.ibr[2 * i + 1])
1267 printf ("%d: 0x%016lx %s\n", i, cur_ctx->regs.ibr[2 * i],
1268 (cur_ctx->regs.ibr[2 * i + 1] & (1UL << 63)) ?
1269 "enabled" : "disabled");
1271 else if (strcmp (arg, "domain") == 0) {
1272 xc_dominfo_t dominfo;
1273 #ifdef HAVE_DEBUG_OP
1274 xen_ia64_debug_op_t debug_op;
1275 int i;
1276 #endif
1277 if (xc_domain_getinfo (xc_handle, domid, 1, &dominfo) < 0) {
1278 perror ("xc_domain_getinfo");
1279 return 0;
1282 printf ("id=%d nr_pages=%lu shared_info_frame=%lu max_mem=%luKB\n",
1283 dominfo.domid, dominfo.nr_pages, dominfo.shared_info_frame,
1284 dominfo.max_memkb);
1285 printf (" nr_online_vcpu=%u max_vcpu_id=%u\n",
1286 dominfo.nr_online_vcpus, dominfo.max_vcpu_id);
1287 printf (" status:");
1288 if (dominfo.dying)
1289 printf (" dying");
1290 if (dominfo.crashed)
1291 printf (" crashed");
1292 if (dominfo.shutdown)
1293 printf (" shutdown(%u)", dominfo.shutdown_reason);
1294 if (dominfo.paused)
1295 printf (" paused");
1296 if (dominfo.blocked)
1297 printf (" blocked");
1298 if (dominfo.running)
1299 printf (" running");
1300 if (dominfo.hvm)
1301 printf (" hvm");
1302 if (dominfo.debugged)
1303 printf (" debug");
1304 printf ("\n");
1306 #ifdef HAVE_DEBUG_OP
1307 if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_GET_FLAGS,
1308 domid, &debug_op) < 0) {
1309 perror ("xc_domain_getinfo");
1310 return 0;
1312 printf ("debug flags: %08lx: ", debug_op.flags);
1313 for (i = 0; debug_flags[i].name; i++)
1314 if (debug_flags[i].bit & debug_op.flags)
1315 printf (" %s", debug_flags[i].name);
1316 printf ("\n");
1317 #endif
1319 else if (*arg == 0)
1320 printf ("choose among br, regs, cr, ar, tr, rr, db\n");
1321 else
1322 printf ("cannot disp '%s'\n", arg);
1323 return 0;
1326 static int
1327 cmd_bev (char *arg)
1329 xen_ia64_debug_op_t debug_op;
1330 int i;
1332 if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_GET_FLAGS,
1333 domid, &debug_op) < 0) {
1334 perror ("get debug flags");
1335 return 0;
1337 if (arg == NULL || arg[0] == 0) {
1338 printf ("debug flags: %08lx:\n", debug_op.flags);
1339 for (i = 0; debug_flags[i].name; i++)
1340 printf (" %c%s\n",
1341 (debug_flags[i].bit & debug_op.flags) ? '+' : '-',
1342 debug_flags[i].name);
1343 return 0;
1345 else {
1346 char *p = strtok ((char *)arg, " ");
1348 while (p != NULL) {
1349 unsigned int flag = 0;
1351 for (i = 0; debug_flags[i].name; i++)
1352 if (strcmp (p, debug_flags[i].name) == 0
1353 || ((p[0] == '-' || p[0] == '+')
1354 && strcmp (p + 1, debug_flags[i].name) == 0)) {
1355 flag = debug_flags[i].bit;
1356 break;
1358 if (flag == 0) {
1359 printf ("unknown event %s\n", p);
1360 return 0;
1362 if (p[0] == '-')
1363 debug_op.flags &= ~flag;
1364 else
1365 debug_op.flags |= flag;
1367 p = strtok (NULL, " ");
1369 if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_SET_FLAGS,
1370 domid, &debug_op) < 0) {
1371 perror ("set debug flags");
1372 return -1;
1374 /* Disabling force_SS and force_DB requires setting psr. */
1375 return vcpu_setcontext (cur_vcpu);
1379 static int
1380 cmd_set (char *line)
1382 char *reg;
1383 unsigned long *addr;
1384 unsigned long val;
1386 reg = parse_arg (&line);
1388 addr = get_reg_addr (reg);
1389 if (addr == NULL) {
1390 printf ("unknown register %s\n", reg);
1391 return -1;
1394 if (parse_expr (&line, &val, 0) < 0)
1395 return -1;
1397 *addr = val;
1399 return vcpu_setcontext (cur_vcpu);
1402 const struct command_desc commands[];
1404 static int
1405 cmd_help (char *line)
1407 int i;
1409 for (i = 0; commands[i].name; i++)
1410 printf ("%s -- %s\n", commands[i].name, commands[i].help);
1412 return 0;
1415 const struct command_desc commands[] = {
1416 { "registers", "display current registers", cmd_registers },
1417 { "sstep", "single step", cmd_sstep },
1418 { "go", "resume execution", cmd_go },
1419 { "quit", "quit debugger", cmd_quit },
1420 { "echo", "display parameters", cmd_echo },
1421 { "disassemble", "disassemble memory", cmd_disassemble },
1422 { "break", "set a break point", cmd_break },
1423 { "watch", "set a watch point", cmd_watch },
1424 { "cb", "resume until branch", cmd_cb },
1425 { "delete", "delete a break point", cmd_delete },
1426 { "disable", "disable a break point", cmd_disable },
1427 { "enable", "enable a break point", cmd_enable },
1428 { "print", "print an expression", cmd_print },
1429 { "disp", "disp br/regs/cr/ar/tr/rr/db/psr/break/domain", cmd_disp},
1430 { "bev", "break on event", cmd_bev},
1431 { "set", "set reg val", cmd_set},
1432 { "help", "disp help", cmd_help },
1433 { NULL, NULL, NULL }
1434 };
1437 int do_command (int vcpu, char *line)
1439 char *cmd;
1440 char *args;
1441 int i;
1442 const struct command_desc *desc;
1443 int flag_ambiguous;
1445 cur_vcpu = vcpu;
1446 cur_ctx = &vcpu_ctx[vcpu];
1448 cmd = parse_arg (&line);
1449 args = line;
1451 desc = NULL;
1452 flag_ambiguous = 0;
1454 for (i = 0; commands[i].name; i++) {
1455 const char *n = commands[i].name;
1456 char *c = cmd;
1458 while (*n == *c && *n)
1459 n++, c++;
1461 if (*c == 0) {
1462 /* Match. */
1463 if (desc != NULL) {
1464 if (!flag_ambiguous)
1465 printf ("ambiguous command: %s", desc->name);
1466 printf (", %s", commands[i].name);
1467 flag_ambiguous = 1;
1469 else
1470 desc = &commands[i];
1474 if (flag_ambiguous) {
1475 printf ("\n");
1476 return -3;
1478 else if (!desc) {
1479 printf ("command not found, try help\n");
1480 return -3;
1483 return (*desc->cmd)(args);
1486 void xenitp (int vcpu)
1488 int ret;
1489 xc_dominfo_t dominfo;
1490 struct sigaction sa;
1492 cur_ctx = &vcpu_ctx[vcpu];
1494 xc_handle = xc_interface_open (); /* for accessing control interface */
1496 ret = xc_domain_getinfo (xc_handle, domid, 1, &dominfo);
1497 if (ret < 0) {
1498 perror ("xc_domain_getinfo");
1499 exit (-1);
1502 if (xc_domain_setdebugging (xc_handle, domid, 1) != 0)
1503 perror ("setdebugging");
1505 ret = xc_domain_pause (xc_handle, domid);
1506 if (ret < 0) {
1507 perror ("xc_domain_pause");
1508 exit (-1);
1511 ret = xc_vcpu_getcontext (xc_handle, domid, vcpu, cur_ctx);
1512 if (ret < 0) {
1513 if (!dominfo.paused)
1514 xc_domain_unpause (xc_handle, domid);
1515 perror ("xc_vcpu_getcontext");
1516 exit (-1);
1519 print_ctx (cur_ctx);
1521 /* Catch ctrl-c. */
1522 sa.sa_handler = &ctrl_c_handler;
1523 sa.sa_flags = 0;
1524 sigemptyset (&sa.sa_mask);
1525 if (sigaction (SIGINT, &sa, NULL) != 0)
1526 perror ("sigaction");
1528 while (1) {
1529 char buf[128];
1530 int len;
1532 printf ("XenITP> ");
1534 if (fgets (buf, sizeof (buf), stdin) == NULL)
1535 break;
1537 len = strlen ((char *)buf);
1538 if (len > 1 && buf[len - 1] == '\n')
1539 buf[len - 1] = 0;
1541 ret = do_command (vcpu, buf);
1542 if (ret == -2)
1543 break;
1546 /* Clear debug bits. */
1547 if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB | PSR_DB)) != 0) {
1548 cur_ctx->regs.psr &= ~(PSR_SS | PSR_TB | PSR_DB);
1549 cur_ctx->regs.psr |= PSR_DD | PSR_ID;
1550 vcpu_setcontext (cur_vcpu);
1553 /* Disable debugging. */
1554 if (xc_domain_setdebugging (xc_handle, domid, 0) != 0)
1555 perror ("setdebugging");
1557 if (!dominfo.paused) {
1558 ret = xc_domain_unpause (xc_handle, domid);
1559 if (ret < 0) {
1560 perror ("xc_domain_unpause");
1561 exit (-1);
1565 xc_interface_close (xc_handle);
1566 if (ret < 0) {
1567 perror ("xc_interface_close");
1568 exit (-1);
1572 static void usage (void)
1574 printf ("usage:\n");
1575 printf (" xenitp <DOMAIN> [VCPU]\n");
1579 int main (int argc, char **argv)
1581 int ch;
1582 static const char *sopts = "h"
1584 static const struct option lopts[] = {
1585 {"help", 0, NULL, 'h'},
1586 {0, 0, 0, 0}
1587 };
1588 int vcpu = 0;
1590 while ((ch = getopt_long (argc, argv, sopts, lopts, NULL)) != -1) {
1591 switch (ch) {
1592 case 'h':
1593 usage ();
1594 exit (-1);
1595 case '?':
1596 fprintf (stderr, "%s --help for more options\n", argv[0]);
1597 exit (-1);
1601 argv += optind;
1602 argc -= optind;
1604 if (argc < 1 || argc > 2) {
1605 usage ();
1606 exit (-1);
1609 domid = atoi (argv[0]);
1610 if (domid == 0) {
1611 fprintf (stderr, "cannot trace dom0\n");
1612 exit (-1);
1615 if (argc == 2)
1616 vcpu = atoi (argv[1]);
1618 xenitp (vcpu);
1620 return 0;
1623 /*
1624 * Local variables:
1625 * mode: C
1626 * c-set-style: "BSD"
1627 * c-basic-offset: 4
1628 * tab-width: 4
1629 * indent-tabs-mode: nil
1630 * End:
1631 */