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__ */