aboutsummaryrefslogtreecommitdiffstats
path: root/tools/debugger/xenitp/xenitp.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/debugger/xenitp/xenitp.c')
-rw-r--r--tools/debugger/xenitp/xenitp.c1599
1 files changed, 1599 insertions, 0 deletions
diff --git a/tools/debugger/xenitp/xenitp.c b/tools/debugger/xenitp/xenitp.c
new file mode 100644
index 0000000000..2c9f5cd6f2
--- /dev/null
+++ b/tools/debugger/xenitp/xenitp.c
@@ -0,0 +1,1599 @@
+/* tools/debugger/xenitp.c - A low-level debugger.
+
+ Based on xenctxt.c, but heavily modified.
+ Copyright 2007 Tristan Gingold <tgingold@free.fr>
+
+ Xenitp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ Xenitp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <time.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <argp.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "xenctrl.h"
+#include <xen/sys/privcmd.h>
+#include "dis-asm.h"
+
+#ifdef __HYPERVISOR_ia64_debug_op
+#define HAVE_DEBUG_OP
+#endif
+
+static int xc_handle = 0;
+static int domid = 0;
+static vcpu_guest_context_t *cur_ctx;
+static int cur_vcpu;
+
+#define PSR_BN (1UL << 44)
+#define PSR_SS (1UL << 40)
+#define PSR_DB (1UL << 24)
+#define PSR_TB (1UL << 26)
+#define PSR_DD (1UL << 39)
+#define PSR_ID (1UL << 37)
+#define PSR_IT (1UL << 36)
+#define PSR_DT (1UL << 17)
+#define PSR_RI_SHIFT 41
+#define CFM_SOF_MASK 0x3f
+
+int virt_to_phys (int is_inst, unsigned long vaddr, unsigned long *paddr);
+
+inline unsigned int ctx_slot (vcpu_guest_context_t *ctx)
+{
+ return (ctx->regs.psr >> PSR_RI_SHIFT) & 3;
+}
+
+unsigned char *
+target_map_memory (unsigned long paddr)
+{
+ static unsigned long cur_page = -1;
+ static unsigned char *cur_map = NULL;
+
+ if ((paddr >> XC_PAGE_SHIFT) != cur_page) {
+ if (cur_map) {
+ munmap (cur_map, XC_PAGE_SIZE);
+ cur_map = NULL;
+ }
+ cur_page = paddr >> XC_PAGE_SHIFT;
+ cur_map = xc_map_foreign_range (xc_handle, domid, XC_PAGE_SIZE,
+ PROT_READ, cur_page);
+ if (cur_map == NULL) {
+ perror ("cannot map page");
+ cur_page = -1;
+ return NULL;
+ }
+ }
+ return cur_map + (paddr & (XC_PAGE_SIZE - 1));
+}
+
+/* Get LENGTH bytes from info's buffer, at target address memaddr.
+ Transfer them to myaddr. */
+int
+target_read_memory (bfd_vma memaddr, bfd_byte *myaddr,
+ unsigned int length, struct disassemble_info *info)
+{
+ int i;
+ unsigned long paddr;
+
+ if (cur_ctx->regs.psr & PSR_IT) {
+ if (virt_to_phys (1, memaddr, &paddr) != 0)
+ return EIO;
+ }
+ else {
+ /* Clear UC. */
+ paddr = memaddr & ~(1UL << 63);
+ }
+
+ for (i = 0; i < length; i++) {
+ unsigned char *p = target_map_memory (paddr + i);
+
+ if (p == NULL)
+ return EIO;
+ myaddr[i] = *p;
+ }
+ return 0;
+}
+
+/* Print an error message. We can assume that this is in response to
+ an error return from buffer_read_memory. */
+void
+perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
+{
+ if (status != EIO)
+ /* Can't happen. */
+ (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
+ else
+ /* Actually, address between memaddr and memaddr + len was
+ out of bounds. */
+ (*info->fprintf_func) (info->stream,
+ "Address 0x%" PRIx64 " is out of bounds.\n",
+ memaddr);
+}
+
+/* This could be in a separate file, to save miniscule amounts of space
+ in statically linked executables. */
+
+/* Just print the address is hex. This is included for completeness even
+ though both GDB and objdump provide their own (to print symbolic
+ addresses). */
+
+void
+generic_print_address (bfd_vma addr, struct disassemble_info *info)
+{
+ (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
+}
+
+/* Just return the given address. */
+
+int
+generic_symbol_at_address (bfd_vma addr, struct disassemble_info * info)
+{
+ return 1;
+}
+
+bfd_boolean
+generic_symbol_is_valid (asymbol * sym ATTRIBUTE_UNUSED,
+ struct disassemble_info *info ATTRIBUTE_UNUSED)
+{
+ return 1;
+}
+
+bfd_vma bfd_getl32 (const bfd_byte *addr)
+{
+ unsigned long v;
+
+ v = (unsigned long) addr[0];
+ v |= (unsigned long) addr[1] << 8;
+ v |= (unsigned long) addr[2] << 16;
+ v |= (unsigned long) addr[3] << 24;
+
+ return (bfd_vma) v;
+}
+
+bfd_vma bfd_getl64 (const bfd_byte *addr)
+{
+ unsigned long v;
+
+ v = (unsigned long) addr[0];
+ v |= (unsigned long) addr[1] << 8;
+ v |= (unsigned long) addr[2] << 16;
+ v |= (unsigned long) addr[3] << 24;
+ v |= (unsigned long) addr[4] << 32;
+ v |= (unsigned long) addr[5] << 40;
+ v |= (unsigned long) addr[6] << 48;
+ v |= (unsigned long) addr[7] << 56;
+
+ return (bfd_vma) v;
+}
+
+bfd_vma bfd_getb32 (const bfd_byte *addr)
+{
+ unsigned long v;
+
+ v = (unsigned long) addr[0] << 24;
+ v |= (unsigned long) addr[1] << 16;
+ v |= (unsigned long) addr[2] << 8;
+ v |= (unsigned long) addr[3];
+
+ return (bfd_vma) v;
+}
+
+bfd_vma bfd_getl16 (const bfd_byte *addr)
+{
+ unsigned long v;
+
+ v = (unsigned long) addr[0];
+ v |= (unsigned long) addr[1] << 8;
+
+ return (bfd_vma) v;
+}
+
+bfd_vma bfd_getb16 (const bfd_byte *addr)
+{
+ unsigned long v;
+
+ v = (unsigned long) addr[0] << 24;
+ v |= (unsigned long) addr[1] << 16;
+
+ return (bfd_vma) v;
+}
+
+void
+init_disassemble_info (struct disassemble_info *info, void *stream,
+ fprintf_ftype fprintf_func)
+{
+ memset (info, 0, sizeof (*info));
+
+ info->flavour = bfd_target_unknown_flavour;
+ info->arch = bfd_arch_unknown;
+ info->endian = BFD_ENDIAN_UNKNOWN;
+ info->octets_per_byte = 1;
+ info->fprintf_func = fprintf_func;
+ info->stream = stream;
+ info->read_memory_func = target_read_memory;
+ info->memory_error_func = perror_memory;
+ info->print_address_func = generic_print_address;
+ info->symbol_at_address_func = generic_symbol_at_address;
+ info->symbol_is_valid = generic_symbol_is_valid;
+ info->display_endian = BFD_ENDIAN_UNKNOWN;
+}
+
+
+void target_disas (FILE *out, unsigned long code, unsigned long size)
+{
+ unsigned long pc;
+ int count;
+ struct disassemble_info disasm_info;
+ int slot;
+ int (*print_insn)(bfd_vma pc, disassemble_info *info);
+
+ INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
+
+ disasm_info.read_memory_func = target_read_memory;
+#if 0
+ disasm_info.buffer = NULL;
+ disasm_info.buffer_vma = (unsigned long)code;
+ disasm_info.buffer_length = size;
+#endif
+
+ disasm_info.endian = BFD_ENDIAN_LITTLE;
+ disasm_info.mach = 0; //bfd_mach_ia64;
+ print_insn = print_insn_ia64;
+
+ for (pc = code, slot = 0; pc < code + size; pc += count, slot++) {
+ fprintf (out, "0x%016lx+%d:%c ", code, slot,
+ ((pc & ~0x0fUL) == cur_ctx->regs.ip
+ && slot == ctx_slot (cur_ctx)) ? '*' : ' ');
+
+ count = print_insn (pc, &disasm_info);
+#if 0
+ {
+ int i;
+ uint8_t b;
+
+ fprintf (out, " {");
+ for (i = 0; i < count; i++) {
+ target_read_memory (pc + i, &b, 1, &disasm_info);
+ fprintf (out, " %02x", b);
+ }
+ fprintf (out, " }");
+ }
+#endif
+ fprintf (out, "\n");
+ if (count < 0)
+ break;
+ }
+}
+
+
+#define PTE_ED_SHIFT 52
+#define PTE_ED_MASK 1
+#define PTE_PPN_SHIFT 12
+#define PTE_PPN_MASK 0x3fffffffff
+#define PTE_AR_SHIFT 9
+#define PTE_AR_MASK 7
+#define PTE_PL_SHIFT 7
+#define PTE_PL_MASK 3
+#define PTE_D_SHIFT 6
+#define PTE_D_MASK 1
+#define PTE_A_SHIFT 5
+#define PTE_A_MASK 1
+#define PTE_MA_SHIFT 2
+#define PTE_MA_MASK 7
+#define PTE_P_SHIFT 0
+#define PTE_P_MASK 1
+#define ITIR_KEY_SHIFT 8
+#define ITIR_KEY_MASK 0xffffff
+#define ITIR_PS_SHIFT 2
+#define ITIR_PS_MASK 0x3f
+#define ITIR_PS_MIN 12
+#define ITIR_PS_MAX 28
+#define RR_RID_SHIFT 8
+#define RR_RID_MASK 0xffffff
+#define RR_PS_SHIFT 2
+#define RR_PS_MASK 0x3f
+#define RR_VE_MASK 1
+
+static const char *get_ps (int ps_val)
+{
+ static const char ps[][5] = {" 4K", " 8K", " 16K", " ",
+ " 64K", " ", "256K", " ",
+ " 1M", " ", " 4M", " ",
+ " 16M", " ", " 64M", " ",
+ "256M"};
+ return ((ps_val >= ITIR_PS_MIN && ps_val <= ITIR_PS_MAX) ?
+ ps[ps_val - ITIR_PS_MIN] : " ");
+
+}
+
+static void print_a_tr (int i, const struct ia64_tr_entry *tr)
+{
+ int ps_val, ma_val;
+ unsigned long pa;
+
+ static const char ma[][4] = {"WB ", " ", " ", " ",
+ "UC ", "UCE", "WC ", "Nat"};
+
+ ps_val = tr->itir >> ITIR_PS_SHIFT & ITIR_PS_MASK;
+ ma_val = tr->pte >> PTE_MA_SHIFT & PTE_MA_MASK;
+ pa = (tr->pte >> PTE_PPN_SHIFT & PTE_PPN_MASK) << PTE_PPN_SHIFT;
+ pa = (pa >> ps_val) << ps_val;
+ printf (" [%d] %ld %06lx %016lx %013lx %02d %s %ld %ld %ld %ld "
+ "%ld %d %s %06lx\n", i,
+ tr->pte >> PTE_P_SHIFT & PTE_P_MASK,
+ tr->rid >> RR_RID_SHIFT & RR_RID_MASK,
+ tr->vadr, pa, ps_val, get_ps (ps_val),
+ tr->pte >> PTE_ED_SHIFT & PTE_ED_MASK,
+ tr->pte >> PTE_PL_SHIFT & PTE_PL_MASK,
+ tr->pte >> PTE_AR_SHIFT & PTE_AR_MASK,
+ tr->pte >> PTE_A_SHIFT & PTE_A_MASK,
+ tr->pte >> PTE_D_SHIFT & PTE_D_MASK,
+ ma_val, ma[ma_val],
+ tr->itir >> ITIR_KEY_SHIFT & ITIR_KEY_MASK);
+}
+
+void print_ctx (vcpu_guest_context_t *ctx)
+{
+ struct vcpu_guest_context_regs *regs = &ctx->regs;
+ int i;
+ unsigned int rbs_size, cfm_sof;
+
+ rbs_size = (regs->ar.bsp - regs->ar.bspstore) / 8;
+ cfm_sof = (regs->cfm & CFM_SOF_MASK);
+ printf ("bspstore: %016lx bsp: %016lx rbs_size=%d, sof=%d\n",
+ regs->ar.bspstore, regs->ar.bsp, rbs_size, cfm_sof);
+
+ for (i = 0; i < cfm_sof; i++) {
+ int off = cfm_sof - i;
+ unsigned int rbs_off =
+ (((62 - ((rbs_size + regs->rbs_voff) % 64) + off)) / 63) + off;
+ if (rbs_off > rbs_size)
+ break;
+ printf (" r%02d: %016lx%s", 32 + i,
+ regs->rbs[rbs_size - rbs_off],
+ (i % 3) != 2 ? " " : "\n");
+ }
+ if ((i % 3) != 0)
+ printf ("\n");
+
+ printf ("\n");
+ printf (" r1: %016lx ", regs->r[1]);
+ printf (" r2: %016lx ", regs->r[2]);
+ printf (" r3: %016lx\n", regs->r[3]);
+ printf (" r4: %016lx ", regs->r[4]);
+ printf (" r5: %016lx ", regs->r[5]);
+ printf (" r6: %016lx\n", regs->r[6]);
+ printf (" r7: %016lx ", regs->r[7]);
+ printf (" r8: %016lx ", regs->r[8]);
+ printf (" r9: %016lx\n", regs->r[9]);
+ printf (" r10: %016lx ", regs->r[10]);
+ printf (" r11: %016lx ", regs->r[11]);
+ printf (" sp: %016lx\n", regs->r[12]);
+ printf (" tp: %016lx ", regs->r[13]);
+ printf (" r14: %016lx ", regs->r[14]);
+ printf (" r15: %016lx\n", regs->r[15]);
+ printf (" r16: %016lx ", regs->r[16]);
+ printf (" r17: %016lx ", regs->r[17]);
+ printf (" r18: %016lx\n", regs->r[18]);
+ printf (" r19: %016lx ", regs->r[19]);
+ printf (" r20: %016lx ", regs->r[20]);
+ printf (" r21: %016lx\n", regs->r[21]);
+ printf (" r22: %016lx ", regs->r[22]);
+ printf (" r23: %016lx ", regs->r[23]);
+ printf (" r24: %016lx\n", regs->r[24]);
+ printf (" r25: %016lx ", regs->r[25]);
+ printf (" r26: %016lx ", regs->r[26]);
+ printf (" r27: %016lx\n", regs->r[27]);
+ printf (" r28: %016lx ", regs->r[28]);
+ printf (" r29: %016lx ", regs->r[29]);
+ printf (" r30: %016lx\n", regs->r[30]);
+ printf (" r31: %016lx ", regs->r[31]);
+ printf (" ");
+ printf (" b0: %016lx\n", regs->b[0]);
+
+ printf ("\n");
+ printf (" psr: %016lx ", regs->psr);
+ printf (" cfm: %016lx ", regs->cfm);
+ printf (" pr: %016lx\n", regs->pr);
+
+ printf ("\n");
+ printf (" ip: %016lx+%d", regs->ip, (int)(regs->psr >> PSR_RI_SHIFT) & 3);
+ printf ("\n");
+ target_disas (stdout, regs->ip, 16);
+}
+
+void print_br (vcpu_guest_context_t *ctx)
+{
+ struct vcpu_guest_context_regs *regs = &ctx->regs;
+
+ printf (" b0: %016lx ", regs->b[0]);
+ printf (" b1: %016lx ", regs->b[1]);
+ printf (" b2: %016lx\n", regs->b[2]);
+ printf (" b3: %016lx ", regs->b[3]);
+ printf (" b4: %016lx ", regs->b[4]);
+ printf (" b5: %016lx\n", regs->b[5]);
+ printf (" b6: %016lx ", regs->b[6]);
+ printf (" b7: %016lx\n", regs->b[7]);
+}
+
+void print_regs (vcpu_guest_context_t *ctx)
+{
+ struct vcpu_guest_context_regs *regs = &ctx->regs;
+
+ printf (" r1: %016lx ", regs->r[1]);
+ printf (" r2: %016lx ", regs->r[2]);
+ printf (" r3: %016lx\n", regs->r[3]);
+ printf (" r4: %016lx ", regs->r[4]);
+ printf (" r5: %016lx ", regs->r[5]);
+ printf (" r6: %016lx\n", regs->r[6]);
+ printf (" r7: %016lx ", regs->r[7]);
+ printf (" r8: %016lx ", regs->r[8]);
+ printf (" r9: %016lx\n", regs->r[9]);
+ printf (" r10: %016lx ", regs->r[10]);
+ printf (" r11: %016lx ", regs->r[11]);
+ printf (" sp: %016lx\n", regs->r[12]);
+ printf (" tp: %016lx ", regs->r[13]);
+ printf (" r14: %016lx ", regs->r[14]);
+ printf (" r15: %016lx\n", regs->r[15]);
+
+ printf (" Bank %d (current) Bank %d\n",
+ (regs->psr & PSR_BN) ? 1 : 0, (regs->psr & PSR_BN) ? 0 : 1);
+ printf ("16:%016lx ", regs->r[16]);
+ printf ("17:%016lx ", regs->r[17]);
+ printf ("16:%016lx ", regs->bank[0]);
+ printf ("17:%016lx\n", regs->bank[1]);
+ printf ("18:%016lx ", regs->r[18]);
+ printf ("19:%016lx ", regs->r[19]);
+ printf ("18:%016lx ", regs->bank[2]);
+ printf ("19:%016lx\n", regs->bank[3]);
+ printf ("20:%016lx ", regs->r[20]);
+ printf ("21:%016lx ", regs->r[21]);
+ printf ("20:%016lx ", regs->bank[4]);
+ printf ("21:%016lx\n", regs->bank[5]);
+ printf ("22:%016lx ", regs->r[22]);
+ printf ("23:%016lx ", regs->r[23]);
+ printf ("22:%016lx ", regs->bank[6]);
+ printf ("23:%016lx\n", regs->bank[7]);
+ printf ("24:%016lx ", regs->r[24]);
+ printf ("25:%016lx ", regs->r[25]);
+ printf ("24:%016lx ", regs->bank[8]);
+ printf ("25:%016lx\n", regs->bank[9]);
+ printf ("26:%016lx ", regs->r[26]);
+ printf ("27:%016lx ", regs->r[27]);
+ printf ("26:%016lx ", regs->bank[10]);
+ printf ("27:%016lx\n", regs->bank[11]);
+ printf ("28:%016lx ", regs->r[28]);
+ printf ("29:%016lx ", regs->r[29]);
+ printf ("28:%016lx ", regs->bank[12]);
+ printf ("29:%016lx\n", regs->bank[13]);
+ printf ("30:%016lx ", regs->r[30]);
+ printf ("31:%016lx ", regs->r[31]);
+ printf ("30:%016lx ", regs->bank[14]);
+ printf ("31:%016lx\n", regs->bank[15]);
+ printf ("\n");
+}
+
+void print_cr (vcpu_guest_context_t *ctx)
+{
+ struct vcpu_guest_context_regs *regs = &ctx->regs;
+
+ printf (" dcr: %016lx ", regs->cr.dcr);
+ printf (" itm: %016lx ", regs->cr.itm);
+ printf (" iva: %016lx\n", regs->cr.iva);
+ printf (" pta: %016lx ", regs->cr.pta);
+ printf (" ipsr: %016lx ", regs->cr.ipsr);
+ printf (" isr: %016lx\n", regs->cr.isr);
+ printf (" iip: %016lx ", regs->cr.iip);
+ printf (" ifa: %016lx ", regs->cr.ifa);
+ printf (" itir: %016lx\n", regs->cr.itir);
+ printf (" iipa: %016lx ", regs->cr.iipa);
+ printf (" ifs: %016lx ", regs->cr.ifs);
+ printf (" iim: %016lx\n", regs->cr.iim);
+ printf (" iha: %016lx ", regs->cr.iha);
+ printf (" lid: %016lx ", regs->cr.lid);
+ printf (" ivr: %016lx\n", regs->cr.ivr);
+ printf (" tpr: %016lx ", regs->cr.tpr);
+ printf (" eoi: %016lx ", regs->cr.eoi);
+ printf (" irr0: %016lx\n", regs->cr.irr[0]);
+ printf (" irr1: %016lx ", regs->cr.irr[1]);
+ printf (" irr2: %016lx ", regs->cr.irr[2]);
+ printf (" irr3: %016lx\n", regs->cr.irr[3]);
+ printf (" itv: %016lx ", regs->cr.itv);
+ printf (" pmv: %016lx ", regs->cr.pmv);
+ printf (" cmcv: %016lx\n", regs->cr.cmcv);
+ printf (" lrr0: %016lx ", regs->cr.lrr0);
+ printf (" lrr1: %016lx ", regs->cr.lrr1);
+ printf (" ev_cb:%016lx\n", ctx->event_callback_ip);
+}
+
+void print_ar (vcpu_guest_context_t *ctx)
+{
+ struct vcpu_guest_context_regs *regs = &ctx->regs;
+
+ printf (" kr0: %016lx ", regs->ar.kr[0]);
+ printf (" kr1: %016lx ", regs->ar.kr[1]);
+ printf (" kr2: %016lx\n", regs->ar.kr[2]);
+ printf (" kr3: %016lx ", regs->ar.kr[3]);
+ printf (" kr4: %016lx ", regs->ar.kr[4]);
+ printf (" kr5: %016lx\n", regs->ar.kr[5]);
+ printf (" kr6: %016lx ", regs->ar.kr[6]);
+ printf (" kr7: %016lx ", regs->ar.kr[7]);
+ printf (" rsc: %016lx\n", regs->ar.rsc);
+ printf (" bsp: %016lx ", regs->ar.bsp);
+ printf (" bsps: %016lx ", regs->ar.bspstore);
+ printf (" rnat: %016lx\n", regs->ar.rnat);
+ printf (" csd: %016lx ", regs->ar.csd);
+ printf (" ccv: %016lx ", regs->ar.ccv);
+ printf (" unat: %016lx\n", regs->ar.unat);
+ printf (" fpsr: %016lx ", regs->ar.fpsr);
+ printf (" itc: %016lx\n", regs->ar.itc);
+ printf (" pfs: %016lx ", regs->ar.pfs);
+ printf (" lc: %016lx ", regs->ar.lc);
+ printf (" ec: %016lx\n", regs->ar.ec);
+}
+
+void print_a_rr (int num, unsigned long rr)
+{
+ int ps_val = (rr >> RR_PS_SHIFT) & RR_PS_MASK;
+
+ printf (" [%d] %06lx %02x %s %ld\n",
+ num, (rr >> RR_RID_SHIFT) & RR_RID_MASK,
+ ps_val, get_ps (ps_val), rr & RR_VE_MASK);
+}
+
+void print_rr (vcpu_guest_context_t *ctx)
+{
+ struct vcpu_guest_context_regs *regs = &ctx->regs;
+ int i;
+
+ printf (" rr: rid ps ve\n");
+ for (i = 0; i < 8; i++)
+ print_a_rr (i, regs->rr[i]);
+}
+
+void print_db (vcpu_guest_context_t *ctx)
+{
+ struct vcpu_guest_context_regs *regs = &ctx->regs;
+ int i;
+
+ for (i = 0; i < 7; i += 2)
+ printf (" ibr[%d]: %016lx ibr[%d]: %016lx\n",
+ i, regs->ibr[i], i + 1, regs->ibr[i + 1]);
+ printf ("\n");
+ for (i = 0; i < 7; i += 2)
+ printf (" dbr[%d]: %016lx dbr[%d]: %016lx\n",
+ i, regs->dbr[i], i + 1, regs->dbr[i + 1]);
+}
+
+struct bit_descr {
+ const char *name;
+ unsigned char sz;
+};
+
+const struct bit_descr psr_bits[] =
+ {
+ {"", 1 }, {"be", 1 }, {"up", 1 }, {"ac", 1 },
+ {"mfl", 1 }, {"mfh", 1 }, {"", 7 },
+ {"ic", 1 }, {"i", 1 }, {"pk", 1 },
+ {"", 1 }, {"dt", 1 }, {"dfl", 1 }, {"dfh", 1 },
+ {"sp", 1 }, {"pp", 1 }, {"di", 1 }, {"si", 1 },
+ {"db", 1 }, {"lp", 1 }, {"tb", 1 }, {"rt", 1 },
+ {"", 4 },
+ {"cpl", 2 }, {"is", 1 }, {"mc", 1 },
+ {"it", 1 }, {"id", 1 }, {"da", 1 }, {"dd", 1 },
+ {"ss", 1 }, {"ri", 2 }, {"ed", 1 },
+ {"bn", 1 }, {"ia", 1 }, {"vm", 1 },
+ {NULL, 0 }
+ };
+
+void print_bits (const struct bit_descr *desc, unsigned long val)
+{
+ const struct bit_descr *d;
+ unsigned int off;
+
+ /* Reverse order. */
+ for (d = desc, off = 0; d->name; d++)
+ off += d->sz;
+
+ d--;
+
+ while (1) {
+ off -= d->sz;
+ if (*d->name) {
+ if (d->sz != 1 || ((val >> off) & 1))
+ printf (" %s", d->name);
+ if (d->sz != 1)
+ printf ("=%lx", (val >> off) & ((1 << d->sz) - 1));
+ }
+ if (d == desc)
+ break;
+ d--;
+ }
+}
+
+void print_tr (vcpu_guest_context_t *ctx)
+{
+ struct vcpu_tr_regs *tr = &ctx->regs.tr;
+ int i;
+
+ printf ("\n itr: P rid va pa ps ed pl "
+ "ar a d ma key\n");
+
+ for (i = 0; i < 8; i++)
+ print_a_tr (i, &tr->itrs[i]);
+
+ printf ("\n dtr: P rid va pa ps ed pl "
+ "ar a d ma key\n");
+
+ for (i = 0; i < 8; i++)
+ print_a_tr (i, &tr->dtrs[i]);
+}
+
+int lock_pages (void *addr, size_t len);
+void unlock_pages (void *addr, size_t len);
+int do_xen_hypercall (int xc_handle, privcmd_hypercall_t *hypercall);
+
+#ifdef HAVE_DEBUG_OP
+static int do_ia64_debug_op (int xc_handle,
+ unsigned long cmd, unsigned long domain,
+ xen_ia64_debug_op_t *op)
+{
+ int ret = -1;
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_ia64_debug_op;
+ hypercall.arg[0] = cmd;
+ hypercall.arg[1] = domain;
+ hypercall.arg[2] = (unsigned long)op;
+
+ if (lock_pages (op, sizeof (*op)) != 0) {
+ perror ("Could not lock memory for Xen hypercall");
+ goto out1;
+ }
+
+ ret = do_xen_hypercall (xc_handle, &hypercall);
+ if (ret < 0) {
+ if (errno == EACCES)
+ fprintf (stderr,"domctl operation failed -- need to "
+ "rebuild the user-space tool set?\n");
+ }
+
+ unlock_pages (op, sizeof (*op));
+
+out1:
+ return ret;
+}
+#endif
+
+static volatile int ctrl_c_hit;
+
+void ctrl_c_handler (int sig)
+{
+ fflush (stdout);
+ ctrl_c_hit = 1;
+}
+
+int wait_domain (int vcpu, vcpu_guest_context_t *ctx)
+{
+ struct timespec ts;
+ xc_dominfo_t dominfo;
+ int ret;
+ int cnt = 0;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 10*1000*1000;
+
+ ret = xc_domain_unpause (xc_handle, domid);
+ if (ret < 0)
+ perror ("xc_domain_unpause");
+
+ ctrl_c_hit = 0;
+
+ while (1) {
+ ret = xc_domain_getinfo (xc_handle, domid, 1, &dominfo);
+ if (ret < 0)
+ perror ("xc_domain_getinfo");
+
+ if (dominfo.paused)
+ break;
+
+ if (ctrl_c_hit) {
+ /* Force pause. */
+ ret = xc_domain_pause (xc_handle, domid);
+ if (ret < 0)
+ perror ("xc_domain_pause");
+
+ break;
+ }
+
+ printf ("%c\b", "/-\\|"[(cnt++) % 4]);
+ fflush (stdout);
+ nanosleep (&ts, NULL);
+ }
+ return xc_vcpu_getcontext (xc_handle, domid, vcpu, ctx);
+}
+
+int virt_to_phys (int is_inst, unsigned long vaddr, unsigned long *paddr)
+{
+ struct ia64_tr_entry *tr;
+ int i;
+
+ /* Search in tr. */
+ if (is_inst)
+ tr = cur_ctx->regs.tr.itrs;
+ else
+ tr = cur_ctx->regs.tr.dtrs;
+ for (i = 0; i < 8; i++, tr++) {
+ int ps_val = (tr->itir >> ITIR_PS_SHIFT) & ITIR_PS_MASK;
+ unsigned long ps_mask = (-1L) << ps_val;
+
+ if ((tr->vadr & ps_mask) == (vaddr & ps_mask)) {
+ *paddr = ((tr->pte & (PTE_PPN_MASK << PTE_PPN_SHIFT)) & ps_mask) |
+ (vaddr & ~ps_mask);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+unsigned long *
+get_reg_addr (const char *name)
+{
+ if (strcmp (name, "ip") == 0)
+ return &cur_ctx->regs.ip;
+ else if (strcmp (name, "psr") == 0)
+ return &cur_ctx->regs.psr;
+ else
+ return 0;
+}
+
+enum prio_expr {EXPR_BASE, EXPR_SUM, EXPR_LOGIC, EXPR_PROD};
+
+int parse_expr (unsigned char **buf, unsigned long *res, enum prio_expr prio);
+
+int next_char (unsigned char **buf)
+{
+ unsigned char *b;
+
+ b = *buf;
+ while (isspace (*b))
+ b++;
+ *buf = b;
+ return *b;
+}
+
+int parse_unary (unsigned char **buf, unsigned long *res)
+{
+ unsigned char c;
+
+ c = next_char (buf);
+ switch (c) {
+ case '0' ... '9':
+ {
+ char *e;
+ *res = strtoul (*buf, &e, 0);
+ if (e == (char *)*buf) {
+ printf ("bad literal\n");
+ return -1;
+ }
+ *buf = e;
+ }
+ break;
+ case '+':
+ (*buf)++;
+ return parse_unary (buf, res);
+ case '$':
+ {
+ unsigned char *b;
+ unsigned char *e;
+ unsigned char c;
+ unsigned long *reg;
+ int len;
+
+ b = *buf;
+ e = b + 1;
+
+ while ((*e >= 'a' && *e <= 'z') ||
+ (*e >= 'A' && *e <= 'Z') ||
+ (*e >= '0' && *e <= '9') ||
+ (*e == '_' || *e == '.'))
+ e++;
+
+ if (b == e) {
+ printf ("identifier missing after '$'\n");
+ return -1;
+ }
+
+ b++;
+ len = e - b;
+
+ c = b[len];
+ b[len] = 0;
+ reg = get_reg_addr (b);
+ b[len] = c;
+
+ if (reg != NULL)
+ *res = *reg;
+ else if (strncmp (b, "d2p", len) == 0 ||
+ strncmp (b, "i2p", len) == 0) {
+ unsigned long vaddr;
+
+ *buf = e;
+ if (parse_unary (buf, &vaddr) != 0)
+ return -1;
+ if (virt_to_phys (*b == 'i', vaddr, res) != 0) {
+ printf ("cannot find vaddr %016lx in tr\n", vaddr);
+ return -1;
+ }
+ return 0;
+ }
+ else {
+ printf ("unknown symbol\n");
+ return -1;
+ }
+ *buf = e;
+ }
+ break;
+ case '(':
+ (*buf)++;
+ if (parse_expr (buf, res, EXPR_BASE) != 0)
+ return -1;
+
+ if (next_char (buf) != ')') {
+ printf ("missing ')'\n");
+ return -1;
+ }
+ else
+ (*buf)++;
+ break;
+ default:
+ printf ("unknown operand '%c' in expression\n", c);
+ return -1;
+ }
+
+ return 0;
+}
+
+int parse_expr (unsigned char **buf, unsigned long *res, enum prio_expr prio)
+{
+ unsigned long val = 0;
+ unsigned long val1;
+
+ if (parse_unary (buf, &val) != 0)
+ return -1;
+
+ while (1) {
+ switch (next_char (buf)) {
+ case '+':
+ if (prio > EXPR_SUM)
+ return 0;
+
+ (*buf)++;
+ if (parse_expr (buf, &val1, EXPR_SUM) < 0)
+ return -1;
+
+ val += val1;
+ break;
+ case '*':
+ if (prio > EXPR_PROD)
+ return 0;
+
+ (*buf)++;
+ if (parse_expr (buf, &val1, EXPR_SUM) < 0)
+ return -1;
+
+ val *= val1;
+ break;
+ default:
+ *res = val;
+ return 0;
+ }
+ }
+}
+
+unsigned char *parse_arg (unsigned char **buf)
+{
+ unsigned char *res;
+ unsigned char *b = *buf;
+
+ /* Eat leading spaces. */
+ while (isspace (*b))
+ b++;
+
+ res = b;
+ while (*b && !isspace (*b))
+ b++;
+
+ /* Set the NUL terminator. */
+ if (*b)
+ *b++ = 0;
+
+ *buf = b;
+ return res;
+}
+
+vcpu_guest_context_t vcpu_ctx[1];
+
+int vcpu_setcontext (int vcpu)
+{
+ int ret;
+
+ ret = xc_vcpu_setcontext (xc_handle, domid, vcpu, &vcpu_ctx[vcpu]);
+ if (ret < 0)
+ perror ("xc_vcpu_setcontext");
+
+ return ret;
+}
+
+struct command_desc
+{
+ const char *name;
+ const char *help;
+ int (*cmd)(unsigned char *line);
+};
+
+static int
+cmd_registers (unsigned char *line)
+{
+ print_ctx (cur_ctx);
+ return 0;
+}
+
+static int
+cmd_sstep (unsigned char *line)
+{
+ if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB)) != PSR_SS) {
+ cur_ctx->regs.psr |= PSR_SS;
+ cur_ctx->regs.psr &= ~PSR_TB;
+ if (vcpu_setcontext (cur_vcpu) < 0)
+ return -1;
+ }
+
+ if (wait_domain (cur_vcpu, cur_ctx) < 0) {
+ perror ("wait_domain");
+ return -1;
+ }
+
+ print_ctx (cur_ctx);
+
+ return 0;
+}
+
+static int
+cmd_go (unsigned char *line)
+{
+ if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB | PSR_DB)) != 0) {
+ cur_ctx->regs.psr &= ~(PSR_SS | PSR_TB);
+ cur_ctx->regs.psr |= PSR_DD | PSR_ID;
+ if (vcpu_setcontext (cur_vcpu) < 0)
+ return -1;
+ }
+
+ if (wait_domain (cur_vcpu, cur_ctx) < 0) {
+ perror ("wait_domain");
+ return -1;
+ }
+
+ print_ctx (cur_ctx);
+
+ return 0;
+}
+
+static int
+cmd_cb (unsigned char *line)
+{
+ if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB)) != PSR_TB) {
+ cur_ctx->regs.psr &= ~PSR_SS;
+ cur_ctx->regs.psr |= PSR_TB;
+ if (vcpu_setcontext (cur_vcpu) < 0)
+ return -1;
+ }
+
+ if (wait_domain (cur_vcpu, cur_ctx) < 0) {
+ perror ("wait_domain");
+ return -1;
+ }
+
+ print_ctx (cur_ctx);
+
+ return 0;
+}
+
+static int
+cmd_quit (unsigned char *line)
+{
+ return -2;
+}
+
+static int
+cmd_echo (unsigned char *line)
+{
+ printf ("%s", line);
+ return 0;
+}
+
+static int
+cmd_disassemble (unsigned char *args)
+{
+ static unsigned long addr;
+
+ if (*args != 0)
+ if (parse_expr (&args, &addr, 0) < 0)
+ return -1;
+
+ target_disas (stdout, addr, 16);
+ addr += 16;
+
+ return 0;
+}
+
+static int
+cmd_break (unsigned char *args)
+{
+ unsigned long addr;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (cur_ctx->regs.ibr[2 * i] == 0 && cur_ctx->regs.ibr[2 * i + 1] == 0)
+ break;
+
+ if (i == 4) {
+ printf ("no availabe break points\n");
+ return -1;
+ }
+
+ if (parse_expr (&args, &addr, 0) < 0)
+ return -1;
+
+ cur_ctx->regs.ibr[2 * i] = addr;
+ cur_ctx->regs.ibr[2 * i + 1] = 0x87fffffffffffff0UL;
+ cur_ctx->regs.psr |= PSR_DB;
+
+ return vcpu_setcontext (cur_vcpu);
+}
+
+static int
+cmd_watch (unsigned char *args)
+{
+ unsigned long addr;
+ unsigned long mask;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (cur_ctx->regs.dbr[2 * i] == 0 && cur_ctx->regs.dbr[2 * i + 1] == 0)
+ break;
+
+ if (i == 4) {
+ printf ("no availabe watch points\n");
+ return -1;
+ }
+
+ if (parse_expr (&args, &addr, 0) < 0)
+ return -1;
+
+ if (parse_expr (&args, &mask, 0) < 0)
+ mask = 3;
+
+ cur_ctx->regs.dbr[2 * i] = addr;
+ cur_ctx->regs.dbr[2 * i + 1] = ~((1UL << mask) - 1) | (0xc7UL << 56);
+ cur_ctx->regs.psr |= PSR_DB;
+
+ return vcpu_setcontext (cur_vcpu);
+}
+
+static int
+cmd_delete (unsigned char *args)
+{
+ unsigned long num;
+
+ if (parse_expr (&args, &num, 0) < 0)
+ return -1;
+
+ if (num < 4) {
+ cur_ctx->regs.ibr[2 * num] = 0;
+ cur_ctx->regs.ibr[2 * num + 1] = 0;
+ }
+ else if (num < 8) {
+ num -= 4;
+ cur_ctx->regs.dbr[2 * num] = 0;
+ cur_ctx->regs.dbr[2 * num + 1] = 0;
+ }
+ else {
+ printf ("breakpoint out of range\n");
+ return -1;
+ }
+
+ cur_ctx->regs.psr |= PSR_DB;
+
+ return vcpu_setcontext (cur_vcpu);
+}
+
+static int
+cmd_disable (unsigned char *args)
+{
+ unsigned long num;
+
+ if (parse_expr (&args, &num, 0) < 0)
+ return -1;
+
+ if (num >= 4) {
+ printf ("breakpoint out of range\n");
+ return -1;
+ }
+
+ cur_ctx->regs.ibr[2 * num + 1] &= ~(1UL << 63);
+
+ return vcpu_setcontext (cur_vcpu);
+}
+
+static int
+cmd_enable (unsigned char *args)
+{
+ unsigned long num;
+
+ if (parse_expr (&args, &num, 0) < 0)
+ return -1;
+
+ if (num >= 4) {
+ printf ("breakpoint out of range\n");
+ return -1;
+ }
+
+ cur_ctx->regs.ibr[2 * num + 1] |= 1UL << 63;
+
+ return vcpu_setcontext (cur_vcpu);
+}
+
+static int
+cmd_print (unsigned char *args)
+{
+ unsigned long addr;
+
+ if (parse_expr (&args, &addr, 0) < 0)
+ return -1;
+
+ printf ("res: 0x%016lx = %ld\n", addr, addr);
+
+ return 0;
+}
+
+struct bit_xlat {
+ unsigned int bit;
+ const char *name;
+};
+
+static const struct bit_xlat debug_flags[] = {
+ { XEN_IA64_DEBUG_ON_KERN_SSTEP, "sstep" },
+ { XEN_IA64_DEBUG_ON_KERN_DEBUG, "debug" },
+ { XEN_IA64_DEBUG_ON_KERN_TBRANCH, "tbranch" },
+ { XEN_IA64_DEBUG_ON_EXTINT, "extint" },
+ { XEN_IA64_DEBUG_ON_EXCEPT, "except" },
+ { XEN_IA64_DEBUG_ON_EVENT, "event" },
+ { XEN_IA64_DEBUG_ON_PRIVOP, "privop" },
+ { XEN_IA64_DEBUG_ON_PAL, "pal" },
+ { XEN_IA64_DEBUG_ON_SAL, "sal" },
+ { XEN_IA64_DEBUG_ON_EFI, "efi" },
+ { XEN_IA64_DEBUG_ON_RFI, "rfi" },
+ { XEN_IA64_DEBUG_ON_MMU, "mmu" },
+ { XEN_IA64_DEBUG_ON_BAD_MPA, "mpa" },
+ { XEN_IA64_DEBUG_FORCE_SS, "ss" },
+ { XEN_IA64_DEBUG_FORCE_DB, "db" },
+ { XEN_IA64_DEBUG_ON_TR, "tr" },
+ { XEN_IA64_DEBUG_ON_TC, "tc" },
+ { 0, NULL }
+};
+
+static int
+cmd_disp (unsigned char *arg)
+{
+ if (strcmp (arg, "br") == 0)
+ print_br (cur_ctx);
+ else if (strcmp (arg, "regs") == 0)
+ print_regs (cur_ctx);
+ else if (strcmp (arg, "cr") == 0)
+ print_cr (cur_ctx);
+ else if (strcmp (arg, "ar") == 0)
+ print_ar (cur_ctx);
+ else if (strcmp (arg, "tr") == 0)
+ print_tr (cur_ctx);
+ else if (strcmp (arg, "rr") == 0)
+ print_rr (cur_ctx);
+ else if (strcmp (arg, "db") == 0)
+ print_db (cur_ctx);
+ else if (strcmp (arg, "psr") == 0) {
+ printf ("psr:");
+ print_bits (psr_bits, cur_ctx->regs.psr);
+ printf ("\n");
+ }
+ else if (strcmp (arg, "ipsr") == 0) {
+ printf ("ipsr:");
+ print_bits (psr_bits, cur_ctx->regs.cr.ipsr);
+ printf ("\n");
+ }
+ else if (strcmp (arg, "break") == 0) {
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (cur_ctx->regs.ibr[2 * i + 1])
+ printf ("%d: 0x%016lx %s\n", i, cur_ctx->regs.ibr[2 * i],
+ (cur_ctx->regs.ibr[2 * i + 1] & (1UL << 63)) ?
+ "enabled" : "disabled");
+ }
+ else if (strcmp (arg, "domain") == 0) {
+ xc_dominfo_t dominfo;
+#ifdef HAVE_DEBUG_OP
+ xen_ia64_debug_op_t debug_op;
+ int i;
+#endif
+ if (xc_domain_getinfo (xc_handle, domid, 1, &dominfo) < 0) {
+ perror ("xc_domain_getinfo");
+ return 0;
+ }
+
+ printf ("id=%d nr_pages=%lu shared_info_frame=%lu max_mem=%luKB\n",
+ dominfo.domid, dominfo.nr_pages, dominfo.shared_info_frame,
+ dominfo.max_memkb);
+ printf (" nr_online_vcpu=%u max_vcpu_id=%u\n",
+ dominfo.nr_online_vcpus, dominfo.max_vcpu_id);
+ printf (" status:");
+ if (dominfo.dying)
+ printf (" dying");
+ if (dominfo.crashed)
+ printf (" crashed");
+ if (dominfo.shutdown)
+ printf (" shutdown(%u)", dominfo.shutdown_reason);
+ if (dominfo.paused)
+ printf (" paused");
+ if (dominfo.blocked)
+ printf (" blocked");
+ if (dominfo.running)
+ printf (" running");
+ if (dominfo.hvm)
+ printf (" hvm");
+ printf ("\n");
+
+#ifdef HAVE_DEBUG_OP
+ if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_GET_FLAGS,
+ domid, &debug_op) < 0) {
+ perror ("xc_domain_getinfo");
+ return 0;
+ }
+ printf ("debug flags: %08lx: ", debug_op.flags);
+ for (i = 0; debug_flags[i].name; i++)
+ if (debug_flags[i].bit & debug_op.flags)
+ printf (" %s", debug_flags[i].name);
+ printf ("\n");
+#endif
+ }
+ else if (*arg == 0)
+ printf ("choose among br, regs, cr, ar, tr, rr, dbg\n");
+ else
+ printf ("cannot disp '%s'\n", arg);
+ return 0;
+}
+
+static int
+cmd_bev (unsigned char *arg)
+{
+ xen_ia64_debug_op_t debug_op;
+ int i;
+
+ if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_GET_FLAGS,
+ domid, &debug_op) < 0) {
+ perror ("get debug flags");
+ return 0;
+ }
+ if (arg == NULL || arg[0] == 0) {
+ printf ("debug flags: %08lx:\n", debug_op.flags);
+ for (i = 0; debug_flags[i].name; i++)
+ printf (" %c%s\n",
+ (debug_flags[i].bit & debug_op.flags) ? '+' : '-',
+ debug_flags[i].name);
+ return 0;
+ }
+ else {
+ char *p = strtok (arg, " ");
+
+ while (p != NULL) {
+ unsigned int flag = 0;
+
+ for (i = 0; debug_flags[i].name; i++)
+ if (strcmp (p, debug_flags[i].name) == 0
+ || ((p[0] == '-' || p[0] == '+')
+ && strcmp (p + 1, debug_flags[i].name) == 0)) {
+ flag = debug_flags[i].bit;
+ break;
+ }
+ if (flag == 0) {
+ printf ("unknown event %s\n", p);
+ return 0;
+ }
+ if (p[0] == '-')
+ debug_op.flags &= ~flag;
+ else
+ debug_op.flags |= flag;
+
+ p = strtok (NULL, " ");
+ }
+ if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_SET_FLAGS,
+ domid, &debug_op) < 0) {
+ perror ("set debug flags");
+ return -1;
+ }
+ /* Disabling force_SS and force_DB requires setting psr. */
+ return vcpu_setcontext (cur_vcpu);
+ }
+}
+
+static int
+cmd_set (unsigned char *line)
+{
+ unsigned char *reg;
+ unsigned long *addr;
+ unsigned long val;
+
+ reg = parse_arg (&line);
+
+ addr = get_reg_addr (reg);
+ if (addr == NULL) {
+ printf ("unknown register %s\n", reg);
+ return -1;
+ }
+
+ if (parse_expr (&line, &val, 0) < 0)
+ return -1;
+
+ *addr = val;
+
+ return vcpu_setcontext (cur_vcpu);
+}
+
+const struct command_desc commands[];
+
+static int
+cmd_help (unsigned char *line)
+{
+ int i;
+
+ for (i = 0; commands[i].name; i++)
+ printf ("%s -- %s\n", commands[i].name, commands[i].help);
+
+ return 0;
+}
+
+const struct command_desc commands[] = {
+ { "registers", "display current registers", cmd_registers },
+ { "sstep", "single step", cmd_sstep },
+ { "go", "resume execution", cmd_go },
+ { "quit", "quit debugger", cmd_quit },
+ { "echo", "display parameters", cmd_echo },
+ { "disassemble", "disassemble memory", cmd_disassemble },
+ { "break", "set a break point", cmd_break },
+ { "watch", "set a watch point", cmd_watch },
+ { "cb", "resume until branch", cmd_cb },
+ { "delete", "delete a break point", cmd_delete },
+ { "disable", "disable a break point", cmd_disable },
+ { "enable", "enable a break point", cmd_enable },
+ { "print", "print an expression", cmd_print },
+ { "disp", "disp br/regs/cr/ar/tr/rr/db/psr/break/domain", cmd_disp},
+ { "bev", "break on event", cmd_bev},
+ { "set", "set reg val", cmd_set},
+ { "help", "disp help", cmd_help },
+ { NULL, NULL }
+};
+
+
+int do_command (int vcpu, unsigned char *line)
+{
+ unsigned char *cmd;
+ unsigned char *args;
+ int i;
+ const struct command_desc *desc;
+ int flag_ambiguous;
+
+ cur_vcpu = vcpu;
+ cur_ctx = &vcpu_ctx[vcpu];
+
+ cmd = parse_arg (&line);
+ args = line;
+
+ desc = NULL;
+ flag_ambiguous = 0;
+
+ for (i = 0; commands[i].name; i++) {
+ const char *n = commands[i].name;
+ unsigned char *c = cmd;
+
+ while (*n == *c && *n)
+ n++, c++;
+
+ if (*c == 0) {
+ /* Match. */
+ if (desc != NULL) {
+ if (!flag_ambiguous)
+ printf ("ambiguous command: %s", desc->name);
+ printf (", %s", commands[i].name);
+ flag_ambiguous = 1;
+ }
+ else
+ desc = &commands[i];
+ }
+ }
+
+ if (flag_ambiguous) {
+ printf ("\n");
+ return -3;
+ }
+ else if (!desc) {
+ printf ("command not found, try help\n");
+ return -3;
+ }
+
+ return (*desc->cmd)(args);
+}
+
+void xenitp (int vcpu)
+{
+ int ret;
+ xc_dominfo_t dominfo;
+ struct sigaction sa;
+
+ cur_ctx = &vcpu_ctx[vcpu];
+
+ xc_handle = xc_interface_open (); /* for accessing control interface */
+
+ ret = xc_domain_getinfo (xc_handle, domid, 1, &dominfo);
+ if (ret < 0) {
+ perror ("xc_domain_getinfo");
+ exit (-1);
+ }
+
+ if (xc_domain_setdebugging (xc_handle, domid, 1) != 0)
+ perror ("setdebugging");
+
+ ret = xc_domain_pause (xc_handle, domid);
+ if (ret < 0) {
+ perror ("xc_domain_pause");
+ exit (-1);
+ }
+
+ ret = xc_vcpu_getcontext (xc_handle, domid, vcpu, cur_ctx);
+ if (ret < 0) {
+ if (!dominfo.paused)
+ xc_domain_unpause (xc_handle, domid);
+ perror ("xc_vcpu_getcontext");
+ exit (-1);
+ }
+
+ print_ctx (cur_ctx);
+
+ /* Catch ctrl-c. */
+ sa.sa_handler = &ctrl_c_handler;
+ sa.sa_flags = 0;
+ sigemptyset (&sa.sa_mask);
+ if (sigaction (SIGINT, &sa, NULL) != 0)
+ perror ("sigaction");
+
+ while (1) {
+ unsigned char buf[128];
+ int len;
+
+ printf ("XenITP> ");
+
+ if (fgets (buf, sizeof (buf), stdin) == NULL)
+ break;
+
+ len = strlen (buf);
+ if (len > 1 && buf[len - 1] == '\n')
+ buf[len - 1] = 0;
+
+ ret = do_command (vcpu, buf);
+ if (ret == -2)
+ break;
+ }
+
+ /* Clear debug bits. */
+ if ((cur_ctx->regs.psr & (PSR_SS | PSR_TB | PSR_DB)) != 0) {
+ cur_ctx->regs.psr &= ~(PSR_SS | PSR_TB | PSR_DB);
+ cur_ctx->regs.psr |= PSR_DD | PSR_ID;
+ vcpu_setcontext (cur_vcpu);
+ }
+
+ /* Disable debugging. */
+ if (xc_domain_setdebugging (xc_handle, domid, 0) != 0)
+ perror ("setdebugging");
+
+ if (!dominfo.paused) {
+ ret = xc_domain_unpause (xc_handle, domid);
+ if (ret < 0) {
+ perror ("xc_domain_unpause");
+ exit (-1);
+ }
+ }
+
+ xc_interface_close (xc_handle);
+ if (ret < 0) {
+ perror ("xc_interface_close");
+ exit (-1);
+ }
+}
+
+static void usage (void)
+{
+ printf ("usage:\n");
+ printf (" xenitp <DOMAIN> [VCPU]\n");
+
+}
+
+int main (int argc, char **argv)
+{
+ int ch;
+ static const char *sopts = "h"
+ ;
+ static const struct option lopts[] = {
+ {"help", 0, NULL, 'h'},
+ {0, 0, 0, 0}
+ };
+ int vcpu = 0;
+
+ while ((ch = getopt_long (argc, argv, sopts, lopts, NULL)) != -1) {
+ switch (ch) {
+ case 'h':
+ usage ();
+ exit (-1);
+ case '?':
+ fprintf (stderr, "%s --help for more options\n", argv[0]);
+ exit (-1);
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc < 1 || argc > 2) {
+ usage ();
+ exit (-1);
+ }
+
+ domid = atoi (argv[0]);
+ if (domid == 0) {
+ fprintf (stderr, "cannot trace dom0\n");
+ exit (-1);
+ }
+
+ if (argc == 2)
+ vcpu = atoi (argv[1]);
+
+ xenitp (vcpu);
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */