[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] add mp debug support to gdbserver
Please comment. -Kip # HG changeset patch # User kmacy@xxxxxxxxxxxxxxxxxxxxx # Node ID 60955b616ca60a0e55f7f956f9e3f418f5bc1f5f # Parent 8098cc1daac47f5ac371947a669b9ba15c6cf3f4 Add MP debug support to gdbserver diff -r 8098cc1daac4 -r 60955b616ca6 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 Sun Dec 4 00:52:38 2005 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c Sun Dec 4 19:02:24 2005 @@ -36,11 +36,26 @@ #include <unistd.h> #include <errno.h> #include <xenctrl.h> +#include <thread_db.h> +#include <xc_ptrace.h> + #define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */ long (*myptrace)(int xc_handle, enum __ptrace_request, uint32_t, long, long); int (*myxcwait)(int xc_handle, int domain, int *status, int options) ; static int xc_handle; + +static inline int +curvcpuid() +{ + struct process_info *process; + if (current_inferior == NULL) + return 0; + process = get_thread_process(current_inferior); + return (process->thread_known ? process->tid : 0); + +} + #define DOMFLAGS_DYING (1<<0) /* Domain is scheduled to die. */ #define DOMFLAGS_SHUTDOWN (1<<2) /* The guest OS has shut down. */ @@ -48,11 +63,14 @@ #define DOMFLAGS_BLOCKED (1<<4) /* Currently blocked pending an event. */ #define DOMFLAGS_RUNNING (1<<5) /* Domain is currently running. */ + + struct inferior_list all_processes; -static int current_domain; +static int current_domid; 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; @@ -96,7 +114,6 @@ point at the following instruction. If we continue and hit a breakpoint instruction, our PC will point at the breakpoint instruction. */ -#if 0 static CORE_ADDR get_stop_pc (void) { @@ -107,9 +124,9 @@ else return stop_pc - the_low_target.decr_pc_after_break; } -#endif + static void * -add_process (int pid) +add_process (int pid, long tid) { struct process_info *process; @@ -118,9 +135,8 @@ process->head.id = pid; - /* Default to tid == lwpid == pid. */ - process->tid = pid; - process->lwpid = pid; + process->tid = tid; + process->lwpid = tid; add_inferior_to_list (&all_processes, &process->head); @@ -143,23 +159,25 @@ } int -linux_attach (int domain) +linux_attach (int domid) { struct process_info *new_process; - current_domain = domain; - if (myptrace (xc_handle, PTRACE_ATTACH, domain, 0, 0) != 0) { - fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domain, + current_domid = domid; + /* this is handled for all active vcpus in PTRACE_ATTACH via the thread_create_callback */ + new_process = (struct process_info *) add_process (domid, curvcpuid()); + /* Don't ignore the initial SIGSTOP if we just attached to this process. */ + /* vcpuid == 0 */ + add_thread (0, new_process); + new_process->stop_expected = 0; + + if (myptrace (xc_handle, PTRACE_ATTACH, domid, 0, 0) != 0) { + fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domid, strerror (errno), errno); fflush (stderr); - _exit (0177); - } - - new_process = (struct process_info *) add_process (domain); - add_thread (domain, new_process); - - /* Don't ignore the initial SIGSTOP if we just attached to this process. */ - new_process->stop_expected = 0; - + if (!using_threads) + _exit (0177); + } + return 0; } @@ -173,20 +191,18 @@ myptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0); } + static void linux_kill (void) { for_each_inferior (&all_threads, linux_kill_one_process); } - static void linux_detach_one_process (struct inferior_list_entry *entry) { - struct thread_info *thread = (struct thread_info *) entry; - struct process_info *process = get_thread_process (thread); - - myptrace (xc_handle, PTRACE_DETACH, pid_of (process), 0, 0); + + myptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0); } @@ -212,7 +228,7 @@ linux_wait (char *status) { int w; - if (myxcwait(xc_handle, current_domain, &w, 0)) + if (myxcwait(xc_handle, current_domid, &w, 0)) return -1; if (w & (DOMFLAGS_SHUTDOWN|DOMFLAGS_DYING)) { @@ -220,6 +236,7 @@ return 0; } + linux_set_inferior(); *status = 'T'; if (expect_signal) @@ -236,8 +253,10 @@ TRACE_ENTER; expect_signal = resume_info->sig; for_each_inferior(&all_threads, regcache_invalidate_one); - - myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, current_domain, 0, 0); + if (debug_threads) + fprintf(stderr, "step: %d\n", step); + myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, + resume_info->thread, 0, 0); } @@ -261,7 +280,9 @@ } buf = malloc (regset->size); - res = myptrace (xc_handle, regset->get_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf); + res = myptrace (xc_handle, regset->get_request, + curvcpuid(), + 0, (PTRACE_XFER_TYPE)buf); if (res < 0) { if (errno == EIO) @@ -313,7 +334,7 @@ buf = malloc (regset->size); regset->fill_function (buf); - res = myptrace (xc_handle, regset->set_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf); + res = myptrace (xc_handle, regset->set_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf); if (res < 0) { if (errno == EIO) @@ -391,7 +412,7 @@ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) { errno = 0; - buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0); + buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0); if (errno) return errno; } @@ -424,13 +445,13 @@ /* Fill start and end extra bytes of buffer with existing memory data. */ - buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid, + buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0); if (count > 1) { buffer[count - 1] - = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid, + = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE)), 0); @@ -444,7 +465,8 @@ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) { errno = 0; - myptrace (xc_handle, PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]); + myptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(), + (PTRACE_ARG3_TYPE) addr, buffer[i]); if (errno) return errno; } @@ -455,9 +477,11 @@ static void linux_look_up_symbols (void) { -#if 0 + if (using_threads) + return; + using_threads = thread_db_init (); -#endif + } static void @@ -535,6 +559,7 @@ void initialize_low (void) { + using_threads = 0; xc_handle = xc_interface_open(); set_target_ops (&linux_xen_target_ops); set_breakpoint_data (the_low_target.breakpoint, @@ -548,5 +573,122 @@ myptrace = xc_ptrace; myxcwait = xc_waitdomain; } - -} + using_threads = thread_db_init (); + +} + + +static void +thread_create_callback(long vcpuid) +{ + struct thread_info *inferior; + struct process_info *process; + + /* If we are attaching to our first thread, things are a little + * different. + */ + if (all_threads.head == all_threads.tail) + { + inferior = (struct thread_info *) all_threads.head; + process = get_thread_process (inferior); + if (process->thread_known == 0) + { + /* Switch to indexing the threads list by TID. */ + change_inferior_id (&all_threads, vcpuid); + goto found; + } + } + if (debug_threads) + fprintf (stderr, "looking up thread %ld\n", + vcpuid); + inferior = (struct thread_info *) find_inferior_id (&all_threads, + vcpuid); + /* if vcpu alread registered - do nothing */ + if (inferior != NULL) + return; + + if (debug_threads) + fprintf (stderr, "Attaching to thread %ld\n", + vcpuid); + + process = add_process(current_domid, vcpuid); + + add_thread(vcpuid, process); + inferior = (struct thread_info *) find_inferior_id (&all_threads, + vcpuid); + if (inferior == NULL) + { + warning ("Could not attach to thread %ld\n", + vcpuid); + return; + } + + +found: + if (debug_threads) + fprintf (stderr, "notifying of new thread %ld\n", + vcpuid); + new_thread_notify (vcpuid); + + process->tid = vcpuid; + process->lwpid = vcpuid; + + process->thread_known = 1; +} + +static void +thread_death_callback(long vcpuid) +{ + if (debug_threads) + fprintf (stderr, "Buuurp...! CPU down event.\n"); +} + +int +thread_db_init(void) +{ + debug_threads = 0; + xc_register_event_handler(thread_create_callback, TD_CREATE); + 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 8098cc1daac4 -r 60955b616ca6 tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c Sun Dec 4 00:52:38 2005 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c Sun Dec 4 19:02:24 2005 @@ -20,7 +20,7 @@ Boston, MA 02111-1307, USA. */ #include "server.h" - +#include "linux-low.h" #include <unistd.h> #include <signal.h> #include <sys/wait.h> @@ -102,7 +102,15 @@ strcpy (own_buf, "OK"); return; } - + if (strcmp ("qC", own_buf) == 0) + { + struct process_info *process; + if (current_inferior == NULL) + return; + process = get_thread_process(current_inferior); + sprintf(own_buf, "QC%x", process->thread_known ? process->tid : 0); + + } if (strcmp ("qfThreadInfo", own_buf) == 0) { thread_ptr = all_threads.head; diff -r 8098cc1daac4 -r 60955b616ca6 tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Sun Dec 4 00:52:38 2005 +++ b/tools/libxc/xc_domain.c Sun Dec 4 19:02:24 2005 @@ -380,6 +380,30 @@ return do_dom0_op(xc_handle, &op); } +int xc_domain_setinfo(int xc_handle, + uint32_t domid, + uint32_t vcpu, + vcpu_guest_context_t *ctxt) +{ + dom0_op_t op; + int rc; + + op.cmd = DOM0_SETDOMAININFO; + op.u.setdomaininfo.domain = domid; + op.u.setdomaininfo.vcpu = vcpu; + op.u.setdomaininfo.ctxt = ctxt; + + if ( (rc = mlock(ctxt, sizeof(*ctxt))) != 0 ) + return rc; + + rc = do_dom0_op(xc_handle, &op); + + safe_munlock(ctxt, sizeof(*ctxt)); + + return rc; + +} + /* * Local variables: * mode: C diff -r 8098cc1daac4 -r 60955b616ca6 tools/libxc/xc_ptrace.c --- a/tools/libxc/xc_ptrace.c Sun Dec 4 00:52:38 2005 +++ b/tools/libxc/xc_ptrace.c Sun Dec 4 19:02:24 2005 @@ -1,130 +1,134 @@ +#define XC_PTRACE_PRIVATE + + #include <sys/ptrace.h> #include <sys/wait.h> +#include <time.h> + #include "xc_private.h" #include "xg_private.h" -#include <time.h> - -#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */ -#define X86_CR0_PG 0x80000000 /* Paging (RW) */ -#define BSD_PAGE_MASK (PAGE_SIZE-1) -#define PDRSHIFT 22 -#define PSL_T 0x00000100 /* trace enable bit */ -#define VCPU 0 /* XXX */ - -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", -}; - -struct gdb_regs { - long ebx; /* 0 */ - long ecx; /* 4 */ - long edx; /* 8 */ - long esi; /* 12 */ - long edi; /* 16 */ - long ebp; /* 20 */ - long eax; /* 24 */ - int xds; /* 28 */ - int xes; /* 32 */ - int xfs; /* 36 */ - int xgs; /* 40 */ - long orig_eax; /* 44 */ - long eip; /* 48 */ - int xcs; /* 52 */ - long eflags; /* 56 */ - long esp; /* 60 */ - int xss; /* 64 */ -}; - -#define FETCH_REGS(cpu) \ - if (!regs_valid[cpu]) \ - { \ - int retval = xc_domain_get_vcpu_context( \ - xc_handle, domid, cpu, &ctxt[cpu]); \ - if (retval) \ - goto error_out; \ - cr3[cpu] = ctxt[cpu].ctrlreg[3]; /* physical address */ \ - regs_valid[cpu] = 1; \ - } - -#define printval(x) printf("%s = %lx\n", #x, (long)x); -#define SET_PT_REGS(pt, xc) \ -{ \ - pt.ebx = xc.ebx; \ - pt.ecx = xc.ecx; \ - pt.edx = xc.edx; \ - pt.esi = xc.esi; \ - pt.edi = xc.edi; \ - pt.ebp = xc.ebp; \ - pt.eax = xc.eax; \ - pt.eip = xc.eip; \ - pt.xcs = xc.cs; \ - pt.eflags = xc.eflags; \ - pt.esp = xc.esp; \ - pt.xss = xc.ss; \ - pt.xes = xc.es; \ - pt.xds = xc.ds; \ - pt.xfs = xc.fs; \ - pt.xgs = xc.gs; \ -} - -#define SET_XC_REGS(pt, xc) \ -{ \ - xc.ebx = pt->ebx; \ - xc.ecx = pt->ecx; \ - xc.edx = pt->edx; \ - xc.esi = pt->esi; \ - xc.edi = pt->edi; \ - xc.ebp = pt->ebp; \ - xc.eax = pt->eax; \ - xc.eip = pt->eip; \ - xc.cs = pt->xcs; \ - xc.eflags = pt->eflags; \ - xc.esp = pt->esp; \ - xc.ss = pt->xss; \ - xc.es = pt->xes; \ - xc.ds = pt->xds; \ - xc.fs = pt->xfs; \ - xc.gs = pt->xgs; \ -} - -#define vtopdi(va) ((va) >> PDRSHIFT) -#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff) +#include <thread_db.h> +#include "xc_ptrace.h" + /* XXX application state */ -static long nr_pages = 0; -unsigned long *page_array = NULL; -static int regs_valid[MAX_VIRT_CPUS]; -static unsigned long cr3[MAX_VIRT_CPUS]; -static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS]; - -static inline int paging_enabled(vcpu_guest_context_t *v) +static long nr_pages = 0; +static unsigned long *page_array = NULL; +static int current_domid = -1; + +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_domain_get_vcpu_context(xc_handle, current_domid, + cpu, &ctxt[cpu]); + if ( retval ) + goto done; + regs_valid |= (1 << cpu); + + } + if ( online == NULL ) + goto done; + + retval = xc_domain_get_vcpu_info(xc_handle, current_domid, + cpu, &info); + *online = info.online; + + done: + return retval; +} + +#define FETCH_REGS(cpu) if (fetch_regs(xc_handle, cpu, NULL)) goto error_out; + + +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 */ + } +} + +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); +} + +/* + * 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))) + goto error_out; + if (online) + *cpumap |= (1 << i); + } + + return 0; + error_out: + return retval; +} + +/* + * 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 { + printf("thread death: %d\n", index - 1); + if (handlers.td_death) handlers.td_death(index - 1); + } + changed_cpumap &= ~(1 << (index - 1)); + } + online_cpumap = cpumap; + } /* --------------------- */ @@ -132,7 +136,6 @@ static void * map_domain_va_pae( int xc_handle, - unsigned long domid, int cpu, void *guest_va, int perm) @@ -144,24 +147,24 @@ FETCH_REGS(cpu); l3 = xc_map_foreign_range( - xc_handle, domid, PAGE_SIZE, PROT_READ, cr3[cpu] >> PAGE_SHIFT); + xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); if ( l3 == NULL ) goto error_out; l2p = l3[l3_table_offset_pae(va)] >> PAGE_SHIFT; - l2 = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ, l2p); + l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p); if ( l2 == NULL ) goto error_out; l1p = l2[l2_table_offset_pae(va)] >> PAGE_SHIFT; - l1 = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, perm, l1p); + l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p); if ( l1 == NULL ) goto error_out; p = l1[l1_table_offset_pae(va)] >> PAGE_SHIFT; if ( v != NULL ) munmap(v, PAGE_SIZE); - v = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, perm, p); + v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p); if ( v == NULL ) goto error_out; @@ -174,16 +177,17 @@ static void * map_domain_va( int xc_handle, - unsigned long domid, int cpu, void *guest_va, int perm) { + unsigned long pde, page; unsigned long va = (unsigned long)guest_va; - long npgs = xc_get_tot_pages(xc_handle, domid); - - static unsigned long cr3_phys[MAX_VIRT_CPUS]; + long npgs = xc_get_tot_pages(xc_handle, current_domid); + + + static uint32_t 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]; @@ -202,7 +206,7 @@ } if ( mode == MODE_PAE ) - return map_domain_va_pae(xc_handle, domid, cpu, guest_va, perm); + return map_domain_va_pae(xc_handle, cpu, guest_va, perm); if ( nr_pages != npgs ) { @@ -214,7 +218,7 @@ printf("Could not allocate memory\n"); goto error_out; } - if ( xc_get_pfn_list(xc_handle, domid, + if ( xc_get_pfn_list(xc_handle, current_domid, page_array, nr_pages) != nr_pages ) { printf("Could not get the page frame list\n"); @@ -224,13 +228,13 @@ FETCH_REGS(cpu); - if ( cr3[cpu] != cr3_phys[cpu] ) - { - cr3_phys[cpu] = cr3[cpu]; + if ( ctxt[cpu].ctrlreg[3] != cr3_phys[cpu] ) + { + cr3_phys[cpu] = ctxt[cpu].ctrlreg[3]; if ( cr3_virt[cpu] ) munmap(cr3_virt[cpu], PAGE_SIZE); cr3_virt[cpu] = xc_map_foreign_range( - xc_handle, domid, PAGE_SIZE, PROT_READ, + xc_handle, current_domid, PAGE_SIZE, PROT_READ, cr3_phys[cpu] >> PAGE_SHIFT); if ( cr3_virt[cpu] == NULL ) goto error_out; @@ -245,7 +249,7 @@ if ( pde_virt[cpu] ) munmap(pde_virt[cpu], PAGE_SIZE); pde_virt[cpu] = xc_map_foreign_range( - xc_handle, domid, PAGE_SIZE, PROT_READ, + xc_handle, current_domid, PAGE_SIZE, PROT_READ, pde_phys[cpu] >> PAGE_SHIFT); if ( pde_virt[cpu] == NULL ) goto error_out; @@ -260,7 +264,7 @@ if ( page_virt[cpu] ) munmap(page_virt[cpu], PAGE_SIZE); page_virt[cpu] = xc_map_foreign_range( - xc_handle, domid, PAGE_SIZE, perm, + xc_handle, current_domid, PAGE_SIZE, perm, page_phys[cpu] >> PAGE_SHIFT); if ( page_virt[cpu] == NULL ) { @@ -286,12 +290,15 @@ 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) ) @@ -309,17 +316,22 @@ nanosleep(&ts,NULL); goto retry; } - + /* XXX check for ^C here */ done: + if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap)) + printf("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, + uint32_t domid_tid, long eaddr, long edata) { @@ -328,18 +340,21 @@ struct gdb_regs pt; long retval = 0; unsigned long *guest_va; - int cpu = VCPU; + cpumap_t cpumap; + int cpu, index; void *addr = (char *)eaddr; void *data = (char *)edata; op.interface_version = DOM0_INTERFACE_VERSION; + + cpu = (request != PTRACE_ATTACH) ? domid_tid : 0; switch ( request ) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: guest_va = (unsigned long *)map_domain_va( - xc_handle, domid, cpu, addr, PROT_READ); + xc_handle, cpu, addr, PROT_READ); if ( guest_va == NULL ) { status = EFAULT; @@ -350,10 +365,10 @@ case PTRACE_POKETEXT: case PTRACE_POKEDATA: + /* XXX assume that all CPUs have the same address space */ guest_va = (unsigned long *)map_domain_va( - xc_handle, domid, cpu, addr, PROT_READ|PROT_WRITE); - if ( guest_va == NULL ) - { + xc_handle, cpu, addr, PROT_READ|PROT_WRITE); + if ( guest_va == NULL ) { status = EFAULT; goto error_out; } @@ -363,6 +378,7 @@ case PTRACE_GETREGS: case PTRACE_GETFPREGS: case PTRACE_GETFPXREGS: + FETCH_REGS(cpu); if ( request == PTRACE_GETREGS ) { @@ -380,44 +396,18 @@ break; case PTRACE_SETREGS: - op.cmd = DOM0_SETDOMAININFO; - SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].user_regs); - op.u.setdomaininfo.domain = domid; - /* XXX need to understand multiple vcpus */ - op.u.setdomaininfo.vcpu = cpu; - op.u.setdomaininfo.ctxt = &ctxt[cpu]; - retval = do_dom0_op(xc_handle, &op); + SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs); + retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]); if (retval) goto error_out; break; - case PTRACE_ATTACH: - op.cmd = DOM0_GETDOMAININFO; - op.u.getdomaininfo.domain = domid; - retval = do_dom0_op(xc_handle, &op); - if ( retval || (op.u.getdomaininfo.domain != domid) ) - { - perror("dom0 op failed"); - goto error_out; - } - if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED ) - { - printf("domain currently paused\n"); - goto error_out; - } - printf("domain not currently paused\n"); - op.cmd = DOM0_PAUSEDOMAIN; - op.u.pausedomain.domain = domid; - retval = do_dom0_op(xc_handle, &op); - break; - case PTRACE_SINGLESTEP: - ctxt[VCPU].user_regs.eflags |= PSL_T; - op.cmd = DOM0_SETDOMAININFO; - op.u.setdomaininfo.domain = domid; - op.u.setdomaininfo.vcpu = 0; - op.u.setdomaininfo.ctxt = &ctxt[cpu]; - retval = do_dom0_op(xc_handle, &op); + /* XXX we can still have problems if the user switches threads + * during single-stepping - but that just seems retarded + */ + ctxt[cpu].user_regs.eflags |= PSL_T; + retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]); if ( retval ) { perror("dom0 op failed"); @@ -429,27 +419,44 @@ case PTRACE_DETACH: if ( request != PTRACE_SINGLESTEP ) { - FETCH_REGS(cpu); - /* Clear trace flag */ - if ( ctxt[cpu].user_regs.eflags & PSL_T ) - { - ctxt[cpu].user_regs.eflags &= ~PSL_T; - op.cmd = DOM0_SETDOMAININFO; - op.u.setdomaininfo.domain = domid; - op.u.setdomaininfo.vcpu = cpu; - op.u.setdomaininfo.ctxt = &ctxt[cpu]; - retval = do_dom0_op(xc_handle, &op); - if ( retval ) - { - perror("dom0 op failed"); - goto error_out; + FOREACH_CPU(cpumap, index) { + cpu = index - 1; + FETCH_REGS(cpu); + /* Clear trace flag */ + if ( ctxt[cpu].user_regs.eflags & PSL_T ) { + ctxt[cpu].user_regs.eflags &= ~PSL_T; + retval = xc_domain_setinfo(xc_handle, current_domid, + cpu, &ctxt[cpu]); + if ( retval ) { + perror("dom0 op failed"); + goto error_out; + } } } } - regs_valid[cpu] = 0; - op.cmd = DOM0_UNPAUSEDOMAIN; - op.u.unpausedomain.domain = domid > 0 ? domid : -domid; + regs_valid = 0; + xc_domain_unpause(xc_handle, current_domid > 0 ? current_domid : -current_domid); + break; + + case PTRACE_ATTACH: + current_domid = domid_tid; + 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) ) + { + perror("dom0 op failed"); + goto error_out; + } + if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED ) + { + printf("domain currently paused\n"); + } else + retval = xc_domain_pause(xc_handle, current_domid); + if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap)) + printf("get_online_cpumap failed\n"); + if (online_cpumap != cpumap) + online_vcpus_changed(cpumap); break; case PTRACE_SETFPREGS: diff -r 8098cc1daac4 -r 60955b616ca6 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Sun Dec 4 00:52:38 2005 +++ b/tools/libxc/xenctrl.h Sun Dec 4 19:02:24 2005 @@ -94,25 +94,12 @@ } xc_core_header_t; -long xc_ptrace( - int xc_handle, - enum __ptrace_request request, - uint32_t domid, - long addr, - long data); - long xc_ptrace_core( int xc_handle, enum __ptrace_request request, uint32_t domid, long addr, long data); - -int xc_waitdomain( - int xc_handle, - int domain, - int *status, - int options); int xc_waitdomain_core( int xc_handle, @@ -219,6 +206,20 @@ unsigned int max_doms, xc_dominfo_t *info); + +/** + * This function will set the vcpu context for the specified domain. + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm domid the domain to set the vcpu context for + * @parm vcpu the vcpu number for the context + * @parm ctxt pointer to the the cpu context with the values to set + * @return the number of domains enumerated or -1 on error + */ +int xc_domain_setinfo(int xc_handle, + uint32_t domid, + uint32_t vcpu, + vcpu_guest_context_t *ctxt); /** * This function will return information about one or more domains, using a * single hypercall. The domain information will be stored into the supplied diff -r 8098cc1daac4 -r 60955b616ca6 tools/libxc/xc_ptrace.h --- /dev/null Sun Dec 4 00:52:38 2005 +++ b/tools/libxc/xc_ptrace.h Sun Dec 4 19:02:24 2005 @@ -0,0 +1,124 @@ +#ifndef XC_PTRACE_ +#define XC_PTRACE_ + +#ifdef XC_PTRACE_PRIVATE +#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */ +#define X86_CR0_PG 0x80000000 /* Paging (RW) */ +#define BSD_PAGE_MASK (PAGE_SIZE-1) +#define PDRSHIFT 22 +#define PSL_T 0x00000100 /* trace enable bit */ + +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", +}; + +struct gdb_regs { + long ebx; /* 0 */ + long ecx; /* 4 */ + long edx; /* 8 */ + long esi; /* 12 */ + long edi; /* 16 */ + long ebp; /* 20 */ + long eax; /* 24 */ + int xds; /* 28 */ + int xes; /* 32 */ + int xfs; /* 36 */ + int xgs; /* 40 */ + long orig_eax; /* 44 */ + long eip; /* 48 */ + int xcs; /* 52 */ + long eflags; /* 56 */ + long esp; /* 60 */ + int xss; /* 64 */ +}; + + +#define printval(x) printf("%s = %lx\n", #x, (long)x); +#define SET_PT_REGS(pt, xc) \ +{ \ + pt.ebx = xc.ebx; \ + pt.ecx = xc.ecx; \ + pt.edx = xc.edx; \ + pt.esi = xc.esi; \ + pt.edi = xc.edi; \ + pt.ebp = xc.ebp; \ + pt.eax = xc.eax; \ + pt.eip = xc.eip; \ + pt.xcs = xc.cs; \ + pt.eflags = xc.eflags; \ + pt.esp = xc.esp; \ + pt.xss = xc.ss; \ + pt.xes = xc.es; \ + pt.xds = xc.ds; \ + pt.xfs = xc.fs; \ + pt.xgs = xc.gs; \ +} + +#define SET_XC_REGS(pt, xc) \ +{ \ + xc.ebx = pt->ebx; \ + xc.ecx = pt->ecx; \ + xc.edx = pt->edx; \ + xc.esi = pt->esi; \ + xc.edi = pt->edi; \ + xc.ebp = pt->ebp; \ + xc.eax = pt->eax; \ + xc.eip = pt->eip; \ + xc.cs = pt->xcs; \ + xc.eflags = pt->eflags; \ + xc.esp = pt->esp; \ + xc.ss = pt->xss; \ + xc.es = pt->xes; \ + xc.ds = pt->xds; \ + xc.fs = pt->xfs; \ + xc.gs = pt->xgs; \ +} + +#define vtopdi(va) ((va) >> PDRSHIFT) +#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff) +#endif + +typedef void (*thr_ev_handler_t)(long); + +void xc_register_event_handler( + thr_ev_handler_t h, + td_event_e e); + +long xc_ptrace( + int xc_handle, + enum __ptrace_request request, + uint32_t domid, + long addr, + long data); + +int xc_waitdomain( + int xc_handle, + int domain, + int *status, + int options); + +#endif /* XC_PTRACE */ _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |