[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 (¤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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |