[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Merge



# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1169292068 0
# Node ID 5dc5e6ba42d2b68edac47a39ac5e318ae1d76119
# Parent  ff4f4596cb29da5f4d672e9a99fe45603282263e
# Parent  0971f0e9461e417875c86c0b3433f99341aa3432
Merge
---
 linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c |   33 +++--
 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c |   28 ++++
 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c    |   16 --
 linux-2.6-xen-sparse/include/xen/xenbus.h              |    5 
 tools/libxc/Makefile                                   |    1 
 tools/libxc/xc_domain.c                                |   22 ---
 tools/libxc/xc_evtchn.c                                |    9 +
 tools/libxc/xc_resume.c                                |   35 +++++
 tools/libxc/xenctrl.h                                  |    9 -
 tools/python/xen/lowlevel/xc/xc.c                      |   24 +++
 tools/python/xen/lowlevel/xs/xs.c                      |   28 ++++
 tools/python/xen/xend/XendDomainInfo.py                |    3 
 tools/python/xen/xend/xenstore/xsutil.py               |    3 
 tools/xenstore/xenstored_core.c                        |    5 
 tools/xenstore/xenstored_domain.c                      |   52 +++++++-
 tools/xenstore/xenstored_domain.h                      |    3 
 tools/xenstore/xs.c                                    |    6 
 tools/xenstore/xs.h                                    |    5 
 xen/arch/x86/domain.c                                  |  109 +++++++++--------
 xen/arch/x86/domctl.c                                  |    1 
 xen/common/domain.c                                    |   38 +++++
 xen/common/event_channel.c                             |   31 ++++
 xen/include/public/event_channel.h                     |   13 ++
 xen/include/public/io/xs_wire.h                        |    3 
 xen/include/xen/compat.h                               |    2 
 xen/include/xen/domain.h                               |    3 
 26 files changed, 389 insertions(+), 98 deletions(-)

diff -r ff4f4596cb29 -r 5dc5e6ba42d2 
linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c    Sat Jan 20 
11:17:42 2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c    Sat Jan 20 
11:21:08 2007 +0000
@@ -85,13 +85,20 @@ static void pre_suspend(void)
                mfn_to_pfn(xen_start_info->console.domU.mfn);
 }
 
-static void post_suspend(void)
+static void post_suspend(int suspend_cancelled)
 {
        int i, j, k, fpp;
        extern unsigned long max_pfn;
        extern unsigned long *pfn_to_mfn_frame_list_list;
        extern unsigned long *pfn_to_mfn_frame_list[];
 
+       if (suspend_cancelled) {
+               xen_start_info->store_mfn =
+                       pfn_to_mfn(xen_start_info->store_mfn);
+               xen_start_info->console.domU.mfn =
+                       pfn_to_mfn(xen_start_info->console.domU.mfn);
+       }
+       
        set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
 
        HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
@@ -120,13 +127,13 @@ static void post_suspend(void)
 #define switch_idle_mm()       ((void)0)
 #define mm_pin_all()           ((void)0)
 #define pre_suspend()          ((void)0)
-#define post_suspend()         ((void)0)
+#define post_suspend(x)                ((void)0)
 
 #endif
 
 int __xen_suspend(void)
 {
-       int err;
+       int err, suspend_cancelled;
 
        extern void time_resume(void);
 
@@ -158,16 +165,17 @@ int __xen_suspend(void)
        pre_suspend();
 
        /*
-        * We'll stop somewhere inside this hypercall. When it returns,
-        * we'll start resuming after the restore.
+        * This hypercall returns 1 if suspend was cancelled or the domain was
+        * merely checkpointed, and 0 if it is resuming in a new domain.
         */
-       HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+       suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
 
-       post_suspend();
+       post_suspend(suspend_cancelled);
 
        gnttab_resume();
 
-       irq_resume();
+       if (!suspend_cancelled)
+               irq_resume();
 
        time_resume();
 
@@ -175,9 +183,12 @@ int __xen_suspend(void)
 
        local_irq_enable();
 
-       xencons_resume();
-
-       xenbus_resume();
+       if (!suspend_cancelled) {
+               xencons_resume();
+               xenbus_resume();
+       } else {
+               xenbus_suspend_cancel();
+       }
 
        smp_resume();
 
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Sat Jan 20 
11:17:42 2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Sat Jan 20 
11:21:08 2007 +0000
@@ -672,6 +672,27 @@ static int suspend_dev(struct device *de
        return 0;
 }
 
+static int suspend_cancel_dev(struct device *dev, void *data)
+{
+       int err = 0;
+       struct xenbus_driver *drv;
+       struct xenbus_device *xdev;
+
+       DPRINTK("");
+
+       if (dev->driver == NULL)
+               return 0;
+       drv = to_xenbus_driver(dev->driver);
+       xdev = container_of(dev, struct xenbus_device, dev);
+       if (drv->suspend_cancel)
+               err = drv->suspend_cancel(xdev);
+       if (err)
+               printk(KERN_WARNING
+                      "xenbus: suspend_cancel %s failed: %i\n",
+                      dev->bus_id, err);
+       return 0;
+}
+
 static int resume_dev(struct device *dev, void *data)
 {
        int err;
@@ -736,6 +757,13 @@ void xenbus_resume(void)
 }
 EXPORT_SYMBOL_GPL(xenbus_resume);
 
+void xenbus_suspend_cancel(void)
+{
+       xs_suspend_cancel();
+       bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_cancel_dev);
+       xenbus_backend_resume(suspend_cancel_dev);
+}
+EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
 
 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
 int xenstored_ready = 0;
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c       Sat Jan 20 
11:17:42 2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c       Sat Jan 20 
11:21:08 2007 +0000
@@ -668,17 +668,7 @@ EXPORT_SYMBOL_GPL(unregister_xenbus_watc
 
 void xs_suspend(void)
 {
-       struct xenbus_watch *watch;
-       char token[sizeof(watch) * 2 + 1];
-
        down_write(&xs_state.suspend_mutex);
-
-       /* No need for watches_lock: the suspend_mutex is sufficient. */
-       list_for_each_entry(watch, &watches, list) {
-               sprintf(token, "%lX", (long)watch);
-               xs_unwatch(watch->node, token);
-       }
-
        mutex_lock(&xs_state.request_mutex);
 }
 
@@ -695,6 +685,12 @@ void xs_resume(void)
                xs_watch(watch->node, token);
        }
 
+       up_write(&xs_state.suspend_mutex);
+}
+
+void xs_suspend_cancel(void)
+{
+       mutex_unlock(&xs_state.request_mutex);
        up_write(&xs_state.suspend_mutex);
 }
 
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 linux-2.6-xen-sparse/include/xen/xenbus.h
--- a/linux-2.6-xen-sparse/include/xen/xenbus.h Sat Jan 20 11:17:42 2007 +0000
+++ b/linux-2.6-xen-sparse/include/xen/xenbus.h Sat Jan 20 11:21:08 2007 +0000
@@ -101,6 +101,7 @@ struct xenbus_driver {
                                 enum xenbus_state backend_state);
        int (*remove)(struct xenbus_device *dev);
        int (*suspend)(struct xenbus_device *dev);
+       int (*suspend_cancel)(struct xenbus_device *dev);
        int (*resume)(struct xenbus_device *dev);
        int (*uevent)(struct xenbus_device *, char **, int, char *, int);
        struct device_driver driver;
@@ -160,13 +161,15 @@ void unregister_xenbus_watch(struct xenb
 void unregister_xenbus_watch(struct xenbus_watch *watch);
 void xs_suspend(void);
 void xs_resume(void);
+void xs_suspend_cancel(void);
 
 /* Used by xenbus_dev to borrow kernel's store connection. */
 void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
 
-/* Called from xen core code. */
+/* Prepare for domain suspend: then resume or cancel the suspend. */
 void xenbus_suspend(void);
 void xenbus_resume(void);
+void xenbus_suspend_cancel(void);
 
 #define XENBUS_IS_ERR_READ(str) ({                     \
        if (!IS_ERR(str) && strlen(str) == 0) {         \
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/libxc/Makefile
--- a/tools/libxc/Makefile      Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/libxc/Makefile      Sat Jan 20 11:21:08 2007 +0000
@@ -15,6 +15,7 @@ CTRL_SRCS-y       += xc_sedf.c
 CTRL_SRCS-y       += xc_sedf.c
 CTRL_SRCS-y       += xc_csched.c
 CTRL_SRCS-y       += xc_tbuf.c
+CTRL_SRCS-y       += xc_resume.c
 CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
 CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c
 CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/libxc/xc_domain.c   Sat Jan 20 11:21:08 2007 +0000
@@ -89,16 +89,6 @@ int xc_domain_shutdown(int xc_handle,
 }
 
 
-int xc_domain_resume(int xc_handle,
-                      uint32_t domid)
-{
-    DECLARE_DOMCTL;
-    domctl.cmd = XEN_DOMCTL_resumedomain;
-    domctl.domain = (domid_t)domid;
-    return do_domctl(xc_handle, &domctl);
-}
-
-
 int xc_vcpu_setaffinity(int xc_handle,
                         uint32_t domid,
                         int vcpu,
@@ -293,9 +283,9 @@ int xc_domain_hvm_setcontext(int xc_hand
 }
 
 int xc_vcpu_getcontext(int xc_handle,
-                               uint32_t domid,
-                               uint32_t vcpu,
-                               vcpu_guest_context_t *ctxt)
+                       uint32_t domid,
+                       uint32_t vcpu,
+                       vcpu_guest_context_t *ctxt)
 {
     int rc;
     DECLARE_DOMCTL;
@@ -602,15 +592,15 @@ int xc_vcpu_setcontext(int xc_handle,
     domctl.u.vcpucontext.vcpu = vcpu;
     set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
 
-    if ( (rc = lock_pages(ctxt, sizeof(*ctxt))) != 0 )
+    if ( (ctxt != NULL) && ((rc = lock_pages(ctxt, sizeof(*ctxt))) != 0) )
         return rc;
 
     rc = do_domctl(xc_handle, &domctl);
 
-    unlock_pages(ctxt, sizeof(*ctxt));
+    if ( ctxt != NULL )
+        unlock_pages(ctxt, sizeof(*ctxt));
 
     return rc;
-
 }
 
 int xc_domain_irq_permission(int xc_handle,
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/libxc/xc_evtchn.c
--- a/tools/libxc/xc_evtchn.c   Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/libxc/xc_evtchn.c   Sat Jan 20 11:21:08 2007 +0000
@@ -37,7 +37,7 @@ int xc_evtchn_alloc_unbound(int xc_handl
                             uint32_t dom,
                             uint32_t remote_dom)
 {
-    int         rc;
+    int rc;
     struct evtchn_alloc_unbound arg = {
         .dom = (domid_t)dom,
         .remote_dom = (domid_t)remote_dom
@@ -49,3 +49,10 @@ int xc_evtchn_alloc_unbound(int xc_handl
 
     return rc;
 }
+
+int xc_evtchn_reset(int xc_handle,
+                    uint32_t dom)
+{
+    struct evtchn_reset arg = { .dom = (domid_t)dom };
+    return do_evtchn_op(xc_handle, EVTCHNOP_reset, &arg, sizeof(arg));
+}
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/libxc/xc_resume.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_resume.c   Sat Jan 20 11:21:08 2007 +0000
@@ -0,0 +1,35 @@
+#include "xc_private.h"
+
+/*
+ * Resume execution of a domain after suspend shutdown.
+ * This can happen in one of two ways:
+ *  1. Resume with special return code.
+ *  2. Reset guest environment so it believes it is resumed in a new
+ *     domain context.
+ * (2) should be used only for guests which cannot handle the special
+ * new return code. (1) is always safe (but slower).
+ * 
+ * XXX Only (2) is implemented below. We need to use (1) by default!
+ */
+int xc_domain_resume(int xc_handle, uint32_t domid)
+{
+    vcpu_guest_context_t ctxt;
+    DECLARE_DOMCTL;
+    int rc;
+
+    /*
+     * Set hypercall return code to indicate that suspend is cancelled
+     * (rather than resuming in a new domain context).
+     */
+#if defined(__i386__) || defined(__x86_64__)
+    if ( (rc = xc_vcpu_getcontext(xc_handle, domid, 0, &ctxt)) != 0 )
+        return rc;
+    ctxt.user_regs.eax = 1;
+    if ( (rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt)) != 0 )
+        return rc;
+#endif
+
+    domctl.cmd = XEN_DOMCTL_resumedomain;
+    domctl.domain = domid;
+    return do_domctl(xc_handle, &domctl);
+}
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/libxc/xenctrl.h     Sat Jan 20 11:21:08 2007 +0000
@@ -360,9 +360,9 @@ int xc_domain_hvm_setcontext(int xc_hand
  * @return 0 on success, -1 on failure
  */
 int xc_vcpu_getcontext(int xc_handle,
-                               uint32_t domid,
-                               uint32_t vcpu,
-                               vcpu_guest_context_t *ctxt);
+                       uint32_t domid,
+                       uint32_t vcpu,
+                       vcpu_guest_context_t *ctxt);
 
 typedef xen_domctl_getvcpuinfo_t xc_vcpuinfo_t;
 int xc_vcpu_getinfo(int xc_handle,
@@ -431,6 +431,9 @@ int xc_evtchn_alloc_unbound(int xc_handl
 int xc_evtchn_alloc_unbound(int xc_handle,
                             uint32_t dom,
                             uint32_t remote_dom);
+
+int xc_evtchn_reset(int xc_handle,
+                    uint32_t dom);
 
 int xc_physdev_pci_access_modify(int xc_handle,
                                  uint32_t domid,
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/python/xen/lowlevel/xc/xc.c Sat Jan 20 11:21:08 2007 +0000
@@ -478,6 +478,24 @@ static PyObject *pyxc_evtchn_alloc_unbou
     return PyInt_FromLong(port);
 }
 
+static PyObject *pyxc_evtchn_reset(XcObject *self,
+                                  PyObject *args,
+                                  PyObject *kwds)
+{
+    uint32_t dom;
+
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+
+    if ( xc_evtchn_reset(self->xc_handle, dom) < 0 )
+        return pyxc_error_to_exception();
+
+    Py_INCREF(zero);
+    return zero;
+}
+
 static PyObject *pyxc_physdev_pci_access_modify(XcObject *self,
                                                 PyObject *args,
                                                 PyObject *kwds)
@@ -1201,6 +1219,12 @@ static PyMethodDef pyxc_methods[] = {
       " dom        [int]: Domain whose port space to allocate from.\n"
       " remote_dom [int]: Remote domain to accept connections from.\n\n"
       "Returns: [int] Unbound event-channel port.\n" },
+
+    { "evtchn_reset", 
+      (PyCFunction)pyxc_evtchn_reset,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Reset all connections.\n"
+      " dom [int]: Domain to reset.\n" },
 
     { "physdev_pci_access_modify",
       (PyCFunction)pyxc_physdev_pci_access_modify,
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/python/xen/lowlevel/xs/xs.c
--- a/tools/python/xen/lowlevel/xs/xs.c Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/python/xen/lowlevel/xs/xs.c Sat Jan 20 11:21:08 2007 +0000
@@ -618,6 +618,33 @@ static PyObject *xspy_introduce_domain(X
     return none(result);
 }
 
+#define xspy_resume_domain_doc "\n"                                \
+       "Tell xenstore to clear its shutdown flag for a domain.\n" \
+       "This ensures that a subsequent shutdown will fire the\n"  \
+       "appropriate watches.\n"                                   \
+       " dom [int]: domain id\n"                                  \
+        "\n"                                                      \
+        "Returns None on success.\n"                              \
+        "Raises xen.lowlevel.xs.Error on error.\n"
+
+static PyObject *xspy_resume_domain(XsHandle *self, PyObject *args)
+{
+    uint32_t dom;
+
+    struct xs_handle *xh = xshandle(self);
+    bool result = 0;
+
+    if (!xh)
+        return NULL;
+    if (!PyArg_ParseTuple(args, "i", &dom))
+        return NULL;
+
+    Py_BEGIN_ALLOW_THREADS
+    result = xs_resume_domain(xh, dom);
+    Py_END_ALLOW_THREADS
+
+    return none(result);
+}
 
 #define xspy_release_domain_doc "\n"                                   \
        "Tell xenstore to release its channel to a domain.\n"           \
@@ -789,6 +816,7 @@ static PyMethodDef xshandle_methods[] = 
     XSPY_METH(transaction_start, METH_NOARGS),
     XSPY_METH(transaction_end,   METH_VARARGS | METH_KEYWORDS),
     XSPY_METH(introduce_domain,  METH_VARARGS),
+    XSPY_METH(resume_domain,     METH_VARARGS),
     XSPY_METH(release_domain,    METH_VARARGS),
     XSPY_METH(close,             METH_NOARGS),
     XSPY_METH(get_domain_path,   METH_VARARGS),
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py   Sat Jan 20 11:21:08 2007 +0000
@@ -45,7 +45,7 @@ from xen.xend.XendError import XendError
 from xen.xend.XendError import XendError, VmError
 from xen.xend.XendDevices import XendDevices
 from xen.xend.xenstore.xstransact import xstransact, complete
-from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
+from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain, 
ResumeDomain
 from xen.xend.xenstore.xswatch import xswatch
 from xen.xend.XendConstants import *
 from xen.xend.XendAPIConstants import *
@@ -1545,6 +1545,7 @@ class XendDomainInfo:
         try:
             if self.domid is not None:
                 xc.domain_resume(self.domid)
+                ResumeDomain(self.domid)
         except:
             log.exception("XendDomainInfo.resume: xc.domain_resume failed on 
domain %s." % (str(self.domid)))
 
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/python/xen/xend/xenstore/xsutil.py
--- a/tools/python/xen/xend/xenstore/xsutil.py  Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/python/xen/xend/xenstore/xsutil.py  Sat Jan 20 11:21:08 2007 +0000
@@ -24,3 +24,6 @@ def IntroduceDomain(domid, page, port):
 
 def GetDomainPath(domid):
     return xshandle().get_domain_path(domid)
+
+def ResumeDomain(domid):
+    return xshandle().resume_domain(domid)
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c   Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/xenstore/xenstored_core.c   Sat Jan 20 11:21:08 2007 +0000
@@ -164,6 +164,7 @@ static char *sockmsg_string(enum xsd_soc
        case XS_WATCH_EVENT: return "WATCH_EVENT";
        case XS_ERROR: return "ERROR";
        case XS_IS_DOMAIN_INTRODUCED: return "XS_IS_DOMAIN_INTRODUCED";
+       case XS_RESUME: return "RESUME";
        default:
                return "**UNKNOWN**";
        }
@@ -1265,6 +1266,10 @@ static void process_message(struct conne
 
        case XS_GET_DOMAIN_PATH:
                do_get_domain_path(conn, onearg(in));
+               break;
+
+       case XS_RESUME:
+               do_resume(conn, onearg(in));
                break;
 
        default:
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/xenstore/xenstored_domain.c Sat Jan 20 11:21:08 2007 +0000
@@ -343,13 +343,14 @@ void do_introduce(struct connection *con
                fire_watches(conn, "@introduceDomain", false);
        }
        else {
-               /* Check that the given details match the ones we have
-                  previously recorded. */
-               if (port != domain->remote_port ||
-                   mfn != domain->mfn) {
-                       send_error(conn, EINVAL);
-                       return;
-               }
+               int rc;
+
+               /* Use XS_INTRODUCE for recreating the xenbus event-channel. */
+               if (domain->port)
+                       xc_evtchn_unbind(xce_handle, domain->port);
+               rc = xc_evtchn_bind_interdomain(xce_handle, domid, port);
+               domain->port = (rc == -1) ? 0 : rc;
+               domain->remote_port = port;
        }
 
        send_ack(conn, XS_INTRODUCE);
@@ -393,6 +394,43 @@ void do_release(struct connection *conn,
        fire_watches(conn, "@releaseDomain", false);
 
        send_ack(conn, XS_RELEASE);
+}
+
+void do_resume(struct connection *conn, const char *domid_str)
+{
+       struct domain *domain;
+       unsigned int domid;
+
+       if (!domid_str) {
+               send_error(conn, EINVAL);
+               return;
+       }
+
+       domid = atoi(domid_str);
+       if (!domid) {
+               send_error(conn, EINVAL);
+               return;
+       }
+
+       if (conn->id != 0) {
+               send_error(conn, EACCES);
+               return;
+       }
+
+       domain = find_domain_by_domid(domid);
+       if (!domain) {
+               send_error(conn, ENOENT);
+               return;
+       }
+
+       if (!domain->conn) {
+               send_error(conn, EINVAL);
+               return;
+       }
+
+       domain->shutdown = 0;
+       
+       send_ack(conn, XS_RESUME);
 }
 
 void do_get_domain_path(struct connection *conn, const char *domid_str)
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/xenstore/xenstored_domain.h
--- a/tools/xenstore/xenstored_domain.h Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/xenstore/xenstored_domain.h Sat Jan 20 11:21:08 2007 +0000
@@ -32,6 +32,9 @@ void do_release(struct connection *conn,
 void do_release(struct connection *conn, const char *domid_str);
 
 /* domid */
+void do_resume(struct connection *conn, const char *domid_str);
+
+/* domid */
 void do_get_domain_path(struct connection *conn, const char *domid_str);
 
 /* Returns the event channel handle */
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c       Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/xenstore/xs.c       Sat Jan 20 11:21:08 2007 +0000
@@ -719,6 +719,12 @@ bool xs_release_domain(struct xs_handle 
        return xs_bool(single_with_domid(h, XS_RELEASE, domid));
 }
 
+/* clear the shutdown bit for the given domain */
+bool xs_resume_domain(struct xs_handle *h, unsigned int domid)
+{
+       return xs_bool(single_with_domid(h, XS_RESUME, domid));
+}
+
 char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
 {
        char domid_str[MAX_STRLEN(domid)];
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 tools/xenstore/xs.h
--- a/tools/xenstore/xs.h       Sat Jan 20 11:17:42 2007 +0000
+++ b/tools/xenstore/xs.h       Sat Jan 20 11:21:08 2007 +0000
@@ -133,6 +133,11 @@ bool xs_introduce_domain(struct xs_handl
                         unsigned int domid,
                         unsigned long mfn,
                          unsigned int eventchn); 
+/* Resume a domain.
+ * Clear the shutdown flag for this domain in the store.
+ */
+bool xs_resume_domain(struct xs_handle *h, unsigned int domid);
+
 /* Release a domain.
  * Tells the store domain to release the memory page to the domain.
  */
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Sat Jan 20 11:17:42 2007 +0000
+++ b/xen/arch/x86/domain.c     Sat Jan 20 11:21:08 2007 +0000
@@ -50,6 +50,8 @@ static void paravirt_ctxt_switch_from(st
 static void paravirt_ctxt_switch_from(struct vcpu *v);
 static void paravirt_ctxt_switch_to(struct vcpu *v);
 
+static void vcpu_destroy_pagetables(struct vcpu *v);
+
 static void continue_idle_domain(struct vcpu *v)
 {
     reset_stack_and_jump(idle_loop);
@@ -657,6 +659,13 @@ int arch_set_info_guest(
 
     return 0;
 #undef c
+}
+
+int arch_vcpu_reset(struct vcpu *v)
+{
+    destroy_gdt(v);
+    vcpu_destroy_pagetables(v);
+    return 0;
 }
 
 long
@@ -1381,63 +1390,73 @@ static void relinquish_memory(struct dom
     spin_unlock_recursive(&d->page_alloc_lock);
 }
 
-void domain_relinquish_resources(struct domain *d)
-{
-    struct vcpu *v;
+static void vcpu_destroy_pagetables(struct vcpu *v)
+{
+    struct domain *d = v->domain;
     unsigned long pfn;
 
-    BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
-
-    /* Drop the in-use references to page-table bases. */
-    for_each_vcpu ( d, v )
-    {
-        /* Drop ref to guest_table (from new_guest_cr3(), svm/vmx cr3 handling,
-         * or sh_update_paging_modes()) */
 #ifdef CONFIG_COMPAT
-        if ( IS_COMPAT(d) )
-        {
-            if ( is_hvm_vcpu(v) )
-                pfn = pagetable_get_pfn(v->arch.guest_table);
-            else
-                pfn = l4e_get_pfn(*(l4_pgentry_t 
*)__va(pagetable_get_paddr(v->arch.guest_table)));
-
-            if ( pfn != 0 )
-            {
-                if ( shadow_mode_refcounts(d) )
-                    put_page(mfn_to_page(pfn));
-                else
-                    put_page_and_type(mfn_to_page(pfn));
-            }
-            continue;
-        }
-#endif
-        pfn = pagetable_get_pfn(v->arch.guest_table);
+    if ( IS_COMPAT(d) )
+    {
+        if ( is_hvm_vcpu(v) )
+            pfn = pagetable_get_pfn(v->arch.guest_table);
+        else
+            pfn = l4e_get_pfn(*(l4_pgentry_t *)
+                              __va(pagetable_get_paddr(v->arch.guest_table)));
+
         if ( pfn != 0 )
         {
             if ( shadow_mode_refcounts(d) )
                 put_page(mfn_to_page(pfn));
             else
                 put_page_and_type(mfn_to_page(pfn));
+        }
+
+        v->arch.guest_table = pagetable_null();
+        v->arch.cr3 = 0;
+        return;
+    }
+#endif
+
+    pfn = pagetable_get_pfn(v->arch.guest_table);
+    if ( pfn != 0 )
+    {
+        if ( shadow_mode_refcounts(d) )
+            put_page(mfn_to_page(pfn));
+        else
+            put_page_and_type(mfn_to_page(pfn));
 #ifdef __x86_64__
-            if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) )
-                v->arch.guest_table_user = pagetable_null();
-#endif
-            v->arch.guest_table = pagetable_null();
-        }
+        if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) )
+            v->arch.guest_table_user = pagetable_null();
+#endif
+        v->arch.guest_table = pagetable_null();
+    }
 
 #ifdef __x86_64__
-        /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */
-        pfn = pagetable_get_pfn(v->arch.guest_table_user);
-        if ( pfn != 0 )
-        {
-            if ( shadow_mode_refcounts(d) )
-                put_page(mfn_to_page(pfn));
-            else
-                put_page_and_type(mfn_to_page(pfn));
-            v->arch.guest_table_user = pagetable_null();
-        }
-#endif
-    }
+    /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */
+    pfn = pagetable_get_pfn(v->arch.guest_table_user);
+    if ( pfn != 0 )
+    {
+        if ( shadow_mode_refcounts(d) )
+            put_page(mfn_to_page(pfn));
+        else
+            put_page_and_type(mfn_to_page(pfn));
+        v->arch.guest_table_user = pagetable_null();
+    }
+#endif
+
+    v->arch.cr3 = 0;
+}
+
+void domain_relinquish_resources(struct domain *d)
+{
+    struct vcpu *v;
+
+    BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
+
+    /* Drop the in-use references to page-table bases. */
+    for_each_vcpu ( d, v )
+        vcpu_destroy_pagetables(v);
 
     /* Tear down shadow mode stuff. */
     shadow_teardown(d);
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Sat Jan 20 11:17:42 2007 +0000
+++ b/xen/arch/x86/domctl.c     Sat Jan 20 11:21:08 2007 +0000
@@ -326,7 +326,6 @@ _long arch_do_domctl(
     }
     break;
 
-
     case XEN_DOMCTL_gethvmcontext:
     { 
         struct hvm_domain_context *c;
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 xen/common/domain.c
--- a/xen/common/domain.c       Sat Jan 20 11:17:42 2007 +0000
+++ b/xen/common/domain.c       Sat Jan 20 11:21:08 2007 +0000
@@ -5,6 +5,7 @@
  */
 
 #include <xen/config.h>
+#include <xen/compat.h>
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/errno.h>
@@ -466,7 +467,12 @@ int set_info_guest(struct domain *d,
 
     if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
         return -EINVAL;
-    
+
+    if ( IS_COMPAT(v->domain)
+         ? compat_handle_is_null(vcpucontext.cmp->ctxt)
+         : guest_handle_is_null(vcpucontext.nat->ctxt) )
+        return vcpu_reset(v);
+
 #ifdef CONFIG_COMPAT
     BUILD_BUG_ON(sizeof(struct vcpu_guest_context)
                  < sizeof(struct compat_vcpu_guest_context));
@@ -520,6 +526,36 @@ int boot_vcpu(struct domain *d, int vcpu
     return arch_set_info_guest(v, ctxt);
 }
 
+int vcpu_reset(struct vcpu *v)
+{
+    struct domain *d = v->domain;
+    int rc;
+
+    domain_pause(d);
+    LOCK_BIGLOCK(d);
+
+    rc = arch_vcpu_reset(v);
+    if ( rc != 0 )
+        goto out;
+
+    set_bit(_VCPUF_down, &v->vcpu_flags);
+
+    clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
+    clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags);
+    clear_bit(_VCPUF_blocked, &v->vcpu_flags);
+    clear_bit(_VCPUF_initialised, &v->vcpu_flags);
+    clear_bit(_VCPUF_nmi_pending, &v->vcpu_flags);
+    clear_bit(_VCPUF_nmi_masked, &v->vcpu_flags);
+    clear_bit(_VCPUF_polling, &v->vcpu_flags);
+
+ out:
+    UNLOCK_BIGLOCK(v->domain);
+    domain_unpause(d);
+
+    return rc;
+}
+
+
 long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg)
 {
     struct domain *d = current->domain;
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 xen/common/event_channel.c
--- a/xen/common/event_channel.c        Sat Jan 20 11:17:42 2007 +0000
+++ b/xen/common/event_channel.c        Sat Jan 20 11:21:08 2007 +0000
@@ -735,6 +735,29 @@ static long evtchn_unmask(evtchn_unmask_
 }
 
 
+static long evtchn_reset(evtchn_reset_t *r)
+{
+    domid_t dom = r->dom;
+    struct domain *d;
+    int i;
+
+    if ( dom == DOMID_SELF )
+        dom = current->domain->domain_id;
+    else if ( !IS_PRIV(current->domain) )
+        return -EPERM;
+
+    if ( (d = find_domain_by_id(dom)) == NULL )
+        return -ESRCH;
+
+    for ( i = 0; port_is_valid(d, i); i++ )
+        (void)__evtchn_close(d, i);
+
+    put_domain(d);
+
+    return 0;
+}
+
+
 long do_event_channel_op(int cmd, XEN_GUEST_HANDLE(void) arg)
 {
     long rc;
@@ -830,6 +853,14 @@ long do_event_channel_op(int cmd, XEN_GU
         if ( copy_from_guest(&unmask, arg, 1) != 0 )
             return -EFAULT;
         rc = evtchn_unmask(&unmask);
+        break;
+    }
+
+    case EVTCHNOP_reset: {
+        struct evtchn_reset reset;
+        if ( copy_from_guest(&reset, arg, 1) != 0 )
+            return -EFAULT;
+        rc = evtchn_reset(&reset);
         break;
     }
 
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 xen/include/public/event_channel.h
--- a/xen/include/public/event_channel.h        Sat Jan 20 11:17:42 2007 +0000
+++ b/xen/include/public/event_channel.h        Sat Jan 20 11:21:08 2007 +0000
@@ -217,6 +217,19 @@ typedef struct evtchn_unmask evtchn_unma
 typedef struct evtchn_unmask evtchn_unmask_t;
 
 /*
+ * EVTCHNOP_reset: Close all event channels associated with specified domain.
+ * NOTES:
+ *  1. <dom> may be specified as DOMID_SELF.
+ *  2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
+ */
+#define EVTCHNOP_reset           10
+struct evtchn_reset {
+    /* IN parameters. */
+    domid_t dom;
+};
+typedef struct evtchn_reset evtchn_reset_t;
+
+/*
  * Argument to event_channel_op_compat() hypercall. Superceded by new
  * event_channel_op() hypercall since 0x00030202.
  */
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 xen/include/public/io/xs_wire.h
--- a/xen/include/public/io/xs_wire.h   Sat Jan 20 11:17:42 2007 +0000
+++ b/xen/include/public/io/xs_wire.h   Sat Jan 20 11:21:08 2007 +0000
@@ -45,7 +45,8 @@ enum xsd_sockmsg_type
     XS_SET_PERMS,
     XS_WATCH_EVENT,
     XS_ERROR,
-    XS_IS_DOMAIN_INTRODUCED
+    XS_IS_DOMAIN_INTRODUCED,
+    XS_RESUME
 };
 
 #define XS_WRITE_NONE "NONE"
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 xen/include/xen/compat.h
--- a/xen/include/xen/compat.h  Sat Jan 20 11:17:42 2007 +0000
+++ b/xen/include/xen/compat.h  Sat Jan 20 11:21:08 2007 +0000
@@ -173,6 +173,8 @@ int switch_native(struct domain *);
 
 #else
 
+#define compat_handle_is_null(hnd) 0
+
 #define BITS_PER_GUEST_LONG(d) BITS_PER_LONG
 
 #endif
diff -r ff4f4596cb29 -r 5dc5e6ba42d2 xen/include/xen/domain.h
--- a/xen/include/xen/domain.h  Sat Jan 20 11:17:42 2007 +0000
+++ b/xen/include/xen/domain.h  Sat Jan 20 11:21:08 2007 +0000
@@ -12,6 +12,7 @@ int boot_vcpu(
 int boot_vcpu(
     struct domain *d, int vcpuid, vcpu_guest_context_u ctxt);
 struct vcpu *alloc_idle_vcpu(unsigned int cpu_id);
+int vcpu_reset(struct vcpu *v);
 
 struct domain *alloc_domain(domid_t domid);
 void free_domain(struct domain *d);
@@ -56,4 +57,6 @@ void arch_dump_vcpu_info(struct vcpu *v)
 
 void arch_dump_domain_info(struct domain *d);
 
+int arch_vcpu_reset(struct vcpu *v);
+
 #endif /* __XEN_DOMAIN_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.