Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP3:GA
xen.21123
xsa343-2.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xsa343-2.patch of Package xen.21123
evtchn: convert per-channel lock to be IRQ-safe ... in order for send_guest_{global,vcpu}_virq() to be able to make use of it. This is part of XSA-343. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Julien Grall <jgrall@amazon.com> --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -242,6 +242,7 @@ static long evtchn_alloc_unbound(evtchn_ int port; domid_t dom = alloc->dom; long rc; + unsigned long flags; d = rcu_lock_domain_by_any_id(dom); if ( d == NULL ) @@ -257,14 +258,14 @@ static long evtchn_alloc_unbound(evtchn_ if ( rc ) goto out; - spin_lock(&chn->lock); + spin_lock_irqsave(&chn->lock, flags); chn->state = ECS_UNBOUND; if ( (chn->u.unbound.remote_domid = alloc->remote_dom) == DOMID_SELF ) chn->u.unbound.remote_domid = current->domain->domain_id; evtchn_port_init(d, chn); - spin_unlock(&chn->lock); + spin_unlock_irqrestore(&chn->lock, flags); alloc->port = port; @@ -277,26 +278,32 @@ static long evtchn_alloc_unbound(evtchn_ } -static void double_evtchn_lock(struct evtchn *lchn, struct evtchn *rchn) +static unsigned long double_evtchn_lock(struct evtchn *lchn, + struct evtchn *rchn) { - if ( lchn < rchn ) + unsigned long flags; + + if ( lchn <= rchn ) { - spin_lock(&lchn->lock); - spin_lock(&rchn->lock); + spin_lock_irqsave(&lchn->lock, flags); + if ( lchn != rchn ) + spin_lock(&rchn->lock); } else { - if ( lchn != rchn ) - spin_lock(&rchn->lock); + spin_lock_irqsave(&rchn->lock, flags); spin_lock(&lchn->lock); } + + return flags; } -static void double_evtchn_unlock(struct evtchn *lchn, struct evtchn *rchn) +static void double_evtchn_unlock(struct evtchn *lchn, struct evtchn *rchn, + unsigned long flags) { - spin_unlock(&lchn->lock); if ( lchn != rchn ) - spin_unlock(&rchn->lock); + spin_unlock(&lchn->lock); + spin_unlock_irqrestore(&rchn->lock, flags); } static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind) @@ -306,6 +313,7 @@ static long evtchn_bind_interdomain(evtc int lport, rport = bind->remote_port; domid_t rdom = bind->remote_dom; long rc; + unsigned long flags; if ( rdom == DOMID_SELF ) rdom = current->domain->domain_id; @@ -341,7 +349,7 @@ static long evtchn_bind_interdomain(evtc if ( rc ) goto out; - double_evtchn_lock(lchn, rchn); + flags = double_evtchn_lock(lchn, rchn); lchn->u.interdomain.remote_dom = rd; lchn->u.interdomain.remote_port = rport; @@ -358,7 +366,7 @@ static long evtchn_bind_interdomain(evtc */ evtchn_port_set_pending(ld, lchn->notify_vcpu_id, lchn); - double_evtchn_unlock(lchn, rchn); + double_evtchn_unlock(lchn, rchn, flags); bind->local_port = lport; @@ -381,6 +389,7 @@ static long evtchn_bind_virq(evtchn_bind struct domain *d = current->domain; int port, virq = bind->virq, vcpu = bind->vcpu; long rc = 0; + unsigned long flags; if ( (virq < 0) || (virq >= ARRAY_SIZE(v->virq_to_evtchn)) ) return -EINVAL; @@ -402,14 +411,14 @@ static long evtchn_bind_virq(evtchn_bind chn = evtchn_from_port(d, port); - spin_lock(&chn->lock); + spin_lock_irqsave(&chn->lock, flags); chn->state = ECS_VIRQ; chn->notify_vcpu_id = vcpu; chn->u.virq = virq; evtchn_port_init(d, chn); - spin_unlock(&chn->lock); + spin_unlock_irqrestore(&chn->lock, flags); v->virq_to_evtchn[virq] = bind->port = port; @@ -426,6 +435,7 @@ static long evtchn_bind_ipi(evtchn_bind_ struct domain *d = current->domain; int port, vcpu = bind->vcpu; long rc = 0; + unsigned long flags; if ( (vcpu < 0) || (vcpu >= d->max_vcpus) || (d->vcpu[vcpu] == NULL) ) @@ -438,13 +448,13 @@ static long evtchn_bind_ipi(evtchn_bind_ chn = evtchn_from_port(d, port); - spin_lock(&chn->lock); + spin_lock_irqsave(&chn->lock, flags); chn->state = ECS_IPI; chn->notify_vcpu_id = vcpu; evtchn_port_init(d, chn); - spin_unlock(&chn->lock); + spin_unlock_irqrestore(&chn->lock, flags); bind->port = port; @@ -488,6 +498,7 @@ static long evtchn_bind_pirq(evtchn_bind struct pirq *info; int port = 0, pirq = bind->pirq; long rc; + unsigned long flags; if ( (pirq < 0) || (pirq >= d->nr_pirqs) ) return -EINVAL; @@ -520,14 +531,14 @@ static long evtchn_bind_pirq(evtchn_bind goto out; } - spin_lock(&chn->lock); + spin_lock_irqsave(&chn->lock, flags); chn->state = ECS_PIRQ; chn->u.pirq.irq = pirq; link_pirq_port(port, chn, v); evtchn_port_init(d, chn); - spin_unlock(&chn->lock); + spin_unlock_irqrestore(&chn->lock, flags); bind->port = port; @@ -548,6 +559,7 @@ static long evtchn_close(struct domain * struct evtchn *chn1, *chn2; int port2; long rc = 0; + unsigned long flags; again: spin_lock(&d1->event_lock); @@ -647,14 +659,14 @@ static long evtchn_close(struct domain * BUG_ON(chn2->state != ECS_INTERDOMAIN); BUG_ON(chn2->u.interdomain.remote_dom != d1); - double_evtchn_lock(chn1, chn2); + flags = double_evtchn_lock(chn1, chn2); free_evtchn(d1, chn1); chn2->state = ECS_UNBOUND; chn2->u.unbound.remote_domid = d1->domain_id; - double_evtchn_unlock(chn1, chn2); + double_evtchn_unlock(chn1, chn2, flags); goto out; @@ -662,9 +674,9 @@ static long evtchn_close(struct domain * BUG(); } - spin_lock(&chn1->lock); + spin_lock_irqsave(&chn1->lock, flags); free_evtchn(d1, chn1); - spin_unlock(&chn1->lock); + spin_unlock_irqrestore(&chn1->lock, flags); out: if ( d2 != NULL ) @@ -684,13 +696,14 @@ int evtchn_send(struct domain *ld, unsig struct evtchn *lchn, *rchn; struct domain *rd; int rport, ret = 0; + unsigned long flags; if ( !port_is_valid(ld, lport) ) return -EINVAL; lchn = evtchn_from_port(ld, lport); - spin_lock(&lchn->lock); + spin_lock_irqsave(&lchn->lock, flags); /* Guest cannot send via a Xen-attached event channel. */ if ( unlikely(consumer_is_xen(lchn)) ) @@ -725,7 +738,7 @@ int evtchn_send(struct domain *ld, unsig } out: - spin_unlock(&lchn->lock); + spin_unlock_irqrestore(&lchn->lock, flags); return ret; } @@ -1216,6 +1229,7 @@ int alloc_unbound_xen_event_channel( { struct evtchn *chn; int port, rc; + unsigned long flags; spin_lock(&ld->event_lock); @@ -1228,14 +1242,14 @@ int alloc_unbound_xen_event_channel( if ( rc ) goto out; - spin_lock(&chn->lock); + spin_lock_irqsave(&chn->lock, flags); chn->state = ECS_UNBOUND; chn->xen_consumer = get_xen_consumer(notification_fn); chn->notify_vcpu_id = lvcpu; chn->u.unbound.remote_domid = remote_domid; - spin_unlock(&chn->lock); + spin_unlock_irqrestore(&chn->lock, flags); write_atomic(&ld->xen_evtchns, ld->xen_evtchns + 1); @@ -1258,11 +1272,12 @@ void notify_via_xen_event_channel(struct { struct evtchn *lchn, *rchn; struct domain *rd; + unsigned long flags; ASSERT(port_is_valid(ld, lport)); lchn = evtchn_from_port(ld, lport); - spin_lock(&lchn->lock); + spin_lock_irqsave(&lchn->lock, flags); if ( likely(lchn->state == ECS_INTERDOMAIN) ) { @@ -1272,7 +1287,7 @@ void notify_via_xen_event_channel(struct evtchn_port_set_pending(rd, rchn->notify_vcpu_id, rchn); } - spin_unlock(&lchn->lock); + spin_unlock_irqrestore(&lchn->lock, flags); } void evtchn_check_pollers(struct domain *d, unsigned int port)
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