[xen master] x86: refactor psr: L3 CAT: set value: assemble features value array.

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[xen master] x86: refactor psr: L3 CAT: set value: assemble features value array.

patchbot
commit 81811cffec3cc090c5d63b5cc09eb7e8512bc3db
Author:     Yi Sun <[hidden email]>
AuthorDate: Tue Aug 1 11:04:00 2017 +0200
Commit:     Jan Beulich <[hidden email]>
CommitDate: Thu Aug 3 12:34:12 2017 +0200

    x86: refactor psr: L3 CAT: set value: assemble features value array.
   
    Only can one COS ID be used by one domain at one time. That means all enabled
    features' COS registers at this COS ID are valid for this domain at that time.
   
    When user updates a feature's value, we need make sure all other features'
    values are not affected. So, we firstly need gather an array which contains
    all features current values and replace the setting feature's value in array
    to new value.
   
    Then, we can try to find if there is a COS ID on which all features' COS
    registers values are same as the array. If we can find, we just use this COS
    ID. If fail to find, we need pick a new COS ID.
   
    This patch implements value array assembling flow.
   
    Signed-off-by: Yi Sun <[hidden email]>
    Reviewed-by: Jan Beulich <[hidden email]>
---
 xen/arch/x86/psr.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 133 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index f1b5837..f7ba892 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -210,6 +210,29 @@ static enum psr_feat_type psr_cbm_type_to_feat_type(enum cbm_type type)
     return feat_type;
 }
 
+static bool psr_check_cbm(unsigned int cbm_len, unsigned long cbm)
+{
+    unsigned int first_bit, zero_bit;
+
+    /* Set bits should only in the range of [0, cbm_len]. */
+    if ( cbm & (~0ul << cbm_len) )
+        return false;
+
+    /* At least one bit need to be set. */
+    if ( cbm == 0 )
+        return false;
+
+    first_bit = find_first_bit(&cbm, cbm_len);
+    zero_bit = find_next_zero_bit(&cbm, cbm_len, first_bit);
+
+    /* Set bits should be contiguous. */
+    if ( zero_bit < cbm_len &&
+         find_next_bit(&cbm, cbm_len, zero_bit) < cbm_len )
+        return false;
+
+    return true;
+}
+
 /* CAT common functions implementation. */
 static int cat_init_feature(const struct cpuid_leaf *regs,
                             struct feat_node *feat,
@@ -601,7 +624,14 @@ int psr_get_val(struct domain *d, unsigned int socket,
 /* Set value functions */
 static unsigned int get_cos_num(void)
 {
-    return 0;
+    unsigned int num = 0, i;
+
+    /* Get all features total amount. */
+    for ( i = 0; i < ARRAY_SIZE(feat_props); i++ )
+        if ( feat_props[i] )
+            num += feat_props[i]->cos_num;
+
+    return num;
 }
 
 static int gather_val_array(uint32_t val[],
@@ -609,7 +639,68 @@ static int gather_val_array(uint32_t val[],
                             const struct psr_socket_info *info,
                             unsigned int old_cos)
 {
-    return -EINVAL;
+    unsigned int i;
+
+    if ( !val )
+        return -EINVAL;
+
+    /* Get all features current values according to old_cos. */
+    for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
+    {
+        unsigned int cos = old_cos, j;
+        const struct feat_node *feat = info->features[i];
+        const struct feat_props *props = feat_props[i];
+
+        if ( !feat )
+            continue;
+
+        if ( !props )
+        {
+            ASSERT_UNREACHABLE();
+            return -ENOENT;
+        }
+
+        if ( array_len < props->cos_num )
+            return -ENOSPC;
+
+        /*
+         * If old_cos exceeds current feature's cos_max, we should get
+         * default value. So assign cos to 0 which stores default value.
+         */
+        if ( cos > feat->cos_max )
+            cos = 0;
+
+        /* Value getting order is same as feature array. */
+        for ( j = 0; j < props->cos_num; j++ )
+            val[j] = feat->cos_reg_val[cos * props->cos_num + j];
+
+        array_len -= props->cos_num;
+        val += props->cos_num;
+    }
+
+    return 0;
+}
+
+static int skip_prior_features(unsigned int *array_len,
+                               enum psr_feat_type feat_type)
+{
+    unsigned int i, skip_len = 0;
+
+    for ( i = 0; i < feat_type; i++ )
+    {
+        const struct feat_props *props = feat_props[i];
+
+        if ( !props )
+            continue;
+
+        if ( *array_len <= props->cos_num )
+            return -ENOSPC;
+
+        *array_len -= props->cos_num;
+        skip_len += props->cos_num;
+    }
+
+    return skip_len;
 }
 
 static int insert_val_into_array(uint32_t val[],
@@ -619,6 +710,46 @@ static int insert_val_into_array(uint32_t val[],
                                  enum cbm_type type,
                                  uint32_t new_val)
 {
+    const struct feat_node *feat;
+    const struct feat_props *props;
+    unsigned int i;
+    int ret;
+
+    ASSERT(feat_type < FEAT_TYPE_NUM);
+
+    ret = skip_prior_features(&array_len, feat_type);
+    if ( ret < 0 )
+        return ret;
+
+    val += ret;
+
+    feat = info->features[feat_type];
+    if ( !feat )
+        return -ENOENT;
+
+    props = feat_props[feat_type];
+    if ( !props )
+    {
+        ASSERT_UNREACHABLE();
+        return -ENOENT;
+    }
+
+    if ( array_len < props->cos_num )
+        return -ENOSPC;
+
+    if ( !psr_check_cbm(feat->cbm_len, new_val) )
+        return -EINVAL;
+
+    /* Value setting position is same as feature array. */
+    for ( i = 0; i < props->cos_num; i++ )
+    {
+        if ( type == props->type[i] )
+        {
+            val[i] = new_val;
+            return 0;
+        }
+    }
+
     return -EINVAL;
 }
 
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
[hidden email]
https://lists.xenproject.org/xen-changelog
Loading...