All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kip Macy <kip.macy@gmail.com>
To: xen-devel@lists.sourceforge.net,
	Keir Fraser <Keir.Fraser@cl.cam.ac.uk>,
	Ian.Pratt@cl.cam.ac.uk
Subject: guest debug support patches
Date: Fri, 11 Mar 2005 11:00:09 -0800	[thread overview]
Message-ID: <b1fa291705031111002a0d9bf7@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1460 bytes --]

These two patches should really be one patch. However, when I try:

bk export -tpatch -r1.1294.1,1.1307,1.1308,1.1309,1.1310,1.1311

The output includes a large number of files that I haven't touched. My
guess is that there is a bug in the graph re-labelling in bk.

Thus patch1 is the output of:
bk export -tpatch -r1.1294.1.1

And patch2 is the output of:
 bk export -tpatch -r1.1307,1.1308,1.1309,1.1310,1.1311

These patches have three real changes:
1) xen/arch/x86/traps.c in do_int3 and do_debug if the trap was hit in
kernel-mode on domain other than dom0 the domain is paused

2) builddomain is re-factored into setdomaininfo, the parts of what
was arch_final_setup_guest that should only be set once are skipped by
means of a new exec_domain flag EDF_DONEINIT

3) xc_ptrace.c implements the ptrace interface via dom0 ops 

known limitations:
- Although the hypervisor-side code should work on x86_64, the
user-side xc_ptrace is currently strictly x86_32, fixing this is a
SMOP

- xc_ptrace assumes the guest is UP - I intend to fix this right after
I get 5.3 booting SMP as a guest - I would wait until this was fixed
were it not for the fact that the resolves can get annoying

- the patch doesn't include the gdbserver side support, I'm not sure
how best to handle this as most GDB maintainers move at a glacial pace
when it comes to incorporating outside patches
 
Comments and suggestions are welcome.

signed off by Kip Macy kmacy at fsmware.com

[-- Attachment #2: patch1 --]
[-- Type: text/plain, Size: 22873 bytes --]

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/03/09 15:04:40-08:00 kmacy@curly.lab.netapp.com 
#   add debug support
# 
# BitKeeper/etc/logging_ok
#   2005/03/09 15:00:56-08:00 kmacy@curly.lab.netapp.com +1 -0
#   Logging to logging@openlogging.org accepted
# 
# tools/libxc/xc_ptrace.c
#   2005/03/09 15:00:37-08:00 kmacy@curly.lab.netapp.com +324 -0
# 
# xen/include/xen/sched.h
#   2005/03/09 15:00:37-08:00 kmacy@curly.lab.netapp.com +2 -1
#   final_setup_guest->set_info_guset
#   add per ed init done flag
# 
# xen/include/xen/domain.h
#   2005/03/09 15:00:37-08:00 kmacy@curly.lab.netapp.com +1 -1
#   arch_final_setup_guest -> arch_set_info_guest
# 
# xen/include/public/dom0_ops.h
#   2005/03/09 15:00:37-08:00 kmacy@curly.lab.netapp.com +7 -7
#   builddomain->setdomaininfo
# 
# xen/common/domain.c
#   2005/03/09 15:00:37-08:00 kmacy@curly.lab.netapp.com +15 -13
#   final_setup_guest -> set_info_guest
# 
# xen/common/dom0_ops.c
#   2005/03/09 15:00:37-08:00 kmacy@curly.lab.netapp.com +3 -3
#   builddomain->setdomaininfo
# 
# tools/libxc/xc_ptrace.c
#   2005/03/09 15:00:37-08:00 kmacy@curly.lab.netapp.com +0 -0
#   BitKeeper file /t/niners/users/xen/050304/xen-unstable.bk/tools/libxc/xc_ptrace.c
# 
# xen/arch/x86/traps.c
#   2005/03/09 15:00:36-08:00 kmacy@curly.lab.netapp.com +11 -1
#   pause guest on int3
# 
# xen/arch/x86/domain.c
#   2005/03/09 15:00:36-08:00 kmacy@curly.lab.netapp.com +27 -19
#   arch_final_setup_guest -> arch_set_info_guest
# 
# xen/arch/ia64/domain.c
#   2005/03/09 15:00:36-08:00 kmacy@curly.lab.netapp.com +1 -1
#   update interface
# 
# tools/libxc/xc_vmx_build.c
#   2005/03/09 15:00:36-08:00 kmacy@curly.lab.netapp.com +3 -3
#   use setdomaininfo
# 
# tools/libxc/xc_plan9_build.c
#   2005/03/09 15:00:36-08:00 kmacy@curly.lab.netapp.com +5 -4
#   use setdomaininfo
# 
# tools/libxc/xc_linux_restore.c
#   2005/03/09 15:00:36-08:00 kmacy@curly.lab.netapp.com +3 -3
#   use setdomaininfo
# 
# tools/libxc/xc_linux_build.c
#   2005/03/09 15:00:36-08:00 kmacy@curly.lab.netapp.com +4 -3
#   use setdomaininfo call
# 
# tools/libxc/Makefile
#   2005/03/09 15:00:36-08:00 kmacy@curly.lab.netapp.com +1 -0
#   compile ptrace
# 
diff -Nru a/tools/libxc/Makefile b/tools/libxc/Makefile
--- a/tools/libxc/Makefile	2005-03-11 10:38:24 -08:00
+++ b/tools/libxc/Makefile	2005-03-11 10:38:24 -08:00
@@ -28,6 +28,7 @@
 SRCS     += xc_misc.c
 SRCS     += xc_physdev.c
 SRCS     += xc_private.c
+SRCS     += xc_ptrace.c
 SRCS     += xc_rrobin.c
 SRCS     += xc_vmx_build.c
 
diff -Nru a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c	2005-03-11 10:38:24 -08:00
+++ b/tools/libxc/xc_linux_build.c	2005-03-11 10:38:24 -08:00
@@ -369,6 +369,7 @@
 
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = (domid_t)domid;
+    launch_op.u.setdomaininfo.exec_domain = 0;
     op.u.getdomaininfo.exec_domain = 0;
     op.u.getdomaininfo.ctxt = ctxt;
     if ( (do_dom0_op(xc_handle, &op) < 0) || 
@@ -459,10 +460,10 @@
 
     memset( &launch_op, 0, sizeof(launch_op) );
 
-    launch_op.u.builddomain.domain   = (domid_t)domid;
-    launch_op.u.builddomain.ctxt = ctxt;
+    launch_op.u.setdomaininfo.domain   = (domid_t)domid;
+    launch_op.u.setdomaininfo.ctxt = ctxt;
 
-    launch_op.cmd = DOM0_BUILDDOMAIN;
+    launch_op.cmd = DOM0_SETDOMAININFO;
     rc = do_dom0_op(xc_handle, &launch_op);
     
     return rc;
diff -Nru a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c
--- a/tools/libxc/xc_linux_restore.c	2005-03-11 10:38:24 -08:00
+++ b/tools/libxc/xc_linux_restore.c	2005-03-11 10:38:24 -08:00
@@ -631,9 +631,9 @@
 
     xcio_info(ioctxt, "Domain ready to be built.\n");
 
-    op.cmd = DOM0_BUILDDOMAIN;
-    op.u.builddomain.domain   = (domid_t)dom;
-    op.u.builddomain.ctxt = &ctxt;
+    op.cmd = DOM0_SETDOMAININFO;
+    op.u.setdomaininfo.domain   = (domid_t)dom;
+    op.u.setdomaininfo.ctxt = &ctxt;
     rc = do_dom0_op(xc_handle, &op);
 
     if ( rc != 0 )
diff -Nru a/tools/libxc/xc_plan9_build.c b/tools/libxc/xc_plan9_build.c
--- a/tools/libxc/xc_plan9_build.c	2005-03-11 10:38:24 -08:00
+++ b/tools/libxc/xc_plan9_build.c	2005-03-11 10:38:24 -08:00
@@ -533,10 +533,11 @@
 
 	memset(&launch_op, 0, sizeof (launch_op));
 
-	launch_op.u.builddomain.domain = (domid_t) domid;
-	//  launch_op.u.builddomain.num_vifs = 1;
-	launch_op.u.builddomain.ctxt = ctxt;
-	launch_op.cmd = DOM0_BUILDDOMAIN;
+	launch_op.u.setdomaininfo.domain = (domid_t) domid;
+	launch_op.u.setdomaininfo.exec_domain = 0;
+	//  launch_op.u.setdomaininfo.num_vifs = 1;
+	launch_op.u.setdomaininfo.ctxt = ctxt;
+	launch_op.cmd = DOM0_SETDOMAININFO;
 	rc = do_dom0_op(xc_handle, &launch_op);
 
 	fprintf(stderr, "RC is %d\n", rc);
diff -Nru a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/tools/libxc/xc_ptrace.c	2005-03-11 10:38:24 -08:00
@@ -0,0 +1,324 @@
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include "xc_private.h"
+#include <asm/elf.h>
+#include <time.h>
+
+
+#define BSD_PAGE_MASK	(PAGE_SIZE-1)
+#define	PG_FRAME	(~((unsigned long)BSD_PAGE_MASK)
+#define PDRSHIFT        22
+#define	PSL_T		0x00000100	/* trace enable bit */
+
+
+/*
+ * long  
+ * ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
+ */
+
+long xc_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",
+    "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) & PAGE_MASK)
+
+/* XXX application state */
+
+
+static int xc_handle;
+static int regs_valid;
+static unsigned long cr3;
+static full_execution_context_t ctxt;
+
+/* --------------------- */
+
+static void *
+map_domain_va(unsigned long domid, void * guest_va)
+{
+    unsigned long pde, page;
+    unsigned long va = (unsigned long)guest_va;
+
+    static unsigned long cr3_phys;
+    static unsigned long *cr3_virt;
+    static unsigned long pde_phys;
+    static unsigned long *pde_virt;
+    static unsigned long page_phys;
+    static unsigned long *page_virt;
+
+    if (cr3 != cr3_phys) 
+    {
+	cr3_phys = cr3;
+	if (cr3_virt)
+	    munmap(cr3_virt, PAGE_SIZE);
+	if ((cr3_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+					     PROT_READ,
+					     cr3_phys >> PAGE_SHIFT)) == NULL)
+	    goto error_out;
+    } 
+    pde = cr3_virt[vtopdi(va)];
+    if (pde != pde_phys) 
+    {
+	pde_phys = pde;
+	if (pde_virt)
+	    munmap(pde_virt, PAGE_SIZE);
+	if ((pde_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+					     PROT_READ,
+					     pde_phys >> PAGE_SHIFT)) == NULL)
+	    goto error_out;
+    }
+    page = pde_virt[
+		    vtopti(va)
+];
+    if (page != page_phys) 
+    {
+	page_phys = page;
+	if (page_virt)
+	    munmap(page_virt, PAGE_SIZE);
+	if ((page_virt = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+					     PROT_READ|PROT_WRITE,
+					     page_phys >> PAGE_SHIFT)) == NULL)
+	    goto error_out;
+    }	
+    return (void *)(((unsigned long)page_virt) | (va &~ BSD_PAGE_MASK));
+
+ error_out:
+    return 0;
+}
+
+int 
+waitdomain(int domain, int *status, int options)
+{
+    dom0_op_t op;
+    int retval;
+    full_execution_context_t ctxt;
+    struct timespec ts;
+    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;
+    op.u.getdomaininfo.ctxt = &ctxt;
+ retry:
+
+    retval = do_dom0_op(xc_handle, &op);
+    if (retval)
+	goto done;
+    
+    *status = op.u.getdomaininfo.flags;
+    
+    if (options & WNOHANG)
+	goto done;
+	
+
+    if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)) {	
+	nanosleep(&ts,NULL);
+	goto retry;
+    }
+ done:
+    return retval;
+
+}
+
+long
+xc_ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data)
+{
+    dom0_op_t op;
+    int status = 0;
+    xc_domaininfo_t info;
+    struct gdb_regs pt;
+    long retval = 0;
+    char *guest_va;
+    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], pid, addr, data);
+#endif
+    switch (request) {	
+    case PTRACE_PEEKTEXT:
+    case PTRACE_PEEKDATA:
+	if ((guest_va = map_domain_va(pid, addr)) == NULL)
+	    goto done;
+	memcpy(data, guest_va, 4);
+	break;
+    case PTRACE_POKETEXT:
+    case PTRACE_POKEDATA:
+	if ((guest_va = map_domain_va(pid, addr)) == NULL)
+	    goto done;
+	memcpy(guest_va, data, 4);
+	break;
+    case PTRACE_GETREGS:
+    case PTRACE_GETFPREGS:
+    case PTRACE_GETFPXREGS:
+	/* XXX hard-coding UP */
+	retval = xc_domain_getfullinfo(xc_handle, pid, 0, &info, &ctxt);
+	if (retval)
+	    goto done;
+	if (request == PTRACE_GETREGS) {
+		SET_PT_REGS(pt, ctxt.cpu_ctxt); 
+		memcpy(data, &pt, sizeof(elf_gregset_t));
+	} else if (request == PTRACE_GETFPREGS)
+	    memcpy(data, &ctxt.fpu_ctxt, sizeof(elf_fpregset_t));
+	else /*if (request == PTRACE_GETFPXREGS)*/
+	    memcpy(data, &ctxt.fpu_ctxt, sizeof(elf_fpxregset_t));
+	cr3 = ctxt.pt_base;
+	regs_valid = 1;
+	break;
+    case PTRACE_SETREGS:
+	op.cmd = DOM0_SETDOMAININFO;
+	SET_XC_REGS(((struct gdb_regs *)data), ctxt.cpu_ctxt);
+	op.u.setdomaininfo.domain = pid;
+	/* XXX need to understand multiple exec_domains */
+	op.u.setdomaininfo.exec_domain = 0;
+	op.u.setdomaininfo.ctxt = &ctxt;
+	retval = do_dom0_op(xc_handle, &op);
+	if (retval)
+	    goto done;
+
+	break;
+    case PTRACE_ATTACH:
+	op.cmd = DOM0_GETDOMAININFO;
+	op.u.getdomaininfo.domain = pid;
+	op.u.getdomaininfo.exec_domain = 0;
+	op.u.getdomaininfo.ctxt = &ctxt;
+	retval = do_dom0_op(xc_handle, &op);
+	if (retval) {
+	    perror("dom0 op failed");
+	    goto done;
+	}
+	if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)
+	    goto done;
+	printf("domain not currently paused\n");
+	op.cmd = DOM0_PAUSEDOMAIN;
+	op.u.pausedomain.domain = pid;
+	retval = do_dom0_op(xc_handle, &op);
+	break;
+    case PTRACE_SINGLESTEP:
+	ctxt.cpu_ctxt.eflags |= PSL_T;
+    case PTRACE_CONT:
+    case PTRACE_DETACH:
+	regs_valid = 0;
+	op.cmd = DOM0_UNPAUSEDOMAIN;
+	op.u.unpausedomain.domain = pid > 0 ? pid : -pid;
+	retval = do_dom0_op(xc_handle, &op);
+	break;
+    case PTRACE_SETFPREGS:
+    case PTRACE_SETFPXREGS:
+    case PTRACE_PEEKUSER:
+    case PTRACE_POKEUSER:
+    case PTRACE_SYSCALL:
+    case PTRACE_KILL:
+	printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
+	/* XXX not yet supported */
+	status = ENOSYS;
+	break;
+    case PTRACE_TRACEME:
+	printf("PTRACE_TRACEME is an invalid request under Xen\n");
+	status = EINVAL;
+    }
+    
+    if (status) {
+	errno = status;
+	retval = -1;
+    }
+ done:
+    return retval;
+}
diff -Nru a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_vmx_build.c
--- a/tools/libxc/xc_vmx_build.c	2005-03-11 10:38:24 -08:00
+++ b/tools/libxc/xc_vmx_build.c	2005-03-11 10:38:24 -08:00
@@ -603,10 +603,10 @@
 
     memset( &launch_op, 0, sizeof(launch_op) );
 
-    launch_op.u.builddomain.domain   = (domid_t)domid;
-    launch_op.u.builddomain.ctxt = ctxt;
+    launch_op.u.setdomaininfo.domain   = (domid_t)domid;
+    launch_op.u.setdomaininfo.ctxt = ctxt;
 
-    launch_op.cmd = DOM0_BUILDDOMAIN;
+    launch_op.cmd = DOM0_SETDOMAININFO;
     rc = do_dom0_op(xc_handle, &launch_op);
     return rc;
 
diff -Nru a/xen/arch/ia64/domain.c b/xen/arch/ia64/domain.c
--- a/xen/arch/ia64/domain.c	2005-03-11 10:38:24 -08:00
+++ b/xen/arch/ia64/domain.c	2005-03-11 10:38:24 -08:00
@@ -200,7 +200,7 @@
 	return;
 }
 
-int arch_final_setup_guest(struct exec_domain *p, full_execution_context_t *c)
+int arch_set_info_guest(struct exec_domain *p, full_execution_context_t *c)
 {
 	dummy();
 	return 1;
diff -Nru a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c	2005-03-11 10:38:24 -08:00
+++ b/xen/arch/x86/domain.c	2005-03-11 10:38:24 -08:00
@@ -422,30 +422,15 @@
 
 
 /* This is called by arch_final_setup_guest and do_boot_vcpu */
-int arch_final_setup_guest(
+
+int arch_set_info_guest(
     struct exec_domain *ed, full_execution_context_t *c)
 {
     struct domain *d = ed->domain;
     unsigned long phys_basetab;
     int i, rc;
 
-    clear_bit(EDF_DONEFPUINIT, &ed->ed_flags);
-    if ( c->flags & ECF_I387_VALID )
-        set_bit(EDF_DONEFPUINIT, &ed->ed_flags);
-
-    ed->arch.flags &= ~TF_kernel_mode;
-    if ( c->flags & ECF_IN_KERNEL )
-        ed->arch.flags |= TF_kernel_mode;
-
-    memcpy(&ed->arch.user_ctxt,
-           &c->cpu_ctxt,
-           sizeof(ed->arch.user_ctxt));
-
-    /* Clear IOPL for unprivileged domains. */
-    if (!IS_PRIV(d))
-        ed->arch.user_ctxt.eflags &= 0xffffcfff;
-
-    /*
+   /*
      * This is sufficient! If the descriptor DPL differs from CS RPL then we'll
      * #GP. If DS, ES, FS, GS are DPL 0 then they'll be cleared automatically.
      * If SS RPL or DPL differs from CS RPL then we'll #GP.
@@ -455,11 +440,30 @@
              ((ed->arch.user_ctxt.ss & 3) == 0) )
                 return -EINVAL;
 
+    memcpy(&ed->arch.user_ctxt,
+           &c->cpu_ctxt,
+           sizeof(ed->arch.user_ctxt));
+
     memcpy(&ed->arch.i387,
            &c->fpu_ctxt,
            sizeof(ed->arch.i387));
 
-    memcpy(ed->arch.traps,
+    if (test_bit(EDF_DONEINIT, &ed->ed_flags))
+        return 0;
+
+    clear_bit(EDF_DONEFPUINIT, &ed->ed_flags);
+    if ( c->flags & ECF_I387_VALID )
+        set_bit(EDF_DONEFPUINIT, &ed->ed_flags);
+
+    ed->arch.flags &= ~TF_kernel_mode;
+    if ( c->flags & ECF_IN_KERNEL )
+        ed->arch.flags |= TF_kernel_mode;
+
+    /* Clear IOPL for unprivileged domains. */
+    if (!IS_PRIV(d))
+        ed->arch.user_ctxt.eflags &= 0xffffcfff;
+
+     memcpy(ed->arch.traps,
            &c->trap_ctxt,
            sizeof(ed->arch.traps));
 
@@ -505,9 +509,13 @@
 #endif
 
     update_pagetables(ed);
+    
+    /* Don't redo final setup */
+    set_bit(EDF_DONEINIT, &ed->ed_flags);
 
     return 0;
 }
+
 
 void new_thread(struct exec_domain *d,
                 unsigned long start_pc,
diff -Nru a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c	2005-03-11 10:38:24 -08:00
+++ b/xen/arch/x86/traps.c	2005-03-11 10:38:24 -08:00
@@ -221,8 +221,18 @@
         DEBUGGER_trap_fatal(TRAP_int3, regs);
         show_registers(regs);
         panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n", smp_processor_id());
-    }
+    } 
+    else if ( KERNEL_MODE(ed, regs) && ed->domain->id != 0 ) 
+    {
+        regs->eflags &= ~X86_EFLAGS_TF;
+        if ( !test_and_set_bit(EDF_CTRLPAUSE, &ed->ed_flags) ) {
+            while (ed == current)
+                __enter_scheduler();
+            domain_pause_by_systemcontroller(ed->domain);
+        }
 
+        return 0;
+    }    
     ti = current->arch.traps + 3;
     tb->flags = TBF_EXCEPTION;
     tb->cs    = ti->cs;
diff -Nru a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c	2005-03-11 10:38:24 -08:00
+++ b/xen/common/dom0_ops.c	2005-03-11 10:38:24 -08:00
@@ -111,13 +111,13 @@
     switch ( op->cmd )
     {
 
-    case DOM0_BUILDDOMAIN:
+    case DOM0_SETDOMAININFO:
     {
-        struct domain *d = find_domain_by_id(op->u.builddomain.domain);
+        struct domain *d = find_domain_by_id(op->u.setdomaininfo.domain);
         ret = -EINVAL;
         if ( d != NULL )
         {
-            ret = final_setup_guest(d, &op->u.builddomain);
+            ret = set_info_guest(d, &op->u.setdomaininfo);
             put_domain(d);
         }
     }
diff -Nru a/xen/common/domain.c b/xen/common/domain.c
--- a/xen/common/domain.c	2005-03-11 10:38:24 -08:00
+++ b/xen/common/domain.c	2005-03-11 10:38:24 -08:00
@@ -260,34 +260,36 @@
  * than domain 0. ie. the domains that are being built by the userspace dom0
  * domain builder.
  */
-int final_setup_guest(struct domain *p, dom0_builddomain_t *builddomain)
+int set_info_guest(struct domain *p, dom0_setdomaininfo_t *setdomain)
 {
     int rc = 0;
     full_execution_context_t *c;
+    struct exec_domain *ed = p->exec_domain[setdomain->exec_domain];
+    
+    if (ed == NULL)
+        return -EINVAL;
+
+    if (test_bit(DF_CONSTRUCTED, &p->d_flags) && 
+        !test_bit(EDF_CTRLPAUSE, &ed->ed_flags))
+        return -EINVAL;
 
     if ( (c = xmalloc(full_execution_context_t)) == NULL )
         return -ENOMEM;
 
-    if ( test_bit(DF_CONSTRUCTED, &p->d_flags) )
-    {
-        rc = -EINVAL;
-        goto out;
-    }
-
-    if ( copy_from_user(c, builddomain->ctxt, sizeof(*c)) )
+    if ( copy_from_user(c, setdomain->ctxt, sizeof(*c)) )
     {
         rc = -EFAULT;
         goto out;
     }
-    
-    if ( (rc = arch_final_setup_guest(p->exec_domain[0],c)) != 0 )
+
+    if ( (rc = arch_set_info_guest(p->exec_domain[setdomain->exec_domain],c)) != 0 )
         goto out;
 
     /* Set up the shared info structure. */
     update_dom_time(p);
-
+    
     set_bit(DF_CONSTRUCTED, &p->d_flags);
-
+    
  out:    
     if ( c != NULL )
         xfree(c);
@@ -334,7 +336,7 @@
 
     sched_add_domain(ed);
 
-    if ( (rc = arch_final_setup_guest(ed, c)) != 0 ) {
+    if ( (rc = arch_set_info_guest(ed, c)) != 0 ) {
         sched_rem_domain(ed);
         goto out;
     }
diff -Nru a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h	2005-03-11 10:38:24 -08:00
+++ b/xen/include/public/dom0_ops.h	2005-03-11 10:38:24 -08:00
@@ -109,16 +109,16 @@
     u64      cpu_time;                /* 40 */
 } PACKED dom0_getdomaininfo_t; /* 48 bytes */
 
-#define DOM0_BUILDDOMAIN      13
+#define DOM0_SETDOMAININFO      13
 typedef struct {
     /* IN variables. */
-    domid_t                 domain;   /*  0 */
-    u16                     __pad0;   /*  2 */
-    u32                     __pad1;   /*  4 */
+    domid_t                   domain;       /*  0 */
+    u16                       exec_domain;  /*  2 */
+    u32                       __pad0;       /*  4 */
     /* IN/OUT parameters */
-    full_execution_context_t *ctxt;   /*  8 */
+    full_execution_context_t *ctxt;         /*  8 */
     MEMORY_PADDING;
-} PACKED dom0_builddomain_t; /* 16 bytes */
+} PACKED dom0_setdomaininfo_t;              /* 16 bytes */
 
 #define DOM0_IOPL             14
 typedef struct {
@@ -426,7 +426,7 @@
         dom0_getmemlist_t        getmemlist;
         dom0_schedctl_t          schedctl;
         dom0_adjustdom_t         adjustdom;
-        dom0_builddomain_t       builddomain;
+        dom0_setdomaininfo_t     setdomaininfo;
         dom0_getdomaininfo_t     getdomaininfo;
         dom0_getpageframeinfo_t  getpageframeinfo;
         dom0_iopl_t              iopl;
diff -Nru a/xen/include/xen/domain.h b/xen/include/xen/domain.h
--- a/xen/include/xen/domain.h	2005-03-11 10:38:24 -08:00
+++ b/xen/include/xen/domain.h	2005-03-11 10:38:24 -08:00
@@ -18,7 +18,7 @@
 
 extern void arch_do_boot_vcpu(struct exec_domain *ed);
 
-extern int  arch_final_setup_guest(
+extern int  arch_set_info_guest(
     struct exec_domain *d, full_execution_context_t *c);
 
 extern void free_perdomain_pt(struct domain *d);
diff -Nru a/xen/include/xen/sched.h b/xen/include/xen/sched.h
--- a/xen/include/xen/sched.h	2005-03-11 10:38:24 -08:00
+++ b/xen/include/xen/sched.h	2005-03-11 10:38:24 -08:00
@@ -220,7 +220,7 @@
     unsigned long image_start, unsigned long image_len, 
     unsigned long initrd_start, unsigned long initrd_len,
     char *cmdline);
-extern int final_setup_guest(struct domain *d, dom0_builddomain_t *);
+extern int set_info_guest(struct domain *d, dom0_setdomaininfo_t *);
 
 struct domain *find_domain_by_id(domid_t dom);
 struct domain *find_last_domain(void);
@@ -316,6 +316,7 @@
 #define EDF_RUNNING     12 /* Currently running on a CPU.                    */
 #define EDF_CPUPINNED   13 /* Disables auto-migration.                       */
 #define EDF_MIGRATED    14 /* Domain migrated between CPUs.                  */
+#define EDF_DONEINIT    15 /* Initialization completed    .                  */
 
 static inline int domain_runnable(struct exec_domain *d)
 {

[-- Attachment #3: patch2 --]
[-- Type: text/plain, Size: 8813 bytes --]

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/03/10 20:28:04-08:00 kmacy@shemp.lab.netapp.com 
#   bug fixes to ptrace emulation
# 
# BitKeeper/etc/logging_ok
#   2005/03/10 20:28:04-08:00 kmacy@shemp.lab.netapp.com +1 -0
#   Logging to logging@openlogging.org accepted
# 
# xen/arch/x86/traps.c
#   2005/03/10 20:27:44-08:00 kmacy@shemp.lab.netapp.com +20 -9
#   handle trace trap as well as int3
# 
# xen/arch/x86/domain.c
#   2005/03/10 20:27:44-08:00 kmacy@shemp.lab.netapp.com +8 -8
#   move register copying above segment check
# 
# tools/libxc/xc_ptrace.c
#   2005/03/10 20:27:44-08:00 kmacy@shemp.lab.netapp.com +34 -17
#   fix mask handling of pts
#   fix single-stepping
#   simplify PEEK and POKE operations
# 
# tools/libxc/xc_linux_build.c
#   2005/03/10 20:27:44-08:00 kmacy@shemp.lab.netapp.com +1 -1
#   move setting of exec_domain to more sensible location
# 
diff -Nru a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c	2005-03-11 10:38:12 -08:00
+++ b/tools/libxc/xc_linux_build.c	2005-03-11 10:38:12 -08:00
@@ -369,7 +369,6 @@
 
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = (domid_t)domid;
-    launch_op.u.setdomaininfo.exec_domain = 0;
     op.u.getdomaininfo.exec_domain = 0;
     op.u.getdomaininfo.ctxt = ctxt;
     if ( (do_dom0_op(xc_handle, &op) < 0) || 
@@ -461,6 +460,7 @@
     memset( &launch_op, 0, sizeof(launch_op) );
 
     launch_op.u.setdomaininfo.domain   = (domid_t)domid;
+    launch_op.u.setdomaininfo.exec_domain = 0;
     launch_op.u.setdomaininfo.ctxt = ctxt;
 
     launch_op.cmd = DOM0_SETDOMAININFO;
diff -Nru a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c
--- a/tools/libxc/xc_ptrace.c	2005-03-11 10:38:12 -08:00
+++ b/tools/libxc/xc_ptrace.c	2005-03-11 10:38:12 -08:00
@@ -110,7 +110,7 @@
 
 
 #define vtopdi(va) ((va) >> PDRSHIFT)
-#define vtopti(va) (((va) >> PAGE_SHIFT) & PAGE_MASK)
+#define vtopti(va) (((va) >> PAGE_SHIFT) & BSD_PAGE_MASK)
 
 /* XXX application state */
 
@@ -156,9 +156,7 @@
 					     pde_phys >> PAGE_SHIFT)) == NULL)
 	    goto error_out;
     }
-    page = pde_virt[
-		    vtopti(va)
-];
+    page = pde_virt[vtopti(va)];
     if (page != page_phys) 
     {
 	page_phys = page;
@@ -169,7 +167,7 @@
 					     page_phys >> PAGE_SHIFT)) == NULL)
 	    goto error_out;
     }	
-    return (void *)(((unsigned long)page_virt) | (va &~ BSD_PAGE_MASK));
+    return (void *)(((unsigned long)page_virt) | (va & BSD_PAGE_MASK));
 
  error_out:
     return 0;
@@ -193,13 +191,15 @@
 	}
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = domain;
+    op.u.getdomaininfo.exec_domain = 0;
     op.u.getdomaininfo.ctxt = &ctxt;
  retry:
 
     retval = do_dom0_op(xc_handle, &op);
-    if (retval)
+    if (retval) {
+	printf("getdomaininfo failed\n");
 	goto done;
-    
+    }
     *status = op.u.getdomaininfo.flags;
     
     if (options & WNOHANG)
@@ -223,35 +223,39 @@
     xc_domaininfo_t info;
     struct gdb_regs pt;
     long retval = 0;
-    char *guest_va;
+    long *guest_va;
+
     op.interface_version = DOM0_INTERFACE_VERSION;
     
     if (!xc_handle)
 	if ((xc_handle = xc_interface_open()) < 0)
 	    return -1;
-#if 0
+#if 0
     printf("%20s %d, %p, %p \n", ptrace_names[request], pid, addr, data);
 #endif
     switch (request) {	
     case PTRACE_PEEKTEXT:
     case PTRACE_PEEKDATA:
-	if ((guest_va = map_domain_va(pid, addr)) == NULL)
-	    goto done;
-	memcpy(data, guest_va, 4);
-	break;
     case PTRACE_POKETEXT:
     case PTRACE_POKEDATA:
-	if ((guest_va = map_domain_va(pid, addr)) == NULL)
+	if ((guest_va = (unsigned long *)map_domain_va(pid, addr)) == NULL)
 	    goto done;
-	memcpy(guest_va, data, 4);
+
+	if (request == PTRACE_PEEKTEXT || request == PTRACE_PEEKDATA)
+	    retval = *guest_va;
+	else
+	    *guest_va = (unsigned long)data;
 	break;
     case PTRACE_GETREGS:
     case PTRACE_GETFPREGS:
     case PTRACE_GETFPXREGS:
 	/* XXX hard-coding UP */
 	retval = xc_domain_getfullinfo(xc_handle, pid, 0, &info, &ctxt);
-	if (retval)
+
+	if (retval) {
+	    printf("getfullinfo failed\n");
 	    goto done;
+	}
 	if (request == PTRACE_GETREGS) {
 		SET_PT_REGS(pt, ctxt.cpu_ctxt); 
 		memcpy(data, &pt, sizeof(elf_gregset_t));
@@ -284,8 +288,10 @@
 	    perror("dom0 op failed");
 	    goto done;
 	}
-	if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)
+	if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) {
+	    printf("domain currently paused\n");
 	    goto done;
+	}
 	printf("domain not currently paused\n");
 	op.cmd = DOM0_PAUSEDOMAIN;
 	op.u.pausedomain.domain = pid;
@@ -293,6 +299,15 @@
 	break;
     case PTRACE_SINGLESTEP:
 	ctxt.cpu_ctxt.eflags |= PSL_T;
+	op.cmd = DOM0_SETDOMAININFO;
+	op.u.setdomaininfo.domain = pid;
+	op.u.setdomaininfo.exec_domain = 0;
+	op.u.setdomaininfo.ctxt = &ctxt;
+	retval = do_dom0_op(xc_handle, &op);	
+	if (retval) {
+	    perror("dom0 op failed");
+	    goto done;
+	}
     case PTRACE_CONT:
     case PTRACE_DETACH:
 	regs_valid = 0;
@@ -306,7 +321,9 @@
     case PTRACE_POKEUSER:
     case PTRACE_SYSCALL:
     case PTRACE_KILL:
+#ifdef DEBUG
 	printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
+#endif
 	/* XXX not yet supported */
 	status = ENOSYS;
 	break;
diff -Nru a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c	2005-03-11 10:38:12 -08:00
+++ b/xen/arch/x86/domain.c	2005-03-11 10:38:12 -08:00
@@ -431,6 +431,14 @@
     unsigned long phys_basetab;
     int i, rc;
 
+    memcpy(&ed->arch.user_ctxt,
+           &c->cpu_ctxt,
+           sizeof(ed->arch.user_ctxt));
+
+    memcpy(&ed->arch.i387,
+           &c->fpu_ctxt,
+           sizeof(ed->arch.i387));
+
    /*
      * This is sufficient! If the descriptor DPL differs from CS RPL then we'll
      * #GP. If DS, ES, FS, GS are DPL 0 then they'll be cleared automatically.
@@ -440,14 +448,6 @@
         if ( ((ed->arch.user_ctxt.cs & 3) == 0) ||
              ((ed->arch.user_ctxt.ss & 3) == 0) )
                 return -EINVAL;
-
-    memcpy(&ed->arch.user_ctxt,
-           &c->cpu_ctxt,
-           sizeof(ed->arch.user_ctxt));
-
-    memcpy(&ed->arch.i387,
-           &c->fpu_ctxt,
-           sizeof(ed->arch.i387));
 
     if (test_bit(EDF_DONEINIT, &ed->ed_flags))
         return 0;
diff -Nru a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c	2005-03-11 10:38:12 -08:00
+++ b/xen/arch/x86/traps.c	2005-03-11 10:38:12 -08:00
@@ -225,14 +225,13 @@
     } 
     else if ( KERNEL_MODE(ed, regs) && ed->domain->id != 0 ) 
     {
-        regs->eflags &= ~X86_EFLAGS_TF;
         if ( !test_and_set_bit(EDF_CTRLPAUSE, &ed->ed_flags) ) {
             while (ed == current)
                 __enter_scheduler();
             domain_pause_by_systemcontroller(ed->domain);
         }
 
-        return 0;
+        goto out;
     }    
     ti = current->arch.traps + 3;
     tb->flags = TBF_EXCEPTION;
@@ -241,6 +240,7 @@
     if ( TI_GET_IF(ti) )
         ed->vcpu_info->evtchn_upcall_mask = 1;
 
+ out:
     return 0;
 }
 
@@ -694,8 +694,8 @@
 asmlinkage int do_debug(struct xen_regs *regs)
 {
     unsigned long condition;
-    struct exec_domain *d = current;
-    struct trap_bounce *tb = &d->arch.trap_bounce;
+    struct exec_domain *ed = current;
+    struct trap_bounce *tb = &ed->arch.trap_bounce;
 
     DEBUGGER_trap_entry(TRAP_debug, regs);
 
@@ -703,7 +703,7 @@
 
     /* Mask out spurious debug traps due to lazy DR7 setting */
     if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
-         (d->arch.debugreg[7] == 0) )
+         (ed->arch.debugreg[7] == 0) )
     {
         __asm__("mov %0,%%db7" : : "r" (0UL));
         goto out;
@@ -720,14 +720,25 @@
          * breakpoint, which can't happen to us.
          */
         goto out;
-    }
+    } 
+    else if ( KERNEL_MODE(ed, regs) && ed->domain->id != 0 ) 
+    {
+        regs->eflags &= ~EF_TF;
+        if ( !test_and_set_bit(EDF_CTRLPAUSE, &ed->ed_flags) ) {
+            while (ed == current)
+                __enter_scheduler();
+            domain_pause_by_systemcontroller(ed->domain);
+        }
+
+        goto out;
+    }    
 
     /* Save debug status register where guest OS can peek at it */
-    d->arch.debugreg[6] = condition;
+    ed->arch.debugreg[6] = condition;
 
     tb->flags = TBF_EXCEPTION;
-    tb->cs    = d->arch.traps[1].cs;
-    tb->eip   = d->arch.traps[1].address;
+    tb->cs    = ed->arch.traps[1].cs;
+    tb->eip   = ed->arch.traps[1].address;
 
  out:
     return EXCRET_not_a_fault;

                 reply	other threads:[~2005-03-11 19:00 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=b1fa291705031111002a0d9bf7@mail.gmail.com \
    --to=kip.macy@gmail.com \
    --cc=Ian.Pratt@cl.cam.ac.uk \
    --cc=Keir.Fraser@cl.cam.ac.uk \
    --cc=xen-devel@lists.sourceforge.net \
    /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.