[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging] xen/xsm: Improve alloc/free of evtchn buckets



commit 935d501ccbf5b8c4db1f6d0730a4a4c998e9e76a
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Sat Jan 16 16:09:10 2021 +0000
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Fri Apr 9 10:31:17 2021 +0100

    xen/xsm: Improve alloc/free of evtchn buckets
    
    Currently, flask_alloc_security_evtchn() is called in loops of
    64 (EVTCHNS_PER_BUCKET), which for non-dummy implementations is a function
    pointer call even in the no-op case.  The non no-op case only sets a single
    constant, and doesn't actually fail.
    
    Spectre v2 protections has made function pointer calls far more expensive, 
and
    64 back-to-back calls is a waste.  Rework the APIs to pass the size of the
    bucket instead, and call them once.
    
    No practical change, but {alloc,free}_evtchn_bucket() should be rather more
    efficient now.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Daniel P. Smith <dpsmith@xxxxxxxxxxxxxxxxxxxx>
---
 xen/common/event_channel.c | 36 ++++++++++++++++--------------------
 xen/include/xsm/dummy.h    |  6 ++++--
 xen/include/xsm/xsm.h      | 14 ++++++++------
 xen/xsm/dummy.c            |  4 ++--
 xen/xsm/flask/hooks.c      | 20 +++++++++++++-------
 5 files changed, 43 insertions(+), 37 deletions(-)

diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index c94ea74b12..5479315aae 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -147,6 +147,14 @@ static bool virq_is_global(unsigned int virq)
     return true;
 }
 
+static void free_evtchn_bucket(struct domain *d, struct evtchn *bucket)
+{
+    if ( !bucket )
+        return;
+
+    xsm_free_security_evtchns(bucket, EVTCHNS_PER_BUCKET);
+    xfree(bucket);
+}
 
 static struct evtchn *alloc_evtchn_bucket(struct domain *d, unsigned int port)
 {
@@ -155,34 +163,22 @@ static struct evtchn *alloc_evtchn_bucket(struct domain 
*d, unsigned int port)
 
     chn = xzalloc_array(struct evtchn, EVTCHNS_PER_BUCKET);
     if ( !chn )
-        return NULL;
+        goto err;
+
+    if ( xsm_alloc_security_evtchns(chn, EVTCHNS_PER_BUCKET) )
+        goto err;
 
     for ( i = 0; i < EVTCHNS_PER_BUCKET; i++ )
     {
-        if ( xsm_alloc_security_evtchn(&chn[i]) )
-        {
-            while ( i-- )
-                xsm_free_security_evtchn(&chn[i]);
-            xfree(chn);
-            return NULL;
-        }
         chn[i].port = port + i;
         rwlock_init(&chn[i].lock);
     }
-    return chn;
-}
-
-static void free_evtchn_bucket(struct domain *d, struct evtchn *bucket)
-{
-    unsigned int i;
 
-    if ( !bucket )
-        return;
-
-    for ( i = 0; i < EVTCHNS_PER_BUCKET; i++ )
-        xsm_free_security_evtchn(bucket + i);
+    return chn;
 
-    xfree(bucket);
+ err:
+    free_evtchn_bucket(d, chn);
+    return NULL;
 }
 
 int evtchn_allocate_port(struct domain *d, evtchn_port_t port)
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index 10739e7f35..a6dab0c809 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -309,12 +309,14 @@ static XSM_INLINE int xsm_evtchn_reset(XSM_DEFAULT_ARG 
struct domain *d1, struct
     return xsm_default_action(action, d1, d2);
 }
 
-static XSM_INLINE int xsm_alloc_security_evtchn(struct evtchn *chn)
+static XSM_INLINE int xsm_alloc_security_evtchns(
+    struct evtchn chn[], unsigned int nr)
 {
     return 0;
 }
 
-static XSM_INLINE void xsm_free_security_evtchn(struct evtchn *chn)
+static XSM_INLINE void xsm_free_security_evtchns(
+    struct evtchn chn[], unsigned int nr)
 {
     return;
 }
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 91ecff4f11..7bdd254420 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -72,8 +72,8 @@ struct xsm_operations {
 
     int (*alloc_security_domain) (struct domain *d);
     void (*free_security_domain) (struct domain *d);
-    int (*alloc_security_evtchn) (struct evtchn *chn);
-    void (*free_security_evtchn) (struct evtchn *chn);
+    int (*alloc_security_evtchns) (struct evtchn chn[], unsigned int nr);
+    void (*free_security_evtchns) (struct evtchn chn[], unsigned int nr);
     char *(*show_security_evtchn) (struct domain *d, const struct evtchn *chn);
     int (*init_hardware_domain) (struct domain *d);
 
@@ -314,14 +314,16 @@ static inline void xsm_free_security_domain (struct 
domain *d)
     xsm_ops->free_security_domain(d);
 }
 
-static inline int xsm_alloc_security_evtchn (struct evtchn *chn)
+static inline int xsm_alloc_security_evtchns(
+    struct evtchn chn[], unsigned int nr)
 {
-    return xsm_ops->alloc_security_evtchn(chn);
+    return xsm_ops->alloc_security_evtchns(chn, nr);
 }
 
-static inline void xsm_free_security_evtchn (struct evtchn *chn)
+static inline void xsm_free_security_evtchns(
+    struct evtchn chn[], unsigned int nr)
 {
-    (void)xsm_ops->free_security_evtchn(chn);
+    xsm_ops->free_security_evtchns(chn, nr);
 }
 
 static inline char *xsm_show_security_evtchn (struct domain *d, const struct 
evtchn *chn)
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index 8bdffe740e..627f12dbff 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -49,8 +49,8 @@ void __init xsm_fixup_ops (struct xsm_operations *ops)
 
     set_to_dummy_if_null(ops, alloc_security_domain);
     set_to_dummy_if_null(ops, free_security_domain);
-    set_to_dummy_if_null(ops, alloc_security_evtchn);
-    set_to_dummy_if_null(ops, free_security_evtchn);
+    set_to_dummy_if_null(ops, alloc_security_evtchns);
+    set_to_dummy_if_null(ops, free_security_evtchns);
     set_to_dummy_if_null(ops, show_security_evtchn);
     set_to_dummy_if_null(ops, init_hardware_domain);
 
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 3b7313b949..5a24d01f04 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -307,19 +307,25 @@ static int flask_evtchn_reset(struct domain *d1, struct 
domain *d2)
     return domain_has_perm(d1, d2, SECCLASS_EVENT, EVENT__RESET);
 }
 
-static int flask_alloc_security_evtchn(struct evtchn *chn)
+static int flask_alloc_security_evtchns(struct evtchn chn[], unsigned int nr)
 {
-    chn->ssid.flask_sid = SECINITSID_UNLABELED;
+    unsigned int i;
+
+    for ( i = 0; i < nr; ++i )
+        chn[i].ssid.flask_sid = SECINITSID_UNLABELED;
 
-    return 0;    
+    return 0;
 }
 
-static void flask_free_security_evtchn(struct evtchn *chn)
+static void flask_free_security_evtchns(struct evtchn chn[], unsigned int nr)
 {
+    unsigned int i;
+
     if ( !chn )
         return;
 
-    chn->ssid.flask_sid = SECINITSID_UNLABELED;
+    for ( i = 0; i < nr; ++i )
+        chn[i].ssid.flask_sid = SECINITSID_UNLABELED;
 }
 
 static char *flask_show_security_evtchn(struct domain *d, const struct evtchn 
*chn)
@@ -1766,8 +1772,8 @@ static struct xsm_operations flask_ops = {
 
     .alloc_security_domain = flask_domain_alloc_security,
     .free_security_domain = flask_domain_free_security,
-    .alloc_security_evtchn = flask_alloc_security_evtchn,
-    .free_security_evtchn = flask_free_security_evtchn,
+    .alloc_security_evtchns = flask_alloc_security_evtchns,
+    .free_security_evtchns = flask_free_security_evtchns,
     .show_security_evtchn = flask_show_security_evtchn,
     .init_hardware_domain = flask_init_hardware_domain,
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.