# 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
|