ia64/xen-unstable

changeset 8399:b5b7a9d9fc56

Add MP debug support to gdbserver.

Signed-off-by: Kip Macy <kip.macy@gmail.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Dec 15 21:02:21 2005 +0100 (2005-12-15)
parents 803d5e9ae5f4
children 6b1d39a56c2b
files tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c tools/libxc/xc_domain.c tools/libxc/xc_ptrace.c tools/libxc/xc_ptrace.h tools/libxc/xenctrl.h
line diff
     1.1 --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Thu Dec 15 20:46:08 2005 +0100
     1.2 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Thu Dec 15 21:02:21 2005 +0100
     1.3 @@ -36,23 +36,41 @@
     1.4  #include <unistd.h>
     1.5  #include <errno.h>
     1.6  #include <xenctrl.h>
     1.7 +#include <thread_db.h>
     1.8 +#include <xc_ptrace.h>
     1.9 +
    1.10  #define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */
    1.11  
    1.12  long (*myptrace)(int xc_handle, enum __ptrace_request, uint32_t, long, long);
    1.13  int (*myxcwait)(int xc_handle, int domain, int *status, int options) ;
    1.14  static int xc_handle;
    1.15  
    1.16 +static inline int
    1.17 +curvcpuid()
    1.18 +{
    1.19 +  struct process_info *process;
    1.20 +  if (current_inferior == NULL)
    1.21 +      return 0;
    1.22 +  process = get_thread_process(current_inferior);
    1.23 +  return (process->thread_known ? process->tid : 0);
    1.24 +
    1.25 +}
    1.26 +
    1.27 +
    1.28  #define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
    1.29  #define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
    1.30  #define DOMFLAGS_PAUSED    (1<<3) /* Currently paused by control software.   */
    1.31  #define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
    1.32  #define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
    1.33  
    1.34 +
    1.35 +
    1.36  struct inferior_list all_processes;
    1.37 -static int current_domain;
    1.38 +static int current_domid;
    1.39  static int expect_signal = 0;
    1.40  static int signal_to_send = 0; 
    1.41  static void linux_resume (struct thread_resume *resume_info);
    1.42 +static void linux_set_inferior (void);
    1.43  
    1.44  int debug_threads;
    1.45  int using_threads;
    1.46 @@ -96,7 +114,6 @@ static int use_regsets_p = 1;
    1.47     point at the following instruction.  If we continue and hit a
    1.48     breakpoint instruction, our PC will point at the breakpoint
    1.49     instruction.  */
    1.50 -#if 0
    1.51  static CORE_ADDR
    1.52  get_stop_pc (void)
    1.53  {
    1.54 @@ -107,9 +124,9 @@ get_stop_pc (void)
    1.55    else
    1.56      return stop_pc - the_low_target.decr_pc_after_break;
    1.57  }
    1.58 -#endif
    1.59 +
    1.60  static void *
    1.61 -add_process (int pid)
    1.62 +add_process (int pid, long tid)
    1.63  {
    1.64    struct process_info *process;
    1.65  
    1.66 @@ -118,9 +135,8 @@ add_process (int pid)
    1.67  
    1.68    process->head.id = pid;
    1.69  
    1.70 -  /* Default to tid == lwpid == pid.  */
    1.71 -  process->tid = pid;
    1.72 -  process->lwpid = pid;
    1.73 +  process->tid = tid;
    1.74 +  process->lwpid = tid;
    1.75  
    1.76    add_inferior_to_list (&all_processes, &process->head);
    1.77  
    1.78 @@ -143,23 +159,25 @@ linux_create_inferior (char *program, ch
    1.79  }
    1.80  
    1.81  int
    1.82 -linux_attach (int domain)
    1.83 +linux_attach (int domid)
    1.84  {
    1.85      struct process_info *new_process;
    1.86 -    current_domain = domain;
    1.87 -    if (myptrace (xc_handle, PTRACE_ATTACH, domain, 0, 0) != 0) {
    1.88 -	fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domain,
    1.89 +    current_domid = domid;
    1.90 +    /* this is handled for all active vcpus in PTRACE_ATTACH via the thread_create_callback */
    1.91 +    new_process = (struct process_info *) add_process (domid, curvcpuid());
    1.92 +    /* Don't ignore the initial SIGSTOP if we just attached to this process.  */
    1.93 +    /* vcpuid == 0 */
    1.94 +    add_thread (0, new_process);
    1.95 +    new_process->stop_expected = 0;
    1.96 +
    1.97 +    if (myptrace (xc_handle, PTRACE_ATTACH, domid, 0, 0) != 0) {
    1.98 +	fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domid,
    1.99  		 strerror (errno), errno);
   1.100  	fflush (stderr);
   1.101 -	_exit (0177);
   1.102 +	if (!using_threads)
   1.103 +	    _exit (0177);
   1.104      }
   1.105 -    
   1.106 -    new_process = (struct process_info *) add_process (domain);
   1.107 -    add_thread (domain, new_process);
   1.108  
   1.109 -    /* Don't ignore the initial SIGSTOP if we just attached to this process.  */
   1.110 -    new_process->stop_expected = 0;
   1.111 -    
   1.112      return 0;
   1.113  }
   1.114  
   1.115 @@ -173,20 +191,18 @@ linux_kill_one_process (struct inferior_
   1.116    myptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0);
   1.117  }
   1.118  
   1.119 +
   1.120  static void
   1.121  linux_kill (void)
   1.122  {
   1.123    for_each_inferior (&all_threads, linux_kill_one_process);
   1.124  }
   1.125  
   1.126 -
   1.127  static void
   1.128  linux_detach_one_process (struct inferior_list_entry *entry)
   1.129  {
   1.130 -  struct thread_info *thread = (struct thread_info *) entry;
   1.131 -  struct process_info *process = get_thread_process (thread);
   1.132  
   1.133 -  myptrace (xc_handle, PTRACE_DETACH, pid_of (process), 0, 0);
   1.134 +  myptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0);
   1.135  }
   1.136  
   1.137  
   1.138 @@ -212,7 +228,7 @@ static unsigned char
   1.139  linux_wait (char *status)
   1.140  {
   1.141    int w;
   1.142 -  if (myxcwait(xc_handle, current_domain, &w, 0))
   1.143 +  if (myxcwait(xc_handle, current_domid, &w, 0))
   1.144        return -1;
   1.145    
   1.146    if (w & (DOMFLAGS_SHUTDOWN|DOMFLAGS_DYING)) {
   1.147 @@ -220,6 +236,7 @@ linux_wait (char *status)
   1.148        return 0;
   1.149    }
   1.150  
   1.151 +  linux_set_inferior();
   1.152  
   1.153    *status = 'T';
   1.154    if (expect_signal)
   1.155 @@ -236,8 +253,10 @@ linux_resume (struct thread_resume *resu
   1.156    TRACE_ENTER;
   1.157    expect_signal = resume_info->sig;
   1.158    for_each_inferior(&all_threads, regcache_invalidate_one);
   1.159 -
   1.160 -  myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, current_domain, 0, 0);
   1.161 +  if (debug_threads)
   1.162 +    fprintf(stderr, "step: %d\n", step);
   1.163 +  myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, 
   1.164 +	    resume_info->thread, 0, 0);
   1.165  
   1.166  }
   1.167  
   1.168 @@ -261,7 +280,9 @@ regsets_fetch_inferior_registers ()
   1.169  	}
   1.170  
   1.171        buf = malloc (regset->size);
   1.172 -      res = myptrace (xc_handle, regset->get_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf);
   1.173 +      res = myptrace (xc_handle, regset->get_request, 
   1.174 +		      curvcpuid(),
   1.175 +		      0, (PTRACE_XFER_TYPE)buf);
   1.176        if (res < 0)
   1.177  	{
   1.178  	  if (errno == EIO)
   1.179 @@ -313,7 +334,7 @@ regsets_store_inferior_registers ()
   1.180  
   1.181        buf = malloc (regset->size);
   1.182        regset->fill_function (buf);
   1.183 -      res = myptrace (xc_handle, regset->set_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf);
   1.184 +      res = myptrace (xc_handle, regset->set_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf);
   1.185        if (res < 0)
   1.186  	{
   1.187  	  if (errno == EIO)
   1.188 @@ -391,7 +412,7 @@ linux_read_memory (CORE_ADDR memaddr, ch
   1.189    for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
   1.190      {
   1.191        errno = 0;
   1.192 -      buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
   1.193 +      buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0);
   1.194        if (errno)
   1.195  	return errno;
   1.196      }
   1.197 @@ -424,13 +445,13 @@ linux_write_memory (CORE_ADDR memaddr, c
   1.198  
   1.199    /* Fill start and end extra bytes of buffer with existing memory data.  */
   1.200  
   1.201 -  buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid,
   1.202 +  buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
   1.203  		      (PTRACE_ARG3_TYPE) addr, 0);
   1.204  
   1.205    if (count > 1)
   1.206      {
   1.207        buffer[count - 1]
   1.208 -	= myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid,
   1.209 +	= myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
   1.210  		  (PTRACE_ARG3_TYPE) (addr + (count - 1)
   1.211  				      * sizeof (PTRACE_XFER_TYPE)),
   1.212  		  0);
   1.213 @@ -444,7 +465,8 @@ linux_write_memory (CORE_ADDR memaddr, c
   1.214    for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
   1.215      {
   1.216        errno = 0;
   1.217 -      myptrace (xc_handle, PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
   1.218 +      myptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(), 
   1.219 +		(PTRACE_ARG3_TYPE) addr, buffer[i]);
   1.220        if (errno)
   1.221  	return errno;
   1.222      }
   1.223 @@ -455,9 +477,11 @@ linux_write_memory (CORE_ADDR memaddr, c
   1.224  static void
   1.225  linux_look_up_symbols (void)
   1.226  {
   1.227 -#if 0
   1.228 +  if (using_threads) 
   1.229 +    return;
   1.230 +
   1.231    using_threads = thread_db_init ();
   1.232 -#endif
   1.233 +
   1.234  }
   1.235  
   1.236  static void
   1.237 @@ -535,6 +559,7 @@ linux_init_signals ()
   1.238  void
   1.239  initialize_low (void)
   1.240  {
   1.241 +  using_threads = 0;
   1.242    xc_handle = xc_interface_open();
   1.243    set_target_ops (&linux_xen_target_ops);
   1.244    set_breakpoint_data (the_low_target.breakpoint,
   1.245 @@ -548,5 +573,122 @@ initialize_low (void)
   1.246        myptrace = xc_ptrace;
   1.247        myxcwait = xc_waitdomain;
   1.248    }
   1.249 +  using_threads = thread_db_init ();
   1.250  
   1.251  }
   1.252 +
   1.253 +
   1.254 +static void
   1.255 +thread_create_callback(long vcpuid)
   1.256 +{
   1.257 +  struct thread_info *inferior;
   1.258 +  struct process_info *process;
   1.259 +
   1.260 +  /*  If we are attaching to our first thread, things are a little
   1.261 +   *  different.  
   1.262 +   */
   1.263 +  if (all_threads.head == all_threads.tail)
   1.264 +    {
   1.265 +      inferior = (struct thread_info *) all_threads.head;
   1.266 +      process = get_thread_process (inferior);
   1.267 +      if (process->thread_known == 0)
   1.268 +	{
   1.269 +	  /* Switch to indexing the threads list by TID.  */
   1.270 +	  change_inferior_id (&all_threads, vcpuid);
   1.271 +	  goto found;
   1.272 +	}
   1.273 +    }
   1.274 +  if (debug_threads)
   1.275 +    fprintf (stderr, "looking up thread %ld\n",
   1.276 +	     vcpuid);
   1.277 +  inferior = (struct thread_info *) find_inferior_id (&all_threads,
   1.278 +						      vcpuid);
   1.279 +  /* if vcpu alread registered - do nothing */
   1.280 +  if (inferior != NULL) 
   1.281 +    return;
   1.282 +
   1.283 +  if (debug_threads)
   1.284 +    fprintf (stderr, "Attaching to thread %ld\n",
   1.285 +	     vcpuid);
   1.286 +
   1.287 +  process = add_process(current_domid, vcpuid);
   1.288 +
   1.289 +  add_thread(vcpuid, process);
   1.290 +  inferior = (struct thread_info *) find_inferior_id (&all_threads,
   1.291 +						      vcpuid);
   1.292 +  if (inferior == NULL)
   1.293 +    {
   1.294 +      warning ("Could not attach to thread %ld\n",
   1.295 +	       vcpuid);
   1.296 +      return;
   1.297 +    }
   1.298 +
   1.299 +
   1.300 +found:
   1.301 +  if (debug_threads)
   1.302 +    fprintf (stderr, "notifying of new thread %ld\n",
   1.303 +	     vcpuid);
   1.304 +  new_thread_notify (vcpuid);
   1.305 +
   1.306 +  process->tid = vcpuid;
   1.307 +  process->lwpid = vcpuid;
   1.308 +
   1.309 +  process->thread_known = 1;
   1.310 +}
   1.311 +
   1.312 +static void
   1.313 +thread_death_callback(long vcpuid)
   1.314 +{
   1.315 +    if (debug_threads)
   1.316 +      fprintf (stderr, "Buuurp...! CPU down event.\n");
   1.317 +}
   1.318 +
   1.319 +int
   1.320 +thread_db_init(void)
   1.321 +{
   1.322 +  debug_threads = 0;
   1.323 +  xc_register_event_handler(thread_create_callback, TD_CREATE);
   1.324 +  xc_register_event_handler(thread_death_callback, TD_DEATH);
   1.325 +  return 1;
   1.326 +}
   1.327 +
   1.328 +/* XXX GAG ME */
   1.329 +static int breakpoint_found;
   1.330 +static void
   1.331 +set_breakpoint_inferior (struct inferior_list_entry *entry)
   1.332 +{
   1.333 +  struct thread_info *thread = (struct thread_info *) entry;
   1.334 +  struct thread_info *saved_inferior = current_inferior;
   1.335 +  CORE_ADDR eip;
   1.336 +  unsigned char buf[2] = {0, 0};
   1.337 +  current_inferior = thread;
   1.338 +  if (!breakpoint_found) {
   1.339 +    eip = get_stop_pc();
   1.340 +    linux_read_memory(eip, buf, 1);
   1.341 +    if (buf[0] == 0xcc) {
   1.342 +      breakpoint_found = 1;
   1.343 +      return;
   1.344 +    }
   1.345 +  } else if (breakpoint_found == 2) {
   1.346 +    if (get_thread_process (current_inferior)->stepping) {
   1.347 +      printf("stepping\n");
   1.348 +      breakpoint_found = 1;
   1.349 +      return;
   1.350 +    } 
   1.351 +  }
   1.352 +  current_inferior = saved_inferior;
   1.353 +
   1.354 +
   1.355 +}
   1.356 +
   1.357 +static void
   1.358 +linux_set_inferior (void)
   1.359 +{
   1.360 +  breakpoint_found = 0;
   1.361 +  for_each_inferior (&all_threads, set_breakpoint_inferior);
   1.362 +  if (!breakpoint_found) {
   1.363 +    breakpoint_found = 2;
   1.364 +    for_each_inferior (&all_threads, set_breakpoint_inferior);
   1.365 +  }
   1.366 +}
   1.367 +
     2.1 --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c	Thu Dec 15 20:46:08 2005 +0100
     2.2 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c	Thu Dec 15 21:02:21 2005 +0100
     2.3 @@ -20,7 +20,7 @@
     2.4     Boston, MA 02111-1307, USA.  */
     2.5  
     2.6  #include "server.h"
     2.7 -
     2.8 +#include "linux-low.h"
     2.9  #include <unistd.h>
    2.10  #include <signal.h>
    2.11  #include <sys/wait.h>
    2.12 @@ -102,7 +102,15 @@ handle_query (char *own_buf)
    2.13        strcpy (own_buf, "OK");
    2.14        return;
    2.15      }
    2.16 +  if (strcmp ("qC", own_buf) == 0)
    2.17 +    {
    2.18 +      struct process_info *process;
    2.19 +      if (current_inferior == NULL)
    2.20 +	return;
    2.21 +      process = get_thread_process(current_inferior);
    2.22 +      sprintf(own_buf, "QC%x", process->thread_known ? process->tid : 0);
    2.23  
    2.24 +    }
    2.25    if (strcmp ("qfThreadInfo", own_buf) == 0)
    2.26      {
    2.27        thread_ptr = all_threads.head;
     3.1 --- a/tools/libxc/xc_domain.c	Thu Dec 15 20:46:08 2005 +0100
     3.2 +++ b/tools/libxc/xc_domain.c	Thu Dec 15 21:02:21 2005 +0100
     3.3 @@ -380,6 +380,30 @@ int xc_domain_ioport_permission(int xc_h
     3.4      return do_dom0_op(xc_handle, &op);
     3.5  }
     3.6  
     3.7 +int xc_domain_setinfo(int xc_handle,
     3.8 +                      uint32_t domid,
     3.9 +                      uint32_t vcpu,
    3.10 +                      vcpu_guest_context_t *ctxt)
    3.11 +{
    3.12 +    dom0_op_t op;
    3.13 +    int rc;
    3.14 +
    3.15 +    op.cmd = DOM0_SETDOMAININFO;
    3.16 +    op.u.setdomaininfo.domain = domid;
    3.17 +    op.u.setdomaininfo.vcpu = vcpu;
    3.18 +    op.u.setdomaininfo.ctxt = ctxt;
    3.19 +
    3.20 +    if ( (rc = mlock(ctxt, sizeof(*ctxt))) != 0 )
    3.21 +        return rc;
    3.22 +
    3.23 +    rc = do_dom0_op(xc_handle, &op);
    3.24 +
    3.25 +    safe_munlock(ctxt, sizeof(*ctxt));
    3.26 +
    3.27 +    return rc;
    3.28 +
    3.29 +}
    3.30 +
    3.31  /*
    3.32   * Local variables:
    3.33   * mode: C
     4.1 --- a/tools/libxc/xc_ptrace.c	Thu Dec 15 20:46:08 2005 +0100
     4.2 +++ b/tools/libxc/xc_ptrace.c	Thu Dec 15 21:02:21 2005 +0100
     4.3 @@ -1,138 +1,141 @@
     4.4 +#define XC_PTRACE_PRIVATE
     4.5 +
     4.6 +
     4.7  #include <sys/ptrace.h>
     4.8  #include <sys/wait.h>
     4.9 -#include "xc_private.h"
    4.10 -#include "xg_private.h"
    4.11  #include <time.h>
    4.12  
    4.13 -#define X86_CR0_PE              0x00000001 /* Enable Protected Mode    (RW) */
    4.14 -#define X86_CR0_PG              0x80000000 /* Paging                   (RW) */
    4.15 -#define BSD_PAGE_MASK (PAGE_SIZE-1)
    4.16 -#define PDRSHIFT        22
    4.17 -#define PSL_T  0x00000100 /* trace enable bit */
    4.18 -#define VCPU            0               /* XXX */
    4.19 +#include "xc_private.h"
    4.20 +#include "xg_private.h"
    4.21 +#include <thread_db.h>
    4.22 +#include "xc_ptrace.h"
    4.23 +
    4.24  
    4.25 -char * ptrace_names[] = {
    4.26 -    "PTRACE_TRACEME",
    4.27 -    "PTRACE_PEEKTEXT",
    4.28 -    "PTRACE_PEEKDATA",
    4.29 -    "PTRACE_PEEKUSER",
    4.30 -    "PTRACE_POKETEXT",
    4.31 -    "PTRACE_POKEDATA",
    4.32 -    "PTRACE_POKEUSER",
    4.33 -    "PTRACE_CONT",
    4.34 -    "PTRACE_KILL",
    4.35 -    "PTRACE_SINGLESTEP",
    4.36 -    "PTRACE_INVALID",
    4.37 -    "PTRACE_INVALID",
    4.38 -    "PTRACE_GETREGS",
    4.39 -    "PTRACE_SETREGS",
    4.40 -    "PTRACE_GETFPREGS",
    4.41 -    "PTRACE_SETFPREGS",
    4.42 -    "PTRACE_ATTACH",
    4.43 -    "PTRACE_DETACH",
    4.44 -    "PTRACE_GETFPXREGS",
    4.45 -    "PTRACE_SETFPXREGS",
    4.46 -    "PTRACE_INVALID",
    4.47 -    "PTRACE_INVALID",
    4.48 -    "PTRACE_INVALID",
    4.49 -    "PTRACE_INVALID",
    4.50 -    "PTRACE_SYSCALL",
    4.51 -};
    4.52 +/* XXX application state */
    4.53 +static long                     nr_pages = 0;
    4.54 +static unsigned long           *page_array = NULL;
    4.55 +static int                      current_domid = -1;
    4.56 +
    4.57 +static cpumap_t                 online_cpumap;
    4.58 +static cpumap_t                 regs_valid;
    4.59 +static vcpu_guest_context_t     ctxt[MAX_VIRT_CPUS];
    4.60 +
    4.61 +extern int ffsll(long long int);
    4.62 +#define FOREACH_CPU(cpumap, i)  for ( cpumap = online_cpumap; (i = ffsll(cpumap)); cpumap &= ~(1 << (index - 1)) ) 
    4.63 +
    4.64  
    4.65 -struct gdb_regs {
    4.66 -    long ebx; /* 0 */
    4.67 -    long ecx; /* 4 */
    4.68 -    long edx; /* 8 */
    4.69 -    long esi; /* 12 */
    4.70 -    long edi; /* 16 */
    4.71 -    long ebp; /* 20 */
    4.72 -    long eax; /* 24 */ 
    4.73 -    int  xds; /* 28 */
    4.74 -    int  xes; /* 32 */
    4.75 -    int  xfs; /* 36 */
    4.76 -    int  xgs; /* 40 */
    4.77 -    long orig_eax; /* 44 */
    4.78 -    long eip;    /* 48 */
    4.79 -    int  xcs;    /* 52 */
    4.80 -    long eflags; /* 56 */
    4.81 -    long esp;    /* 60 */     
    4.82 -    int  xss;    /* 64 */
    4.83 -};
    4.84 +static int
    4.85 +fetch_regs(int xc_handle, int cpu, int *online)
    4.86 +{
    4.87 +    xc_vcpuinfo_t info;
    4.88 +    int retval = 0;
    4.89  
    4.90 -#define FETCH_REGS(cpu)                                         \
    4.91 -    if (!regs_valid[cpu])                                       \
    4.92 -    {                                                           \
    4.93 -        int retval = xc_domain_get_vcpu_context(                \
    4.94 -            xc_handle, domid, cpu, &ctxt[cpu]);                 \
    4.95 -        if (retval)                                             \
    4.96 -            goto error_out;                                     \
    4.97 -        cr3[cpu] = ctxt[cpu].ctrlreg[3]; /* physical address */ \
    4.98 -        regs_valid[cpu] = 1;                                    \
    4.99 -    }
   4.100 +    if (online)
   4.101 +        *online = 0;
   4.102 +    if ( !(regs_valid & (1 << cpu)) ) { 
   4.103 +        retval = xc_domain_get_vcpu_context(xc_handle, current_domid, 
   4.104 +						cpu, &ctxt[cpu]);
   4.105 +        if ( retval ) 
   4.106 +            goto done;
   4.107 +	regs_valid |= (1 << cpu);
   4.108  
   4.109 -#define printval(x) printf("%s = %lx\n", #x, (long)x);
   4.110 -#define SET_PT_REGS(pt, xc)                     \
   4.111 -{                                               \
   4.112 -    pt.ebx = xc.ebx;                            \
   4.113 -    pt.ecx = xc.ecx;                            \
   4.114 -    pt.edx = xc.edx;                            \
   4.115 -    pt.esi = xc.esi;                            \
   4.116 -    pt.edi = xc.edi;                            \
   4.117 -    pt.ebp = xc.ebp;                            \
   4.118 -    pt.eax = xc.eax;                            \
   4.119 -    pt.eip = xc.eip;                            \
   4.120 -    pt.xcs = xc.cs;                             \
   4.121 -    pt.eflags = xc.eflags;                      \
   4.122 -    pt.esp = xc.esp;                            \
   4.123 -    pt.xss = xc.ss;                             \
   4.124 -    pt.xes = xc.es;                             \
   4.125 -    pt.xds = xc.ds;                             \
   4.126 -    pt.xfs = xc.fs;                             \
   4.127 -    pt.xgs = xc.gs;                             \
   4.128 +    }
   4.129 +	if ( online == NULL )
   4.130 +	    goto done;
   4.131 +
   4.132 +	retval = xc_domain_get_vcpu_info(xc_handle, current_domid,
   4.133 +					 cpu, &info);
   4.134 +	*online = info.online;
   4.135 +    
   4.136 + done:
   4.137 +    return retval;    
   4.138  }
   4.139  
   4.140 -#define SET_XC_REGS(pt, xc)                     \
   4.141 -{                                               \
   4.142 -    xc.ebx = pt->ebx;                           \
   4.143 -    xc.ecx = pt->ecx;                           \
   4.144 -    xc.edx = pt->edx;                           \
   4.145 -    xc.esi = pt->esi;                           \
   4.146 -    xc.edi = pt->edi;                           \
   4.147 -    xc.ebp = pt->ebp;                           \
   4.148 -    xc.eax = pt->eax;                           \
   4.149 -    xc.eip = pt->eip;                           \
   4.150 -    xc.cs = pt->xcs;                            \
   4.151 -    xc.eflags = pt->eflags;                     \
   4.152 -    xc.esp = pt->esp;                           \
   4.153 -    xc.ss = pt->xss;                            \
   4.154 -    xc.es = pt->xes;                            \
   4.155 -    xc.ds = pt->xds;                            \
   4.156 -    xc.fs = pt->xfs;                            \
   4.157 -    xc.gs = pt->xgs;                            \
   4.158 +#define FETCH_REGS(cpu) if (fetch_regs(xc_handle, cpu, NULL)) goto error_out;
   4.159 +
   4.160 +
   4.161 +static struct thr_ev_handlers {
   4.162 +    thr_ev_handler_t td_create;
   4.163 +    thr_ev_handler_t td_death;
   4.164 +} handlers;
   4.165 +
   4.166 +void 
   4.167 +xc_register_event_handler(thr_ev_handler_t h, 
   4.168 +                          td_event_e e)
   4.169 +{
   4.170 +    switch (e) {
   4.171 +    case TD_CREATE:
   4.172 +        handlers.td_create = h;
   4.173 +        break;
   4.174 +    case TD_DEATH:
   4.175 +        handlers.td_death = h;
   4.176 +        break;
   4.177 +    default:
   4.178 +        abort(); /* XXX */
   4.179 +    }
   4.180  }
   4.181  
   4.182 -#define vtopdi(va) ((va) >> PDRSHIFT)
   4.183 -#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
   4.184 -
   4.185 -/* XXX application state */
   4.186 -static long   nr_pages = 0;
   4.187 -unsigned long   *page_array = NULL;
   4.188 -static int                      regs_valid[MAX_VIRT_CPUS];
   4.189 -static unsigned long            cr3[MAX_VIRT_CPUS];
   4.190 -static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
   4.191 -
   4.192 -static inline int paging_enabled(vcpu_guest_context_t *v)
   4.193 +static inline int 
   4.194 +paging_enabled(vcpu_guest_context_t *v)
   4.195  {
   4.196      unsigned long cr0 = v->ctrlreg[0];
   4.197      return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
   4.198  }
   4.199  
   4.200 +/*
   4.201 + * Fetch registers for all online cpus and set the cpumap
   4.202 + * to indicate which cpus are online
   4.203 + *
   4.204 + */
   4.205 +
   4.206 +static int
   4.207 +get_online_cpumap(int xc_handle, dom0_getdomaininfo_t *d, cpumap_t *cpumap)
   4.208 +{
   4.209 +    int i, online, retval;
   4.210 +    
   4.211 +    *cpumap = 0;
   4.212 +    for (i = 0; i <= d->max_vcpu_id; i++) {
   4.213 +        if ((retval = fetch_regs(xc_handle, i, &online)))
   4.214 +            goto error_out;        
   4.215 +        if (online)
   4.216 +            *cpumap |= (1 << i);            
   4.217 +    }
   4.218 +    
   4.219 +    return 0;
   4.220 + error_out:
   4.221 +    return retval;
   4.222 +}
   4.223 +
   4.224 +/* 
   4.225 + * Notify GDB of any vcpus that have come online or gone offline
   4.226 + * update online_cpumap
   4.227 + *
   4.228 + */
   4.229 +
   4.230 +static void
   4.231 +online_vcpus_changed(cpumap_t cpumap)
   4.232 +{
   4.233 +    cpumap_t changed_cpumap = cpumap ^ online_cpumap;
   4.234 +    int index;
   4.235 +    
   4.236 +    while ( (index = ffsll(changed_cpumap)) ) {
   4.237 +        if ( cpumap & (1 << (index - 1)) ) {
   4.238 +            if (handlers.td_create) handlers.td_create(index - 1);
   4.239 +        } else {
   4.240 +            printf("thread death: %d\n", index - 1);
   4.241 +            if (handlers.td_death) handlers.td_death(index - 1);
   4.242 +        }
   4.243 +        changed_cpumap &= ~(1 << (index - 1));
   4.244 +    }
   4.245 +    online_cpumap = cpumap;
   4.246 +    
   4.247 +}
   4.248 +
   4.249  /* --------------------- */
   4.250  
   4.251  static void *
   4.252  map_domain_va_pae(
   4.253      int xc_handle,
   4.254 -    unsigned long domid,
   4.255      int cpu,
   4.256      void *guest_va,
   4.257      int perm)
   4.258 @@ -144,24 +147,24 @@ map_domain_va_pae(
   4.259      FETCH_REGS(cpu);
   4.260  
   4.261      l3 = xc_map_foreign_range(
   4.262 -        xc_handle, domid, PAGE_SIZE, PROT_READ, cr3[cpu] >> PAGE_SHIFT);
   4.263 +        xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT);
   4.264      if ( l3 == NULL )
   4.265          goto error_out;
   4.266  
   4.267      l2p = l3[l3_table_offset_pae(va)] >> PAGE_SHIFT;
   4.268 -    l2 = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ, l2p);
   4.269 +    l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p);
   4.270      if ( l2 == NULL )
   4.271          goto error_out;
   4.272  
   4.273      l1p = l2[l2_table_offset_pae(va)] >> PAGE_SHIFT;
   4.274 -    l1 = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, perm, l1p);
   4.275 +    l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p);
   4.276      if ( l1 == NULL )
   4.277          goto error_out;
   4.278  
   4.279      p = l1[l1_table_offset_pae(va)] >> PAGE_SHIFT;
   4.280      if ( v != NULL )
   4.281          munmap(v, PAGE_SIZE);
   4.282 -    v = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, perm, p);
   4.283 +    v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p);
   4.284      if ( v == NULL )
   4.285          goto error_out;
   4.286  
   4.287 @@ -174,16 +177,17 @@ map_domain_va_pae(
   4.288  static void *
   4.289  map_domain_va(
   4.290      int xc_handle,
   4.291 -    unsigned long domid,
   4.292      int cpu,
   4.293      void *guest_va,
   4.294      int perm)
   4.295  {
   4.296 +
   4.297      unsigned long pde, page;
   4.298      unsigned long va = (unsigned long)guest_va;
   4.299 -    long npgs = xc_get_tot_pages(xc_handle, domid);
   4.300 +    long npgs = xc_get_tot_pages(xc_handle, current_domid);
   4.301  
   4.302 -    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
   4.303 +
   4.304 +    static uint32_t  cr3_phys[MAX_VIRT_CPUS];
   4.305      static unsigned long *cr3_virt[MAX_VIRT_CPUS];
   4.306      static unsigned long  pde_phys[MAX_VIRT_CPUS];
   4.307      static unsigned long *pde_virt[MAX_VIRT_CPUS];
   4.308 @@ -202,7 +206,7 @@ map_domain_va(
   4.309      }
   4.310  
   4.311      if ( mode == MODE_PAE )
   4.312 -        return map_domain_va_pae(xc_handle, domid, cpu, guest_va, perm);
   4.313 +        return map_domain_va_pae(xc_handle, cpu, guest_va, perm);
   4.314  
   4.315      if ( nr_pages != npgs )
   4.316      {
   4.317 @@ -214,7 +218,7 @@ map_domain_va(
   4.318              printf("Could not allocate memory\n");
   4.319              goto error_out;
   4.320          }
   4.321 -        if ( xc_get_pfn_list(xc_handle, domid,
   4.322 +        if ( xc_get_pfn_list(xc_handle, current_domid,
   4.323                               page_array, nr_pages) != nr_pages )
   4.324          {
   4.325              printf("Could not get the page frame list\n");
   4.326 @@ -224,13 +228,13 @@ map_domain_va(
   4.327  
   4.328      FETCH_REGS(cpu);
   4.329  
   4.330 -    if ( cr3[cpu] != cr3_phys[cpu] )
   4.331 +    if ( ctxt[cpu].ctrlreg[3] != cr3_phys[cpu] )
   4.332      {
   4.333 -        cr3_phys[cpu] = cr3[cpu];
   4.334 +        cr3_phys[cpu] = ctxt[cpu].ctrlreg[3];
   4.335          if ( cr3_virt[cpu] )
   4.336              munmap(cr3_virt[cpu], PAGE_SIZE);
   4.337          cr3_virt[cpu] = xc_map_foreign_range(
   4.338 -            xc_handle, domid, PAGE_SIZE, PROT_READ,
   4.339 +            xc_handle, current_domid, PAGE_SIZE, PROT_READ,
   4.340              cr3_phys[cpu] >> PAGE_SHIFT);
   4.341          if ( cr3_virt[cpu] == NULL )
   4.342              goto error_out;
   4.343 @@ -245,7 +249,7 @@ map_domain_va(
   4.344          if ( pde_virt[cpu] )
   4.345              munmap(pde_virt[cpu], PAGE_SIZE);
   4.346          pde_virt[cpu] = xc_map_foreign_range(
   4.347 -            xc_handle, domid, PAGE_SIZE, PROT_READ,
   4.348 +            xc_handle, current_domid, PAGE_SIZE, PROT_READ,
   4.349              pde_phys[cpu] >> PAGE_SHIFT);
   4.350          if ( pde_virt[cpu] == NULL )
   4.351              goto error_out;
   4.352 @@ -260,7 +264,7 @@ map_domain_va(
   4.353          if ( page_virt[cpu] )
   4.354              munmap(page_virt[cpu], PAGE_SIZE);
   4.355          page_virt[cpu] = xc_map_foreign_range(
   4.356 -            xc_handle, domid, PAGE_SIZE, perm,
   4.357 +            xc_handle, current_domid, PAGE_SIZE, perm,
   4.358              page_phys[cpu] >> PAGE_SHIFT);
   4.359          if ( page_virt[cpu] == NULL )
   4.360          {
   4.361 @@ -286,12 +290,15 @@ xc_waitdomain(
   4.362      DECLARE_DOM0_OP;
   4.363      int retval;
   4.364      struct timespec ts;
   4.365 +    cpumap_t cpumap;
   4.366 +
   4.367      ts.tv_sec = 0;
   4.368      ts.tv_nsec = 10*1000*1000;
   4.369  
   4.370      op.cmd = DOM0_GETDOMAININFO;
   4.371      op.u.getdomaininfo.domain = domain;
   4.372 -
   4.373 +    
   4.374 +    
   4.375   retry:
   4.376      retval = do_dom0_op(xc_handle, &op);
   4.377      if ( retval || (op.u.getdomaininfo.domain != domain) )
   4.378 @@ -309,17 +316,22 @@ xc_waitdomain(
   4.379          nanosleep(&ts,NULL);
   4.380          goto retry;
   4.381      }
   4.382 -
   4.383 +    /* XXX check for ^C here */
   4.384   done:
   4.385 +    if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap))
   4.386 +        printf("get_online_cpumap failed\n");
   4.387 +    if (online_cpumap != cpumap)
   4.388 +        online_vcpus_changed(cpumap);
   4.389      return retval;
   4.390  
   4.391  }
   4.392  
   4.393 +
   4.394  long
   4.395  xc_ptrace(
   4.396      int xc_handle,
   4.397      enum __ptrace_request request,
   4.398 -    uint32_t domid,
   4.399 +    uint32_t domid_tid,
   4.400      long eaddr,
   4.401      long edata)
   4.402  {
   4.403 @@ -328,18 +340,21 @@ xc_ptrace(
   4.404      struct gdb_regs pt;
   4.405      long            retval = 0;
   4.406      unsigned long  *guest_va;
   4.407 -    int             cpu = VCPU;
   4.408 +    cpumap_t        cpumap;
   4.409 +    int             cpu, index;
   4.410      void           *addr = (char *)eaddr;
   4.411      void           *data = (char *)edata;
   4.412  
   4.413      op.interface_version = DOM0_INTERFACE_VERSION;
   4.414 +
   4.415 +    cpu = (request != PTRACE_ATTACH) ? domid_tid : 0;
   4.416      
   4.417      switch ( request )
   4.418      { 
   4.419      case PTRACE_PEEKTEXT:
   4.420      case PTRACE_PEEKDATA:
   4.421          guest_va = (unsigned long *)map_domain_va(
   4.422 -            xc_handle, domid, cpu, addr, PROT_READ);
   4.423 +            xc_handle, cpu, addr, PROT_READ);
   4.424          if ( guest_va == NULL )
   4.425          {
   4.426              status = EFAULT;
   4.427 @@ -350,10 +365,10 @@ xc_ptrace(
   4.428  
   4.429      case PTRACE_POKETEXT:
   4.430      case PTRACE_POKEDATA:
   4.431 +        /* XXX assume that all CPUs have the same address space */
   4.432          guest_va = (unsigned long *)map_domain_va(
   4.433 -            xc_handle, domid, cpu, addr, PROT_READ|PROT_WRITE);
   4.434 -        if ( guest_va == NULL )
   4.435 -        {
   4.436 +                            xc_handle, cpu, addr, PROT_READ|PROT_WRITE);
   4.437 +        if ( guest_va == NULL ) {
   4.438              status = EFAULT;
   4.439              goto error_out;
   4.440          }
   4.441 @@ -363,6 +378,7 @@ xc_ptrace(
   4.442      case PTRACE_GETREGS:
   4.443      case PTRACE_GETFPREGS:
   4.444      case PTRACE_GETFPXREGS:
   4.445 +        
   4.446          FETCH_REGS(cpu);
   4.447          if ( request == PTRACE_GETREGS )
   4.448          {
   4.449 @@ -380,44 +396,18 @@ xc_ptrace(
   4.450          break;
   4.451  
   4.452      case PTRACE_SETREGS:
   4.453 -        op.cmd = DOM0_SETDOMAININFO;
   4.454 -        SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].user_regs);
   4.455 -        op.u.setdomaininfo.domain = domid;
   4.456 -        /* XXX need to understand multiple vcpus */
   4.457 -        op.u.setdomaininfo.vcpu = cpu;
   4.458 -        op.u.setdomaininfo.ctxt = &ctxt[cpu];
   4.459 -        retval = do_dom0_op(xc_handle, &op);
   4.460 +        SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs);
   4.461 +        retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
   4.462          if (retval)
   4.463              goto error_out;
   4.464          break;
   4.465  
   4.466 -    case PTRACE_ATTACH:
   4.467 -        op.cmd = DOM0_GETDOMAININFO;
   4.468 -        op.u.getdomaininfo.domain = domid;
   4.469 -        retval = do_dom0_op(xc_handle, &op);
   4.470 -        if ( retval || (op.u.getdomaininfo.domain != domid) )
   4.471 -        {
   4.472 -            perror("dom0 op failed");
   4.473 -            goto error_out;
   4.474 -        }
   4.475 -        if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED )
   4.476 -        {
   4.477 -            printf("domain currently paused\n");
   4.478 -            goto error_out;
   4.479 -        }
   4.480 -        printf("domain not currently paused\n");
   4.481 -        op.cmd = DOM0_PAUSEDOMAIN;
   4.482 -        op.u.pausedomain.domain = domid;
   4.483 -        retval = do_dom0_op(xc_handle, &op);
   4.484 -        break;
   4.485 -
   4.486      case PTRACE_SINGLESTEP:
   4.487 -        ctxt[VCPU].user_regs.eflags |= PSL_T;
   4.488 -        op.cmd = DOM0_SETDOMAININFO;
   4.489 -        op.u.setdomaininfo.domain = domid;
   4.490 -        op.u.setdomaininfo.vcpu = 0;
   4.491 -        op.u.setdomaininfo.ctxt = &ctxt[cpu];
   4.492 -        retval = do_dom0_op(xc_handle, &op); 
   4.493 +        /*  XXX we can still have problems if the user switches threads
   4.494 +         *  during single-stepping - but that just seems retarded
   4.495 +         */
   4.496 +        ctxt[cpu].user_regs.eflags |= PSL_T; 
   4.497 +        retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
   4.498          if ( retval )
   4.499          {
   4.500              perror("dom0 op failed");
   4.501 @@ -429,27 +419,44 @@ xc_ptrace(
   4.502      case PTRACE_DETACH:
   4.503          if ( request != PTRACE_SINGLESTEP )
   4.504          {
   4.505 -            FETCH_REGS(cpu);
   4.506 -            /* Clear trace flag */
   4.507 -            if ( ctxt[cpu].user_regs.eflags & PSL_T )
   4.508 -            {
   4.509 -                ctxt[cpu].user_regs.eflags &= ~PSL_T;
   4.510 -                op.cmd = DOM0_SETDOMAININFO;
   4.511 -                op.u.setdomaininfo.domain = domid;
   4.512 -                op.u.setdomaininfo.vcpu = cpu;
   4.513 -                op.u.setdomaininfo.ctxt = &ctxt[cpu];
   4.514 -                retval = do_dom0_op(xc_handle, &op); 
   4.515 -                if ( retval )
   4.516 -                {
   4.517 -                    perror("dom0 op failed");
   4.518 -                    goto error_out;
   4.519 +            FOREACH_CPU(cpumap, index) {
   4.520 +                cpu = index - 1;
   4.521 +                FETCH_REGS(cpu);
   4.522 +                /* Clear trace flag */
   4.523 +                if ( ctxt[cpu].user_regs.eflags & PSL_T ) {
   4.524 +                    ctxt[cpu].user_regs.eflags &= ~PSL_T;
   4.525 +                    retval = xc_domain_setinfo(xc_handle, current_domid, 
   4.526 +                                               cpu, &ctxt[cpu]);
   4.527 +                    if ( retval ) {
   4.528 +                        perror("dom0 op failed");
   4.529 +                        goto error_out;
   4.530 +                    }
   4.531                  }
   4.532              }
   4.533          }
   4.534 -        regs_valid[cpu] = 0;
   4.535 -        op.cmd = DOM0_UNPAUSEDOMAIN;
   4.536 -        op.u.unpausedomain.domain = domid > 0 ? domid : -domid;
   4.537 +        regs_valid = 0;
   4.538 +        xc_domain_unpause(xc_handle, current_domid > 0 ? current_domid : -current_domid);
   4.539 +        break;
   4.540 +
   4.541 +    case PTRACE_ATTACH:
   4.542 +        current_domid = domid_tid;
   4.543 +        op.cmd = DOM0_GETDOMAININFO;
   4.544 +        op.u.getdomaininfo.domain = current_domid;
   4.545          retval = do_dom0_op(xc_handle, &op);
   4.546 +        if ( retval || (op.u.getdomaininfo.domain != current_domid) )
   4.547 +        {
   4.548 +            perror("dom0 op failed");
   4.549 +            goto error_out;
   4.550 +        }
   4.551 +        if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED )
   4.552 +        {
   4.553 +            printf("domain currently paused\n");
   4.554 +        } else
   4.555 +            retval = xc_domain_pause(xc_handle, current_domid);
   4.556 +    if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap))
   4.557 +        printf("get_online_cpumap failed\n");
   4.558 +    if (online_cpumap != cpumap)
   4.559 +        online_vcpus_changed(cpumap);
   4.560          break;
   4.561  
   4.562      case PTRACE_SETFPREGS:
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/libxc/xc_ptrace.h	Thu Dec 15 21:02:21 2005 +0100
     5.3 @@ -0,0 +1,124 @@
     5.4 +#ifndef XC_PTRACE_
     5.5 +#define XC_PTRACE_
     5.6 +
     5.7 +#ifdef XC_PTRACE_PRIVATE
     5.8 +#define X86_CR0_PE              0x00000001 /* Enable Protected Mode    (RW) */
     5.9 +#define X86_CR0_PG              0x80000000 /* Paging                   (RW) */
    5.10 +#define BSD_PAGE_MASK (PAGE_SIZE-1)
    5.11 +#define PDRSHIFT        22
    5.12 +#define PSL_T  0x00000100 /* trace enable bit */
    5.13 +
    5.14 +char * ptrace_names[] = {
    5.15 +    "PTRACE_TRACEME",
    5.16 +    "PTRACE_PEEKTEXT",
    5.17 +    "PTRACE_PEEKDATA",
    5.18 +    "PTRACE_PEEKUSER",
    5.19 +    "PTRACE_POKETEXT",
    5.20 +    "PTRACE_POKEDATA",
    5.21 +    "PTRACE_POKEUSER",
    5.22 +    "PTRACE_CONT",
    5.23 +    "PTRACE_KILL",
    5.24 +    "PTRACE_SINGLESTEP",
    5.25 +    "PTRACE_INVALID",
    5.26 +    "PTRACE_INVALID",
    5.27 +    "PTRACE_GETREGS",
    5.28 +    "PTRACE_SETREGS",
    5.29 +    "PTRACE_GETFPREGS",
    5.30 +    "PTRACE_SETFPREGS",
    5.31 +    "PTRACE_ATTACH",
    5.32 +    "PTRACE_DETACH",
    5.33 +    "PTRACE_GETFPXREGS",
    5.34 +    "PTRACE_SETFPXREGS",
    5.35 +    "PTRACE_INVALID",
    5.36 +    "PTRACE_INVALID",
    5.37 +    "PTRACE_INVALID",
    5.38 +    "PTRACE_INVALID",
    5.39 +    "PTRACE_SYSCALL",
    5.40 +};
    5.41 +
    5.42 +struct gdb_regs {
    5.43 +    long ebx; /* 0 */
    5.44 +    long ecx; /* 4 */
    5.45 +    long edx; /* 8 */
    5.46 +    long esi; /* 12 */
    5.47 +    long edi; /* 16 */
    5.48 +    long ebp; /* 20 */
    5.49 +    long eax; /* 24 */ 
    5.50 +    int  xds; /* 28 */
    5.51 +    int  xes; /* 32 */
    5.52 +    int  xfs; /* 36 */
    5.53 +    int  xgs; /* 40 */
    5.54 +    long orig_eax; /* 44 */
    5.55 +    long eip;    /* 48 */
    5.56 +    int  xcs;    /* 52 */
    5.57 +    long eflags; /* 56 */
    5.58 +    long esp;    /* 60 */     
    5.59 +    int  xss;    /* 64 */
    5.60 +};
    5.61 +
    5.62 +
    5.63 +#define printval(x) printf("%s = %lx\n", #x, (long)x);
    5.64 +#define SET_PT_REGS(pt, xc)                     \
    5.65 +{                                               \
    5.66 +    pt.ebx = xc.ebx;                            \
    5.67 +    pt.ecx = xc.ecx;                            \
    5.68 +    pt.edx = xc.edx;                            \
    5.69 +    pt.esi = xc.esi;                            \
    5.70 +    pt.edi = xc.edi;                            \
    5.71 +    pt.ebp = xc.ebp;                            \
    5.72 +    pt.eax = xc.eax;                            \
    5.73 +    pt.eip = xc.eip;                            \
    5.74 +    pt.xcs = xc.cs;                             \
    5.75 +    pt.eflags = xc.eflags;                      \
    5.76 +    pt.esp = xc.esp;                            \
    5.77 +    pt.xss = xc.ss;                             \
    5.78 +    pt.xes = xc.es;                             \
    5.79 +    pt.xds = xc.ds;                             \
    5.80 +    pt.xfs = xc.fs;                             \
    5.81 +    pt.xgs = xc.gs;                             \
    5.82 +}
    5.83 +
    5.84 +#define SET_XC_REGS(pt, xc)                     \
    5.85 +{                                               \
    5.86 +    xc.ebx = pt->ebx;                           \
    5.87 +    xc.ecx = pt->ecx;                           \
    5.88 +    xc.edx = pt->edx;                           \
    5.89 +    xc.esi = pt->esi;                           \
    5.90 +    xc.edi = pt->edi;                           \
    5.91 +    xc.ebp = pt->ebp;                           \
    5.92 +    xc.eax = pt->eax;                           \
    5.93 +    xc.eip = pt->eip;                           \
    5.94 +    xc.cs = pt->xcs;                            \
    5.95 +    xc.eflags = pt->eflags;                     \
    5.96 +    xc.esp = pt->esp;                           \
    5.97 +    xc.ss = pt->xss;                            \
    5.98 +    xc.es = pt->xes;                            \
    5.99 +    xc.ds = pt->xds;                            \
   5.100 +    xc.fs = pt->xfs;                            \
   5.101 +    xc.gs = pt->xgs;                            \
   5.102 +}
   5.103 +
   5.104 +#define vtopdi(va) ((va) >> PDRSHIFT)
   5.105 +#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
   5.106 +#endif
   5.107 +
   5.108 +typedef void (*thr_ev_handler_t)(long);
   5.109 +
   5.110 +void xc_register_event_handler(
   5.111 +    thr_ev_handler_t h, 
   5.112 +    td_event_e e);
   5.113 +
   5.114 +long xc_ptrace(
   5.115 +    int xc_handle,
   5.116 +    enum __ptrace_request request, 
   5.117 +    uint32_t  domid,
   5.118 +    long addr, 
   5.119 +    long data);
   5.120 +
   5.121 +int xc_waitdomain(
   5.122 +    int xc_handle,
   5.123 +    int domain, 
   5.124 +    int *status, 
   5.125 +    int options);
   5.126 +
   5.127 +#endif /* XC_PTRACE */
     6.1 --- a/tools/libxc/xenctrl.h	Thu Dec 15 20:46:08 2005 +0100
     6.2 +++ b/tools/libxc/xenctrl.h	Thu Dec 15 21:02:21 2005 +0100
     6.3 @@ -94,13 +94,6 @@ typedef struct xc_core_header {
     6.4  } xc_core_header_t;
     6.5  
     6.6  
     6.7 -long xc_ptrace(
     6.8 -    int xc_handle,
     6.9 -    enum __ptrace_request request, 
    6.10 -    uint32_t  domid,
    6.11 -    long addr, 
    6.12 -    long data);
    6.13 -
    6.14  long xc_ptrace_core(
    6.15      int xc_handle,
    6.16      enum __ptrace_request request, 
    6.17 @@ -108,12 +101,6 @@ long xc_ptrace_core(
    6.18      long addr, 
    6.19      long data);
    6.20  
    6.21 -int xc_waitdomain(
    6.22 -    int xc_handle,
    6.23 -    int domain, 
    6.24 -    int *status, 
    6.25 -    int options);
    6.26 -
    6.27  int xc_waitdomain_core(
    6.28      int xc_handle,
    6.29      int domain, 
    6.30 @@ -219,6 +206,20 @@ int xc_domain_getinfo(int xc_handle,
    6.31                        unsigned int max_doms,
    6.32                        xc_dominfo_t *info);
    6.33  
    6.34 +
    6.35 +/**
    6.36 + * This function will set the vcpu context for the specified domain.
    6.37 + *
    6.38 + * @parm xc_handle a handle to an open hypervisor interface
    6.39 + * @parm domid the domain to set the vcpu context for
    6.40 + * @parm vcpu the vcpu number for the context
    6.41 + * @parm ctxt pointer to the the cpu context with the values to set
    6.42 + * @return the number of domains enumerated or -1 on error
    6.43 + */
    6.44 +int xc_domain_setinfo(int xc_handle,
    6.45 +                      uint32_t domid,
    6.46 +                      uint32_t vcpu,
    6.47 +                      vcpu_guest_context_t *ctxt);
    6.48  /**
    6.49   * This function will return information about one or more domains, using a
    6.50   * single hypercall.  The domain information will be stored into the supplied