From: Kip Macy <kmacy@fsmware.com>
To: xen-devel@lists.xensource.com
Subject: [PATCH] add mp debug support to gdbserver
Date: Sun, 4 Dec 2005 13:07:38 -0800 (PST) [thread overview]
Message-ID: <20051204130552.M52946@demos.bsdclusters.com> (raw)
Please comment.
-Kip
# HG changeset patch
# User kmacy@localhost.localdomain
# 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 */
next reply other threads:[~2005-12-04 21:07 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-12-04 21:07 Kip Macy [this message]
-- strict thread matches above, loose matches on Subject: below --
2005-12-04 21:11 [PATCH] add MP debug support to gdbserver Kip Macy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20051204130552.M52946@demos.bsdclusters.com \
--to=kmacy@fsmware.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.