]> xenbits.xensource.com Git - people/andrewcoop/xen.git/commitdiff
x86: refactor psr: L3 CAT: set value: implement write msr flow.
authorYi Sun <yi.y.sun@linux.intel.com>
Tue, 1 Aug 2017 09:04:00 +0000 (11:04 +0200)
committerJan Beulich <jbeulich@suse.com>
Thu, 3 Aug 2017 10:35:19 +0000 (12:35 +0200)
Continue from previous patch:
'x86: refactor psr: L3 CAT: set value: implement cos id picking flow.'

We have got the feature value and COS ID to set. Then, we write MSRs of the
designated feature.

Till now, set value process is completed.

Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/psr.c

index b553112d99b3f42d27eebc7098105bbf2829fb8a..6ea2e4e1ad0f4fbecd6f1eeff2ebaaa1e266190c 100644 (file)
@@ -113,6 +113,9 @@ static const struct feat_props {
     /* get_feat_info is used to return feature HW info through sysctl. */
     bool (*get_feat_info)(const struct feat_node *feat,
                           uint32_t data[], unsigned int array_len);
+
+    /* write_msr is used to write out feature MSR register. */
+    void (*write_msr)(unsigned int cos, uint32_t val, enum cbm_type type);
 } *feat_props[FEAT_TYPE_NUM];
 
 /*
@@ -289,11 +292,17 @@ static bool cat_get_feat_info(const struct feat_node *feat,
 }
 
 /* L3 CAT props */
+static void l3_cat_write_msr(unsigned int cos, uint32_t val, enum cbm_type type)
+{
+    wrmsrl(MSR_IA32_PSR_L3_MASK(cos), val);
+}
+
 static const struct feat_props l3_cat_props = {
     .cos_num = 1,
     .type[0] = PSR_CBM_TYPE_L3,
     .alt_type = PSR_CBM_TYPE_UNKNOWN,
     .get_feat_info = cat_get_feat_info,
+    .write_msr = l3_cat_write_msr,
 };
 
 static void __init parse_psr_bool(char *s, char *value, char *feature,
@@ -947,11 +956,79 @@ static int pick_avail_cos(const struct psr_socket_info *info,
     return -EOVERFLOW;
 }
 
+static unsigned int get_socket_cpu(unsigned int socket)
+{
+    if ( likely(socket < nr_sockets) )
+        return cpumask_any(socket_cpumask[socket]);
+
+    return nr_cpu_ids;
+}
+
+struct cos_write_info
+{
+    unsigned int cos;
+    struct feat_node *feature;
+    const uint32_t *val;
+    const struct feat_props *props;
+};
+
+static void do_write_psr_msrs(void *data)
+{
+    const struct cos_write_info *info = data;
+    struct feat_node *feat = info->feature;
+    const struct feat_props *props = info->props;
+    unsigned int i, cos = info->cos, cos_num = props->cos_num;
+
+    for ( i = 0; i < cos_num; i++ )
+    {
+        if ( feat->cos_reg_val[cos * cos_num + i] != info->val[i] )
+        {
+            feat->cos_reg_val[cos * cos_num + i] = info->val[i];
+            props->write_msr(cos, info->val[i], props->type[i]);
+        }
+    }
+}
+
 static int write_psr_msrs(unsigned int socket, unsigned int cos,
                           const uint32_t val[], unsigned int array_len,
                           enum psr_feat_type feat_type)
 {
-    return -ENOENT;
+    int ret;
+    struct psr_socket_info *info = get_socket_info(socket);
+    struct cos_write_info data =
+    {
+        .cos = cos,
+        .feature = info->features[feat_type],
+        .props = feat_props[feat_type],
+    };
+
+    if ( cos > info->features[feat_type]->cos_max )
+        return -EINVAL;
+
+    /* Skip to the feature's value head. */
+    ret = skip_prior_features(&array_len, feat_type);
+    if ( ret < 0 )
+        return ret;
+
+    val += ret;
+
+    if ( array_len < feat_props[feat_type]->cos_num )
+        return -ENOSPC;
+
+    data.val = val;
+
+    if ( socket == cpu_to_socket(smp_processor_id()) )
+        do_write_psr_msrs(&data);
+    else
+    {
+        unsigned int cpu = get_socket_cpu(socket);
+
+        if ( cpu >= nr_cpu_ids )
+            return -ENOTSOCK;
+        on_selected_cpus(cpumask_of(cpu), do_write_psr_msrs, &data, 1);
+    }
+
+    return 0;
 }
 
 int psr_set_val(struct domain *d, unsigned int socket,