ia64/xen-unstable

changeset 13546:5dc5e6ba42d2

Merge
author Tim Deegan <Tim.Deegan@xensource.com>
date Sat Jan 20 11:21:08 2007 +0000 (2007-01-20)
parents ff4f4596cb29 0971f0e9461e
children a514ae6bc150
files xen/arch/x86/domain.c xen/arch/x86/domctl.c xen/common/domain.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c	Sat Jan 20 11:17:42 2007 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c	Sat Jan 20 11:21:08 2007 +0000
     1.3 @@ -85,13 +85,20 @@ static void pre_suspend(void)
     1.4  		mfn_to_pfn(xen_start_info->console.domU.mfn);
     1.5  }
     1.6  
     1.7 -static void post_suspend(void)
     1.8 +static void post_suspend(int suspend_cancelled)
     1.9  {
    1.10  	int i, j, k, fpp;
    1.11  	extern unsigned long max_pfn;
    1.12  	extern unsigned long *pfn_to_mfn_frame_list_list;
    1.13  	extern unsigned long *pfn_to_mfn_frame_list[];
    1.14  
    1.15 +	if (suspend_cancelled) {
    1.16 +		xen_start_info->store_mfn =
    1.17 +			pfn_to_mfn(xen_start_info->store_mfn);
    1.18 +		xen_start_info->console.domU.mfn =
    1.19 +			pfn_to_mfn(xen_start_info->console.domU.mfn);
    1.20 +	}
    1.21 +	
    1.22  	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
    1.23  
    1.24  	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
    1.25 @@ -120,13 +127,13 @@ static void post_suspend(void)
    1.26  #define switch_idle_mm()	((void)0)
    1.27  #define mm_pin_all()		((void)0)
    1.28  #define pre_suspend()		((void)0)
    1.29 -#define post_suspend()		((void)0)
    1.30 +#define post_suspend(x)		((void)0)
    1.31  
    1.32  #endif
    1.33  
    1.34  int __xen_suspend(void)
    1.35  {
    1.36 -	int err;
    1.37 +	int err, suspend_cancelled;
    1.38  
    1.39  	extern void time_resume(void);
    1.40  
    1.41 @@ -158,16 +165,17 @@ int __xen_suspend(void)
    1.42  	pre_suspend();
    1.43  
    1.44  	/*
    1.45 -	 * We'll stop somewhere inside this hypercall. When it returns,
    1.46 -	 * we'll start resuming after the restore.
    1.47 +	 * This hypercall returns 1 if suspend was cancelled or the domain was
    1.48 +	 * merely checkpointed, and 0 if it is resuming in a new domain.
    1.49  	 */
    1.50 -	HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
    1.51 +	suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
    1.52  
    1.53 -	post_suspend();
    1.54 +	post_suspend(suspend_cancelled);
    1.55  
    1.56  	gnttab_resume();
    1.57  
    1.58 -	irq_resume();
    1.59 +	if (!suspend_cancelled)
    1.60 +		irq_resume();
    1.61  
    1.62  	time_resume();
    1.63  
    1.64 @@ -175,9 +183,12 @@ int __xen_suspend(void)
    1.65  
    1.66  	local_irq_enable();
    1.67  
    1.68 -	xencons_resume();
    1.69 -
    1.70 -	xenbus_resume();
    1.71 +	if (!suspend_cancelled) {
    1.72 +		xencons_resume();
    1.73 +		xenbus_resume();
    1.74 +	} else {
    1.75 +		xenbus_suspend_cancel();
    1.76 +	}
    1.77  
    1.78  	smp_resume();
    1.79  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Sat Jan 20 11:17:42 2007 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Sat Jan 20 11:21:08 2007 +0000
     2.3 @@ -672,6 +672,27 @@ static int suspend_dev(struct device *de
     2.4  	return 0;
     2.5  }
     2.6  
     2.7 +static int suspend_cancel_dev(struct device *dev, void *data)
     2.8 +{
     2.9 +	int err = 0;
    2.10 +	struct xenbus_driver *drv;
    2.11 +	struct xenbus_device *xdev;
    2.12 +
    2.13 +	DPRINTK("");
    2.14 +
    2.15 +	if (dev->driver == NULL)
    2.16 +		return 0;
    2.17 +	drv = to_xenbus_driver(dev->driver);
    2.18 +	xdev = container_of(dev, struct xenbus_device, dev);
    2.19 +	if (drv->suspend_cancel)
    2.20 +		err = drv->suspend_cancel(xdev);
    2.21 +	if (err)
    2.22 +		printk(KERN_WARNING
    2.23 +		       "xenbus: suspend_cancel %s failed: %i\n",
    2.24 +		       dev->bus_id, err);
    2.25 +	return 0;
    2.26 +}
    2.27 +
    2.28  static int resume_dev(struct device *dev, void *data)
    2.29  {
    2.30  	int err;
    2.31 @@ -736,6 +757,13 @@ void xenbus_resume(void)
    2.32  }
    2.33  EXPORT_SYMBOL_GPL(xenbus_resume);
    2.34  
    2.35 +void xenbus_suspend_cancel(void)
    2.36 +{
    2.37 +	xs_suspend_cancel();
    2.38 +	bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_cancel_dev);
    2.39 +	xenbus_backend_resume(suspend_cancel_dev);
    2.40 +}
    2.41 +EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
    2.42  
    2.43  /* A flag to determine if xenstored is 'ready' (i.e. has started) */
    2.44  int xenstored_ready = 0;
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Sat Jan 20 11:17:42 2007 +0000
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Sat Jan 20 11:21:08 2007 +0000
     3.3 @@ -668,17 +668,7 @@ EXPORT_SYMBOL_GPL(unregister_xenbus_watc
     3.4  
     3.5  void xs_suspend(void)
     3.6  {
     3.7 -	struct xenbus_watch *watch;
     3.8 -	char token[sizeof(watch) * 2 + 1];
     3.9 -
    3.10  	down_write(&xs_state.suspend_mutex);
    3.11 -
    3.12 -	/* No need for watches_lock: the suspend_mutex is sufficient. */
    3.13 -	list_for_each_entry(watch, &watches, list) {
    3.14 -		sprintf(token, "%lX", (long)watch);
    3.15 -		xs_unwatch(watch->node, token);
    3.16 -	}
    3.17 -
    3.18  	mutex_lock(&xs_state.request_mutex);
    3.19  }
    3.20  
    3.21 @@ -698,6 +688,12 @@ void xs_resume(void)
    3.22  	up_write(&xs_state.suspend_mutex);
    3.23  }
    3.24  
    3.25 +void xs_suspend_cancel(void)
    3.26 +{
    3.27 +	mutex_unlock(&xs_state.request_mutex);
    3.28 +	up_write(&xs_state.suspend_mutex);
    3.29 +}
    3.30 +
    3.31  static int xenwatch_handle_callback(void *data)
    3.32  {
    3.33  	struct xs_stored_msg *msg = data;
     4.1 --- a/linux-2.6-xen-sparse/include/xen/xenbus.h	Sat Jan 20 11:17:42 2007 +0000
     4.2 +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h	Sat Jan 20 11:21:08 2007 +0000
     4.3 @@ -101,6 +101,7 @@ struct xenbus_driver {
     4.4  				 enum xenbus_state backend_state);
     4.5  	int (*remove)(struct xenbus_device *dev);
     4.6  	int (*suspend)(struct xenbus_device *dev);
     4.7 +	int (*suspend_cancel)(struct xenbus_device *dev);
     4.8  	int (*resume)(struct xenbus_device *dev);
     4.9  	int (*uevent)(struct xenbus_device *, char **, int, char *, int);
    4.10  	struct device_driver driver;
    4.11 @@ -160,13 +161,15 @@ int register_xenbus_watch(struct xenbus_
    4.12  void unregister_xenbus_watch(struct xenbus_watch *watch);
    4.13  void xs_suspend(void);
    4.14  void xs_resume(void);
    4.15 +void xs_suspend_cancel(void);
    4.16  
    4.17  /* Used by xenbus_dev to borrow kernel's store connection. */
    4.18  void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
    4.19  
    4.20 -/* Called from xen core code. */
    4.21 +/* Prepare for domain suspend: then resume or cancel the suspend. */
    4.22  void xenbus_suspend(void);
    4.23  void xenbus_resume(void);
    4.24 +void xenbus_suspend_cancel(void);
    4.25  
    4.26  #define XENBUS_IS_ERR_READ(str) ({			\
    4.27  	if (!IS_ERR(str) && strlen(str) == 0) {		\
     5.1 --- a/tools/libxc/Makefile	Sat Jan 20 11:17:42 2007 +0000
     5.2 +++ b/tools/libxc/Makefile	Sat Jan 20 11:21:08 2007 +0000
     5.3 @@ -15,6 +15,7 @@ CTRL_SRCS-y       += xc_private.c
     5.4  CTRL_SRCS-y       += xc_sedf.c
     5.5  CTRL_SRCS-y       += xc_csched.c
     5.6  CTRL_SRCS-y       += xc_tbuf.c
     5.7 +CTRL_SRCS-y       += xc_resume.c
     5.8  CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
     5.9  CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c
    5.10  CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
     6.1 --- a/tools/libxc/xc_domain.c	Sat Jan 20 11:17:42 2007 +0000
     6.2 +++ b/tools/libxc/xc_domain.c	Sat Jan 20 11:21:08 2007 +0000
     6.3 @@ -89,16 +89,6 @@ int xc_domain_shutdown(int xc_handle,
     6.4  }
     6.5  
     6.6  
     6.7 -int xc_domain_resume(int xc_handle,
     6.8 -                      uint32_t domid)
     6.9 -{
    6.10 -    DECLARE_DOMCTL;
    6.11 -    domctl.cmd = XEN_DOMCTL_resumedomain;
    6.12 -    domctl.domain = (domid_t)domid;
    6.13 -    return do_domctl(xc_handle, &domctl);
    6.14 -}
    6.15 -
    6.16 -
    6.17  int xc_vcpu_setaffinity(int xc_handle,
    6.18                          uint32_t domid,
    6.19                          int vcpu,
    6.20 @@ -293,9 +283,9 @@ int xc_domain_hvm_setcontext(int xc_hand
    6.21  }
    6.22  
    6.23  int xc_vcpu_getcontext(int xc_handle,
    6.24 -                               uint32_t domid,
    6.25 -                               uint32_t vcpu,
    6.26 -                               vcpu_guest_context_t *ctxt)
    6.27 +                       uint32_t domid,
    6.28 +                       uint32_t vcpu,
    6.29 +                       vcpu_guest_context_t *ctxt)
    6.30  {
    6.31      int rc;
    6.32      DECLARE_DOMCTL;
    6.33 @@ -602,15 +592,15 @@ int xc_vcpu_setcontext(int xc_handle,
    6.34      domctl.u.vcpucontext.vcpu = vcpu;
    6.35      set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
    6.36  
    6.37 -    if ( (rc = lock_pages(ctxt, sizeof(*ctxt))) != 0 )
    6.38 +    if ( (ctxt != NULL) && ((rc = lock_pages(ctxt, sizeof(*ctxt))) != 0) )
    6.39          return rc;
    6.40  
    6.41      rc = do_domctl(xc_handle, &domctl);
    6.42  
    6.43 -    unlock_pages(ctxt, sizeof(*ctxt));
    6.44 +    if ( ctxt != NULL )
    6.45 +        unlock_pages(ctxt, sizeof(*ctxt));
    6.46  
    6.47      return rc;
    6.48 -
    6.49  }
    6.50  
    6.51  int xc_domain_irq_permission(int xc_handle,
     7.1 --- a/tools/libxc/xc_evtchn.c	Sat Jan 20 11:17:42 2007 +0000
     7.2 +++ b/tools/libxc/xc_evtchn.c	Sat Jan 20 11:21:08 2007 +0000
     7.3 @@ -37,7 +37,7 @@ int xc_evtchn_alloc_unbound(int xc_handl
     7.4                              uint32_t dom,
     7.5                              uint32_t remote_dom)
     7.6  {
     7.7 -    int         rc;
     7.8 +    int rc;
     7.9      struct evtchn_alloc_unbound arg = {
    7.10          .dom = (domid_t)dom,
    7.11          .remote_dom = (domid_t)remote_dom
    7.12 @@ -49,3 +49,10 @@ int xc_evtchn_alloc_unbound(int xc_handl
    7.13  
    7.14      return rc;
    7.15  }
    7.16 +
    7.17 +int xc_evtchn_reset(int xc_handle,
    7.18 +                    uint32_t dom)
    7.19 +{
    7.20 +    struct evtchn_reset arg = { .dom = (domid_t)dom };
    7.21 +    return do_evtchn_op(xc_handle, EVTCHNOP_reset, &arg, sizeof(arg));
    7.22 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/libxc/xc_resume.c	Sat Jan 20 11:21:08 2007 +0000
     8.3 @@ -0,0 +1,35 @@
     8.4 +#include "xc_private.h"
     8.5 +
     8.6 +/*
     8.7 + * Resume execution of a domain after suspend shutdown.
     8.8 + * This can happen in one of two ways:
     8.9 + *  1. Resume with special return code.
    8.10 + *  2. Reset guest environment so it believes it is resumed in a new
    8.11 + *     domain context.
    8.12 + * (2) should be used only for guests which cannot handle the special
    8.13 + * new return code. (1) is always safe (but slower).
    8.14 + * 
    8.15 + * XXX Only (2) is implemented below. We need to use (1) by default!
    8.16 + */
    8.17 +int xc_domain_resume(int xc_handle, uint32_t domid)
    8.18 +{
    8.19 +    vcpu_guest_context_t ctxt;
    8.20 +    DECLARE_DOMCTL;
    8.21 +    int rc;
    8.22 +
    8.23 +    /*
    8.24 +     * Set hypercall return code to indicate that suspend is cancelled
    8.25 +     * (rather than resuming in a new domain context).
    8.26 +     */
    8.27 +#if defined(__i386__) || defined(__x86_64__)
    8.28 +    if ( (rc = xc_vcpu_getcontext(xc_handle, domid, 0, &ctxt)) != 0 )
    8.29 +        return rc;
    8.30 +    ctxt.user_regs.eax = 1;
    8.31 +    if ( (rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt)) != 0 )
    8.32 +        return rc;
    8.33 +#endif
    8.34 +
    8.35 +    domctl.cmd = XEN_DOMCTL_resumedomain;
    8.36 +    domctl.domain = domid;
    8.37 +    return do_domctl(xc_handle, &domctl);
    8.38 +}
     9.1 --- a/tools/libxc/xenctrl.h	Sat Jan 20 11:17:42 2007 +0000
     9.2 +++ b/tools/libxc/xenctrl.h	Sat Jan 20 11:21:08 2007 +0000
     9.3 @@ -360,9 +360,9 @@ int xc_domain_hvm_setcontext(int xc_hand
     9.4   * @return 0 on success, -1 on failure
     9.5   */
     9.6  int xc_vcpu_getcontext(int xc_handle,
     9.7 -                               uint32_t domid,
     9.8 -                               uint32_t vcpu,
     9.9 -                               vcpu_guest_context_t *ctxt);
    9.10 +                       uint32_t domid,
    9.11 +                       uint32_t vcpu,
    9.12 +                       vcpu_guest_context_t *ctxt);
    9.13  
    9.14  typedef xen_domctl_getvcpuinfo_t xc_vcpuinfo_t;
    9.15  int xc_vcpu_getinfo(int xc_handle,
    9.16 @@ -432,6 +432,9 @@ int xc_evtchn_alloc_unbound(int xc_handl
    9.17                              uint32_t dom,
    9.18                              uint32_t remote_dom);
    9.19  
    9.20 +int xc_evtchn_reset(int xc_handle,
    9.21 +                    uint32_t dom);
    9.22 +
    9.23  int xc_physdev_pci_access_modify(int xc_handle,
    9.24                                   uint32_t domid,
    9.25                                   int bus,
    10.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Sat Jan 20 11:17:42 2007 +0000
    10.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Sat Jan 20 11:21:08 2007 +0000
    10.3 @@ -478,6 +478,24 @@ static PyObject *pyxc_evtchn_alloc_unbou
    10.4      return PyInt_FromLong(port);
    10.5  }
    10.6  
    10.7 +static PyObject *pyxc_evtchn_reset(XcObject *self,
    10.8 +				   PyObject *args,
    10.9 +				   PyObject *kwds)
   10.10 +{
   10.11 +    uint32_t dom;
   10.12 +
   10.13 +    static char *kwd_list[] = { "dom", NULL };
   10.14 +
   10.15 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
   10.16 +        return NULL;
   10.17 +
   10.18 +    if ( xc_evtchn_reset(self->xc_handle, dom) < 0 )
   10.19 +        return pyxc_error_to_exception();
   10.20 +
   10.21 +    Py_INCREF(zero);
   10.22 +    return zero;
   10.23 +}
   10.24 +
   10.25  static PyObject *pyxc_physdev_pci_access_modify(XcObject *self,
   10.26                                                  PyObject *args,
   10.27                                                  PyObject *kwds)
   10.28 @@ -1202,6 +1220,12 @@ static PyMethodDef pyxc_methods[] = {
   10.29        " remote_dom [int]: Remote domain to accept connections from.\n\n"
   10.30        "Returns: [int] Unbound event-channel port.\n" },
   10.31  
   10.32 +    { "evtchn_reset", 
   10.33 +      (PyCFunction)pyxc_evtchn_reset,
   10.34 +      METH_VARARGS | METH_KEYWORDS, "\n"
   10.35 +      "Reset all connections.\n"
   10.36 +      " dom [int]: Domain to reset.\n" },
   10.37 +
   10.38      { "physdev_pci_access_modify",
   10.39        (PyCFunction)pyxc_physdev_pci_access_modify,
   10.40        METH_VARARGS | METH_KEYWORDS, "\n"
    11.1 --- a/tools/python/xen/lowlevel/xs/xs.c	Sat Jan 20 11:17:42 2007 +0000
    11.2 +++ b/tools/python/xen/lowlevel/xs/xs.c	Sat Jan 20 11:21:08 2007 +0000
    11.3 @@ -618,6 +618,33 @@ static PyObject *xspy_introduce_domain(X
    11.4      return none(result);
    11.5  }
    11.6  
    11.7 +#define xspy_resume_domain_doc "\n"                                \
    11.8 +	"Tell xenstore to clear its shutdown flag for a domain.\n" \
    11.9 +	"This ensures that a subsequent shutdown will fire the\n"  \
   11.10 +	"appropriate watches.\n"                                   \
   11.11 +	" dom [int]: domain id\n"			           \
   11.12 +        "\n"						           \
   11.13 +        "Returns None on success.\n"				   \
   11.14 +        "Raises xen.lowlevel.xs.Error on error.\n"
   11.15 +
   11.16 +static PyObject *xspy_resume_domain(XsHandle *self, PyObject *args)
   11.17 +{
   11.18 +    uint32_t dom;
   11.19 +
   11.20 +    struct xs_handle *xh = xshandle(self);
   11.21 +    bool result = 0;
   11.22 +
   11.23 +    if (!xh)
   11.24 +        return NULL;
   11.25 +    if (!PyArg_ParseTuple(args, "i", &dom))
   11.26 +        return NULL;
   11.27 +
   11.28 +    Py_BEGIN_ALLOW_THREADS
   11.29 +    result = xs_resume_domain(xh, dom);
   11.30 +    Py_END_ALLOW_THREADS
   11.31 +
   11.32 +    return none(result);
   11.33 +}
   11.34  
   11.35  #define xspy_release_domain_doc "\n"					\
   11.36  	"Tell xenstore to release its channel to a domain.\n"		\
   11.37 @@ -789,6 +816,7 @@ static PyMethodDef xshandle_methods[] = 
   11.38      XSPY_METH(transaction_start, METH_NOARGS),
   11.39      XSPY_METH(transaction_end,   METH_VARARGS | METH_KEYWORDS),
   11.40      XSPY_METH(introduce_domain,  METH_VARARGS),
   11.41 +    XSPY_METH(resume_domain,     METH_VARARGS),
   11.42      XSPY_METH(release_domain,    METH_VARARGS),
   11.43      XSPY_METH(close,             METH_NOARGS),
   11.44      XSPY_METH(get_domain_path,   METH_VARARGS),
    12.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Sat Jan 20 11:17:42 2007 +0000
    12.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Sat Jan 20 11:21:08 2007 +0000
    12.3 @@ -45,7 +45,7 @@ from xen.xend.XendBootloader import boot
    12.4  from xen.xend.XendError import XendError, VmError
    12.5  from xen.xend.XendDevices import XendDevices
    12.6  from xen.xend.xenstore.xstransact import xstransact, complete
    12.7 -from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
    12.8 +from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain, ResumeDomain
    12.9  from xen.xend.xenstore.xswatch import xswatch
   12.10  from xen.xend.XendConstants import *
   12.11  from xen.xend.XendAPIConstants import *
   12.12 @@ -1545,6 +1545,7 @@ class XendDomainInfo:
   12.13          try:
   12.14              if self.domid is not None:
   12.15                  xc.domain_resume(self.domid)
   12.16 +                ResumeDomain(self.domid)
   12.17          except:
   12.18              log.exception("XendDomainInfo.resume: xc.domain_resume failed on domain %s." % (str(self.domid)))
   12.19  
    13.1 --- a/tools/python/xen/xend/xenstore/xsutil.py	Sat Jan 20 11:17:42 2007 +0000
    13.2 +++ b/tools/python/xen/xend/xenstore/xsutil.py	Sat Jan 20 11:21:08 2007 +0000
    13.3 @@ -24,3 +24,6 @@ def IntroduceDomain(domid, page, port):
    13.4  
    13.5  def GetDomainPath(domid):
    13.6      return xshandle().get_domain_path(domid)
    13.7 +
    13.8 +def ResumeDomain(domid):
    13.9 +    return xshandle().resume_domain(domid)
    14.1 --- a/tools/xenstore/xenstored_core.c	Sat Jan 20 11:17:42 2007 +0000
    14.2 +++ b/tools/xenstore/xenstored_core.c	Sat Jan 20 11:21:08 2007 +0000
    14.3 @@ -164,6 +164,7 @@ static char *sockmsg_string(enum xsd_soc
    14.4  	case XS_WATCH_EVENT: return "WATCH_EVENT";
    14.5  	case XS_ERROR: return "ERROR";
    14.6  	case XS_IS_DOMAIN_INTRODUCED: return "XS_IS_DOMAIN_INTRODUCED";
    14.7 +	case XS_RESUME: return "RESUME";
    14.8  	default:
    14.9  		return "**UNKNOWN**";
   14.10  	}
   14.11 @@ -1267,6 +1268,10 @@ static void process_message(struct conne
   14.12  		do_get_domain_path(conn, onearg(in));
   14.13  		break;
   14.14  
   14.15 +	case XS_RESUME:
   14.16 +		do_resume(conn, onearg(in));
   14.17 +		break;
   14.18 +
   14.19  	default:
   14.20  		eprintf("Client unknown operation %i", in->hdr.msg.type);
   14.21  		send_error(conn, ENOSYS);
    15.1 --- a/tools/xenstore/xenstored_domain.c	Sat Jan 20 11:17:42 2007 +0000
    15.2 +++ b/tools/xenstore/xenstored_domain.c	Sat Jan 20 11:21:08 2007 +0000
    15.3 @@ -343,13 +343,14 @@ void do_introduce(struct connection *con
    15.4  		fire_watches(conn, "@introduceDomain", false);
    15.5  	}
    15.6  	else {
    15.7 -		/* Check that the given details match the ones we have
    15.8 -		   previously recorded. */
    15.9 -		if (port != domain->remote_port ||
   15.10 -		    mfn != domain->mfn) {
   15.11 -			send_error(conn, EINVAL);
   15.12 -			return;
   15.13 -		}
   15.14 +		int rc;
   15.15 +
   15.16 +		/* Use XS_INTRODUCE for recreating the xenbus event-channel. */
   15.17 +		if (domain->port)
   15.18 +			xc_evtchn_unbind(xce_handle, domain->port);
   15.19 +		rc = xc_evtchn_bind_interdomain(xce_handle, domid, port);
   15.20 +		domain->port = (rc == -1) ? 0 : rc;
   15.21 +		domain->remote_port = port;
   15.22  	}
   15.23  
   15.24  	send_ack(conn, XS_INTRODUCE);
   15.25 @@ -395,6 +396,43 @@ void do_release(struct connection *conn,
   15.26  	send_ack(conn, XS_RELEASE);
   15.27  }
   15.28  
   15.29 +void do_resume(struct connection *conn, const char *domid_str)
   15.30 +{
   15.31 +	struct domain *domain;
   15.32 +	unsigned int domid;
   15.33 +
   15.34 +	if (!domid_str) {
   15.35 +		send_error(conn, EINVAL);
   15.36 +		return;
   15.37 +	}
   15.38 +
   15.39 +	domid = atoi(domid_str);
   15.40 +	if (!domid) {
   15.41 +		send_error(conn, EINVAL);
   15.42 +		return;
   15.43 +	}
   15.44 +
   15.45 +	if (conn->id != 0) {
   15.46 +		send_error(conn, EACCES);
   15.47 +		return;
   15.48 +	}
   15.49 +
   15.50 +	domain = find_domain_by_domid(domid);
   15.51 +	if (!domain) {
   15.52 +		send_error(conn, ENOENT);
   15.53 +		return;
   15.54 +	}
   15.55 +
   15.56 +	if (!domain->conn) {
   15.57 +		send_error(conn, EINVAL);
   15.58 +		return;
   15.59 +	}
   15.60 +
   15.61 +	domain->shutdown = 0;
   15.62 +	
   15.63 +	send_ack(conn, XS_RESUME);
   15.64 +}
   15.65 +
   15.66  void do_get_domain_path(struct connection *conn, const char *domid_str)
   15.67  {
   15.68  	char *path;
    16.1 --- a/tools/xenstore/xenstored_domain.h	Sat Jan 20 11:17:42 2007 +0000
    16.2 +++ b/tools/xenstore/xenstored_domain.h	Sat Jan 20 11:21:08 2007 +0000
    16.3 @@ -32,6 +32,9 @@ void do_is_domain_introduced(struct conn
    16.4  void do_release(struct connection *conn, const char *domid_str);
    16.5  
    16.6  /* domid */
    16.7 +void do_resume(struct connection *conn, const char *domid_str);
    16.8 +
    16.9 +/* domid */
   16.10  void do_get_domain_path(struct connection *conn, const char *domid_str);
   16.11  
   16.12  /* Returns the event channel handle */
    17.1 --- a/tools/xenstore/xs.c	Sat Jan 20 11:17:42 2007 +0000
    17.2 +++ b/tools/xenstore/xs.c	Sat Jan 20 11:21:08 2007 +0000
    17.3 @@ -719,6 +719,12 @@ bool xs_release_domain(struct xs_handle 
    17.4  	return xs_bool(single_with_domid(h, XS_RELEASE, domid));
    17.5  }
    17.6  
    17.7 +/* clear the shutdown bit for the given domain */
    17.8 +bool xs_resume_domain(struct xs_handle *h, unsigned int domid)
    17.9 +{
   17.10 +	return xs_bool(single_with_domid(h, XS_RESUME, domid));
   17.11 +}
   17.12 +
   17.13  char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
   17.14  {
   17.15  	char domid_str[MAX_STRLEN(domid)];
    18.1 --- a/tools/xenstore/xs.h	Sat Jan 20 11:17:42 2007 +0000
    18.2 +++ b/tools/xenstore/xs.h	Sat Jan 20 11:21:08 2007 +0000
    18.3 @@ -133,6 +133,11 @@ bool xs_introduce_domain(struct xs_handl
    18.4  			 unsigned int domid,
    18.5  			 unsigned long mfn,
    18.6                           unsigned int eventchn); 
    18.7 +/* Resume a domain.
    18.8 + * Clear the shutdown flag for this domain in the store.
    18.9 + */
   18.10 +bool xs_resume_domain(struct xs_handle *h, unsigned int domid);
   18.11 +
   18.12  /* Release a domain.
   18.13   * Tells the store domain to release the memory page to the domain.
   18.14   */
    19.1 --- a/xen/arch/x86/domain.c	Sat Jan 20 11:17:42 2007 +0000
    19.2 +++ b/xen/arch/x86/domain.c	Sat Jan 20 11:21:08 2007 +0000
    19.3 @@ -50,6 +50,8 @@ DEFINE_PER_CPU(struct vcpu *, curr_vcpu)
    19.4  static void paravirt_ctxt_switch_from(struct vcpu *v);
    19.5  static void paravirt_ctxt_switch_to(struct vcpu *v);
    19.6  
    19.7 +static void vcpu_destroy_pagetables(struct vcpu *v);
    19.8 +
    19.9  static void continue_idle_domain(struct vcpu *v)
   19.10  {
   19.11      reset_stack_and_jump(idle_loop);
   19.12 @@ -659,6 +661,13 @@ int arch_set_info_guest(
   19.13  #undef c
   19.14  }
   19.15  
   19.16 +int arch_vcpu_reset(struct vcpu *v)
   19.17 +{
   19.18 +    destroy_gdt(v);
   19.19 +    vcpu_destroy_pagetables(v);
   19.20 +    return 0;
   19.21 +}
   19.22 +
   19.23  long
   19.24  arch_do_vcpu_op(
   19.25      int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg)
   19.26 @@ -1381,63 +1390,73 @@ static void relinquish_memory(struct dom
   19.27      spin_unlock_recursive(&d->page_alloc_lock);
   19.28  }
   19.29  
   19.30 -void domain_relinquish_resources(struct domain *d)
   19.31 +static void vcpu_destroy_pagetables(struct vcpu *v)
   19.32  {
   19.33 -    struct vcpu *v;
   19.34 +    struct domain *d = v->domain;
   19.35      unsigned long pfn;
   19.36  
   19.37 -    BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
   19.38 -
   19.39 -    /* Drop the in-use references to page-table bases. */
   19.40 -    for_each_vcpu ( d, v )
   19.41 +#ifdef CONFIG_COMPAT
   19.42 +    if ( IS_COMPAT(d) )
   19.43      {
   19.44 -        /* Drop ref to guest_table (from new_guest_cr3(), svm/vmx cr3 handling,
   19.45 -         * or sh_update_paging_modes()) */
   19.46 -#ifdef CONFIG_COMPAT
   19.47 -        if ( IS_COMPAT(d) )
   19.48 -        {
   19.49 -            if ( is_hvm_vcpu(v) )
   19.50 -                pfn = pagetable_get_pfn(v->arch.guest_table);
   19.51 -            else
   19.52 -                pfn = l4e_get_pfn(*(l4_pgentry_t *)__va(pagetable_get_paddr(v->arch.guest_table)));
   19.53 +        if ( is_hvm_vcpu(v) )
   19.54 +            pfn = pagetable_get_pfn(v->arch.guest_table);
   19.55 +        else
   19.56 +            pfn = l4e_get_pfn(*(l4_pgentry_t *)
   19.57 +                              __va(pagetable_get_paddr(v->arch.guest_table)));
   19.58  
   19.59 -            if ( pfn != 0 )
   19.60 -            {
   19.61 -                if ( shadow_mode_refcounts(d) )
   19.62 -                    put_page(mfn_to_page(pfn));
   19.63 -                else
   19.64 -                    put_page_and_type(mfn_to_page(pfn));
   19.65 -            }
   19.66 -            continue;
   19.67 -        }
   19.68 -#endif
   19.69 -        pfn = pagetable_get_pfn(v->arch.guest_table);
   19.70          if ( pfn != 0 )
   19.71          {
   19.72              if ( shadow_mode_refcounts(d) )
   19.73                  put_page(mfn_to_page(pfn));
   19.74              else
   19.75                  put_page_and_type(mfn_to_page(pfn));
   19.76 +        }
   19.77 +
   19.78 +        v->arch.guest_table = pagetable_null();
   19.79 +        v->arch.cr3 = 0;
   19.80 +        return;
   19.81 +    }
   19.82 +#endif
   19.83 +
   19.84 +    pfn = pagetable_get_pfn(v->arch.guest_table);
   19.85 +    if ( pfn != 0 )
   19.86 +    {
   19.87 +        if ( shadow_mode_refcounts(d) )
   19.88 +            put_page(mfn_to_page(pfn));
   19.89 +        else
   19.90 +            put_page_and_type(mfn_to_page(pfn));
   19.91  #ifdef __x86_64__
   19.92 -            if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) )
   19.93 -                v->arch.guest_table_user = pagetable_null();
   19.94 +        if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) )
   19.95 +            v->arch.guest_table_user = pagetable_null();
   19.96  #endif
   19.97 -            v->arch.guest_table = pagetable_null();
   19.98 -        }
   19.99 +        v->arch.guest_table = pagetable_null();
  19.100 +    }
  19.101  
  19.102  #ifdef __x86_64__
  19.103 -        /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */
  19.104 -        pfn = pagetable_get_pfn(v->arch.guest_table_user);
  19.105 -        if ( pfn != 0 )
  19.106 -        {
  19.107 -            if ( shadow_mode_refcounts(d) )
  19.108 -                put_page(mfn_to_page(pfn));
  19.109 -            else
  19.110 -                put_page_and_type(mfn_to_page(pfn));
  19.111 -            v->arch.guest_table_user = pagetable_null();
  19.112 -        }
  19.113 +    /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */
  19.114 +    pfn = pagetable_get_pfn(v->arch.guest_table_user);
  19.115 +    if ( pfn != 0 )
  19.116 +    {
  19.117 +        if ( shadow_mode_refcounts(d) )
  19.118 +            put_page(mfn_to_page(pfn));
  19.119 +        else
  19.120 +            put_page_and_type(mfn_to_page(pfn));
  19.121 +        v->arch.guest_table_user = pagetable_null();
  19.122 +    }
  19.123  #endif
  19.124 -    }
  19.125 +
  19.126 +    v->arch.cr3 = 0;
  19.127 +}
  19.128 +
  19.129 +void domain_relinquish_resources(struct domain *d)
  19.130 +{
  19.131 +    struct vcpu *v;
  19.132 +
  19.133 +    BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
  19.134 +
  19.135 +    /* Drop the in-use references to page-table bases. */
  19.136 +    for_each_vcpu ( d, v )
  19.137 +        vcpu_destroy_pagetables(v);
  19.138  
  19.139      /* Tear down shadow mode stuff. */
  19.140      shadow_teardown(d);
    20.1 --- a/xen/arch/x86/domctl.c	Sat Jan 20 11:17:42 2007 +0000
    20.2 +++ b/xen/arch/x86/domctl.c	Sat Jan 20 11:21:08 2007 +0000
    20.3 @@ -326,7 +326,6 @@
    20.4      }
    20.5      break;
    20.6  
    20.7 -
    20.8      case XEN_DOMCTL_gethvmcontext:
    20.9      { 
   20.10          struct hvm_domain_context *c;
    21.1 --- a/xen/common/domain.c	Sat Jan 20 11:17:42 2007 +0000
    21.2 +++ b/xen/common/domain.c	Sat Jan 20 11:21:08 2007 +0000
    21.3 @@ -5,6 +5,7 @@
    21.4   */
    21.5  
    21.6  #include <xen/config.h>
    21.7 +#include <xen/compat.h>
    21.8  #include <xen/init.h>
    21.9  #include <xen/lib.h>
   21.10  #include <xen/errno.h>
   21.11 @@ -466,7 +467,12 @@ int set_info_guest(struct domain *d,
   21.12  
   21.13      if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
   21.14          return -EINVAL;
   21.15 -    
   21.16 +
   21.17 +    if ( IS_COMPAT(v->domain)
   21.18 +         ? compat_handle_is_null(vcpucontext.cmp->ctxt)
   21.19 +         : guest_handle_is_null(vcpucontext.nat->ctxt) )
   21.20 +        return vcpu_reset(v);
   21.21 +
   21.22  #ifdef CONFIG_COMPAT
   21.23      BUILD_BUG_ON(sizeof(struct vcpu_guest_context)
   21.24                   < sizeof(struct compat_vcpu_guest_context));
   21.25 @@ -520,6 +526,36 @@ int boot_vcpu(struct domain *d, int vcpu
   21.26      return arch_set_info_guest(v, ctxt);
   21.27  }
   21.28  
   21.29 +int vcpu_reset(struct vcpu *v)
   21.30 +{
   21.31 +    struct domain *d = v->domain;
   21.32 +    int rc;
   21.33 +
   21.34 +    domain_pause(d);
   21.35 +    LOCK_BIGLOCK(d);
   21.36 +
   21.37 +    rc = arch_vcpu_reset(v);
   21.38 +    if ( rc != 0 )
   21.39 +        goto out;
   21.40 +
   21.41 +    set_bit(_VCPUF_down, &v->vcpu_flags);
   21.42 +
   21.43 +    clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
   21.44 +    clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags);
   21.45 +    clear_bit(_VCPUF_blocked, &v->vcpu_flags);
   21.46 +    clear_bit(_VCPUF_initialised, &v->vcpu_flags);
   21.47 +    clear_bit(_VCPUF_nmi_pending, &v->vcpu_flags);
   21.48 +    clear_bit(_VCPUF_nmi_masked, &v->vcpu_flags);
   21.49 +    clear_bit(_VCPUF_polling, &v->vcpu_flags);
   21.50 +
   21.51 + out:
   21.52 +    UNLOCK_BIGLOCK(v->domain);
   21.53 +    domain_unpause(d);
   21.54 +
   21.55 +    return rc;
   21.56 +}
   21.57 +
   21.58 +
   21.59  long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg)
   21.60  {
   21.61      struct domain *d = current->domain;
    22.1 --- a/xen/common/event_channel.c	Sat Jan 20 11:17:42 2007 +0000
    22.2 +++ b/xen/common/event_channel.c	Sat Jan 20 11:21:08 2007 +0000
    22.3 @@ -735,6 +735,29 @@ static long evtchn_unmask(evtchn_unmask_
    22.4  }
    22.5  
    22.6  
    22.7 +static long evtchn_reset(evtchn_reset_t *r)
    22.8 +{
    22.9 +    domid_t dom = r->dom;
   22.10 +    struct domain *d;
   22.11 +    int i;
   22.12 +
   22.13 +    if ( dom == DOMID_SELF )
   22.14 +        dom = current->domain->domain_id;
   22.15 +    else if ( !IS_PRIV(current->domain) )
   22.16 +        return -EPERM;
   22.17 +
   22.18 +    if ( (d = find_domain_by_id(dom)) == NULL )
   22.19 +        return -ESRCH;
   22.20 +
   22.21 +    for ( i = 0; port_is_valid(d, i); i++ )
   22.22 +        (void)__evtchn_close(d, i);
   22.23 +
   22.24 +    put_domain(d);
   22.25 +
   22.26 +    return 0;
   22.27 +}
   22.28 +
   22.29 +
   22.30  long do_event_channel_op(int cmd, XEN_GUEST_HANDLE(void) arg)
   22.31  {
   22.32      long rc;
   22.33 @@ -833,6 +856,14 @@ long do_event_channel_op(int cmd, XEN_GU
   22.34          break;
   22.35      }
   22.36  
   22.37 +    case EVTCHNOP_reset: {
   22.38 +        struct evtchn_reset reset;
   22.39 +        if ( copy_from_guest(&reset, arg, 1) != 0 )
   22.40 +            return -EFAULT;
   22.41 +        rc = evtchn_reset(&reset);
   22.42 +        break;
   22.43 +    }
   22.44 +
   22.45      default:
   22.46          rc = -ENOSYS;
   22.47          break;
    23.1 --- a/xen/include/public/event_channel.h	Sat Jan 20 11:17:42 2007 +0000
    23.2 +++ b/xen/include/public/event_channel.h	Sat Jan 20 11:21:08 2007 +0000
    23.3 @@ -217,6 +217,19 @@ struct evtchn_unmask {
    23.4  typedef struct evtchn_unmask evtchn_unmask_t;
    23.5  
    23.6  /*
    23.7 + * EVTCHNOP_reset: Close all event channels associated with specified domain.
    23.8 + * NOTES:
    23.9 + *  1. <dom> may be specified as DOMID_SELF.
   23.10 + *  2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
   23.11 + */
   23.12 +#define EVTCHNOP_reset           10
   23.13 +struct evtchn_reset {
   23.14 +    /* IN parameters. */
   23.15 +    domid_t dom;
   23.16 +};
   23.17 +typedef struct evtchn_reset evtchn_reset_t;
   23.18 +
   23.19 +/*
   23.20   * Argument to event_channel_op_compat() hypercall. Superceded by new
   23.21   * event_channel_op() hypercall since 0x00030202.
   23.22   */
    24.1 --- a/xen/include/public/io/xs_wire.h	Sat Jan 20 11:17:42 2007 +0000
    24.2 +++ b/xen/include/public/io/xs_wire.h	Sat Jan 20 11:21:08 2007 +0000
    24.3 @@ -45,7 +45,8 @@ enum xsd_sockmsg_type
    24.4      XS_SET_PERMS,
    24.5      XS_WATCH_EVENT,
    24.6      XS_ERROR,
    24.7 -    XS_IS_DOMAIN_INTRODUCED
    24.8 +    XS_IS_DOMAIN_INTRODUCED,
    24.9 +    XS_RESUME
   24.10  };
   24.11  
   24.12  #define XS_WRITE_NONE "NONE"
    25.1 --- a/xen/include/xen/compat.h	Sat Jan 20 11:17:42 2007 +0000
    25.2 +++ b/xen/include/xen/compat.h	Sat Jan 20 11:21:08 2007 +0000
    25.3 @@ -173,6 +173,8 @@ int switch_native(struct domain *);
    25.4  
    25.5  #else
    25.6  
    25.7 +#define compat_handle_is_null(hnd) 0
    25.8 +
    25.9  #define BITS_PER_GUEST_LONG(d) BITS_PER_LONG
   25.10  
   25.11  #endif
    26.1 --- a/xen/include/xen/domain.h	Sat Jan 20 11:17:42 2007 +0000
    26.2 +++ b/xen/include/xen/domain.h	Sat Jan 20 11:21:08 2007 +0000
    26.3 @@ -12,6 +12,7 @@ struct vcpu *alloc_vcpu(
    26.4  int boot_vcpu(
    26.5      struct domain *d, int vcpuid, vcpu_guest_context_u ctxt);
    26.6  struct vcpu *alloc_idle_vcpu(unsigned int cpu_id);
    26.7 +int vcpu_reset(struct vcpu *v);
    26.8  
    26.9  struct domain *alloc_domain(domid_t domid);
   26.10  void free_domain(struct domain *d);
   26.11 @@ -56,4 +57,6 @@ void arch_dump_vcpu_info(struct vcpu *v)
   26.12  
   26.13  void arch_dump_domain_info(struct domain *d);
   26.14  
   26.15 +int arch_vcpu_reset(struct vcpu *v);
   26.16 +
   26.17  #endif /* __XEN_DOMAIN_H__ */