diff -r b2abc70be89e tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/configure.srv --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/configure.srv Wed Jul 19 07:17:54 2006 -0600 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/configure.srv Fri Jul 21 11:56:08 2006 +0200 @@ -30,7 +30,7 @@ case "${target}" in srv_linux_thread_db=yes ;; ia64-*-linux*) srv_regobj=reg-ia64.o - srv_tgtobj="linux-low.o linux-ia64-low.o" + srv_tgtobj="linux-xen-low.o linux-ia64-low.o" srv_linux_usrregs=yes ;; m68*-*-linux*) srv_regobj=reg-m68k.o diff -r b2abc70be89e tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c Wed Jul 19 07:17:54 2006 -0600 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c Fri Jul 21 11:56:08 2006 +0200 @@ -37,6 +37,7 @@ #include #include #include +#define XC_PTRACE_PRIVATE #include #define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */ @@ -68,7 +69,6 @@ static int expect_signal = 0; static int expect_signal = 0; static int signal_to_send = 0; static void linux_resume (struct thread_resume *resume_info); -static void linux_set_inferior (void); int debug_threads; int using_threads; @@ -83,45 +83,15 @@ struct pending_signals #define PTRACE_ARG3_TYPE long #define PTRACE_XFER_TYPE long +#ifdef HAVE_LINUX_REGSETS static int use_regsets_p = 1; +#endif #define pid_of(proc) ((proc)->head.id) /* FIXME: Delete eventually. */ #define inferior_pid (pid_of (get_thread_process (current_inferior))) - -/* This function should only be called if the process got a SIGTRAP. - The SIGTRAP could mean several things. - - On i386, where decr_pc_after_break is non-zero: - If we were single-stepping this process using PTRACE_SINGLESTEP, - we will get only the one SIGTRAP (even if the instruction we - stepped over was a breakpoint). The value of $eip will be the - next instruction. - If we continue the process using PTRACE_CONT, we will get a - SIGTRAP when we hit a breakpoint. The value of $eip will be - the instruction after the breakpoint (i.e. needs to be - decremented). If we report the SIGTRAP to GDB, we must also - report the undecremented PC. If we cancel the SIGTRAP, we - must resume at the decremented PC. - - (Presumably, not yet tested) On a non-decr_pc_after_break machine - with hardware or kernel single-step: - If we single-step over a breakpoint instruction, our PC will - point at the following instruction. If we continue and hit a - breakpoint instruction, our PC will point at the breakpoint - instruction. */ -static CORE_ADDR -get_stop_pc (void) -{ - CORE_ADDR stop_pc = (*the_low_target.get_pc) (); - - if (get_thread_process (current_inferior)->stepping) - return stop_pc; - else - return stop_pc - the_low_target.decr_pc_after_break; -} static void * add_process (int pid, long tid) @@ -252,6 +222,7 @@ linux_resume (struct thread_resume *resu } +#ifdef HAVE_LINUX_REGSETS static int regsets_fetch_inferior_registers () { @@ -355,29 +326,126 @@ regsets_store_inferior_registers () } return 0; } - - +#endif /* HAVE_LINUX_REGSETS */ + +#ifdef HAVE_LINUX_USRREGS + +static int +register_addr (int regnum) +{ + int addr; + + if (regnum < 0 || regnum >= the_low_target.num_regs) + error ("Invalid register number %d.", regnum); + + addr = the_low_target.regmap[regnum]; + + return addr; +} + +/* Fetch one register. */ +static void +fetch_register (int regno, struct gdb_regs *regs) +{ + CORE_ADDR regaddr; + + regaddr = register_addr (regno); + if (regaddr == -1) + return; + fprintf (stderr, "fetch_register %d : off=%d = %016lx\n", + regno, regaddr, *((unsigned long *)((char *)regs + regaddr))); + supply_register (regno, (char *)regs + regaddr); +} + +/* Fetch all registers, or just one, from the child process. */ +static void +usr_fetch_inferior_registers (int regno) +{ + int res; + struct gdb_regs regs; + + if (regno >= the_low_target.num_regs) + return; + if ((*the_low_target.cannot_fetch_register) (regno)) + return; + + errno = 0; + res = xc_ptrace (xc_handle, PTRACE_GETREGS, curvcpuid(), 0, (long)®s); + if (res < 0 && errno != 0) + { + /* Warning, not error, in case we are attached; sometimes the + kernel doesn't let us at the registers. */ + char *err = strerror (errno); + char *msg = alloca (strlen (err) + 128); + sprintf (msg, "reading register %d: %s", regno, err); + error (msg); + return; + } + + if (regno == -1 || regno == 0) + for (regno = 0; regno < the_low_target.num_regs; regno++) + fetch_register (regno, ®s); + else + fetch_register (regno, ®s); +} + +/* Store our register values back into the inferior. + If REGNO is -1, do this for all registers. + Otherwise, REGNO specifies which register (so we can save time). */ +static void +usr_store_inferior_registers (int regno) +{ + CORE_ADDR regaddr; + int res; + struct gdb_regs regs; + + for (regno = 0; regno < the_low_target.num_regs; regno++) { + regaddr = register_addr (regno); + if (regaddr != -1) + collect_register (regno, (char *)®s + regaddr); + } + + errno = 0; + res = xc_ptrace (xc_handle, PTRACE_SETREGS, curvcpuid(), 0, (long)®s); + if (res < 0 && errno != 0) + { + char *err = strerror (errno); + char *msg = alloca (strlen (err) + 128); + sprintf (msg, "writing registers: %s", err); + error (msg); + } +} +#endif /* HAVE_LINUX_USRREGS */ void linux_fetch_registers (int regno) { +#ifdef HAVE_LINUX_REGSETS if (use_regsets_p) { if (regsets_fetch_inferior_registers () == 0) return; } - +#endif +#ifdef HAVE_LINUX_USRREGS + usr_fetch_inferior_registers (regno); +#endif } void linux_store_registers (int regno) { +#ifdef HAVE_LINUX_REGSETS if (use_regsets_p) { if (regsets_store_inferior_registers () == 0) return; } +#endif +#ifdef HAVE_LINUX_USRREGS + usr_store_inferior_registers (regno); +#endif } @@ -635,44 +703,3 @@ thread_db_init(void) xc_register_event_handler(thread_death_callback, TD_DEATH); return 1; } - -/* XXX GAG ME */ -static int breakpoint_found; -static void -set_breakpoint_inferior (struct inferior_list_entry *entry) -{ - struct thread_info *thread = (struct thread_info *) entry; - struct thread_info *saved_inferior = current_inferior; - CORE_ADDR eip; - unsigned char buf[2] = {0, 0}; - current_inferior = thread; - if (!breakpoint_found) { - eip = get_stop_pc(); - linux_read_memory(eip, buf, 1); - if (buf[0] == 0xcc) { - breakpoint_found = 1; - return; - } - } else if (breakpoint_found == 2) { - if (get_thread_process (current_inferior)->stepping) { - printf("stepping\n"); - breakpoint_found = 1; - return; - } - } - current_inferior = saved_inferior; - - -} - -static void -linux_set_inferior (void) -{ - breakpoint_found = 0; - for_each_inferior (&all_threads, set_breakpoint_inferior); - if (!breakpoint_found) { - breakpoint_found = 2; - for_each_inferior (&all_threads, set_breakpoint_inferior); - } -} - diff -r b2abc70be89e tools/debugger/gdb/gdbbuild --- a/tools/debugger/gdb/gdbbuild Wed Jul 19 07:17:54 2006 -0600 +++ b/tools/debugger/gdb/gdbbuild Fri Jul 21 11:56:08 2006 +0200 @@ -2,7 +2,7 @@ [ "$GDB_MIRROR" ] || GDB_MIRROR="ftp://ftp.gnu.org/gnu/gdb/" -rm -rf gdb-6.2.1 gdb-6.2.1-linux-i386-xen +rm -rf gdb-6.2.1 gdb-6.2.1-linux-xen [ -a gdb-6.2.1.tar.bz2 ] || wget -c "$GDB_MIRROR/gdb-6.2.1.tar.bz2" tar xjf gdb-6.2.1.tar.bz2 @@ -10,8 +10,8 @@ bash ./mkbuildtree ../gdb-6.2.1 bash ./mkbuildtree ../gdb-6.2.1 cd .. -mkdir gdb-6.2.1-linux-i386-xen -cd gdb-6.2.1-linux-i386-xen +mkdir gdb-6.2.1-linux-xen +cd gdb-6.2.1-linux-xen ../gdb-6.2.1/configure # Use $MAKE if set, else use gmake if present, otherwise use make diff -r b2abc70be89e tools/libxc/ia64/Makefile --- a/tools/libxc/ia64/Makefile Wed Jul 19 07:17:54 2006 -0600 +++ b/tools/libxc/ia64/Makefile Fri Jul 21 11:56:08 2006 +0200 @@ -1,4 +1,6 @@ CTRL_SRCS-$(CONFIG_IA64) += ia64/xc_ia64 CTRL_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_stubs.c +CTRL_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_ptrace.c +CTRL_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_ptrace_core.c GUEST_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_hvm_build.c GUEST_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_linux_save.c diff -r b2abc70be89e tools/libxc/xc_ptrace.h --- a/tools/libxc/xc_ptrace.h Wed Jul 19 07:17:54 2006 -0600 +++ b/tools/libxc/xc_ptrace.h Fri Jul 21 11:56:08 2006 +0200 @@ -4,10 +4,12 @@ #include #ifdef XC_PTRACE_PRIVATE +#if defined(__x86_64__) || defined(__i386__) #define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */ #define X86_CR0_PG 0x80000000 /* Paging (RW) */ #define BSD_PAGE_MASK (PAGE_SIZE-1) #define PSL_T 0x00000100 /* trace enable bit */ +#endif #ifdef __x86_64__ struct gdb_regs @@ -158,9 +160,207 @@ struct gdb_regs { xc.fs = pt->xfs; \ xc.gs = pt->xgs; \ } +#elif __ia64__ +struct gdb_regs +{ + struct ia64_fpreg fph[96]; + unsigned long nat_bits; + unsigned long empty1; + struct ia64_fpreg f2; + struct ia64_fpreg f3; + struct ia64_fpreg f4; + struct ia64_fpreg f5; + struct ia64_fpreg f10; + struct ia64_fpreg f11; + struct ia64_fpreg f12; + struct ia64_fpreg f13; + struct ia64_fpreg f14; + struct ia64_fpreg f15; + struct ia64_fpreg f16; + struct ia64_fpreg f17; + struct ia64_fpreg f18; + struct ia64_fpreg f19; + struct ia64_fpreg f20; + struct ia64_fpreg f21; + struct ia64_fpreg f22; + struct ia64_fpreg f23; + struct ia64_fpreg f24; + struct ia64_fpreg f25; + struct ia64_fpreg f26; + struct ia64_fpreg f27; + struct ia64_fpreg f28; + struct ia64_fpreg f29; + struct ia64_fpreg f30; + struct ia64_fpreg f31; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long b1; + unsigned long b2; + unsigned long b3; + unsigned long b4; + unsigned long b5; + unsigned long ar_ec; + unsigned long ar_lc; + unsigned long empty2[5]; + unsigned long cr_ipsr; + unsigned long cr_iip; + unsigned long cfm; + unsigned long ar_unat; + unsigned long ar_pfs; + unsigned long ar_rsc; + unsigned long ar_rnat; + unsigned long ar_bspstore; + unsigned long pr; + unsigned long b6; + unsigned long ar_bsp; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r16; + unsigned long r17; + unsigned long r18; + unsigned long r19; + unsigned long r20; + unsigned long r21; + unsigned long r22; + unsigned long r23; + unsigned long r24; + unsigned long r25; + unsigned long r26; + unsigned long r27; + unsigned long r28; + unsigned long r29; + unsigned long r30; + unsigned long r31; + unsigned long ar_ccv; + unsigned long ar_fpsr; + unsigned long b0; + unsigned long b7; + unsigned long f6; + unsigned long f7; + unsigned long f8; + unsigned long f9; + unsigned long ar_csd; + unsigned long ar_ssd; + unsigned long rsvd1[710]; + unsigned long dbr[8]; + unsigned long rsvd2[504]; + unsigned long ibr[8]; + unsigned long rsvd3[504]; + unsigned long pmd[4]; +}; + +#define SET_PT_REGS(pt, xc) \ +{ \ + pt.cr_iip = xc.cr_iip; \ + pt.cr_ipsr = xc.cr_ipsr; \ + pt.cfm = xc.cr_ifs; /* FIXME ?? */ \ + pt.ar_ccv = xc.ar_ccv; \ + pt.ar_unat = xc.ar_unat; \ + pt.ar_rsc = xc.ar_rsc; \ + pt.ar_pfs = xc.ar_pfs; \ + pt.ar_rnat = xc.ar_rnat; \ + pt.ar_bspstore = xc.ar_bspstore; \ + pt.ar_fpsr = xc.ar_fpsr; \ + pt.pr = xc.pr; \ + pt.b0 = xc.b0; \ + pt.b6 = xc.b6; \ + pt.b7 = xc.b7; \ + pt.r1 = xc.r1; \ + pt.r2 = xc.r2; \ + pt.r3 = xc.r3; \ + pt.r4 = xc.r4; \ + pt.r5 = xc.r5; \ + pt.r6 = xc.r6; \ + pt.r7 = xc.r7; \ + pt.r8 = xc.r8; \ + pt.r9 = xc.r9; \ + pt.r10 = xc.r10; \ + pt.r11 = xc.r11; \ + pt.r12 = xc.r12; \ + pt.r13 = xc.r13; \ + pt.r14 = xc.r14; \ + pt.r15 = xc.r15; \ + pt.r16 = xc.r16; \ + pt.r17 = xc.r17; \ + pt.r18 = xc.r18; \ + pt.r19 = xc.r19; \ + pt.r20 = xc.r20; \ + pt.r21 = xc.r21; \ + pt.r22 = xc.r22; \ + pt.r23 = xc.r23; \ + pt.r24 = xc.r24; \ + pt.r25 = xc.r25; \ + pt.r26 = xc.r26; \ + pt.r27 = xc.r27; \ + pt.r28 = xc.r28; \ + pt.r29 = xc.r29; \ + pt.r30 = xc.r30; \ + pt.r31 = xc.r31; \ +} + +#define SET_XC_REGS(pt, xc) \ +{ \ + xc.cr_iip = pt->cr_iip; \ + xc.cr_ipsr = pt->cr_ipsr; \ + xc.cr_ifs = pt->cfm; /* FIXME ?? */ \ + xc.ar_ccv = pt->ar_ccv; \ + xc.ar_unat = pt->ar_unat; \ + xc.ar_rsc = pt->ar_rsc; \ + xc.ar_pfs = pt->ar_pfs; \ + xc.ar_rnat = pt->ar_rnat; \ + xc.ar_bspstore = pt->ar_bspstore; \ + xc.ar_fpsr = pt->ar_fpsr; \ + xc.pr = pt->pr; \ + xc.b0 = pt->b0; \ + xc.b6 = pt->b6; \ + xc.b7 = pt->b7; \ + xc.r1 = pt->r1; \ + xc.r2 = pt->r2; \ + xc.r3 = pt->r3; \ + xc.r4 = pt->r4; \ + xc.r5 = pt->r5; \ + xc.r6 = pt->r6; \ + xc.r7 = pt->r7; \ + xc.r8 = pt->r8; \ + xc.r9 = pt->r9; \ + xc.r10 = pt->r10; \ + xc.r11 = pt->r11; \ + xc.r12 = pt->r12; \ + xc.r13 = pt->r13; \ + xc.r14 = pt->r14; \ + xc.r15 = pt->r15; \ + xc.r16 = pt->r16; \ + xc.r17 = pt->r17; \ + xc.r18 = pt->r18; \ + xc.r19 = pt->r19; \ + xc.r20 = pt->r20; \ + xc.r21 = pt->r21; \ + xc.r22 = pt->r22; \ + xc.r23 = pt->r23; \ + xc.r24 = pt->r24; \ + xc.r25 = pt->r25; \ + xc.r26 = pt->r26; \ + xc.r27 = pt->r27; \ + xc.r28 = pt->r28; \ + xc.r29 = pt->r29; \ + xc.r30 = pt->r30; \ + xc.r31 = pt->r31; \ +} + #endif -#endif +#endif /* XC_PTRACE_PRIVATE */ typedef void (*thr_ev_handler_t)(long); diff -r b2abc70be89e tools/libxc/ia64/xc_ia64_ptrace.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxc/ia64/xc_ia64_ptrace.c Fri Jul 21 11:56:08 2006 +0200 @@ -0,0 +1,491 @@ +#define XC_PTRACE_PRIVATE + +#include +#include +#include + +#include "xc_private.h" +#include "xg_private.h" +#include "xc_ptrace.h" + +/* psr single step bit. */ +#define PSR_SS (1UL << 40) + +#if 0 +#ifdef DEBUG +static char *ptrace_names[] = { + "PTRACE_TRACEME", + "PTRACE_PEEKTEXT", + "PTRACE_PEEKDATA", + "PTRACE_PEEKUSER", + "PTRACE_POKETEXT", + "PTRACE_POKEDATA", + "PTRACE_POKEUSER", + "PTRACE_CONT", + "PTRACE_KILL", + "PTRACE_SINGLESTEP", + "PTRACE_INVALID", + "PTRACE_INVALID", + "PTRACE_GETREGS", + "PTRACE_SETREGS", + "PTRACE_GETFPREGS", + "PTRACE_SETFPREGS", + "PTRACE_ATTACH", + "PTRACE_DETACH", + "PTRACE_GETFPXREGS", + "PTRACE_SETFPXREGS", + "PTRACE_INVALID", + "PTRACE_INVALID", + "PTRACE_INVALID", + "PTRACE_INVALID", + "PTRACE_SYSCALL", +}; +#endif +#endif + +static int current_domid = -1; +static int current_isfile; + +static cpumap_t online_cpumap; +static cpumap_t regs_valid; +static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS]; + +extern int ffsll(long long int); +#define FOREACH_CPU(cpumap, i) for ( cpumap = online_cpumap; (i = ffsll(cpumap)); cpumap &= ~(1 << (index - 1)) ) + + +static int +fetch_regs(int xc_handle, int cpu, int *online) +{ + xc_vcpuinfo_t info; + int retval = 0; + + if (online) + *online = 0; + if ( !(regs_valid & (1 << cpu)) ) + { + retval = xc_vcpu_getcontext(xc_handle, current_domid, + cpu, &ctxt[cpu]); + if ( retval ) + goto done; + regs_valid |= (1 << cpu); + fprintf (stderr, "cpu %d: iip=%016lx, ifs=%016lx\n", + cpu, ctxt[cpu].user_regs.cr_iip, ctxt[cpu].user_regs.cr_ifs); + fprintf (stderr, " pfs=%016lx, rsc=%016lx, bspst=%016lx\n", + ctxt[cpu].user_regs.ar_pfs, ctxt[cpu].user_regs.ar_rsc, + ctxt[cpu].user_regs.ar_bspstore); + } + if ( online == NULL ) + goto done; + + retval = xc_vcpu_getinfo(xc_handle, current_domid, cpu, &info); + *online = info.online; + + done: + return retval; +} + +static struct thr_ev_handlers { + thr_ev_handler_t td_create; + thr_ev_handler_t td_death; +} handlers; + +void +xc_register_event_handler(thr_ev_handler_t h, + td_event_e e) +{ + switch (e) { + case TD_CREATE: + handlers.td_create = h; + break; + case TD_DEATH: + handlers.td_death = h; + break; + default: + abort(); /* XXX */ + } +} + +#if defined(__i386__) || defined(__x86_64__) +static inline int +paging_enabled(vcpu_guest_context_t *v) +{ + unsigned long cr0 = v->ctrlreg[0]; + return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG); +} +#endif + +/* + * Fetch registers for all online cpus and set the cpumap + * to indicate which cpus are online + * + */ + +static int +get_online_cpumap(int xc_handle, dom0_getdomaininfo_t *d, cpumap_t *cpumap) +{ + int i, online, retval; + + *cpumap = 0; + for (i = 0; i <= d->max_vcpu_id; i++) { + if ((retval = fetch_regs(xc_handle, i, &online))) + return retval; + if (online) + *cpumap |= (1 << i); + } + + return 0; +} + +/* + * Notify GDB of any vcpus that have come online or gone offline + * update online_cpumap + * + */ + +static void +online_vcpus_changed(cpumap_t cpumap) +{ + cpumap_t changed_cpumap = cpumap ^ online_cpumap; + int index; + + while ( (index = ffsll(changed_cpumap)) ) { + if ( cpumap & (1 << (index - 1)) ) + { + if (handlers.td_create) handlers.td_create(index - 1); + } else { + IPRINTF("thread death: %d\n", index - 1); + if (handlers.td_death) handlers.td_death(index - 1); + } + changed_cpumap &= ~(1 << (index - 1)); + } + online_cpumap = cpumap; + +} + +static unsigned long +translate_va (int cpu, unsigned long va) +{ + int i; + + for (i = 0; i < 8; i++) { + struct ia64_tr_entry *tr = &ctxt[cpu].extra_regs.dtrs[i]; + unsigned long ps; + unsigned long mask; + + ps = (tr->itir >> 2) & 0x3f; + mask = (1UL << ps) - 1; + if ((va & ~mask) == (tr->vadr & ~mask)) { + unsigned long res = (tr->pte & 0x0003fffffffff000UL) | (va & mask); + fprintf (stderr, "map_domain_va: %lx -> %lx\n", va, res); + return res; + } + } + fprintf (stderr, "map_domain_va: cannot translate %lx\n", va); + return 0; + +} + +static void * +map_domain_va( + int xc_handle, + int cpu, + void *guest_va, + int perm) +{ + unsigned long pa; + unsigned int npage; + static unsigned int page; + static unsigned char *mem; + + pa = translate_va (cpu, (unsigned long)guest_va); + if (pa == 0) + return NULL; + + npage = pa >> PAGE_SHIFT; + if (page != npage) { + xen_pfn_t pfn; + + if (mem) { + munmap (mem, PAGE_SIZE); + mem = NULL; + } + page = 0; + if (xc_ia64_get_pfn_list(xc_handle, current_domid, + &pfn, npage, 1) != 1) { + fprintf (stderr, "cannot get pfn for page %x\n", npage); + return NULL; + } + mem = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, + PROT_READ|PROT_WRITE, pfn); + if (mem == NULL) { + fprintf (stderr, "cannot map pfn %lx\n", pfn); + return NULL; + } + page = npage; + } + return mem + (pa & (PAGE_SIZE - 1)); +} + +int control_c_pressed_flag = 0; + +static int +__xc_waitdomain( + int xc_handle, + int domain, + int *status, + int options) +{ + DECLARE_DOM0_OP; + int retval; + struct timespec ts; + cpumap_t cpumap; + + ts.tv_sec = 0; + ts.tv_nsec = 10*1000*1000; + + op.cmd = DOM0_GETDOMAININFO; + op.u.getdomaininfo.domain = domain; + + retry: + retval = do_dom0_op(xc_handle, &op); + if ( retval || (op.u.getdomaininfo.domain != domain) ) + { + IPRINTF("getdomaininfo failed\n"); + goto done; + } + *status = op.u.getdomaininfo.flags; + + if ( options & WNOHANG ) + goto done; + + if (control_c_pressed_flag) { + xc_domain_pause(xc_handle, domain); + control_c_pressed_flag = 0; + goto done; + } + + if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ) + { + nanosleep(&ts,NULL); + goto retry; + } + done: + if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap)) + IPRINTF("get_online_cpumap failed\n"); + if (online_cpumap != cpumap) + online_vcpus_changed(cpumap); + return retval; + +} + +long +xc_ptrace( + int xc_handle, + enum __ptrace_request request, + uint32_t domid_tid, + long eaddr, + long edata) +{ + DECLARE_DOM0_OP; + struct gdb_regs pt; + long retval = 0; + unsigned long *guest_va; + cpumap_t cpumap; + int cpu, index; + void *addr = (char *)eaddr; + void *data = (char *)edata; + + cpu = (request != PTRACE_ATTACH) ? domid_tid : 0; + + switch ( request ) + { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + if (current_isfile) + guest_va = (unsigned long *)map_domain_va_core(current_domid, + cpu, addr, ctxt); + else + guest_va = (unsigned long *)map_domain_va(xc_handle, + cpu, addr, PROT_READ); + if ( guest_va == NULL ) + goto out_error; + retval = *guest_va; + break; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + /* XXX assume that all CPUs have the same address space */ + if (current_isfile) + guest_va = (unsigned long *)map_domain_va_core(current_domid, + cpu, addr, ctxt); + else + guest_va = (unsigned long *)map_domain_va(xc_handle, + cpu, addr, PROT_READ|PROT_WRITE); + if ( guest_va == NULL ) + goto out_error; + *guest_va = (unsigned long)data; + break; + + case PTRACE_GETREGS: + if (!current_isfile && fetch_regs(xc_handle, cpu, NULL)) + goto out_error; + SET_PT_REGS(pt, ctxt[cpu].user_regs); + memcpy(data, &pt, sizeof(struct gdb_regs)); + break; + +#ifdef PTRACE_GETFPREGS + case PTRACE_GETFPREGS: + if (!current_isfile && fetch_regs(xc_handle, cpu, NULL)) + goto out_error; + memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof (elf_fpregset_t)); + break; +#endif + +#ifdef PTRACE_GETFPXREGS + case PTRACE_GETFPXREGS: + if (!current_isfile && fetch_regs(xc_handle, cpu, NULL)) + goto out_error; + memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt)); + break; +#endif + + case PTRACE_SETREGS: + if (current_isfile) + goto out_unsupported; /* XXX not yet supported */ + SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs); + if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, + &ctxt[cpu]))) + goto out_error_dom0; + break; + + case PTRACE_SINGLESTEP: + if (current_isfile) + goto out_unsupported; /* XXX not yet supported */ + /* XXX we can still have problems if the user switches threads + * during single-stepping - but that just seems retarded + */ + ctxt[cpu].user_regs.cr_ipsr |= PSR_SS; + if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, + &ctxt[cpu]))) + goto out_error_dom0; + /* FALLTHROUGH */ + + case PTRACE_CONT: + case PTRACE_DETACH: + if (current_isfile) + goto out_unsupported; /* XXX not yet supported */ + if ( request != PTRACE_SINGLESTEP ) + { + FOREACH_CPU(cpumap, index) { + cpu = index - 1; + if (fetch_regs(xc_handle, cpu, NULL)) + goto out_error; + /* Clear trace flag */ + if ( ctxt[cpu].user_regs.cr_ipsr & PSR_SS ) + { + ctxt[cpu].user_regs.cr_ipsr &= ~PSR_SS; + if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, + cpu, &ctxt[cpu]))) + goto out_error_dom0; + } + } + } + if ( request == PTRACE_DETACH ) + { + op.cmd = DOM0_SETDEBUGGING; + op.u.setdebugging.domain = current_domid; + op.u.setdebugging.enable = 0; + if ((retval = do_dom0_op(xc_handle, &op))) + goto out_error_dom0; + } + regs_valid = 0; + if ((retval = xc_domain_unpause(xc_handle, current_domid > 0 ? + current_domid : -current_domid))) + goto out_error_dom0; + break; + + case PTRACE_ATTACH: + current_domid = domid_tid; + current_isfile = (int)edata; + if (current_isfile) + break; + op.cmd = DOM0_GETDOMAININFO; + op.u.getdomaininfo.domain = current_domid; + retval = do_dom0_op(xc_handle, &op); + if ( retval || (op.u.getdomaininfo.domain != current_domid) ) + goto out_error_dom0; + if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED ) + IPRINTF("domain currently paused\n"); + else if ((retval = xc_domain_pause(xc_handle, current_domid))) + goto out_error_dom0; + op.cmd = DOM0_SETDEBUGGING; + op.u.setdebugging.domain = current_domid; + op.u.setdebugging.enable = 1; + if ((retval = do_dom0_op(xc_handle, &op))) + goto out_error_dom0; + + if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap)) + IPRINTF("get_online_cpumap failed\n"); + if (online_cpumap != cpumap) + online_vcpus_changed(cpumap); + break; + +#ifdef PTRACE_SETFPREGS + case PTRACE_SETFPREGS: +#endif +#ifdef PTRACE_SETFPXREGS + case PTRACE_SETFPXREGS: +#endif + case PTRACE_PEEKUSER: + case PTRACE_POKEUSER: + case PTRACE_SYSCALL: + case PTRACE_KILL: + goto out_unsupported; /* XXX not yet supported */ + + case PTRACE_TRACEME: + IPRINTF("PTRACE_TRACEME is an invalid request under Xen\n"); + goto out_error; + + default: + goto out_unsupported; /* XXX not yet supported */ + } + + return retval; + + out_error_dom0: + perror("dom0 op failed"); + out_error: + errno = EINVAL; + return retval; + + out_unsupported: +#ifdef DEBUG + IPRINTF("unsupported xc_ptrace request %d\n", request); +#endif + errno = ENOSYS; + return -1; + +} + +int +xc_waitdomain( + int xc_handle, + int domain, + int *status, + int options) +{ + if (current_isfile) + return xc_waitdomain_core(xc_handle, domain, status, options, ctxt); + return __xc_waitdomain(xc_handle, domain, status, options); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r b2abc70be89e tools/libxc/ia64/xc_ia64_ptrace_core.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxc/ia64/xc_ia64_ptrace_core.c Fri Jul 21 11:56:08 2006 +0200 @@ -0,0 +1,176 @@ +#define XC_PTRACE_PRIVATE + +#include +#include +#include "xc_private.h" +#include "xg_private.h" +#include "xc_ptrace.h" +#include + +/* XXX application state */ + +static long nr_pages = 0; +static unsigned long *p2m_array = NULL; +static unsigned long *m2p_array = NULL; +static unsigned long pages_offset; +#if 0 +static unsigned long cr3[MAX_VIRT_CPUS]; +#endif + +void * +map_domain_va_core(unsigned long domfd, int cpu, void * guest_va, + vcpu_guest_context_t *ctxt) +{ + return NULL; +} + +#if 0 +/* --------------------- */ + +static unsigned long +map_mtop_offset(unsigned long ma) +{ + return pages_offset + (m2p_array[ma >> PAGE_SHIFT] << PAGE_SHIFT); + return 0; +} + + +void * +map_domain_va_core(unsigned long domfd, int cpu, void * guest_va, + vcpu_guest_context_t *ctxt) +{ + unsigned long pde, page; + unsigned long va = (unsigned long)guest_va; + void *v; + + static unsigned long cr3_phys[MAX_VIRT_CPUS]; + static unsigned long *cr3_virt[MAX_VIRT_CPUS]; + static unsigned long pde_phys[MAX_VIRT_CPUS]; + static unsigned long *pde_virt[MAX_VIRT_CPUS]; + static unsigned long page_phys[MAX_VIRT_CPUS]; + static unsigned long *page_virt[MAX_VIRT_CPUS]; + + if (cr3[cpu] != cr3_phys[cpu]) + { + cr3_phys[cpu] = cr3[cpu]; + if (cr3_virt[cpu]) + munmap(cr3_virt[cpu], PAGE_SIZE); + v = mmap( + NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, + map_mtop_offset(xen_cr3_to_pfn(cr3_phys[cpu]))); + if (v == MAP_FAILED) + { + perror("mmap failed"); + return NULL; + } + cr3_virt[cpu] = v; + } + if ((pde = cr3_virt[cpu][l2_table_offset_i386(va)]) == 0) /* logical address */ + return NULL; + if (ctxt[cpu].flags & VGCF_HVM_GUEST) + pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; + if (pde != pde_phys[cpu]) + { + pde_phys[cpu] = pde; + if (pde_virt[cpu]) + munmap(pde_virt[cpu], PAGE_SIZE); + v = mmap( + NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, + map_mtop_offset(pde_phys[cpu])); + if (v == MAP_FAILED) + return NULL; + pde_virt[cpu] = v; + } + if ((page = pde_virt[cpu][l1_table_offset_i386(va)]) == 0) /* logical address */ + return NULL; + if (ctxt[cpu].flags & VGCF_HVM_GUEST) + page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT; + if (page != page_phys[cpu]) + { + page_phys[cpu] = page; + if (page_virt[cpu]) + munmap(page_virt[cpu], PAGE_SIZE); + v = mmap( + NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, + map_mtop_offset(page_phys[cpu])); + if (v == MAP_FAILED) + { + IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, l1_table_offset_i386(va)); + page_phys[cpu] = 0; + return NULL; + } + page_virt[cpu] = v; + } + return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); +} +#endif + +int +xc_waitdomain_core( + int xc_handle, + int domfd, + int *status, + int options, + vcpu_guest_context_t *ctxt) +{ + int nr_vcpus; + int i; + xc_core_header_t header; + + /* If the file is already loaded, returns now. */ + if (nr_pages != 0) + return 0; + + if (read(domfd, &header, sizeof(header)) != sizeof(header)) + return -1; + + if (header.xch_magic != XC_CORE_MAGIC) { + IPRINTF("Magic number missmatch: 0x%08x (file) != " + " 0x%08x (code)\n", header.xch_magic, + XC_CORE_MAGIC); + return -1; + } + + nr_pages = header.xch_nr_pages; + nr_vcpus = header.xch_nr_vcpus; + pages_offset = header.xch_pages_offset; + + if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) != + sizeof(vcpu_guest_context_t)*nr_vcpus) + return -1; + +#if 0 + for (i = 0; i < nr_vcpus; i++) + cr3[i] = ctxt[i].ctrlreg[3]; +#endif + + if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) { + IPRINTF("Could not allocate p2m_array\n"); + return -1; + } + + if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) != + sizeof(unsigned long)*nr_pages) + return -1; + + if ((m2p_array = malloc((1<<20) * sizeof(unsigned long))) == NULL) { + IPRINTF("Could not allocate m2p array\n"); + return -1; + } + bzero(m2p_array, sizeof(unsigned long)* 1 << 20); + + for (i = 0; i < nr_pages; i++) + m2p_array[p2m_array[i]] = i; + + return 0; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */