[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |