From: Jan Beulich <jbeulich@suse.com>
To: "xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
George Dunlap <George.Dunlap@eu.citrix.com>,
Ian Jackson <iwj@xenproject.org>, Julien Grall <julien@xen.org>,
Wei Liu <wl@xen.org>, Stefano Stabellini <sstabellini@kernel.org>
Subject: [PATCH v5 1/6] evtchn: use per-channel lock where possible
Date: Wed, 27 Jan 2021 09:15:14 +0100 [thread overview]
Message-ID: <081b2253-e445-4242-3f0c-0f2912412d43@suse.com> (raw)
In-Reply-To: <306e62e8-9070-2db9-c959-858465c50c1d@suse.com>
Neither evtchn_status() nor domain_dump_evtchn_info() nor
flask_get_peer_sid() need to hold the per-domain lock - they all only
read a single channel's state (at a time, in the dump case).
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v4: New.
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -974,15 +974,16 @@ int evtchn_status(evtchn_status_t *statu
if ( d == NULL )
return -ESRCH;
- spin_lock(&d->event_lock);
-
if ( !port_is_valid(d, port) )
{
- rc = -EINVAL;
- goto out;
+ rcu_unlock_domain(d);
+ return -EINVAL;
}
chn = evtchn_from_port(d, port);
+
+ evtchn_read_lock(chn);
+
if ( consumer_is_xen(chn) )
{
rc = -EACCES;
@@ -1027,7 +1028,7 @@ int evtchn_status(evtchn_status_t *statu
status->vcpu = chn->notify_vcpu_id;
out:
- spin_unlock(&d->event_lock);
+ evtchn_read_unlock(chn);
rcu_unlock_domain(d);
return rc;
@@ -1582,22 +1583,32 @@ void evtchn_move_pirqs(struct vcpu *v)
static void domain_dump_evtchn_info(struct domain *d)
{
unsigned int port;
- int irq;
printk("Event channel information for domain %d:\n"
"Polling vCPUs: {%*pbl}\n"
" port [p/m/s]\n", d->domain_id, d->max_vcpus, d->poll_mask);
- spin_lock(&d->event_lock);
-
for ( port = 1; port_is_valid(d, port); ++port )
{
- const struct evtchn *chn;
+ struct evtchn *chn;
char *ssid;
+ if ( !(port & 0x3f) )
+ process_pending_softirqs();
+
chn = evtchn_from_port(d, port);
+
+ if ( !evtchn_read_trylock(chn) )
+ {
+ printk(" %4u in flux\n", port);
+ continue;
+ }
+
if ( chn->state == ECS_FREE )
+ {
+ evtchn_read_unlock(chn);
continue;
+ }
printk(" %4u [%d/%d/",
port,
@@ -1607,26 +1618,49 @@ static void domain_dump_evtchn_info(stru
printk("]: s=%d n=%d x=%d",
chn->state, chn->notify_vcpu_id, chn->xen_consumer);
+ ssid = xsm_show_security_evtchn(d, chn);
+
switch ( chn->state )
{
case ECS_UNBOUND:
printk(" d=%d", chn->u.unbound.remote_domid);
break;
+
case ECS_INTERDOMAIN:
printk(" d=%d p=%d",
chn->u.interdomain.remote_dom->domain_id,
chn->u.interdomain.remote_port);
break;
- case ECS_PIRQ:
- irq = domain_pirq_to_irq(d, chn->u.pirq.irq);
- printk(" p=%d i=%d", chn->u.pirq.irq, irq);
+
+ case ECS_PIRQ: {
+ unsigned int pirq = chn->u.pirq.irq;
+
+ /*
+ * The per-channel locks nest inside the per-domain one, so we
+ * can't acquire the latter without first letting go of the former.
+ */
+ evtchn_read_unlock(chn);
+ chn = NULL;
+ if ( spin_trylock(&d->event_lock) )
+ {
+ int irq = domain_pirq_to_irq(d, pirq);
+
+ spin_unlock(&d->event_lock);
+ printk(" p=%u i=%d", pirq, irq);
+ }
+ else
+ printk(" p=%u i=?", pirq);
break;
+ }
+
case ECS_VIRQ:
printk(" v=%d", chn->u.virq);
break;
}
- ssid = xsm_show_security_evtchn(d, chn);
+ if ( chn )
+ evtchn_read_unlock(chn);
+
if (ssid) {
printk(" Z=%s\n", ssid);
xfree(ssid);
@@ -1634,8 +1668,6 @@ static void domain_dump_evtchn_info(stru
printk("\n");
}
}
-
- spin_unlock(&d->event_lock);
}
static void dump_evtchn_info(unsigned char key)
--- a/xen/xsm/flask/flask_op.c
+++ b/xen/xsm/flask/flask_op.c
@@ -555,12 +555,13 @@ static int flask_get_peer_sid(struct xen
struct evtchn *chn;
struct domain_security_struct *dsec;
- spin_lock(&d->event_lock);
-
if ( !port_is_valid(d, arg->evtchn) )
- goto out;
+ return -EINVAL;
chn = evtchn_from_port(d, arg->evtchn);
+
+ evtchn_read_lock(chn);
+
if ( chn->state != ECS_INTERDOMAIN )
goto out;
@@ -573,7 +574,7 @@ static int flask_get_peer_sid(struct xen
rv = 0;
out:
- spin_unlock(&d->event_lock);
+ evtchn_read_unlock(chn);
return rv;
}
next prev parent reply other threads:[~2021-01-27 8:15 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-27 8:13 [PATCH v5 0/6] evtchn: (not so) recent XSAs follow-on Jan Beulich
2021-01-27 8:15 ` Jan Beulich [this message]
2021-01-27 8:16 ` [PATCH v5 2/6] evtchn: convert domain event lock to an r/w one Jan Beulich
2021-05-27 11:01 ` Roger Pau Monné
2021-05-27 11:16 ` Jan Beulich
2022-07-07 18:00 ` Julien Grall
2021-01-27 8:16 ` [PATCH v5 3/6] evtchn: slightly defer lock acquire where possible Jan Beulich
2021-01-27 8:16 ` [PATCH v5 4/6] evtchn: add helper for port_is_valid() + evtchn_from_port() Jan Beulich
2021-01-27 8:17 ` [PATCH v5 5/6] evtchn: type adjustments Jan Beulich
2021-01-27 8:17 ` [PATCH v5 6/6] evtchn: drop acquiring of per-channel lock from send_guest_{global,vcpu}_virq() Jan Beulich
2021-04-21 15:23 ` Ping: [PATCH v5 0/6] evtchn: (not so) recent XSAs follow-on Jan Beulich
2021-04-21 15:56 ` Julien Grall
2021-04-22 8:53 ` Jan Beulich
2021-05-14 15:29 ` Roger Pau Monné
2021-05-17 7:15 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=081b2253-e445-4242-3f0c-0f2912412d43@suse.com \
--to=jbeulich@suse.com \
--cc=George.Dunlap@eu.citrix.com \
--cc=andrew.cooper3@citrix.com \
--cc=iwj@xenproject.org \
--cc=julien@xen.org \
--cc=sstabellini@kernel.org \
--cc=wl@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.