[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-ia64-devel] [RFC][PATCH 1/3] xen&domain gdb debugger



Add gdb-ia64 tool.
Hypervisor and domain gdb debugger for IA64 system.

# HG changeset patch
# User Kouya Shimura <kouya@xxxxxxxxxxxxxx>
# Date 1200915237 -32400
# Node ID c227ba80ed6e29e6fc2358512ce028fa55e461de
# Parent  ff90abf572f2d5aa7d4a7f764b3c343b66a06210
Add gdb-ia64 tool.
Hypervisor and domain gdb debugger for IA64 system.

Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx>

diff -r ff90abf572f2 -r c227ba80ed6e tools/debugger/gdb-ia64/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/debugger/gdb-ia64/Makefile  Mon Jan 21 20:33:57 2008 +0900
@@ -0,0 +1,29 @@
+XEN_ROOT=$(PWD)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+GDB_VERSION=6.7.1
+GDB_MIRROR=ftp://ftp.gnu.org/gnu/gdb
+
+TARBALL=gdb-$(GDB_VERSION).tar.bz2
+PATCH=patch-$(GDB_VERSION)-ia64-xen
+SRCDIR=gdb-$(GDB_VERSION)
+BUILDDIR=gdb-$(GDB_VERSION)-linux-ia64-xen
+
+$(TARBALL):
+       wget -c "$(GDB_MIRROR)/$(TARBALL)"
+
+$(SRCDIR): $(TARBALL) $(PATCH)
+       rm -fr $(SRCDIR)
+       tar xjf $(TARBALL)
+       patch -p0 < $(PATCH)
+       (cd $(SRCDIR)/gdb; ln -s ../../gdb-$(GDB_VERSION)-xen-sparse/gdb/* .)
+
+$(BUILDDIR): $(SRCDIR)
+       mkdir $(BUILDDIR)
+       (cd $(BUILDDIR); ../$(SRCDIR)/configure)
+
+all:   $(BUILDDIR)
+       XEN_ROOT=$(XEN_ROOT) $(MAKE) -C $(BUILDDIR)
+
+clean:
+       rm -fr $(SRCDIR) $(BUILDDIR)
diff -r ff90abf572f2 -r c227ba80ed6e tools/debugger/gdb-ia64/README
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/debugger/gdb-ia64/README    Mon Jan 21 20:33:57 2008 +0900
@@ -0,0 +1,47 @@
+Hypervisor & Domain GDB debugger for IA64 system
+----------------------------------------------------
+
+Lines marked below with [*] are optional, if you want full
+source-level debugging of your kernel image.
+
+To build the GDB:
+ 0. Build rest of the Xen first from the base directory
+ 1. Run make from within this directory.
+ 2. Copy ./gdb-6.7.1-linux-ia64-xen/gdb/gdb to your test machine.
+    This gdb is upper compatible and also available for ordinary
+    application debugging.
+
+To build a debuggable guest domU kernel image:
+ 1. cd build-linux-2.6.xx-xen_ia64
+ 2. make menuconfig
+ 3. From within the configurator, enable the following options:
+    # Kernel hacking -> Compile the kernel with debug info [*]
+                     -> Compile the kernel with frame pointers
+ 4. (Re)build and (re)install your xenU kernel image.
+
+To debug a running hypervisor:
+ 1. Run 'su gdb /path/to/xen/xen-syms'. (need root priviledge)
+ 2. From within the gdb session:
+    (gdb) target xen
+    (gdb) print *domain_list
+ There are so many restrictions for debugging a hypervisor.
+ It can't stop the cpu and has no breakpoint function.
+ All it can do are to peek and poke memory.
+
+To debug a running guest:
+ 1. Use 'xm list' to discover its domain id.
+ 2. Run 'su gdb /path/to/build-linux-2.6.xx-xen_ia64/vmlinux'.
+ 3. From within the gdb session:
+    (gdb) target dom <domid>
+    (gdb) bt
+    (gdb) disass
+ 4. Use 'vcpu' command to switch another vcpu. (default vcpu0)
+
+BUGS:
+ - can't access virtual address when it's not mapped by TRs.
+ - can't examine data when psr.dt=1 and psr.it=0
+ - Hardware watchpoint doesn't work for PV domain.
+ - not fully supoort SMP yet. can't track a breakpoint correctly.
+ ... and so on.
+
+Use this debugger at your own risk. it might crash the system.
diff -r ff90abf572f2 -r c227ba80ed6e 
tools/debugger/gdb-ia64/gdb-6.7.1-xen-sparse/gdb/ia64-xen.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/debugger/gdb-ia64/gdb-6.7.1-xen-sparse/gdb/ia64-xen.c       Mon Jan 
21 20:33:57 2008 +0900
@@ -0,0 +1,888 @@
+/* debugging interface for Xen domain.
+
+   This file is part of GDB.
+
+   This program 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 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "regcache.h"
+
+#include "xenctrl.h"
+#include "xc_private.h"
+#include "ia64-tdep.h"
+
+#ifdef __HYPERVISOR_ia64_debug_op
+#define HAVE_DEBUG_OP
+#include <xen/arch-ia64/debug_op.h>
+#endif
+
+#define MAX_WATCHPOINTS 4
+#define IA64_DBR_MASK    0x00ffffffffffffffL
+#define IA64_DBR_PL0     (1UL << 56)
+#define IA64_DBR_PL1     (1UL << 57)
+#define IA64_DBR_PL2     (1UL << 58)
+#define IA64_DBR_PL3     (1UL << 59)
+#define IA64_DBR_PL0123  (0xfUL << 56)
+#define IA64_DBR_W       (1UL << 62)
+#define IA64_DBR_R       (1UL << 63)
+#define IA64_DBR_RW      (3UL << 62)
+
+#define IA64_PSR_DT      (1UL << 17)
+#define IA64_PSR_DB      (1UL << 24)
+#define IA64_PSR_IT      (1UL << 36)
+#define IA64_PSR_ID      (1UL << 37)
+#define IA64_PSR_DD      (1UL << 39)
+#define IA64_PSR_SS      (1UL << 40)
+
+#define ITIR_PS_SHIFT              2
+#define ITIR_PS_MASK            0x3f
+#define PTE_PPN_MASK    0x3fffffffff
+#define PTE_PPN_SHIFT             12
+
+/* Prototypes */
+static void xen_dom_fetch_register (struct regcache *regcache, int regno);
+static void xen_dom_store_register (struct regcache *regcache, int regno);
+static void xen_kill (void);
+static void xen_dom_open (char *args, int from_tty);
+static void xen_dom_close (int quitting);
+static void xen_dom_detach (char *args, int from_tty);
+static void xen_dom_resume (ptid_t ptid, int step, enum target_signal siggnal);
+static ptid_t xen_dom_wait (ptid_t ptid, struct target_waitstatus *status);
+static void xen_dom_mourn_inferior (void);
+static void xen_dom_stop (void);
+
+static void xen_hv_open (char *args, int from_tty);
+static void xen_hv_close (int quitting);
+
+/* Forward data declarations */
+extern struct target_ops xen_dom_ops;
+extern struct target_ops xen_hv_ops;
+
+extern unsigned long ia64_breakpoint;
+static unsigned long ia64_breakpoint_original;
+
+static int xc_handle = -1;
+static int domid;
+static int vcpu = 0;
+
+static xc_dominfo_t dominfo;
+static vcpu_guest_context_t ctxt;
+
+#ifdef MAP_PRIVREGS
+static mapped_regs_t *mregs;
+#endif
+
+static void xc_set_debug(int xc_handle, domid_t domid, int enable)
+{
+  struct xen_domctl domctl;
+
+  domctl.cmd = XEN_DOMCTL_setdebugging;
+  domctl.domain = domid;
+  domctl.u.setdebugging.enable = enable;
+  if (do_domctl (xc_handle, &domctl))
+    error (_("set debugging"));
+}
+
+#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;
+}
+
+static int
+debug_on(int xc_handle)
+{
+  xen_ia64_debug_op_t debug_op;
+  if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_GET_FLAGS,
+                       domid, &debug_op) < 0)
+    return -1;
+  debug_op.flags |= (
+    XEN_IA64_DEBUG_FORCE_DB |
+    XEN_IA64_DEBUG_ON_KERN_SSTEP |
+    XEN_IA64_DEBUG_ON_KERN_DEBUG);
+  if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_SET_FLAGS,
+                       domid, &debug_op) < 0)
+    return -1;
+  return 0;
+}
+
+static int
+debug_off(int xc_handle)
+{
+  xen_ia64_debug_op_t debug_op;
+  if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_GET_FLAGS,
+                       domid, &debug_op) < 0)
+    return -1;
+  debug_op.flags &= ~(
+    XEN_IA64_DEBUG_FORCE_DB |
+    XEN_IA64_DEBUG_ON_KERN_SSTEP |
+    XEN_IA64_DEBUG_ON_KERN_DEBUG);
+  if (do_ia64_debug_op (xc_handle, XEN_IA64_DEBUG_OP_SET_FLAGS,
+                       domid, &debug_op) < 0)
+    return -1;
+  return 0;
+}
+#else
+#define debug_on do {} while(0)
+#define debug_off do {} while(0)
+#endif
+
+static unsigned long
+vtr_lookup (struct ia64_tr_entry *tr, int num, unsigned long vaddr)
+{
+  int i;
+  int ps_val;
+  unsigned long ps_mask, paddr;
+
+  for (i = 0; i < num; i++, tr++) {
+    ps_val = (tr->itir >> ITIR_PS_SHIFT) & ITIR_PS_MASK;
+    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 paddr;
+    }
+  }
+  return -1;
+}
+
+static unsigned long
+virt_to_phys (CORE_ADDR vaddr)
+{
+  struct vcpu_tr_regs *trs = &ctxt.regs.tr;
+  CORE_ADDR paddr;
+
+  paddr =
+    vtr_lookup (trs->itrs, sizeof (trs->itrs) / sizeof (trs->itrs[0]), vaddr);
+  if (paddr != -1)
+    return paddr;
+  paddr =
+    vtr_lookup (trs->dtrs, sizeof (trs->dtrs) / sizeof (trs->dtrs[0]), vaddr);
+  if (paddr != -1)
+    return paddr;
+  return -1;
+}
+
+#define IS_RBS_ADDR(ADDR) \
+    (ADDR >= ctxt.regs.ar.bspstore && ADDR < ctxt.regs.ar.bsp)
+
+static void * rbs_addr (CORE_ADDR addr)
+{
+    unsigned long bsp = ctxt.regs.ar.bsp;
+    unsigned long rbs_sz = (ctxt.regs.ar.bsp - ctxt.regs.ar.bspstore) / 8;
+    unsigned long off;
+    unsigned long rbs_off;
+
+    off = ((bsp - addr) >> 3) - (((bsp - (addr & (-64 << 3))) >> 3) / 64);
+    rbs_off = (((62 - ((rbs_sz + ctxt.regs.rbs_voff) % 63) + off)) / 63) + off;
+    return &ctxt.regs.rbs[rbs_sz - rbs_off];
+}
+
+
+static void
+xen_dom_fetch_register (struct regcache *regcache, int regno)
+{
+  int i;
+  CORE_ADDR ip;
+
+  if (remote_debug)
+    printf_filtered (_("%s regno=%d\n"), __func__, regno);
+
+  if (xc_vcpu_getcontext (xc_handle, domid, vcpu, &ctxt) < 0)
+    error (_("can't get vcpu context. domain is killed?"));
+
+  for (i = IA64_GR1_REGNUM; i < IA64_GR32_REGNUM; i++)
+    regcache_raw_supply (regcache, i, &ctxt.regs.r[i - IA64_GR0_REGNUM]);
+
+  for (i = 0; i < 8; i++)
+    regcache_raw_supply (regcache, IA64_BR0_REGNUM + i, &ctxt.regs.b[i]);
+
+  for (i = 0; i < 8; i++)
+    regcache_raw_supply (regcache, IA64_KR0_REGNUM + i, &ctxt.regs.ar.kr[i]);
+
+  regcache_raw_supply (regcache, IA64_PR_REGNUM, &ctxt.regs.pr);
+
+  ip = ctxt.regs.ip + ((ctxt.regs.psr >> 41) & 3);
+  regcache_raw_supply (regcache, IA64_IP_REGNUM, &ip);
+
+  regcache_raw_supply (regcache, IA64_PSR_REGNUM, &ctxt.regs.psr);
+  regcache_raw_supply (regcache, IA64_CFM_REGNUM, &ctxt.regs.cfm);
+  regcache_raw_supply (regcache, IA64_RSC_REGNUM, &ctxt.regs.ar.rsc);
+  regcache_raw_supply (regcache, IA64_BSP_REGNUM, &ctxt.regs.ar.bsp);
+  regcache_raw_supply (regcache, IA64_BSPSTORE_REGNUM, &ctxt.regs.ar.bspstore);
+  regcache_raw_supply (regcache, IA64_RNAT_REGNUM, &ctxt.regs.ar.rnat);
+  regcache_raw_supply (regcache, IA64_CSD_REGNUM, &ctxt.regs.ar.csd);
+  regcache_raw_supply (regcache, IA64_CCV_REGNUM, &ctxt.regs.ar.ccv);
+  regcache_raw_supply (regcache, IA64_UNAT_REGNUM, &ctxt.regs.ar.unat);
+  regcache_raw_supply (regcache, IA64_FPSR_REGNUM, &ctxt.regs.ar.fpsr);
+  regcache_raw_supply (regcache, IA64_PFS_REGNUM, &ctxt.regs.ar.pfs);
+  regcache_raw_supply (regcache, IA64_LC_REGNUM, &ctxt.regs.ar.lc);
+  regcache_raw_supply (regcache, IA64_EC_REGNUM, &ctxt.regs.ar.ec);
+}
+
+
+static void
+xen_dom_store_reg (struct regcache *regcache, int regno)
+{
+  if (regno < IA64_GR32_REGNUM)
+    regcache_raw_collect (regcache, regno, 
+                         &ctxt.regs.r[regno - IA64_GR0_REGNUM]);
+  else if (regno >= IA64_BR0_REGNUM && regno <= IA64_BR7_REGNUM)
+    regcache_raw_collect (regcache, regno, 
+                         &ctxt.regs.b[regno - IA64_BR0_REGNUM]);
+  else if (regno >= IA64_KR0_REGNUM && regno <= IA64_KR7_REGNUM)
+    regcache_raw_collect (regcache, regno,
+                         &ctxt.regs.ar.kr[regno - IA64_KR0_REGNUM]);
+  else
+    switch (regno)
+      {
+      case IA64_PR_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.pr); break;
+      case IA64_IP_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ip); break;
+      case IA64_PSR_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.psr); break;
+      case IA64_CFM_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.cfm); break;
+      case IA64_RSC_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.rsc); break;
+      case IA64_BSP_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.bsp); break;
+      case IA64_BSPSTORE_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.bspstore); break;
+      case IA64_RNAT_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.rnat); break;
+      case IA64_CSD_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.csd); break;
+      case IA64_CCV_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.ccv); break;
+      case IA64_UNAT_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.unat); break;
+      case IA64_FPSR_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.fpsr); break;
+      case IA64_PFS_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.pfs); break;
+      case IA64_LC_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.lc); break;
+      case IA64_EC_REGNUM:
+       regcache_raw_collect (regcache, regno, &ctxt.regs.ar.ec); break;
+      }
+}
+
+static void
+xen_dom_store_register (struct regcache *regcache, int regno)
+{
+  if (regno != -1)
+    xen_dom_store_reg (regcache, regno);
+
+  xc_vcpu_setcontext (xc_handle, domid, vcpu, &ctxt);
+}
+
+static void
+xen_kill (void)
+{
+  if (remote_debug)
+    printf_filtered ("xen_kill\n");
+
+  target_mourn_inferior ();
+}
+
+static void
+xen_dom_open (char *args, int from_tty)
+{
+  if (remote_debug)
+    printf_filtered ("xen_dom_open: args \"%s\"\n", args ? args : "(null)");
+
+  if (xc_handle != -1)
+    unpush_target (&xen_dom_ops);
+
+  if (args == NULL)
+    error (_("specify domid."));
+
+  domid = atoi (args);
+  if (domid == 0)
+    error (_("specify domid. dom0 can't be debugged."));
+
+  xc_handle = xc_interface_open ();
+  if (xc_handle == -1)
+    error (_("can't connect to Xen. Maybe you are not root."));
+
+  if (xc_domain_getinfo (xc_handle, domid, 1, &dominfo) < 0)
+    error (_("Domain %d does not exist?"), domid);
+
+  printf_filtered ("Connected to the Xen domain %d.\n", domid);
+  printf_filtered ("\tpages=%lu max_mem=%luKB\n",
+                  dominfo.nr_pages, dominfo.max_memkb);
+  printf_filtered ("\tonline_vcpu=%u max_vcpu_id=%u\n",
+                  dominfo.nr_online_vcpus, dominfo.max_vcpu_id);
+
+  push_target (&xen_dom_ops);
+
+  if (xc_vcpu_getcontext (xc_handle, domid, vcpu, &ctxt) < 0)
+      error (_("can't get vcpu(%d) context\n"), vcpu);
+
+#ifdef MAP_PRIVREGS
+  if (ctxt.privregs_pfn) {
+    mregs = xc_map_foreign_range (xc_handle, domid, XC_PAGE_SIZE, PROT_READ, 
ctxt.privregs_pfn);
+    if (mregs == NULL)
+      error (_("can't map privregs"));
+  }
+#endif
+
+  xc_set_debug (xc_handle, domid, 1);
+  debug_on(xc_handle);
+  xc_domain_pause (xc_handle, domid);
+
+  inferior_ptid = pid_to_ptid (domid);
+  target_mark_running (&xen_dom_ops);
+
+  ia64_breakpoint = 0;
+}
+
+/* Close out local state before this target loses control. */
+
+static void
+xen_dom_close (int quitting)
+{
+  generic_mourn_inferior ();
+
+#ifdef MAP_PRIVREGS
+  if (mregs != NULL)
+      munmap (mregs, XC_PAGE_SIZE);
+#endif
+
+  if (xc_handle != -1)
+    {
+      debug_off(xc_handle);
+
+      xc_domain_unpause (xc_handle, domid);
+
+      xc_interface_close (xc_handle);
+      xc_handle = -1;
+    }
+
+  ia64_breakpoint = ia64_breakpoint_original;
+}
+
+static void
+xen_dom_detach (char *args, int from_tty)
+{
+  pop_target ();               /* calls xen_dom_close to do the real work */
+  if (from_tty)
+    printf_filtered ("Ending %s debugging\n", target_shortname);
+}
+
+static void
+xen_dom_resume (ptid_t ptid, int step, enum target_signal siggnal)
+{
+  if (remote_debug)
+    printf_filtered ("%s step=%d\n", __func__, step);
+
+  if (step)
+    ctxt.regs.psr |= (IA64_PSR_SS | IA64_PSR_ID | IA64_PSR_DD);
+  else if (ctxt.regs.psr & IA64_PSR_SS)
+    ctxt.regs.psr &= ~IA64_PSR_SS;
+
+  /* enables hw watchpoints and breakpoints. */
+  ctxt.regs.psr |= IA64_PSR_DB;
+
+  xc_vcpu_setcontext (xc_handle, domid, vcpu, &ctxt);
+
+  xc_domain_unpause (xc_handle, domid);
+}
+
+static void
+xen_dom_stop (void)
+{
+  xc_domain_pause (xc_handle, domid);
+}
+
+static int stop_reason;
+
+static void
+xen_dom_cntrl_c (int signo)
+{
+  stop_reason = TARGET_SIGNAL_INT;
+  xen_dom_stop ();
+}
+
+static ptid_t
+xen_dom_wait (ptid_t ptid, struct target_waitstatus *status)
+{
+  static RETSIGTYPE (*prev_sigint) ();
+  int sigrc = 0;
+
+  xc_dominfo_t info;
+  struct timespec ts;
+  int retval;
+
+  if (remote_debug)
+    printf_filtered ("xen_dom_wait\n");
+
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+  {
+    struct sigaction sa, osa;
+    sa.sa_handler = xen_dom_cntrl_c;
+    sigemptyset (&sa.sa_mask);
+    sa.sa_flags = 0;
+    sigaction (SIGINT, &sa, &osa);
+    prev_sigint = osa.sa_handler;
+  }
+#else
+  prev_sigint = signal (SIGINT, xen_dom_cntrl_c);
+#endif
+
+  ts.tv_sec = 0;
+  ts.tv_nsec = 10*1000*1000;   /* 10ms */
+
+  stop_reason = 0;
+
+  while(1)
+    {
+      retval = xc_domain_getinfo (xc_handle, domid, 1, &info);
+
+      if ( (retval == 0) || (info.domid != domid) )
+       {
+         status->kind = TARGET_WAITKIND_EXITED;
+         status->value.integer = 0;
+         break;
+       }
+
+#if 0
+      if (info.crashed)
+       {
+         status->kind = TARGET_WAITKIND_SIGNALLED;
+         status->value.sig = TARGET_SIGNAL_ABRT;
+         break;
+       }
+#endif
+
+      if (info.paused)
+       {
+         if (stop_reason == 0)
+           stop_reason = TARGET_SIGNAL_TRAP;
+
+         status->kind = TARGET_WAITKIND_STOPPED; // SIGNALLED;
+         status->value.sig = stop_reason;
+         break;
+       }
+
+      nanosleep (&ts,NULL);
+      ts.tv_nsec = 100*1000*1000;      /* 100ms */
+    }
+
+  signal (SIGINT, prev_sigint);
+
+  return inferior_ptid;
+}
+
+/* Transfer LEN bytes between GDB address MYADDR and target address
+   MEMADDR.  If WRITE is non-zero, transfer them to the target,
+   otherwise transfer them from the target.  TARGET is unused.
+
+   Returns the number of bytes transferred. */
+
+static int
+xen_xfer_inferior_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len,
+                            int write, struct mem_attrib *attrib,
+                            struct target_ops *target)
+{
+  unsigned long paddr, offset;
+  unsigned char *map;
+  int sz, copy_len;
+
+  if (remote_debug)
+    printf_filtered (_("%s: %s 0x%lx(%d)\n"), __func__, 
+                    write ? "write" : "read", memaddr, len);
+
+  if (domid != DOMID_XEN && IS_RBS_ADDR (memaddr))
+    {
+      if (write)
+       memcpy (rbs_addr (memaddr), myaddr, len);
+      else
+       memcpy (myaddr, rbs_addr (memaddr), len);
+      return len;
+    }
+
+  for (copy_len = 0; copy_len < len; copy_len += sz, memaddr += sz)
+    {
+      if ((domid == DOMID_XEN) || 
+         ((ctxt.regs.psr & IA64_PSR_IT) == 0)) /* should check IA64_PSR_DT? */
+       paddr = memaddr;
+      else
+       {
+         paddr = virt_to_phys (memaddr);
+         if (paddr == -1)
+           return 0;
+       }
+
+      map = xc_map_foreign_range (xc_handle, domid, XC_PAGE_SIZE, 
+                                 write ? PROT_WRITE : PROT_READ, 
+                                 paddr >> XC_PAGE_SHIFT);
+      if (map == NULL)
+       return 0;
+
+      offset = paddr & (XC_PAGE_SIZE - 1);
+      sz = len - copy_len;
+      if (offset + sz > XC_PAGE_SIZE)
+       sz = XC_PAGE_SIZE - offset;
+
+      if (write)
+       memcpy (map + offset, myaddr + copy_len, sz);
+      else
+       memcpy (myaddr + copy_len, map + offset, sz);
+
+      munmap (map, XC_PAGE_SIZE);
+    }
+  return copy_len;
+}
+
+/* Clear the notion of what the break points are.  */
+
+static void
+xen_dom_mourn_inferior (void)
+{
+  int i;
+
+  if (remote_debug)
+    printf_filtered ("xen_dom_mourn_inferior:\n");
+
+  for (i = 0; i < MAX_WATCHPOINTS * 2; i++)
+    {
+      ctxt.regs.dbr[i] = 0;
+      ctxt.regs.ibr[i] = 0;
+    }
+  ctxt.regs.psr &= ~(IA64_PSR_SS | IA64_PSR_DB);
+  xc_vcpu_setcontext (xc_handle, domid, vcpu, &ctxt);
+
+  remove_breakpoints ();
+  target_mark_exited (&xen_dom_ops);
+  generic_mourn_inferior ();
+}
+
+
+
+static void
+fetch_debug_register_pair (int idx, long *dbr_addr, long *dbr_mask)
+{
+  if (dbr_addr)
+    *dbr_addr = ctxt.regs.dbr[2 * idx];
+  if (dbr_mask)
+    *dbr_mask = ctxt.regs.dbr[2 * idx + 1];
+}
+
+static void
+store_debug_register_pair (int idx, long *dbr_addr, long *dbr_mask)
+{
+  if (dbr_addr)
+    ctxt.regs.dbr[2 * idx] =  *dbr_addr;
+  if (dbr_mask)
+    ctxt.regs.dbr[2 * idx + 1] =  *dbr_mask;
+}
+
+static int
+is_valid_len (int len)
+{
+  if (len <= 0)
+    return 0;
+  /* power of 2 ? */
+  if (len != (1 << (ffs (len) - 1)))
+    return 0;
+  return 1;
+}
+
+static int
+xen_dom_insert_watchpoint (CORE_ADDR addr, int len, int rw)
+{
+  int idx;
+  long dbr_addr, dbr_mask;
+
+  if (remote_debug)
+    printf_filtered (_("%s addr=0x%lx len=%d\n"), __func__, addr, len);
+
+  if (!is_valid_len (len))
+    return -1;
+
+  for (idx = 0; idx < MAX_WATCHPOINTS; idx++)
+    {
+      fetch_debug_register_pair (idx, NULL, &dbr_mask);
+      if ((dbr_mask & IA64_DBR_RW) == 0)
+       {
+         /* Exit loop if both r and w bits clear */
+         break;
+       }
+    }
+
+  if (idx == MAX_WATCHPOINTS)
+    return -1;
+
+  dbr_addr = (long) addr;
+  dbr_mask = (~(len - 1) & IA64_DBR_MASK);  /* construct mask to match */
+  dbr_mask |= IA64_DBR_PL0123; /* match all privilege level */
+  switch (rw)
+    {
+    case hw_write:
+      dbr_mask |= IA64_DBR_W;
+      break;
+    case hw_read:
+      dbr_mask |= IA64_DBR_R;
+      break;
+    case hw_access:
+      dbr_mask |= IA64_DBR_RW;
+      break;
+    default:
+      return -1;
+    }
+
+  store_debug_register_pair (idx, &dbr_addr, &dbr_mask);
+  return 0;
+}
+
+static int
+xen_dom_remove_watchpoint (CORE_ADDR addr, int len, int type)
+{
+  int idx;
+  long dbr_addr, dbr_mask;
+
+  if (remote_debug)
+    printf_filtered (_("%s addr=0x%lx len=%d\n"), __func__, addr, len);
+
+  if (!is_valid_len (len))
+    return -1;
+
+  for (idx = 0; idx < MAX_WATCHPOINTS; idx++)
+    {
+      fetch_debug_register_pair (idx, &dbr_addr, &dbr_mask);
+
+      if (((dbr_mask & IA64_DBR_RW) != 0) && (addr == (CORE_ADDR) dbr_addr))
+       {
+         dbr_addr = 0;
+         dbr_mask = 0;
+         store_debug_register_pair (idx, &dbr_addr, &dbr_mask);
+         return 0;
+       }
+    }
+  return -1;
+}
+
+static int
+xen_dom_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
+{
+  int idx;
+  long dbr_addr, dbr_mask;
+  CORE_ADDR ifa = ctxt.regs.cr.ifa;
+
+  if (remote_debug)
+    printf_filtered (_("%s ifa=0x%lx\n"), __func__, ctxt.regs.cr.ifa);
+
+  for (idx = 0; idx < MAX_WATCHPOINTS; idx++)
+    {
+      fetch_debug_register_pair (idx, &dbr_addr, &dbr_mask);
+
+      if (((dbr_mask & IA64_DBR_RW) != 0) && 
+         ((ifa & dbr_mask) == ((CORE_ADDR) dbr_addr & dbr_mask)))
+       {
+         *addr_p = (CORE_ADDR)ctxt.regs.cr.ifa;
+         ctxt.regs.cr.ifa = 0;
+         return 1;
+       }
+    }
+  return 0;
+}
+
+static int
+xen_dom_stopped_by_watchpoint (void)
+{
+  CORE_ADDR addr;
+  return xen_dom_stopped_data_address (&current_target, &addr);
+}
+
+static int
+xen_dom_can_use_hw_breakpoint (int type, int cnt, int othertype)
+{
+  /* not support PV domain currently */ 
+  return dominfo.hvm;
+}
+
+
+static void
+xen_hv_open (char *args, int from_tty)
+{
+  int ret;
+
+  if (remote_debug)
+    printf_filtered ("xen_hv_open: args \"%s\"\n", args ? args : "(null)");
+
+  domid = DOMID_XEN;
+  xc_handle = xc_interface_open ();
+  if (xc_handle == -1)
+    error (_("can't connect to Xen. Maybe you are not root"));
+
+  push_target (&xen_hv_ops);
+
+  printf_filtered ("Connected to the Xen Hypervisor.\n");
+
+  inferior_ptid = pid_to_ptid (domid);
+  target_mark_running (&xen_hv_ops);
+}
+
+static void
+xen_hv_close (int quitting)
+{
+  if (remote_debug)
+    printf_filtered ("xen_hv_close: quitting %d\n", quitting);
+
+  generic_mourn_inferior ();
+
+  if (xc_handle != -1)
+    {
+      xc_interface_close (xc_handle);
+      xc_handle = -1;
+    }
+}
+
+static void
+xen_hv_mourn_inferior (void)
+{
+  if (remote_debug)
+    printf_filtered ("xen_hv_mourn_inferior:\n");
+
+  target_mark_exited (&xen_hv_ops);
+  generic_mourn_inferior ();
+}
+
+static int
+xen_hv_insert_breakpoint (struct bp_target_info *bp_tgt)
+{
+  return -1;
+}
+
+static int
+xen_hv_remove_breakpoint (struct bp_target_info *bp_tgt)
+{
+  return -1;
+}
+
+
+/* Define the target subroutine names */
+
+struct target_ops xen_dom_ops;
+
+static void
+init_xen_dom_ops (void)
+{
+  xen_dom_ops.to_shortname = "dom";
+  xen_dom_ops.to_longname = "xen guest domain";
+  xen_dom_ops.to_doc = "Use a xen guest domain.";
+  xen_dom_ops.to_open = xen_dom_open;
+  xen_dom_ops.to_close = xen_dom_close;
+  xen_dom_ops.to_detach = xen_dom_detach;
+  xen_dom_ops.to_resume = xen_dom_resume;
+  xen_dom_ops.to_wait = xen_dom_wait;
+  xen_dom_ops.to_fetch_registers = xen_dom_fetch_register;
+  xen_dom_ops.to_store_registers = xen_dom_store_register;
+  xen_dom_ops.deprecated_xfer_memory = xen_xfer_inferior_memory;
+  xen_dom_ops.to_insert_breakpoint = memory_insert_breakpoint;
+  xen_dom_ops.to_remove_breakpoint = memory_remove_breakpoint;
+  xen_dom_ops.to_kill = xen_kill;
+  xen_dom_ops.to_mourn_inferior = xen_dom_mourn_inferior;
+  xen_dom_ops.to_stop = xen_dom_stop;
+  xen_dom_ops.to_stratum = process_stratum;
+
+  xen_dom_ops.to_have_steppable_watchpoint = 1;
+  xen_dom_ops.to_can_use_hw_breakpoint = xen_dom_can_use_hw_breakpoint;
+  xen_dom_ops.to_stopped_by_watchpoint = xen_dom_stopped_by_watchpoint;
+  xen_dom_ops.to_stopped_data_address = xen_dom_stopped_data_address;
+  xen_dom_ops.to_insert_watchpoint = xen_dom_insert_watchpoint;
+  xen_dom_ops.to_remove_watchpoint = xen_dom_remove_watchpoint;
+
+  xen_dom_ops.to_magic = OPS_MAGIC;
+}
+
+
+struct target_ops xen_hv_ops;
+
+static void
+init_xen_hv_ops (void)
+{
+  xen_hv_ops.to_shortname = "xen";
+  xen_hv_ops.to_longname = "xen hypervisor";
+  xen_hv_ops.to_doc = "Use a xen hypervisor.";
+  xen_hv_ops.to_open = xen_hv_open;
+  xen_hv_ops.to_close = xen_hv_close;
+  xen_hv_ops.deprecated_xfer_memory = xen_xfer_inferior_memory;
+  xen_hv_ops.to_insert_breakpoint = xen_hv_insert_breakpoint;
+  xen_hv_ops.to_remove_breakpoint = xen_hv_remove_breakpoint;
+  xen_hv_ops.to_kill = xen_kill;
+  xen_hv_ops.to_mourn_inferior = xen_hv_mourn_inferior;
+  xen_hv_ops.to_stratum = process_stratum;
+  xen_hv_ops.to_magic = OPS_MAGIC;
+}
+
+static void
+xen_dom_vcpu_command (char *args, int from_tty)
+{
+  if (!args || args[0] == 0)
+    {
+      printf_filtered ("Current vcpu = %d\n", vcpu);
+      return;
+    }
+
+  vcpu = atoi (args);
+  registers_changed ();
+}
+
+void
+_initialize_xen (void)
+{
+  ia64_breakpoint_original = ia64_breakpoint;
+
+  init_xen_hv_ops ();
+  add_target (&xen_hv_ops);
+
+  init_xen_dom_ops ();
+  add_target (&xen_dom_ops);
+  add_com ("vcpu", class_obscure, xen_dom_vcpu_command, 
+          _("Use this command to switch between vcpus."));
+}
diff -r ff90abf572f2 -r c227ba80ed6e 
tools/debugger/gdb-ia64/patch-6.7.1-ia64-xen
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/debugger/gdb-ia64/patch-6.7.1-ia64-xen      Mon Jan 21 20:33:57 
2008 +0900
@@ -0,0 +1,63 @@
+--- gdb-6.7.1/gdb/Makefile.in.orig     2007-09-05 09:14:02.000000000 +0900
++++ gdb-6.7.1/gdb/Makefile.in  2008-01-15 11:58:53.000000000 +0900
+@@ -135,6 +135,9 @@ READLINE_CFLAGS = @READLINE_CFLAGS@
+ # Where is expat?  This will be empty if expat was not available.
+ LIBEXPAT = @LIBEXPAT@
+ 
++# Where is libxenctrl?
++LIBXENCTRL = -lxenctrl
++
+ WARN_CFLAGS = @WARN_CFLAGS@
+ WERROR_CFLAGS = @WERROR_CFLAGS@
+ GDB_WARN_CFLAGS = $(WARN_CFLAGS)
+@@ -387,7 +390,7 @@ INSTALLED_LIBS=-lbfd -lreadline -lopcode
+ CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) \
+       $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
+       $(LIBICONV) $(LIBEXPAT) \
+-      $(LIBIBERTY) $(WIN32LIBS)
++      $(LIBIBERTY) $(WIN32LIBS) $(LIBXENCTRL)
+ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \
+       $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS)
+ 
+@@ -419,7 +422,7 @@ SER_HARDWIRE = @SER_HARDWIRE@
+ 
+ # The `remote' debugging target is supported for most architectures,
+ # but not all (e.g. 960)
+-REMOTE_OBS = remote.o dcache.o tracepoint.o ax-general.o ax-gdb.o 
remote-fileio.o
++REMOTE_OBS = remote.o dcache.o tracepoint.o ax-general.o ax-gdb.o 
remote-fileio.o ia64-xen.o
+ 
+ # This is remote-sim.o if a simulator is to be linked in.
+ SIM_OBS =
+@@ -1556,6 +1559,10 @@ v850ice.o: $(srcdir)/v850ice.c
+               $(GDBTK_CFLAGS) \
+               $(srcdir)/v850ice.c
+ 
++ia64-xen.o: $(srcdir)/ia64-xen.c
++      $(CC) -c $(INTERNAL_CFLAGS) -I$(XEN_ROOT)/tools/libxc \
++      $(srcdir)/ia64-xen.c $<
++
+ # Message files.  Based on code in gcc/Makefile.in.
+ 
+ # Rules for generating translated message descriptions.  Disabled by
+@@ -2171,6 +2178,9 @@ ia64-tdep.o: ia64-tdep.c $(defs_h) $(inf
+       $(elf_bfd_h) $(dis_asm_h) $(infcall_h) $(osabi_h) $(ia64_tdep_h) \
+       $(elf_ia64_h) $(libunwind_frame_h) $(libunwind_ia64_h) \
+       $(cp_abi_h) $(gdbtypes_h)
++ia64-xen.o: ia64-xen.c $(defs_h) $(inferior_h) $(value_h) $(target_h) \
++      $(gdbcore_h) $(gdb_callback_h) $(command_h) \
++      $(regcache_h) $(gdb_assert_h) $(arch_utils_h)
+ infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
+       $(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
+       $(objfiles_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h) \
+--- gdb-6.7.1/gdb/ia64-tdep.c.orig     2007-09-19 08:53:07.000000000 +0900
++++ gdb-6.7.1/gdb/ia64-tdep.c  2008-01-15 11:55:07.000000000 +0900
+@@ -553,7 +553,8 @@ fetch_instruction (CORE_ADDR addr, instr
+ #if 0
+ #define IA64_BREAKPOINT 0x00002000040LL
+ #endif
+-#define IA64_BREAKPOINT 0x00003333300LL
++unsigned long long ia64_breakpoint = 0x00003333300LL;
++#define IA64_BREAKPOINT ia64_breakpoint
+ 
+ static int
+ ia64_memory_insert_breakpoint (struct bp_target_info *bp_tgt)
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.