Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1
xen
19519-domctl-deadlock.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 19519-domctl-deadlock.patch of Package xen
# HG changeset patch # User Keir Fraser <keir.fraser@citrix.com> # Date 1239194915 -3600 # Node ID 3929487cdb821d4c26160828ed44589499716aa0 # Parent 9f945f16bd0224d4b761333366e355837944f21d Avoid deadlocks on domctl_lock when pausing domains/vcpus. Signed-off-by: Keir Fraser <keir.fraser@citrix.com> --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2459,20 +2459,23 @@ long do_hvm_op(unsigned long op, XEN_GUE if ( !paging_mode_hap(d) ) break; - domain_pause(d); - /* * Update GUEST_CR3 in each VMCS to point at identity map. * All foreign updates to guest state must synchronise on * the domctl_lock. */ - spin_lock(&domctl_lock); + rc = -EAGAIN; + if ( !domctl_lock_acquire() ) + break; + + rc = 0; + domain_pause(d); d->arch.hvm_domain.params[a.index] = a.value; for_each_vcpu ( d, v ) paging_update_cr3(v); - spin_unlock(&domctl_lock); - domain_unpause(d); + + domctl_lock_release(); break; case HVM_PARAM_DM_DOMAIN: /* Privileged domains only, as we must domain_pause(d). */ --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -25,7 +25,7 @@ #include <public/domctl.h> #include <xsm/xsm.h> -DEFINE_SPINLOCK(domctl_lock); +static DEFINE_SPINLOCK(domctl_lock); extern long arch_do_domctl( struct xen_domctl *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl); @@ -188,6 +188,33 @@ static unsigned int default_vcpu0_locati return cpu; } +bool_t domctl_lock_acquire(void) +{ + /* + * Caller may try to pause its own VCPUs. We must prevent deadlock + * against other non-domctl routines which try to do the same. + */ + if ( !spin_trylock(¤t->domain->hypercall_deadlock_mutex) ) + return 0; + + /* + * Trylock here is paranoia if we have multiple privileged domains. Then + * we could have one domain trying to pause another which is spinning + * on domctl_lock -- results in deadlock. + */ + if ( spin_trylock(&domctl_lock) ) + return 1; + + spin_unlock(¤t->domain->hypercall_deadlock_mutex); + return 0; +} + +void domctl_lock_release(void) +{ + spin_unlock(&domctl_lock); + spin_unlock(¤t->domain->hypercall_deadlock_mutex); +} + long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) { long ret = 0; @@ -202,7 +229,9 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc if ( op->interface_version != XEN_DOMCTL_INTERFACE_VERSION ) return -EACCES; - spin_lock(&domctl_lock); + if ( !domctl_lock_acquire() ) + return hypercall_create_continuation( + __HYPERVISOR_domctl, "h", u_domctl); switch ( op->cmd ) { @@ -867,7 +896,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc break; } - spin_unlock(&domctl_lock); + domctl_lock_release(); return ret; } --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -54,6 +54,9 @@ void arch_dump_domain_info(struct domain void arch_vcpu_reset(struct vcpu *v); +bool_t domctl_lock_acquire(void); +void domctl_lock_release(void); + extern unsigned int xen_processor_pmbits; #endif /* __XEN_DOMAIN_H__ */ --- a/xen/include/xen/hypercall.h +++ b/xen/include/xen/hypercall.h @@ -30,7 +30,6 @@ do_sched_op( int cmd, XEN_GUEST_HANDLE(void) arg); -extern spinlock_t domctl_lock; extern long do_domctl( XEN_GUEST_HANDLE(xen_domctl_t) u_domctl);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor