aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-09-19 15:21:09 +0000
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-09-19 15:21:09 +0000
commitb54b5b2b14960253c8309cae7b91147d5327f7db (patch)
tree951d43ad25e325a6606f19afe53c9f7082540c91 /tools/libxc
parente8b6ab5acb1a0db13602c644d869cbd6108740b7 (diff)
downloadxen-b54b5b2b14960253c8309cae7b91147d5327f7db.tar.gz
xen-b54b5b2b14960253c8309cae7b91147d5327f7db.tar.bz2
xen-b54b5b2b14960253c8309cae7b91147d5327f7db.zip
Fix xc_ptrace (live debug, not coredump debug) for 32-bit pae.
Clean up interfaces and add simple documentation for using the domU debug interfaces. Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'tools/libxc')
-rw-r--r--tools/libxc/Makefile2
-rw-r--r--tools/libxc/xc_ptrace.c230
-rw-r--r--tools/libxc/xc_ptrace_core.c13
-rw-r--r--tools/libxc/xenctrl.h42
4 files changed, 193 insertions, 94 deletions
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index f1ac817d1f..9c4b705641 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -30,8 +30,10 @@ BUILD_SRCS += xc_load_elf.c
ifeq ($(XEN_TARGET_ARCH),ia64)
BUILD_SRCS += xc_ia64_stubs.c
else
+ifeq ($(XEN_TARGET_ARCH),x86_32)
SRCS += xc_ptrace.c
SRCS += xc_ptrace_core.c
+endif
BUILD_SRCS += xc_load_aout9.c
BUILD_SRCS += xc_linux_restore.c
BUILD_SRCS += xc_linux_save.c
diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c
index 1fe0fcbe54..f1170d30f0 100644
--- a/tools/libxc/xc_ptrace.c
+++ b/tools/libxc/xc_ptrace.c
@@ -1,6 +1,7 @@
#include <sys/ptrace.h>
#include <sys/wait.h>
#include "xc_private.h"
+#include "xg_private.h"
#include <time.h>
#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */
@@ -10,14 +11,6 @@
#define PSL_T 0x00000100 /* trace enable bit */
#define VCPU 0 /* XXX */
-/*
- * long
- * ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
- */
-
-
-int waitdomain(int domain, int *status, int options);
-
char * ptrace_names[] = {
"PTRACE_TRACEME",
"PTRACE_PEEKTEXT",
@@ -122,8 +115,6 @@ struct gdb_regs {
#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
/* XXX application state */
-
-static int xc_handle;
static long nr_pages = 0;
unsigned long *page_array = NULL;
static int regs_valid[MAX_VIRT_CPUS];
@@ -133,14 +124,60 @@ static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
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);
}
/* --------------------- */
static void *
-map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm)
+map_domain_va_pae(
+ int xc_handle,
+ unsigned long domid,
+ int cpu,
+ void *guest_va,
+ int perm)
+{
+ unsigned long l2p, l1p, p, va = (unsigned long)guest_va;
+ u64 *l3, *l2, *l1;
+ static void *v;
+
+ FETCH_REGS(cpu);
+
+ l3 = xc_map_foreign_range(
+ xc_handle, domid, PAGE_SIZE, PROT_READ, cr3[cpu] >> 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);
+ 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);
+ 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);
+ if ( v == NULL )
+ goto error_out;
+
+ return (void *)((unsigned long)v | (va & (PAGE_SIZE - 1)));
+
+ error_out:
+ return NULL;
+}
+
+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;
@@ -151,20 +188,35 @@ map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm)
static unsigned long pde_phys[MAX_VIRT_CPUS];
static unsigned long *pde_virt[MAX_VIRT_CPUS];
static unsigned long page_phys[MAX_VIRT_CPUS];
- static unsigned long *page_virt[MAX_VIRT_CPUS];
-
+ static unsigned long *page_virt[MAX_VIRT_CPUS];
static int prev_perm[MAX_VIRT_CPUS];
+ static enum { MODE_UNKNOWN, MODE_32, MODE_PAE } mode;
+
+ if ( mode == MODE_UNKNOWN )
+ {
+ xen_capabilities_info_t caps;
+ (void)xc_version(xc_handle, XENVER_capabilities, caps);
+ mode = MODE_32;
+ if ( strstr(caps, "_x86_32p") )
+ mode = MODE_PAE;
+ }
+
+ if ( mode == MODE_PAE )
+ return map_domain_va_pae(xc_handle, domid, cpu, guest_va, perm);
- if (nr_pages != npgs) {
- if (nr_pages > 0)
+ if ( nr_pages != npgs )
+ {
+ if ( nr_pages > 0 )
free(page_array);
nr_pages = npgs;
- if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
+ if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
+ {
printf("Could not allocate memory\n");
goto error_out;
}
-
- if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) {
+ if ( xc_get_pfn_list(xc_handle, domid,
+ page_array, nr_pages) != nr_pages )
+ {
printf("Could not get the page frame list\n");
goto error_out;
}
@@ -172,48 +224,52 @@ map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm)
FETCH_REGS(cpu);
- if (cr3[cpu] != cr3_phys[cpu])
+ if ( cr3[cpu] != cr3_phys[cpu] )
{
cr3_phys[cpu] = cr3[cpu];
- if (cr3_virt[cpu])
+ if ( cr3_virt[cpu] )
munmap(cr3_virt[cpu], PAGE_SIZE);
- if ((cr3_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- PROT_READ,
- cr3_phys[cpu] >> PAGE_SHIFT)) == NULL)
+ cr3_virt[cpu] = xc_map_foreign_range(
+ xc_handle, domid, PAGE_SIZE, PROT_READ,
+ cr3_phys[cpu] >> PAGE_SHIFT);
+ if ( cr3_virt[cpu] == NULL )
goto error_out;
- }
- if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */
+ }
+ if ( (pde = cr3_virt[cpu][vtopdi(va)]) == 0 )
goto error_out;
- if ((ctxt[cpu].flags & VGCF_VMX_GUEST) && paging_enabled(&ctxt[cpu]))
+ if ( (ctxt[cpu].flags & VGCF_VMX_GUEST) && paging_enabled(&ctxt[cpu]) )
pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
- if (pde != pde_phys[cpu])
+ if ( pde != pde_phys[cpu] )
{
pde_phys[cpu] = pde;
- if (pde_virt[cpu])
+ if ( pde_virt[cpu] )
munmap(pde_virt[cpu], PAGE_SIZE);
- if ((pde_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- PROT_READ,
- pde_phys[cpu] >> PAGE_SHIFT)) == NULL)
+ pde_virt[cpu] = xc_map_foreign_range(
+ xc_handle, domid, PAGE_SIZE, PROT_READ,
+ pde_phys[cpu] >> PAGE_SHIFT);
+ if ( pde_virt[cpu] == NULL )
goto error_out;
}
- if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */
+ if ( (page = pde_virt[cpu][vtopti(va)]) == 0 )
goto error_out;
- if (ctxt[cpu].flags & VGCF_VMX_GUEST && paging_enabled(&ctxt[cpu]))
+ if ( (ctxt[cpu].flags & VGCF_VMX_GUEST) && paging_enabled(&ctxt[cpu]) )
page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
- if (page != page_phys[cpu] || perm != prev_perm[cpu])
+ if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) )
{
page_phys[cpu] = page;
- if (page_virt[cpu])
+ if ( page_virt[cpu] )
munmap(page_virt[cpu], PAGE_SIZE);
- if ((page_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- perm,
- page_phys[cpu] >> PAGE_SHIFT)) == NULL) {
- printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va));
+ page_virt[cpu] = xc_map_foreign_range(
+ xc_handle, domid, PAGE_SIZE, perm,
+ page_phys[cpu] >> PAGE_SHIFT);
+ if ( page_virt[cpu] == NULL )
+ {
page_phys[cpu] = 0;
goto error_out;
}
prev_perm[cpu] = perm;
}
+
return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
error_out:
@@ -221,7 +277,11 @@ map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm)
}
int
-xc_waitdomain(int domain, int *status, int options)
+xc_waitdomain(
+ int xc_handle,
+ int domain,
+ int *status,
+ int options)
{
dom0_op_t op;
int retval;
@@ -229,38 +289,39 @@ xc_waitdomain(int domain, int *status, int options)
ts.tv_sec = 0;
ts.tv_nsec = 10*1000*1000;
- if (!xc_handle)
- if ((xc_handle = xc_interface_open()) < 0)
- {
- printf("xc_interface_open failed\n");
- return -1;
- }
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = domain;
- retry:
+ retry:
retval = do_dom0_op(xc_handle, &op);
- if (retval || op.u.getdomaininfo.domain != domain) {
+ if ( retval || (op.u.getdomaininfo.domain != domain) )
+ {
printf("getdomaininfo failed\n");
goto done;
}
*status = op.u.getdomaininfo.flags;
- if (options & WNOHANG)
+ if ( options & WNOHANG )
goto done;
-
- if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)) {
+ if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) )
+ {
nanosleep(&ts,NULL);
goto retry;
}
+
done:
return retval;
}
long
-xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
+xc_ptrace(
+ int xc_handle,
+ enum __ptrace_request request,
+ u32 domid,
+ long eaddr,
+ long edata)
{
dom0_op_t op;
int status = 0;
@@ -273,44 +334,51 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
op.interface_version = DOM0_INTERFACE_VERSION;
- if (!xc_handle)
- if ((xc_handle = xc_interface_open()) < 0)
- return -1;
-#if 0
- printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data);
-#endif
- switch (request) {
+ switch ( request )
+ {
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
- if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ)) == NULL) {
+ guest_va = (unsigned long *)map_domain_va(
+ xc_handle, domid, cpu, addr, PROT_READ);
+ if ( guest_va == NULL )
+ {
status = EFAULT;
goto error_out;
}
-
retval = *guest_va;
break;
+
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ|PROT_WRITE)) == NULL) {
+ guest_va = (unsigned long *)map_domain_va(
+ xc_handle, domid, cpu, addr, PROT_READ|PROT_WRITE);
+ if ( guest_va == NULL )
+ {
status = EFAULT;
goto error_out;
}
-
*guest_va = (unsigned long)data;
break;
+
case PTRACE_GETREGS:
case PTRACE_GETFPREGS:
case PTRACE_GETFPXREGS:
FETCH_REGS(cpu);
-
- if (request == PTRACE_GETREGS) {
+ if ( request == PTRACE_GETREGS )
+ {
SET_PT_REGS(pt, ctxt[cpu].user_regs);
memcpy(data, &pt, sizeof(struct gdb_regs));
- } else if (request == PTRACE_GETFPREGS)
+ }
+ else if (request == PTRACE_GETFPREGS)
+ {
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
+ }
else /*if (request == PTRACE_GETFPXREGS)*/
+ {
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
+ }
break;
+
case PTRACE_SETREGS:
op.cmd = DOM0_SETDOMAININFO;
SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].user_regs);
@@ -321,17 +389,19 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
retval = do_dom0_op(xc_handle, &op);
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) {
+ if ( retval || (op.u.getdomaininfo.domain != domid) )
+ {
perror("dom0 op failed");
goto error_out;
}
- if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) {
+ if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED )
+ {
printf("domain currently paused\n");
goto error_out;
}
@@ -340,6 +410,7 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
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;
@@ -347,24 +418,29 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
op.u.setdomaininfo.vcpu = 0;
op.u.setdomaininfo.ctxt = &ctxt[cpu];
retval = do_dom0_op(xc_handle, &op);
- if (retval) {
+ if ( retval )
+ {
perror("dom0 op failed");
goto error_out;
}
/* FALLTHROUGH */
+
case PTRACE_CONT:
case PTRACE_DETACH:
- if (request != PTRACE_SINGLESTEP) {
+ if ( request != PTRACE_SINGLESTEP )
+ {
FETCH_REGS(cpu);
/* Clear trace flag */
- if (ctxt[cpu].user_regs.eflags & PSL_T) {
+ 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) {
+ if ( retval )
+ {
perror("dom0 op failed");
goto error_out;
}
@@ -375,6 +451,7 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
op.u.unpausedomain.domain = domid > 0 ? domid : -domid;
retval = do_dom0_op(xc_handle, &op);
break;
+
case PTRACE_SETFPREGS:
case PTRACE_SETFPXREGS:
case PTRACE_PEEKUSER:
@@ -387,15 +464,18 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
/* XXX not yet supported */
status = ENOSYS;
break;
+
case PTRACE_TRACEME:
printf("PTRACE_TRACEME is an invalid request under Xen\n");
status = EINVAL;
}
- if (status) {
+ if ( status )
+ {
errno = status;
retval = -1;
}
+
error_out:
return retval;
}
diff --git a/tools/libxc/xc_ptrace_core.c b/tools/libxc/xc_ptrace_core.c
index ed05dc5666..ffb23cea2d 100644
--- a/tools/libxc/xc_ptrace_core.c
+++ b/tools/libxc/xc_ptrace_core.c
@@ -166,7 +166,11 @@ map_domain_va(unsigned long domfd, int cpu, void * guest_va)
}
int
-xc_waitdomain_core(int domfd, int *status, int options)
+xc_waitdomain_core(
+ int xc_handle,
+ int domfd,
+ int *status,
+ int options)
{
int retval = -1;
int nr_vcpus;
@@ -215,7 +219,12 @@ xc_waitdomain_core(int domfd, int *status, int options)
}
long
-xc_ptrace_core(enum __ptrace_request request, u32 domfd, long eaddr, long edata)
+xc_ptrace_core(
+ int xc_handle,
+ enum __ptrace_request request,
+ u32 domfd,
+ long eaddr,
+ long edata)
{
int status = 0;
struct gdb_regs pt;
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 5b0adffe50..5094e17ba7 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -101,23 +101,31 @@ typedef struct xc_core_header {
} xc_core_header_t;
-long xc_ptrace(enum __ptrace_request request,
- u32 domid,
- long addr,
- long data);
-
-long xc_ptrace_core(enum __ptrace_request request,
- u32 domid,
- long addr,
- long data);
-
-int xc_waitdomain(int domain,
- int *status,
- int options);
-
-int xc_waitdomain_core(int domain,
- int *status,
- int options);
+long xc_ptrace(
+ int xc_handle,
+ enum __ptrace_request request,
+ u32 domid,
+ long addr,
+ long data);
+
+long xc_ptrace_core(
+ int xc_handle,
+ enum __ptrace_request request,
+ u32 domid,
+ long addr,
+ long data);
+
+int xc_waitdomain(
+ int xc_handle,
+ int domain,
+ int *status,
+ int options);
+
+int xc_waitdomain_core(
+ int xc_handle,
+ int domain,
+ int *status,
+ int options);
/*
* DOMAIN MANAGEMENT FUNCTIONS