WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ia64-devel

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

To: xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-ia64-devel] [RFC][PATCH 1/3] xen&domain gdb debugger
From: Kouya Shimura <kouya@xxxxxxxxxxxxxx>
Date: Mon, 21 Jan 2008 21:20:55 +0900
Delivery-date: Mon, 21 Jan 2008 04:21:18 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-ia64-devel-request@lists.xensource.com?subject=help>
List-id: Discussion of the ia64 port of Xen <xen-ia64-devel.lists.xensource.com>
List-post: <mailto:xen-ia64-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ia64-devel>, <mailto:xen-ia64-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ia64-devel>, <mailto:xen-ia64-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-ia64-devel-bounces@xxxxxxxxxxxxxxxxxxx
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
<Prev in Thread] Current Thread [Next in Thread>