debuggers.hg

view tools/debugger/xenitp/xenitp.c @ 19826:2f9e1348aa98

x86_64: allow more vCPU-s per guest

Since the shared info layout is fixed, guests are required to use
VCPUOP_register_vcpu_info prior to booting any vCPU beyond the
traditional limit of 32.

MAX_VIRT_CPUS, being an implemetation detail of the hypervisor, is no
longer being exposed in the public headers.

The tools changes are clearly incomplete (and done only so things
would
build again), and the current state of the tools (using scalar
variables all over the place to represent vCPU bitmaps) very likely
doesn't permit booting DomU-s with more than the traditional number of
vCPU-s. Testing of the extended functionality was done with Dom0 (96
vCPU-s, as well as 128 vCPU-s out of which the kernel elected - by way
of a simple kernel side patch - to use only some, resulting in a
sparse
bitmap).

ia64 changes only to make things build, and build-tested only (and the
tools part only as far as the build would go without encountering
unrelated problems in the blktap code).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:14:16 2009 +0100 (2009-06-18)
parents 26ecd1f9e128
children 3ffdb094c2c0
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 #include <xen/arch-ia64/debug_op.h>
41 #endif
43 static int xc_handle = 0;
44 static int domid = 0;
45 static vcpu_guest_context_t *cur_ctx;
46 static int cur_vcpu;
48 #define PSR_BN (1UL << 44)
49 #define PSR_SS (1UL << 40)
50 #define PSR_DB (1UL << 24)
51 #define PSR_TB (1UL << 26)
52 #define PSR_DD (1UL << 39)
53 #define PSR_ID (1UL << 37)
54 #define PSR_IT (1UL << 36)
55 #define PSR_DT (1UL << 17)
56 #define PSR_RI_SHIFT 41
57 #define CFM_SOF_MASK 0x3f
59 int virt_to_phys (int is_inst, unsigned long vaddr, unsigned long *paddr);
61 /* wrapper for vcpu_gest_context_any_t */
62 static int xc_ia64_vcpu_getcontext(int xc_handle,
63 uint32_t domid,
64 uint32_t vcpu,
65 vcpu_guest_context_t *ctxt)
66 {
67 return xc_vcpu_getcontext(xc_handle, domid, vcpu,
68 (vcpu_guest_context_any_t *)ctxt);
69 }
71 static inline unsigned int ctx_slot (vcpu_guest_context_t *ctx)
72 {
73 return (ctx->regs.psr >> PSR_RI_SHIFT) & 3;
74 }
76 unsigned char *
77 target_map_memory (unsigned long paddr)
78 {
79 static unsigned long cur_page = (unsigned long)-1;
80 static unsigned char *cur_map = NULL;
82 if ((paddr >> XC_PAGE_SHIFT) != cur_page) {
83 if (cur_map) {
84 munmap (cur_map, XC_PAGE_SIZE);
85 cur_map = NULL;
86 }
87 cur_page = paddr >> XC_PAGE_SHIFT;
88 cur_map = xc_map_foreign_range (xc_handle, domid, XC_PAGE_SIZE,
89 PROT_READ, cur_page);
90 if (cur_map == NULL) {
91 perror ("cannot map page");
92 cur_page = -1;
93 return NULL;
94 }
95 }
96 return cur_map + (paddr & (XC_PAGE_SIZE - 1));
97 }
99 /* Get LENGTH bytes from info's buffer, at target address memaddr.
100 Transfer them to myaddr. */
101 int
102 target_read_memory (bfd_vma memaddr, bfd_byte *myaddr,
103 unsigned int length, struct disassemble_info *info)
104 {
105 int i;
106 unsigned long paddr;
108 if (cur_ctx->regs.psr & PSR_IT) {
109 if (virt_to_phys (1, memaddr, &paddr) != 0)
110 return EIO;
111 }
112 else {
113 /* Clear UC. */
114 paddr = memaddr & ~(1UL << 63);
115 }
117 for (i = 0; i < length; i++) {
118 unsigned char *p = target_map_memory (paddr + i);
120 if (p == NULL)
121 return EIO;
122 myaddr[i] = *p;
123 }
124 return 0;
125 }
127 /* Print an error message. We can assume that this is in response to
128 an error return from buffer_read_memory. */
129 void
130 perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
131 {
132 if (status != EIO)
133 /* Can't happen. */
134 (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
135 else
136 /* Actually, address between memaddr and memaddr + len was
137 out of bounds. */
138 (*info->fprintf_func) (info->stream,
139 "Address 0x%" PRIx64 " is out of bounds.\n",
140 memaddr);
141 }
143 /* This could be in a separate file, to save miniscule amounts of space
144 in statically linked executables. */
146 /* Just print the address is hex. This is included for completeness even
147 though both GDB and objdump provide their own (to print symbolic
148 addresses). */
150 void
151 generic_print_address (bfd_vma addr, struct disassemble_info *info)
152 {
153 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
154 }
156 /* Just return the given address. */
158 int
159 generic_symbol_at_address (bfd_vma addr, struct disassemble_info * info)
160 {
161 return 1;
162 }
164 bfd_boolean
165 generic_symbol_is_valid (asymbol * sym ATTRIBUTE_UNUSED,
166 struct disassemble_info *info ATTRIBUTE_UNUSED)
167 {
168 return 1;
169 }
171 bfd_vma bfd_getl32 (const bfd_byte *addr)
172 {
173 unsigned long v;
175 v = (unsigned long) addr[0];
176 v |= (unsigned long) addr[1] << 8;
177 v |= (unsigned long) addr[2] << 16;
178 v |= (unsigned long) addr[3] << 24;
180 return (bfd_vma) v;
181 }
183 bfd_vma bfd_getl64 (const bfd_byte *addr)
184 {
185 unsigned long v;
187 v = (unsigned long) addr[0];
188 v |= (unsigned long) addr[1] << 8;
189 v |= (unsigned long) addr[2] << 16;
190 v |= (unsigned long) addr[3] << 24;
191 v |= (unsigned long) addr[4] << 32;
192 v |= (unsigned long) addr[5] << 40;
193 v |= (unsigned long) addr[6] << 48;
194 v |= (unsigned long) addr[7] << 56;
196 return (bfd_vma) v;
197 }
199 bfd_vma bfd_getb32 (const bfd_byte *addr)
200 {
201 unsigned long v;
203 v = (unsigned long) addr[0] << 24;
204 v |= (unsigned long) addr[1] << 16;
205 v |= (unsigned long) addr[2] << 8;
206 v |= (unsigned long) addr[3];
208 return (bfd_vma) v;
209 }
211 bfd_vma bfd_getl16 (const bfd_byte *addr)
212 {
213 unsigned long v;
215 v = (unsigned long) addr[0];
216 v |= (unsigned long) addr[1] << 8;
218 return (bfd_vma) v;
219 }
221 bfd_vma bfd_getb16 (const bfd_byte *addr)
222 {
223 unsigned long v;
225 v = (unsigned long) addr[0] << 24;
226 v |= (unsigned long) addr[1] << 16;
228 return (bfd_vma) v;
229 }
231 void
232 init_disassemble_info (struct disassemble_info *info, void *stream,
233 fprintf_ftype fprintf_func)
234 {
235 memset (info, 0, sizeof (*info));
237 info->flavour = bfd_target_unknown_flavour;
238 info->arch = bfd_arch_unknown;
239 info->endian = BFD_ENDIAN_UNKNOWN;
240 info->octets_per_byte = 1;
241 info->fprintf_func = fprintf_func;
242 info->stream = stream;
243 info->read_memory_func = target_read_memory;
244 info->memory_error_func = perror_memory;
245 info->print_address_func = generic_print_address;
246 info->symbol_at_address_func = generic_symbol_at_address;
247 info->symbol_is_valid = generic_symbol_is_valid;
248 info->display_endian = BFD_ENDIAN_UNKNOWN;
249 }
252 void target_disas (FILE *out, unsigned long code, unsigned long size)
253 {
254 unsigned long pc;
255 int count;
256 struct disassemble_info disasm_info;
258 INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
260 disasm_info.read_memory_func = target_read_memory;
261 #if 0
262 disasm_info.buffer = NULL;
263 disasm_info.buffer_vma = (unsigned long)code;
264 disasm_info.buffer_length = size;
265 #endif
267 disasm_info.endian = BFD_ENDIAN_LITTLE;
268 disasm_info.mach = 0; //bfd_mach_ia64;
270 for (pc = code; pc < code + size; pc += count) {
271 int slot = (pc & 0x0f) / 6;
272 fprintf (out, "0x%016lx+%d:%c ", pc & ~0x0fUL, slot,
273 ((pc & ~0x0fUL) == cur_ctx->regs.ip
274 && slot == ctx_slot (cur_ctx)) ? '*' : ' ');
276 count = print_insn_ia64 (pc, &disasm_info);
278 #if 0
279 {
280 int i;
281 uint8_t b;
283 fprintf (out, " {");
284 for (i = 0; i < count; i++) {
285 target_read_memory (pc + i, &b, 1, &disasm_info);
286 fprintf (out, " %02x", b);
287 }
288 fprintf (out, " }");
289 }
290 #endif
291 fprintf (out, "\n");
292 if (count < 0)
293 break;
294 }
295 }
298 #define PTE_ED_SHIFT 52
299 #define PTE_ED_MASK 1
300 #define PTE_PPN_SHIFT 12
301 #define PTE_PPN_MASK 0x3fffffffff
302 #define PTE_AR_SHIFT 9
303 #define PTE_AR_MASK 7
304 #define PTE_PL_SHIFT 7
305 #define PTE_PL_MASK 3
306 #define PTE_D_SHIFT 6
307 #define PTE_D_MASK 1
308 #define PTE_A_SHIFT 5
309 #define PTE_A_MASK 1
310 #define PTE_MA_SHIFT 2
311 #define PTE_MA_MASK 7
312 #define PTE_P_SHIFT 0
313 #define PTE_P_MASK 1
314 #define ITIR_KEY_SHIFT 8
315 #define ITIR_KEY_MASK 0xffffff
316 #define ITIR_PS_SHIFT 2
317 #define ITIR_PS_MASK 0x3f
318 #define ITIR_PS_MIN 12
319 #define ITIR_PS_MAX 28
320 #define RR_RID_SHIFT 8
321 #define RR_RID_MASK 0xffffff
322 #define RR_PS_SHIFT 2
323 #define RR_PS_MASK 0x3f
324 #define RR_VE_MASK 1
326 static const char *get_ps (int ps_val)
327 {
328 static const char ps[][5] = {" 4K", " 8K", " 16K", " ",
329 " 64K", " ", "256K", " ",
330 " 1M", " ", " 4M", " ",
331 " 16M", " ", " 64M", " ",
332 "256M"};
333 return ((ps_val >= ITIR_PS_MIN && ps_val <= ITIR_PS_MAX) ?
334 ps[ps_val - ITIR_PS_MIN] : " ");
336 }
338 static void print_a_tr (int i, const struct ia64_tr_entry *tr)
339 {
340 int ps_val, ma_val;
341 unsigned long pa;
343 static const char ma[][4] = {"WB ", " ", " ", " ",
344 "UC ", "UCE", "WC ", "Nat"};
346 ps_val = tr->itir >> ITIR_PS_SHIFT & ITIR_PS_MASK;
347 ma_val = tr->pte >> PTE_MA_SHIFT & PTE_MA_MASK;
348 pa = (tr->pte >> PTE_PPN_SHIFT & PTE_PPN_MASK) << PTE_PPN_SHIFT;
349 pa = (pa >> ps_val) << ps_val;
350 printf (" [%2d] %ld %06lx %016lx %013lx %02d %s %ld %ld %ld %ld "
351 "%ld %d %s %06lx\n", i,
352 tr->pte >> PTE_P_SHIFT & PTE_P_MASK,
353 tr->rid >> RR_RID_SHIFT & RR_RID_MASK,
354 tr->vadr, pa, ps_val, get_ps (ps_val),
355 tr->pte >> PTE_ED_SHIFT & PTE_ED_MASK,
356 tr->pte >> PTE_PL_SHIFT & PTE_PL_MASK,
357 tr->pte >> PTE_AR_SHIFT & PTE_AR_MASK,
358 tr->pte >> PTE_A_SHIFT & PTE_A_MASK,
359 tr->pte >> PTE_D_SHIFT & PTE_D_MASK,
360 ma_val, ma[ma_val],
361 tr->itir >> ITIR_KEY_SHIFT & ITIR_KEY_MASK);
362 }
364 void print_ctx (vcpu_guest_context_t *ctx)
365 {
366 struct vcpu_guest_context_regs *regs = &ctx->regs;
367 int i;
368 unsigned int rbs_size, cfm_sof;
370 rbs_size = (regs->ar.bsp - regs->ar.bspstore) / 8;
371 cfm_sof = (regs->cfm & CFM_SOF_MASK);
372 printf ("bspstore: %016lx bsp: %016lx rbs_size=%d, sof=%d\n",
373 regs->ar.bspstore, regs->ar.bsp, rbs_size, cfm_sof);
375 for (i = 0; i < cfm_sof; i++) {
376 int off = cfm_sof - i;
377 unsigned int rbs_off =
378 (((62 - ((rbs_size + regs->rbs_voff) % 64) + off)) / 63) + off;
379 if (rbs_off > rbs_size)
380 break;
381 printf (" r%02d: %016lx%s", 32 + i,
382 regs->rbs[rbs_size - rbs_off],
383 (i % 3) != 2 ? " " : "\n");
384 }
385 if ((i % 3) != 0)
386 printf ("\n");
388 printf ("\n");
389 printf (" r1: %016lx ", regs->r[1]);
390 printf (" r2: %016lx ", regs->r[2]);
391 printf (" r3: %016lx\n", regs->r[3]);
392 printf (" r4: %016lx ", regs->r[4]);
393 printf (" r5: %016lx ", regs->r[5]);
394 printf (" r6: %016lx\n", regs->r[6]);
395 printf (" r7: %016lx ", regs->r[7]);
396 printf (" r8: %016lx ", regs->r[8]);
397 printf (" r9: %016lx\n", regs->r[9]);
398 printf (" r10: %016lx ", regs->r[10]);
399 printf (" r11: %016lx ", regs->r[11]);
400 printf (" sp: %016lx\n", regs->r[12]);
401 printf (" tp: %016lx ", regs->r[13]);
402 printf (" r14: %016lx ", regs->r[14]);
403 printf (" r15: %016lx\n", regs->r[15]);
404 printf (" r16: %016lx ", regs->r[16]);
405 printf (" r17: %016lx ", regs->r[17]);
406 printf (" r18: %016lx\n", regs->r[18]);
407 printf (" r19: %016lx ", regs->r[19]);
408 printf (" r20: %016lx ", regs->r[20]);
409 printf (" r21: %016lx\n", regs->r[21]);
410 printf (" r22: %016lx ", regs->r[22]);
411 printf (" r23: %016lx ", regs->r[23]);
412 printf (" r24: %016lx\n", regs->r[24]);
413 printf (" r25: %016lx ", regs->r[25]);
414 printf (" r26: %016lx ", regs->r[26]);
415 printf (" r27: %016lx\n", regs->r[27]);
416 printf (" r28: %016lx ", regs->r[28]);
417 printf (" r29: %016lx ", regs->r[29]);
418 printf (" r30: %016lx\n", regs->r[30]);
419 printf (" r31: %016lx ", regs->r[31]);
420 printf (" ");
421 printf (" b0: %016lx\n", regs->b[0]);
423 printf ("\n");
424 printf (" psr: %016lx ", regs->psr);
425 printf (" cfm: %016lx ", regs->cfm);
426 printf (" pr: %016lx\n", regs->pr);
428 printf ("\n");
429 printf (" ip: %016lx+%d", regs->ip, (int)(regs->psr >> PSR_RI_SHIFT) & 3);
430 printf ("\n");
431 target_disas (stdout, regs->ip, 16);
432 }
434 void print_br (vcpu_guest_context_t *ctx)
435 {
436 struct vcpu_guest_context_regs *regs = &ctx->regs;
438 printf (" b0: %016lx ", regs->b[0]);
439 printf (" b1: %016lx ", regs->b[1]);
440 printf (" b2: %016lx\n", regs->b[2]);
441 printf (" b3: %016lx ", regs->b[3]);
442 printf (" b4: %016lx ", regs->b[4]);
443 printf (" b5: %016lx\n", regs->b[5]);
444 printf (" b6: %016lx ", regs->b[6]);
445 printf (" b7: %016lx\n", regs->b[7]);
446 }
448 void print_regs (vcpu_guest_context_t *ctx)
449 {
450 struct vcpu_guest_context_regs *regs = &ctx->regs;
452 printf (" r1: %016lx ", regs->r[1]);
453 printf (" r2: %016lx ", regs->r[2]);
454 printf (" r3: %016lx\n", regs->r[3]);
455 printf (" r4: %016lx ", regs->r[4]);
456 printf (" r5: %016lx ", regs->r[5]);
457 printf (" r6: %016lx\n", regs->r[6]);
458 printf (" r7: %016lx ", regs->r[7]);
459 printf (" r8: %016lx ", regs->r[8]);
460 printf (" r9: %016lx\n", regs->r[9]);
461 printf (" r10: %016lx ", regs->r[10]);
462 printf (" r11: %016lx ", regs->r[11]);
463 printf (" sp: %016lx\n", regs->r[12]);
464 printf (" tp: %016lx ", regs->r[13]);
465 printf (" r14: %016lx ", regs->r[14]);
466 printf (" r15: %016lx\n", regs->r[15]);
468 printf (" Bank %d (current) Bank %d\n",
469 (regs->psr & PSR_BN) ? 1 : 0, (regs->psr & PSR_BN) ? 0 : 1);
470 printf ("16:%016lx ", regs->r[16]);
471 printf ("17:%016lx ", regs->r[17]);
472 printf ("16:%016lx ", regs->bank[0]);
473 printf ("17:%016lx\n", regs->bank[1]);
474 printf ("18:%016lx ", regs->r[18]);
475 printf ("19:%016lx ", regs->r[19]);
476 printf ("18:%016lx ", regs->bank[2]);
477 printf ("19:%016lx\n", regs->bank[3]);
478 printf ("20:%016lx ", regs->r[20]);
479 printf ("21:%016lx ", regs->r[21]);
480 printf ("20:%016lx ", regs->bank[4]);
481 printf ("21:%016lx\n", regs->bank[5]);
482 printf ("22:%016lx ", regs->r[22]);
483 printf ("23:%016lx ", regs->r[23]);
484 printf ("22:%016lx ", regs->bank[6]);
485 printf ("23:%016lx\n", regs->bank[7]);
486 printf ("24:%016lx ", regs->r[24]);
487 printf ("25:%016lx ", regs->r[25]);
488 printf ("24:%016lx ", regs->bank[8]);
489 printf ("25:%016lx\n", regs->bank[9]);
490 printf ("26:%016lx ", regs->r[26]);
491 printf ("27:%016lx ", regs->r[27]);
492 printf ("26:%016lx ", regs->bank[10]);
493 printf ("27:%016lx\n", regs->bank[11]);
494 printf ("28:%016lx ", regs->r[28]);
495 printf ("29:%016lx ", regs->r[29]);
496 printf ("28:%016lx ", regs->bank[12]);
497 printf ("29:%016lx\n", regs->bank[13]);
498 printf ("30:%016lx ", regs->r[30]);
499 printf ("31:%016lx ", regs->r[31]);
500 printf ("30:%016lx ", regs->bank[14]);
501 printf ("31:%016lx\n", regs->bank[15]);
502 printf ("\n");
503 }
505 void print_cr (vcpu_guest_context_t *ctx)
506 {
507 struct vcpu_guest_context_regs *regs = &ctx->regs;
509 printf (" dcr: %016lx ", regs->cr.dcr);
510 printf (" itm: %016lx ", regs->cr.itm);
511 printf (" iva: %016lx\n", regs->cr.iva);
512 printf (" pta: %016lx ", regs->cr.pta);
513 printf (" ipsr: %016lx ", regs->cr.ipsr);
514 printf (" isr: %016lx\n", regs->cr.isr);
515 printf (" iip: %016lx ", regs->cr.iip);
516 printf (" ifa: %016lx ", regs->cr.ifa);
517 printf (" itir: %016lx\n", regs->cr.itir);
518 printf (" iipa: %016lx ", regs->cr.iipa);
519 printf (" ifs: %016lx ", regs->cr.ifs);
520 printf (" iim: %016lx\n", regs->cr.iim);
521 printf (" iha: %016lx ", regs->cr.iha);
522 printf (" lid: %016lx ", regs->cr.lid);
523 printf (" ivr: %016lx\n", regs->cr.ivr);
524 printf (" tpr: %016lx ", regs->cr.tpr);
525 printf (" eoi: %016lx ", regs->cr.eoi);
526 printf (" irr0: %016lx\n", regs->cr.irr[0]);
527 printf (" irr1: %016lx ", regs->cr.irr[1]);
528 printf (" irr2: %016lx ", regs->cr.irr[2]);
529 printf (" irr3: %016lx\n", regs->cr.irr[3]);
530 printf (" itv: %016lx ", regs->cr.itv);
531 printf (" pmv: %016lx ", regs->cr.pmv);
532 printf (" cmcv: %016lx\n", regs->cr.cmcv);
533 printf (" lrr0: %016lx ", regs->cr.lrr0);
534 printf (" lrr1: %016lx ", regs->cr.lrr1);
535 printf (" ev_cb:%016lx\n", ctx->event_callback_ip);
536 }
538 void print_ar (vcpu_guest_context_t *ctx)
539 {
540 struct vcpu_guest_context_regs *regs = &ctx->regs;
542 printf (" kr0: %016lx ", regs->ar.kr[0]);
543 printf (" kr1: %016lx ", regs->ar.kr[1]);
544 printf (" kr2: %016lx\n", regs->ar.kr[2]);
545 printf (" kr3: %016lx ", regs->ar.kr[3]);
546 printf (" kr4: %016lx ", regs->ar.kr[4]);
547 printf (" kr5: %016lx\n", regs->ar.kr[5]);
548 printf (" kr6: %016lx ", regs->ar.kr[6]);
549 printf (" kr7: %016lx ", regs->ar.kr[7]);
550 printf (" rsc: %016lx\n", regs->ar.rsc);
551 printf (" bsp: %016lx ", regs->ar.bsp);
552 printf (" bsps: %016lx ", regs->ar.bspstore);
553 printf (" rnat: %016lx\n", regs->ar.rnat);
554 printf (" csd: %016lx ", regs->ar.csd);
555 printf (" ccv: %016lx ", regs->ar.ccv);
556 printf (" unat: %016lx\n", regs->ar.unat);
557 printf (" fpsr: %016lx ", regs->ar.fpsr);
558 printf (" itc: %016lx\n", regs->ar.itc);
559 printf (" pfs: %016lx ", regs->ar.pfs);
560 printf (" lc: %016lx ", regs->ar.lc);
561 printf (" ec: %016lx\n", regs->ar.ec);
562 }
564 void print_a_rr (int num, unsigned long rr)
565 {
566 int ps_val = (rr >> RR_PS_SHIFT) & RR_PS_MASK;
568 printf (" [%d] %06lx %02x %s %ld\n",
569 num, (rr >> RR_RID_SHIFT) & RR_RID_MASK,
570 ps_val, get_ps (ps_val), rr & RR_VE_MASK);
571 }
573 void print_rr (vcpu_guest_context_t *ctx)
574 {
575 struct vcpu_guest_context_regs *regs = &ctx->regs;
576 int i;
578 printf (" rr: rid ps ve\n");
579 for (i = 0; i < 8; i++)
580 print_a_rr (i, regs->rr[i]);
581 }
583 void print_db (vcpu_guest_context_t *ctx)
584 {
585 struct vcpu_guest_context_regs *regs = &ctx->regs;
586 int i;
588 for (i = 0; i < 7; i += 2)
589 printf (" ibr[%d]: %016lx ibr[%d]: %016lx\n",
590 i, regs->ibr[i], i + 1, regs->ibr[i + 1]);
591 printf ("\n");
592 for (i = 0; i < 7; i += 2)
593 printf (" dbr[%d]: %016lx dbr[%d]: %016lx\n",
594 i, regs->dbr[i], i + 1, regs->dbr[i + 1]);
595 }
597 struct bit_descr {
598 const char *name;
599 unsigned char sz;
600 };
602 const struct bit_descr psr_bits[] =
603 {
604 {"", 1 }, {"be", 1 }, {"up", 1 }, {"ac", 1 },
605 {"mfl", 1 }, {"mfh", 1 }, {"", 7 },
606 {"ic", 1 }, {"i", 1 }, {"pk", 1 },
607 {"", 1 }, {"dt", 1 }, {"dfl", 1 }, {"dfh", 1 },
608 {"sp", 1 }, {"pp", 1 }, {"di", 1 }, {"si", 1 },
609 {"db", 1 }, {"lp", 1 }, {"tb", 1 }, {"rt", 1 },
610 {"", 4 },
611 {"cpl", 2 }, {"is", 1 }, {"mc", 1 },
612 {"it", 1 }, {"id", 1 }, {"da", 1 }, {"dd", 1 },
613 {"ss", 1 }, {"ri", 2 }, {"ed", 1 },
614 {"bn", 1 }, {"ia", 1 }, {"vm", 1 },
615 {NULL, 0 }
616 };
618 void print_bits (const struct bit_descr *desc, unsigned long val)
619 {
620 const struct bit_descr *d;
621 unsigned int off;
623 /* Reverse order. */
624 for (d = desc, off = 0; d->name; d++)
625 off += d->sz;
627 d--;
629 while (1) {
630 off -= d->sz;
631 if (*d->name) {
632 if (d->sz != 1 || ((val >> off) & 1))
633 printf (" %s", d->name);
634 if (d->sz != 1)
635 printf ("=%lx", (val >> off) & ((1 << d->sz) - 1));
636 }
637 if (d == desc)
638 break;
639 d--;
640 }
641 }
643 void print_tr (vcpu_guest_context_t *ctx)
644 {
645 struct vcpu_tr_regs *tr = &ctx->regs.tr;
646 int i;
648 printf ("\n itr: P rid va pa ps ed pl "
649 "ar a d ma key\n");
651 for (i = 0; i < sizeof (tr->itrs) / sizeof (tr->itrs[0]); i++)
652 print_a_tr (i, &tr->itrs[i]);
654 printf ("\n dtr: P rid va pa ps ed pl "
655 "ar a d ma key\n");
657 for (i = 0; i < sizeof (tr->dtrs) / sizeof (tr->dtrs[0]); i++)
658 print_a_tr (i, &tr->dtrs[i]);
659 }
661 int lock_pages (void *addr, size_t len);
662 void unlock_pages (void *addr, size_t len);
663 int do_xen_hypercall (int xc_handle, privcmd_hypercall_t *hypercall);
665 #ifdef HAVE_DEBUG_OP
666 static int do_ia64_debug_op (int xc_handle,
667 unsigned long cmd, unsigned long domain,
668 xen_ia64_debug_op_t *op)
669 {
670 int ret = -1;
671 privcmd_hypercall_t hypercall;
673 hypercall.op = __HYPERVISOR_ia64_debug_op;
674 hypercall.arg[0] = cmd;
675 hypercall.arg[1] = domain;
676 hypercall.arg[2] = (unsigned long)op;
678 if (lock_pages (op, sizeof (*op)) != 0) {
679 perror ("Could not lock memory for Xen hypercall");
680 goto out1;
681 }
683 ret = do_xen_hypercall (xc_handle, &hypercall);
684 if (ret < 0) {
685 if (errno == EACCES)
686 fprintf (stderr,"domctl operation failed -- need to "
687 "rebuild the user-space tool set?\n");
688 }
690 unlock_pages (op, sizeof (*op));
692 out1:
693 return ret;
694 }
695 #endif
697 static volatile int ctrl_c_hit;
699 void ctrl_c_handler (int sig)
700 {
701 ctrl_c_hit = 1;
702 }
704 int wait_domain (int vcpu, vcpu_guest_context_t *ctx)
705 {
706 struct timespec ts;
707 xc_dominfo_t dominfo;
708 int ret;
709 int cnt = 0;
711 ts.tv_sec = 0;
712 ts.tv_nsec = 10*1000*1000;
714 ret = xc_domain_unpause (xc_handle, domid);
715 if (ret < 0)
716 perror ("xc_domain_unpause");
718 ctrl_c_hit = 0;
720 while (1) {
721 ret = xc_domain_getinfo (xc_handle, domid, 1, &dominfo);
722 if (ret < 0)
723 perror ("xc_domain_getinfo");
725 if (dominfo.paused)
726 break;
728 if (ctrl_c_hit) {
729 fflush (stdout);
730 /* Force pause. */
731 ret = xc_domain_pause (xc_handle, domid);
732 if (ret < 0)
733 perror ("xc_domain_pause");
735 break;
736 }
738 printf ("%c\b", "/-\\|"[(cnt++) % 4]);
739 fflush (stdout);
740 nanosleep (&ts, NULL);
741 }
742 return xc_ia64_vcpu_getcontext (xc_handle, domid, vcpu, ctx);
743 }
745 int virt_to_phys (int is_inst, unsigned long vaddr, unsigned long *paddr)
746 {
747 struct vcpu_tr_regs *trs = &cur_ctx->regs.tr;
748 struct ia64_tr_entry *tr;
749 int i;
750 int num;
752 /* Search in tr. */
753 if (is_inst) {
754 tr = trs->itrs;
755 num = sizeof (trs->itrs) / sizeof (trs->itrs[0]);
756 }
757 else {
758 tr = trs->dtrs;
759 num = sizeof (trs->dtrs) / sizeof (trs->dtrs[0]);
760 }
761 for (i = 0; i < num; i++, tr++) {
762 int ps_val = (tr->itir >> ITIR_PS_SHIFT) & ITIR_PS_MASK;
763 unsigned long ps_mask = (-1L) << ps_val;
765 if ((tr->vadr & ps_mask) == (vaddr & ps_mask)) {
766 *paddr = ((tr->pte & (PTE_PPN_MASK << PTE_PPN_SHIFT)) & ps_mask) |
767 (vaddr & ~ps_mask);
768 return 0;
769 }
770 }
771 return -1;
772 }
774 unsigned long *
775 get_reg_addr (const char *name)
776 {
777 if (strcmp (name, "ip") == 0)
778 return &cur_ctx->regs.ip;
779 else if (strcmp (name, "psr") == 0)
780 return &cur_ctx->regs.psr;
781 else if (strcmp (name, "iip") == 0)
782 return &cur_ctx->regs.cr.iip;
783 else if (strcmp (name, "b0") == 0)
784 return &cur_ctx->regs.b[0];
785 else
786 return 0;
787 }
789 enum prio_expr {EXPR_BASE, EXPR_SUM, EXPR_LOGIC, EXPR_PROD};
791 int parse_expr (char **buf, unsigned long *res, enum prio_expr prio);
793 int next_char (char **buf)
794 {
795 char *b;
797 b = *buf;
798 while (isspace ((unsigned char)*b))
799 b++;
800 *buf = b;
801 return *b;
802 }
804 int parse_unary (char **buf, unsigned long *res)
805 {
806 char c;
808 c = next_char (buf);
809 switch (c) {
810 case '0' ... '9':
811 {
812 char *e;
813 *res = strtoul (*buf, &e, 0);
814 if (e == *buf) {
815 printf ("bad literal\n");
816 return -1;
817 }
818 *buf = e;
819 }
820 break;
821 case '+':
822 (*buf)++;
823 return parse_unary (buf, res);
824 case '$':
825 {
826 char *b;
827 char *e;
828 char c;
829 unsigned long *reg;
830 int len;
832 b = *buf;
833 e = b + 1;
835 while ((*e >= 'a' && *e <= 'z') ||
836 (*e >= 'A' && *e <= 'Z') ||
837 (*e >= '0' && *e <= '9') ||
838 (*e == '_' || *e == '.'))
839 e++;
841 if (b == e) {
842 printf ("identifier missing after '$'\n");
843 return -1;
844 }
846 b++;
847 len = e - b;
849 c = b[len];
850 b[len] = 0;
851 reg = get_reg_addr (b);
852 b[len] = c;
854 if (reg != NULL)
855 *res = *reg;
856 else if (strncmp (b, "d2p", len) == 0 ||
857 strncmp (b, "i2p", len) == 0) {
858 unsigned long vaddr;
860 *buf = e;
861 if (parse_unary (buf, &vaddr) != 0)
862 return -1;
863 if (virt_to_phys (*b == 'i', vaddr, res) != 0) {
864 printf ("cannot find vaddr %016lx in tr\n", vaddr);
865 return -1;
866 }
867 return 0;
868 }
869 else {
870 printf ("unknown symbol\n");
871 return -1;
872 }
873 *buf = e;
874 }
875 break;
876 case '(':
877 (*buf)++;
878 if (parse_expr (buf, res, EXPR_BASE) != 0)
879 return -1;
881 if (next_char (buf) != ')') {
882 printf ("missing ')'\n");
883 return -1;
884 }
885 else
886 (*buf)++;
887 break;
888 default:
889 printf ("unknown operand '%c' in expression\n", c);
890 return -1;
891 }
893 return 0;
894 }
896 int parse_expr (char **buf, unsigned long *res, enum prio_expr prio)
897 {
898 unsigned long val = 0;
899 unsigned long val1;
900 char c;
902 if (parse_unary (buf, &val) != 0)
903 return -1;
905 while (1) {
906 c = next_char (buf);
907 switch (c) {
908 case '+':
909 case '-':
910 if (prio > EXPR_SUM)
911 return 0;
912 (*buf)++;
913 if (parse_expr (buf, &val1, EXPR_SUM) < 0)
914 return -1;
915 if (c == '+')
916 val += val1;
917 else
918 val -= val1;
919 break;
920 case '*':
921 if (prio > EXPR_PROD)
922 return 0;
924 (*buf)++;
925 if (parse_expr (buf, &val1, EXPR_SUM) < 0)
926 return -1;
928 val *= val1;
929 break;
930 default:
931 *res = val;
932 return 0;
933 }
934 }
935 }
937 char *parse_arg (char **buf)
938 {
939 char *res;
940 char *b = *buf;
942 /* Eat leading spaces. */
943 while (isspace ((unsigned char)*b))
944 b++;
946 res = b;
947 while (*b && !isspace ((unsigned char)*b))
948 b++;
950 /* Set the NUL terminator. */
951 if (*b)
952 *b++ = 0;
954 *buf = b;
955 return res;
956 }
958 vcpu_guest_context_any_t *vcpu_ctx_any;
960 int vcpu_setcontext (int vcpu)
961 {
962 int ret;
964 ret = xc_vcpu_setcontext (xc_handle, domid, vcpu, &vcpu_ctx_any[vcpu]);
965 if (ret < 0)
966 perror ("xc_vcpu_setcontext");
968 return ret;
969 }
971 enum cmd_status { CMD_ERROR, CMD_OK, CMD_REPEAT, CMD_QUIT };
973 struct command_desc
974 {
975 const char *name;
976 const char *help;
977 enum cmd_status (*cmd)(char *line);
978 };
980 static enum cmd_status
981 cmd_registers (char *line)
982 {
983 print_ctx (cur_ctx);
984 return CMD_OK;
985 }
987 static enum cmd_status
988 cmd_sstep (char *line)
989 {
990 /* Set psr.dd and psr.id to skip over current breakpoint. */
991 cur_ctx->regs.psr |= PSR_SS | PSR_DD | PSR_ID;
992 cur_ctx->regs.psr &= ~PSR_TB;
993 if (vcpu_setcontext (cur_vcpu) < 0)
994 return CMD_ERROR;
996 if (wait_domain (cur_vcpu, cur_ctx) < 0) {
997 perror ("wait_domain");
998 return CMD_ERROR;
999 }
1001 print_ctx (cur_ctx);
1003 return CMD_REPEAT;
1006 static enum cmd_status
1007 cmd_go (char *line)
1009 unsigned long n = 1;
1011 if (*line != 0) {
1012 if (parse_expr (&line, &n, 0) < 0)
1013 return CMD_ERROR;
1015 while (n > 0) {
1016 /* Set psr.dd and psr.id to skip over current breakpoint. */
1017 if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB | PSR_DB)) != 0) {
1018 cur_ctx->regs.psr &= ~(PSR_SS | PSR_TB);
1019 cur_ctx->regs.psr |= PSR_DD | PSR_ID;
1020 if (vcpu_setcontext (cur_vcpu) < 0)
1021 return CMD_ERROR;
1024 if (wait_domain (cur_vcpu, cur_ctx) < 0) {
1025 perror ("wait_domain");
1026 return CMD_ERROR;
1028 print_ctx (cur_ctx);
1029 n--;
1032 return CMD_REPEAT;
1035 static enum cmd_status
1036 cmd_cb (char *line)
1038 if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB)) != PSR_TB) {
1039 cur_ctx->regs.psr &= ~PSR_SS;
1040 cur_ctx->regs.psr |= PSR_TB;
1041 if (vcpu_setcontext (cur_vcpu) < 0)
1042 return CMD_ERROR;
1045 if (wait_domain (cur_vcpu, cur_ctx) < 0) {
1046 perror ("wait_domain");
1047 return CMD_ERROR;
1050 print_ctx (cur_ctx);
1052 return CMD_REPEAT;
1055 static int quit_paused;
1057 static enum cmd_status
1058 cmd_quit (char *line)
1060 if (!strcmp (line, "paused"))
1061 quit_paused = 1;
1062 return CMD_QUIT;
1065 static enum cmd_status
1066 cmd_echo (char *line)
1068 printf ("%s", line);
1069 return CMD_OK;
1072 static enum cmd_status
1073 cmd_disassemble (char *args)
1075 static unsigned long addr;
1076 unsigned long end_addr = addr + 16;
1078 if (*args != 0) {
1079 if (parse_expr (&args, &addr, 0) < 0)
1080 return CMD_ERROR;
1081 if (*args != 0) {
1082 if (parse_expr (&args, &end_addr, 0) < 0)
1083 return CMD_ERROR;
1085 else
1086 end_addr = addr + 16;
1088 target_disas (stdout, addr, end_addr - addr);
1089 addr = end_addr;
1090 return CMD_REPEAT;
1093 static enum cmd_status
1094 cmd_dump (char *args)
1096 static unsigned long addr;
1097 unsigned long end_addr = addr + 256;
1098 unsigned long p;
1100 if (*args != 0) {
1101 if (parse_expr (&args, &addr, 0) < 0)
1102 return CMD_ERROR;
1103 if (*args != 0) {
1104 if (parse_expr (&args, &end_addr, 0) < 0)
1105 return CMD_ERROR;
1107 else
1108 end_addr = addr + 256;
1110 for (p = addr; p < end_addr; p += 16) {
1111 int i;
1112 printf ("%016lx:", p);
1113 for (i = 0; i < 16; i++) {
1114 unsigned char *m = target_map_memory (p + i);
1115 printf ("%c%02x", i == 8 ? '-' : ' ', *m);
1117 printf ("\n");
1119 addr = end_addr;
1120 return CMD_REPEAT;
1123 static enum cmd_status
1124 cmd_break (char *args)
1126 unsigned long addr;
1127 int i;
1129 for (i = 0; i < 4; i++)
1130 if (cur_ctx->regs.ibr[2 * i] == 0 && cur_ctx->regs.ibr[2 * i + 1] == 0)
1131 break;
1133 if (i == 4) {
1134 printf ("no availabe break points\n");
1135 return CMD_ERROR;
1138 if (parse_expr (&args, &addr, 0) < 0)
1139 return CMD_ERROR;
1141 cur_ctx->regs.ibr[2 * i] = addr;
1142 cur_ctx->regs.ibr[2 * i + 1] = 0x87fffffffffffff0UL;
1143 cur_ctx->regs.psr |= PSR_DB;
1145 if (vcpu_setcontext (cur_vcpu) < 0)
1146 return CMD_ERROR;
1147 else
1148 return CMD_OK;
1151 static enum cmd_status
1152 cmd_watch (char *args)
1154 unsigned long addr;
1155 unsigned long mask;
1156 int i;
1158 for (i = 0; i < 4; i++)
1159 if (cur_ctx->regs.dbr[2 * i] == 0 && cur_ctx->regs.dbr[2 * i + 1] == 0)
1160 break;
1162 if (i == 4) {
1163 printf ("no availabe watch points\n");
1164 return CMD_ERROR;
1167 if (parse_expr (&args, &addr, 0) < 0)
1168 return CMD_ERROR;
1170 if (*args == 0)
1171 mask = 3;
1172 else if (parse_expr (&args, &mask, 0) < 0)
1173 return CMD_ERROR;
1175 cur_ctx->regs.dbr[2 * i] = addr;
1176 cur_ctx->regs.dbr[2 * i + 1] = ~((1UL << mask) - 1) | (0xc7UL << 56);
1177 cur_ctx->regs.psr |= PSR_DB;
1179 if (vcpu_setcontext (cur_vcpu) < 0)
1180 return CMD_ERROR;
1181 else {
1182 printf ("Watchpoint %d set\n", i);
1183 return CMD_OK;
1187 static enum cmd_status
1188 cmd_delete (char *args)
1190 unsigned long num;
1192 if (parse_expr (&args, &num, 0) < 0)
1193 return CMD_ERROR;
1195 if (num < 4) {
1196 cur_ctx->regs.ibr[2 * num] = 0;
1197 cur_ctx->regs.ibr[2 * num + 1] = 0;
1199 else if (num < 8) {
1200 num -= 4;
1201 cur_ctx->regs.dbr[2 * num] = 0;
1202 cur_ctx->regs.dbr[2 * num + 1] = 0;
1204 else {
1205 printf ("breakpoint out of range\n");
1206 return CMD_ERROR;
1209 cur_ctx->regs.psr |= PSR_DB;
1211 if (vcpu_setcontext (cur_vcpu) < 0)
1212 return CMD_ERROR;
1213 else
1214 return CMD_OK;
1217 static enum cmd_status
1218 cmd_disable (char *args)
1220 unsigned long num;
1222 if (parse_expr (&args, &num, 0) < 0)
1223 return CMD_ERROR;
1225 if (num >= 4) {
1226 printf ("breakpoint out of range\n");
1227 return CMD_ERROR;
1230 cur_ctx->regs.ibr[2 * num + 1] &= ~(1UL << 63);
1232 if (vcpu_setcontext (cur_vcpu) < 0)
1233 return CMD_ERROR;
1234 else
1235 return CMD_OK;
1238 static enum cmd_status
1239 cmd_enable (char *args)
1241 unsigned long num;
1243 if (parse_expr (&args, &num, 0) < 0)
1244 return CMD_ERROR;
1246 if (num >= 4) {
1247 printf ("breakpoint out of range\n");
1248 return CMD_ERROR;
1251 cur_ctx->regs.ibr[2 * num + 1] |= 1UL << 63;
1253 if (vcpu_setcontext (cur_vcpu) < 0)
1254 return CMD_ERROR;
1255 else
1256 return CMD_OK;
1259 static enum cmd_status
1260 cmd_print (char *args)
1262 unsigned long addr;
1264 if (parse_expr (&args, &addr, 0) < 0)
1265 return CMD_ERROR;
1267 printf ("res: 0x%016lx = %ld\n", addr, addr);
1269 return CMD_OK;
1272 struct bit_xlat {
1273 unsigned int bit;
1274 const char *name;
1275 };
1277 static const struct bit_xlat debug_flags[] = {
1278 { XEN_IA64_DEBUG_ON_KERN_SSTEP, "sstep" },
1279 { XEN_IA64_DEBUG_ON_KERN_DEBUG, "debug" },
1280 { XEN_IA64_DEBUG_ON_KERN_TBRANCH, "tbranch" },
1281 { XEN_IA64_DEBUG_ON_EXTINT, "extint" },
1282 { XEN_IA64_DEBUG_ON_EXCEPT, "except" },
1283 { XEN_IA64_DEBUG_ON_EVENT, "event" },
1284 { XEN_IA64_DEBUG_ON_PRIVOP, "privop" },
1285 { XEN_IA64_DEBUG_ON_PAL, "pal" },
1286 { XEN_IA64_DEBUG_ON_SAL, "sal" },
1287 { XEN_IA64_DEBUG_ON_EFI, "efi" },
1288 { XEN_IA64_DEBUG_ON_RFI, "rfi" },
1289 { XEN_IA64_DEBUG_ON_MMU, "mmu" },
1290 { XEN_IA64_DEBUG_ON_BAD_MPA, "mpa" },
1291 { XEN_IA64_DEBUG_FORCE_SS, "ss" },
1292 { XEN_IA64_DEBUG_FORCE_DB, "db" },
1293 { XEN_IA64_DEBUG_ON_TR, "tr" },
1294 { XEN_IA64_DEBUG_ON_TC, "tc" },
1295 #if 0
1296 { XEN_IA64_DEBUG_ON_KEYS, "keys" },
1297 { XEN_IA64_DEBUG_ON_MOV_TO_CR, "mov_to_cr" },
1298 { XEN_IA64_DEBUG_ON_VHPT, "vhpt" },
1299 { XEN_IA64_DEBUG_ON_IOSAPIC, "iosapic" },
1300 #endif
1301 { 0, NULL }
1302 };
1304 static enum cmd_status
1305 cmd_disp (char *arg)
1307 if (strcmp (arg, "br") == 0)
1308 print_br (cur_ctx);
1309 else if (strcmp (arg, "regs") == 0)
1310 print_regs (cur_ctx);
1311 else if (strcmp (arg, "cr") == 0)
1312 print_cr (cur_ctx);
1313 else if (strcmp (arg, "ar") == 0)
1314 print_ar (cur_ctx);
1315 else if (strcmp (arg, "tr") == 0)
1316 print_tr (cur_ctx);
1317 else if (strcmp (arg, "rr") == 0)
1318 print_rr (cur_ctx);
1319 else if (strcmp (arg, "db") == 0)
1320 print_db (cur_ctx);
1321 else if (strcmp (arg, "psr") == 0) {
1322 printf ("psr:");
1323 print_bits (psr_bits, cur_ctx->regs.psr);
1324 printf ("\n");
1326 else if (strcmp (arg, "ipsr") == 0) {
1327 printf ("ipsr:");
1328 print_bits (psr_bits, cur_ctx->regs.cr.ipsr);
1329 printf ("\n");
1331 else if (strcmp (arg, "break") == 0) {
1332 int i;
1334 for (i = 0; i < 4; i++)
1335 if (cur_ctx->regs.ibr[2 * i + 1])
1336 printf ("%d: 0x%016lx %s\n", i, cur_ctx->regs.ibr[2 * i],
1337 (cur_ctx->regs.ibr[2 * i + 1] & (1UL << 63)) ?
1338 "enabled" : "disabled");
1339 for (i = 0; i < 4; i++)
1340 if (cur_ctx->regs.dbr[2 * i + 1])
1341 printf ("%d: 0x%016lx %s\n", i, cur_ctx->regs.dbr[2 * i],
1342 (cur_ctx->regs.dbr[2 * i + 1] & (1UL << 63)) ?
1343 "enabled" : "disabled");
1345 else if (strcmp (arg, "domain") == 0) {
1346 xc_dominfo_t dominfo;
1347 #ifdef HAVE_DEBUG_OP
1348 xen_ia64_debug_op_t debug_op;
1349 int i;
1350 #endif
1351 if (xc_domain_getinfo (xc_handle, domid, 1, &dominfo) < 0) {
1352 perror ("xc_domain_getinfo");
1353 return 0;
1356 printf ("id=%d nr_pages=%lu shared_info_frame=%lu max_mem=%luKB\n",
1357 dominfo.domid, dominfo.nr_pages, dominfo.shared_info_frame,
1358 dominfo.max_memkb);
1359 printf (" nr_online_vcpu=%u max_vcpu_id=%u\n",
1360 dominfo.nr_online_vcpus, dominfo.max_vcpu_id);
1361 printf (" status:");
1362 if (dominfo.dying)
1363 printf (" dying");
1364 if (dominfo.crashed)
1365 printf (" crashed");
1366 if (dominfo.shutdown)
1367 printf (" shutdown(%u)", dominfo.shutdown_reason);
1368 if (dominfo.paused)
1369 printf (" paused");
1370 if (dominfo.blocked)
1371 printf (" blocked");
1372 if (dominfo.running)
1373 printf (" running");
1374 if (dominfo.hvm)
1375 printf (" hvm");
1376 if (dominfo.debugged)
1377 printf (" debug");
1378 printf ("\n");
1380 #ifdef HAVE_DEBUG_OP
1381 if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_GET_FLAGS,
1382 domid, &debug_op) < 0) {
1383 perror ("xc_domain_getinfo");
1384 return 0;
1386 printf ("debug flags: %08lx: ", debug_op.flags);
1387 for (i = 0; debug_flags[i].name; i++)
1388 if (debug_flags[i].bit & debug_op.flags)
1389 printf (" %s", debug_flags[i].name);
1390 printf ("\n");
1391 #endif
1393 else if (*arg == 0)
1394 printf ("choose among br, regs, cr, ar, tr, rr, db\n");
1395 else {
1396 printf ("cannot disp '%s'\n", arg);
1397 return CMD_ERROR;
1399 return CMD_OK;
1402 static enum cmd_status
1403 cmd_bev (char *arg)
1405 xen_ia64_debug_op_t debug_op;
1406 int i;
1408 if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_GET_FLAGS,
1409 domid, &debug_op) < 0) {
1410 perror ("get debug flags");
1411 return CMD_ERROR;
1413 if (arg == NULL || arg[0] == 0) {
1414 printf ("debug flags: %08lx:\n", debug_op.flags);
1415 for (i = 0; debug_flags[i].name; i++)
1416 printf (" %c%s\n",
1417 (debug_flags[i].bit & debug_op.flags) ? '+' : '-',
1418 debug_flags[i].name);
1419 return CMD_OK;
1421 else {
1422 char *p = strtok ((char *)arg, " ");
1424 while (p != NULL) {
1425 unsigned int flag = 0;
1427 for (i = 0; debug_flags[i].name; i++)
1428 if (strcmp (p, debug_flags[i].name) == 0
1429 || ((p[0] == '-' || p[0] == '+')
1430 && strcmp (p + 1, debug_flags[i].name) == 0)) {
1431 flag = debug_flags[i].bit;
1432 break;
1434 if (flag == 0) {
1435 printf ("unknown event %s\n", p);
1436 return CMD_ERROR;
1438 if (p[0] == '-')
1439 debug_op.flags &= ~flag;
1440 else
1441 debug_op.flags |= flag;
1443 p = strtok (NULL, " ");
1445 if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_SET_FLAGS,
1446 domid, &debug_op) < 0) {
1447 perror ("set debug flags");
1448 return CMD_ERROR;
1450 /* Disabling force_SS and force_DB requires setting psr. */
1451 if (vcpu_setcontext (cur_vcpu) < 0)
1452 return CMD_ERROR;
1453 else
1454 return CMD_OK;
1458 static enum cmd_status
1459 cmd_set (char *line)
1461 char *reg;
1462 unsigned long *addr;
1463 unsigned long val;
1465 reg = parse_arg (&line);
1467 addr = get_reg_addr (reg);
1468 if (addr == NULL) {
1469 printf ("unknown register %s\n", reg);
1470 return CMD_ERROR;
1473 if (parse_expr (&line, &val, 0) < 0)
1474 return CMD_ERROR;
1476 *addr = val;
1478 if (vcpu_setcontext (cur_vcpu) < 0)
1479 return CMD_ERROR;
1480 else
1481 return CMD_OK;
1484 const struct command_desc commands[];
1486 static enum cmd_status
1487 cmd_help (char *line)
1489 int i;
1491 for (i = 0; commands[i].name; i++)
1492 printf ("%s -- %s\n", commands[i].name, commands[i].help);
1494 return CMD_OK;
1497 const struct command_desc commands[] = {
1498 { "registers", "display current registers", cmd_registers },
1499 { "sstep", "single step", cmd_sstep },
1500 { "go", "resume execution", cmd_go },
1501 { "quit", "quit debugger", cmd_quit },
1502 { "echo", "display parameters", cmd_echo },
1503 { "disassemble", "disassemble memory", cmd_disassemble },
1504 { "dump", "dump memory", cmd_dump },
1505 { "break", "set a break point", cmd_break },
1506 { "watch", "set a watch point", cmd_watch },
1507 { "cb", "resume until branch", cmd_cb },
1508 { "delete", "delete a break point", cmd_delete },
1509 { "disable", "disable a break point", cmd_disable },
1510 { "enable", "enable a break point", cmd_enable },
1511 { "print", "print an expression", cmd_print },
1512 { "disp", "disp br/regs/cr/ar/tr/rr/db/psr/break/domain", cmd_disp},
1513 { "bev", "break on event", cmd_bev},
1514 { "set", "set reg val", cmd_set},
1515 { "help", "disp help", cmd_help },
1516 { NULL, NULL, NULL }
1517 };
1520 enum cmd_status do_command (int vcpu, char *line)
1522 char *cmd;
1523 char *args;
1524 int i;
1525 const struct command_desc *desc;
1526 static const struct command_desc *last_desc;
1527 enum cmd_status status;
1528 int flag_ambiguous;
1530 cur_vcpu = vcpu;
1531 cur_ctx = &vcpu_ctx_any[vcpu].c;
1533 /* Handle repeat last-command. */
1534 if (*line == 0) {
1535 if (last_desc != NULL)
1536 return (*last_desc->cmd)("");
1537 else
1538 return CMD_OK;
1540 last_desc = NULL;
1542 cmd = parse_arg (&line);
1543 args = line;
1545 desc = NULL;
1546 flag_ambiguous = 0;
1548 for (i = 0; commands[i].name; i++) {
1549 const char *n = commands[i].name;
1550 char *c = cmd;
1552 while (*n == *c && *n)
1553 n++, c++;
1555 if (*c == 0) {
1556 /* Match. */
1557 if (desc != NULL) {
1558 if (!flag_ambiguous)
1559 printf ("ambiguous command: %s", desc->name);
1560 printf (", %s", commands[i].name);
1561 flag_ambiguous = 1;
1563 else
1564 desc = &commands[i];
1568 if (flag_ambiguous) {
1569 printf ("\n");
1570 return CMD_ERROR;
1572 else if (!desc) {
1573 printf ("command not found, try help\n");
1574 return CMD_ERROR;
1577 status = (*desc->cmd)(args);
1578 if (status == CMD_REPEAT)
1579 last_desc = desc;
1580 return status;
1583 void xenitp (int vcpu)
1585 int ret;
1586 struct sigaction sa;
1587 xc_dominfo_t dominfo;
1589 xc_handle = xc_interface_open (); /* for accessing control interface */
1591 ret = xc_domain_getinfo (xc_handle, domid, 1, &dominfo);
1592 if (ret < 0) {
1593 perror ("xc_domain_getinfo");
1594 exit (-1);
1597 vcpu_ctx_any = calloc (sizeof(vcpu_ctx_any), dominfo.max_vcpu_id + 1);
1598 if (!vcpu_ctx_any) {
1599 perror ("vcpu context array alloc");
1600 exit (-1);
1602 cur_ctx = &vcpu_ctx_any[vcpu].c;
1604 if (xc_domain_setdebugging (xc_handle, domid, 1) != 0)
1605 perror ("setdebugging");
1607 ret = xc_domain_pause (xc_handle, domid);
1608 if (ret < 0) {
1609 perror ("xc_domain_pause");
1610 exit (-1);
1613 ret = xc_ia64_vcpu_getcontext (xc_handle, domid, vcpu, cur_ctx);
1614 if (ret < 0) {
1615 perror ("xc_ia64_vcpu_getcontext");
1616 exit (-1);
1619 print_ctx (cur_ctx);
1621 /* Catch ctrl-c. */
1622 sa.sa_handler = &ctrl_c_handler;
1623 sa.sa_flags = 0;
1624 sigemptyset (&sa.sa_mask);
1625 if (sigaction (SIGINT, &sa, NULL) != 0)
1626 perror ("sigaction");
1628 while (1) {
1629 char buf[128];
1630 int len;
1632 printf ("XenITP> ");
1633 fflush (stdout);
1635 if (fgets (buf, sizeof (buf), stdin) == NULL)
1636 break;
1638 len = strlen ((char *)buf);
1639 if (len >= 1 && buf[len - 1] == '\n')
1640 buf[len - 1] = 0;
1642 ret = do_command (vcpu, buf);
1643 if (ret == CMD_QUIT)
1644 break;
1647 /* Clear debug bits. */
1648 if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB | PSR_DB)) != 0) {
1649 cur_ctx->regs.psr &= ~(PSR_SS | PSR_TB | PSR_DB);
1650 cur_ctx->regs.psr |= PSR_DD | PSR_ID;
1651 vcpu_setcontext (cur_vcpu);
1654 /* Disable debugging. */
1655 if (xc_domain_setdebugging (xc_handle, domid, 0) != 0)
1656 perror ("setdebugging");
1658 if (!quit_paused) {
1659 ret = xc_domain_unpause (xc_handle, domid);
1660 if (ret < 0) {
1661 perror ("xc_domain_unpause");
1662 exit (-1);
1666 xc_interface_close (xc_handle);
1667 if (ret < 0) {
1668 perror ("xc_interface_close");
1669 exit (-1);
1673 static void usage (void)
1675 printf ("usage:\n");
1676 printf (" xenitp <DOMAIN> [VCPU]\n");
1680 int main (int argc, char **argv)
1682 int ch;
1683 static const char *sopts = "h"
1685 static const struct option lopts[] = {
1686 {"help", 0, NULL, 'h'},
1687 {0, 0, 0, 0}
1688 };
1689 int vcpu = 0;
1691 while ((ch = getopt_long (argc, argv, sopts, lopts, NULL)) != -1) {
1692 switch (ch) {
1693 case 'h':
1694 usage ();
1695 exit (-1);
1696 case '?':
1697 fprintf (stderr, "%s --help for more options\n", argv[0]);
1698 exit (-1);
1702 argv += optind;
1703 argc -= optind;
1705 if (argc < 1 || argc > 2) {
1706 usage ();
1707 exit (-1);
1710 domid = atoi (argv[0]);
1711 if (domid == 0) {
1712 fprintf (stderr, "cannot trace dom0\n");
1713 exit (-1);
1716 if (argc == 2)
1717 vcpu = atoi (argv[1]);
1719 xenitp (vcpu);
1721 return 0;
1724 /*
1725 * Local variables:
1726 * mode: C
1727 * c-set-style: "BSD"
1728 * c-basic-offset: 4
1729 * tab-width: 4
1730 * indent-tabs-mode: nil
1731 * End:
1732 */