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
|