WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] add mp debug support to gdbserver

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] add mp debug support to gdbserver
From: Kip Macy <kmacy@xxxxxxxxxxx>
Date: Sun, 4 Dec 2005 13:07:38 -0800 (PST)
Delivery-date: Mon, 05 Dec 2005 07:48:42 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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

<Prev in Thread] Current Thread [Next in Thread>