From 39407bed9c03dad5707aab7dd71946e1589c9460 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 15 Oct 2008 15:56:26 +0100 Subject: [PATCH] x86: make injection of spurious page faults configurable per domain Some distro kernels do not handle spurious page faults so allow these to be supressed on a per VM basis. Signed-off-by: Ian Campbell --- tools/libxc/xc_domain.c | 12 ++++++++++++ tools/libxc/xenctrl.h | 3 +++ tools/python/xen/lowlevel/xc/xc.c | 21 +++++++++++++++++++++ tools/python/xen/xend/XendConfig.py | 1 + tools/python/xen/xend/XendDomainInfo.py | 4 ++++ tools/python/xen/xm/create.py | 9 ++++++++- xen/arch/x86/domctl.c | 15 +++++++++++++++ xen/arch/x86/traps.c | 4 ++++ xen/include/asm-x86/domain.h | 2 ++ xen/include/public/domctl.h | 4 ++++ 10 files changed, 74 insertions(+), 1 deletion(-) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 767843b3ca..e1bf86ee6a 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -1049,6 +1049,18 @@ int xc_domain_get_machine_address_size(int xc, uint32_t domid) return rc == 0 ? domctl.u.address_size.size : rc; } +int xc_domain_suppress_spurious_page_faults(int xc, uint32_t domid) +{ + DECLARE_DOMCTL; + + memset(&domctl, 0, sizeof(domctl)); + domctl.domain = domid; + domctl.cmd = XEN_DOMCTL_suppress_spurious_page_faults; + + return do_domctl(xc, &domctl); + +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index bdeaf2647c..100749a9ab 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -1103,6 +1103,9 @@ int xc_domain_set_machine_address_size(int handle, int xc_domain_get_machine_address_size(int handle, uint32_t domid); +int xc_domain_suppress_spurious_page_faults(int handle, + uint32_t domid); + /* Set the target domain */ int xc_domain_set_target(int xc_handle, uint32_t domid, diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 01e0542c9e..59a16b3ee7 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -859,6 +859,21 @@ static PyObject *pyxc_dom_set_machine_address_size(XcObject *self, return zero; } +static PyObject *pyxc_dom_suppress_spurious_page_faults(XcObject *self, + PyObject *args, + PyObject *kwds) +{ + uint32_t dom; + + if (!PyArg_ParseTuple(args, "i", &dom)) + return NULL; + + if (xc_domain_suppress_spurious_page_faults(self->xc_handle, dom) != 0) + return pyxc_error_to_exception(); + + Py_INCREF(zero); + return zero; +} #endif /* __i386__ || __x86_64__ */ static PyObject *pyxc_hvm_build(XcObject *self, @@ -1911,6 +1926,12 @@ static PyMethodDef pyxc_methods[] = { "Set maximum machine address size for this domain.\n" " dom [int]: Identifier of domain.\n" " width [int]: Maximum machine address width.\n" }, + + { "domain_suppress_spurious_page_faults", + (PyCFunction)pyxc_dom_suppress_spurious_page_faults, + METH_VARARGS, "\n" + "Do not propagate spurious page faults to this guest.\n" + " dom [int]: Identifier of domain.\n" }, #endif { NULL, NULL, 0, NULL } diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 83e55e3d05..2a27c161f1 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -210,6 +210,7 @@ XENAPI_CFG_TYPES = { 'cpuid' : dict, 'cpuid_check' : dict, 'machine_address_size': int, + 'suppress_spurious_page_faults': bool0, } # List of legacy configuration keys that have no equivalent in the diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index faf96a79c6..67228f2b31 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2241,6 +2241,10 @@ class XendDomainInfo: if self.info.has_key('machine_address_size'): log.debug("_initDomain: setting maximum machine address size %d" % self.info['machine_address_size']) xc.domain_set_machine_address_size(self.domid, self.info['machine_address_size']) + + if self.info.has_key('suppress_spurious_page_faults') and self.info['suppress_spurious_page_faults']: + log.debug("_initDomain: suppressing spurious page faults") + xc.domain_suppress_spurious_page_faults(self.domid) self._createChannels() diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 401e7645f3..11661e7e10 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -583,6 +583,10 @@ gopts.var('machine_address_size', val='BITS', fn=set_int, default=None, use="""Maximum machine address size""") +gopts.var('suppress_spurious_page_faults', val='yes|no', + fn=set_bool, default=None, + use="""Do not inject spurious page faults into this guest""") + def err(msg): """Print an error to stderr and exit. """ @@ -634,6 +638,9 @@ def configure_image(vals): if vals.machine_address_size: config_image.append(['machine_address_size', vals.machine_address_size]) + if vals.suppress_spurious_page_faults: + config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults]) + return config_image def configure_disks(config_devs, vals): @@ -887,7 +894,7 @@ def make_config(vals): 'restart', 'on_poweroff', 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features', 'on_xend_start', 'on_xend_stop', 'target', 'cpuid', - 'cpuid_check', 'machine_address_size']) + 'cpuid_check', 'machine_address_size', 'suppress_spurious_page_faults']) if vals.uuid is not None: config.append(['uuid', vals.uuid]) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index abbaa7f8a3..a145583137 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1028,6 +1028,21 @@ long arch_do_domctl( } break; + case XEN_DOMCTL_suppress_spurious_page_faults: + { + struct domain *d; + + ret = -ESRCH; + d = rcu_lock_domain_by_id(domctl->domain); + if ( d != NULL ) + { + d->arch.suppress_spurious_page_faults = 1; + rcu_unlock_domain(d); + ret = 0; + } + } + break; + default: ret = -ENOSYS; break; diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index a9bbc27e77..3046b89495 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -1242,6 +1242,10 @@ asmlinkage void do_page_fault(struct cpu_user_regs *regs) regs->error_code, _p(addr)); } + if ( unlikely(current->domain->arch.suppress_spurious_page_faults + && spurious_page_fault(addr, regs)) ) + return; + propagate_page_fault(addr, regs->error_code); } diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index ba0601513e..3acab04f27 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -250,6 +250,8 @@ struct arch_domain bool_t is_32bit_pv; /* Is shared-info page in 32-bit format? */ bool_t has_32bit_shinfo; + /* Domain cannot handle spurious page faults? */ + bool_t suppress_spurious_page_faults; /* Continuable domain_relinquish_resources(). */ enum { diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 090681722a..b7075ac447 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -614,6 +614,10 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_subscribe_t); #define XEN_DOMCTL_set_machine_address_size 51 #define XEN_DOMCTL_get_machine_address_size 52 +/* + * Do not inject spurious page faults into this domain. + */ +#define XEN_DOMCTL_suppress_spurious_page_faults 53 struct xen_domctl { uint32_t cmd; -- 2.30.2