[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.