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 (¤t_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
|