x86/resctrl: Group staged configuration into a separate struct
authorJames Morse <james.morse@arm.com>
Wed, 28 Jul 2021 17:06:26 +0000 (17:06 +0000)
committerBorislav Petkov <bp@suse.de>
Wed, 11 Aug 2021 14:32:32 +0000 (16:32 +0200)
When configuration changes are made, the new value is written to struct
rdt_domain's new_ctrl field and the have_new_ctrl flag is set. Later
new_ctrl is copied to hardware by a call to update_domains().

Once the CDP resources are merged, there will be one new_ctrl field in
use by two struct resctrl_schema requiring a per-schema IPI to copy the
value to hardware.

Move new_ctrl and have_new_ctrl into a new struct resctrl_staged_config.
Before the CDP resources can be merged, struct rdt_domain will need an
array of these, one per type of configuration. Using the type as an
index to the array will ensure that a schema configuration string can't
specify the same domain twice.

Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Jamie Iles <jamie@nuviainc.com>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Link: https://lkml.kernel.org/r/20210728170637.25610-14-james.morse@arm.com
arch/x86/kernel/cpu/resctrl/ctrlmondata.c
arch/x86/kernel/cpu/resctrl/rdtgroup.c
include/linux/resctrl.h

index 104b285..9ddfa76 100644 (file)
@@ -62,16 +62,17 @@ int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
 {
        struct rdt_resource *r = s->res;
        unsigned long bw_val;
+       struct resctrl_staged_config *cfg = &d->staged_config;
 
-       if (d->have_new_ctrl) {
+       if (cfg->have_new_ctrl) {
                rdt_last_cmd_printf("Duplicate domain %d\n", d->id);
                return -EINVAL;
        }
 
        if (!bw_validate(data->buf, &bw_val, r))
                return -EINVAL;
-       d->new_ctrl = bw_val;
-       d->have_new_ctrl = true;
+       cfg->new_ctrl = bw_val;
+       cfg->have_new_ctrl = true;
 
        return 0;
 }
@@ -129,11 +130,12 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
 int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
              struct rdt_domain *d)
 {
+       struct resctrl_staged_config *cfg = &d->staged_config;
        struct rdtgroup *rdtgrp = data->rdtgrp;
        struct rdt_resource *r = s->res;
        u32 cbm_val;
 
-       if (d->have_new_ctrl) {
+       if (cfg->have_new_ctrl) {
                rdt_last_cmd_printf("Duplicate domain %d\n", d->id);
                return -EINVAL;
        }
@@ -175,8 +177,8 @@ int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
                }
        }
 
-       d->new_ctrl = cbm_val;
-       d->have_new_ctrl = true;
+       cfg->new_ctrl = cbm_val;
+       cfg->have_new_ctrl = true;
 
        return 0;
 }
@@ -190,6 +192,7 @@ int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
 static int parse_line(char *line, struct resctrl_schema *s,
                      struct rdtgroup *rdtgrp)
 {
+       struct resctrl_staged_config *cfg;
        struct rdt_resource *r = s->res;
        struct rdt_parse_data data;
        char *dom = NULL, *id;
@@ -219,6 +222,7 @@ next:
                        if (r->parse_ctrlval(&data, s, d))
                                return -EINVAL;
                        if (rdtgrp->mode ==  RDT_MODE_PSEUDO_LOCKSETUP) {
+                               cfg = &d->staged_config;
                                /*
                                 * In pseudo-locking setup mode and just
                                 * parsed a valid CBM that should be
@@ -229,7 +233,7 @@ next:
                                 */
                                rdtgrp->plr->s = s;
                                rdtgrp->plr->d = d;
-                               rdtgrp->plr->cbm = d->new_ctrl;
+                               rdtgrp->plr->cbm = cfg->new_ctrl;
                                d->plr = rdtgrp->plr;
                                return 0;
                        }
@@ -239,14 +243,27 @@ next:
        return -EINVAL;
 }
 
+static void apply_config(struct rdt_hw_domain *hw_dom,
+                        struct resctrl_staged_config *cfg, int closid,
+                        cpumask_var_t cpu_mask, bool mba_sc)
+{
+       struct rdt_domain *dom = &hw_dom->d_resctrl;
+       u32 *dc = !mba_sc ? hw_dom->ctrl_val : hw_dom->mbps_val;
+
+       if (cfg->new_ctrl != dc[closid]) {
+               cpumask_set_cpu(cpumask_any(&dom->cpu_mask), cpu_mask);
+               dc[closid] = cfg->new_ctrl;
+       }
+}
+
 int update_domains(struct rdt_resource *r, int closid)
 {
+       struct resctrl_staged_config *cfg;
        struct rdt_hw_domain *hw_dom;
        struct msr_param msr_param;
        cpumask_var_t cpu_mask;
        struct rdt_domain *d;
        bool mba_sc;
-       u32 *dc;
        int cpu;
 
        if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
@@ -259,11 +276,9 @@ int update_domains(struct rdt_resource *r, int closid)
        mba_sc = is_mba_sc(r);
        list_for_each_entry(d, &r->domains, list) {
                hw_dom = resctrl_to_arch_dom(d);
-               dc = !mba_sc ? hw_dom->ctrl_val : hw_dom->mbps_val;
-               if (d->have_new_ctrl && d->new_ctrl != dc[closid]) {
-                       cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
-                       dc[closid] = d->new_ctrl;
-               }
+               cfg = &hw_dom->d_resctrl.staged_config;
+               if (cfg->have_new_ctrl)
+                       apply_config(hw_dom, cfg, closid, cpu_mask, mba_sc);
        }
 
        /*
@@ -335,7 +350,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 
        list_for_each_entry(s, &resctrl_schema_all, list) {
                list_for_each_entry(dom, &s->res->domains, list)
-                       dom->have_new_ctrl = false;
+                       memset(&dom->staged_config, 0, sizeof(dom->staged_config));
        }
 
        while ((tok = strsep(&buf, "\n")) != NULL) {
index 1f8c8d7..62cc82d 100644 (file)
@@ -2752,6 +2752,7 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s,
                                 u32 closid)
 {
        struct rdt_resource *r_cdp = NULL;
+       struct resctrl_staged_config *cfg;
        struct rdt_domain *d_cdp = NULL;
        struct rdt_resource *r = s->res;
        u32 used_b = 0, unused_b = 0;
@@ -2761,8 +2762,9 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s,
        int i;
 
        rdt_cdp_peer_get(r, d, &r_cdp, &d_cdp);
-       d->have_new_ctrl = false;
-       d->new_ctrl = r->cache.shareable_bits;
+       cfg = &d->staged_config;
+       cfg->have_new_ctrl = false;
+       cfg->new_ctrl = r->cache.shareable_bits;
        used_b = r->cache.shareable_bits;
        ctrl = resctrl_to_arch_dom(d)->ctrl_val;
        for (i = 0; i < closids_supported(); i++, ctrl++) {
@@ -2786,29 +2788,29 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s,
                                peer_ctl = 0;
                        used_b |= *ctrl | peer_ctl;
                        if (mode == RDT_MODE_SHAREABLE)
-                               d->new_ctrl |= *ctrl | peer_ctl;
+                               cfg->new_ctrl |= *ctrl | peer_ctl;
                }
        }
        if (d->plr && d->plr->cbm > 0)
                used_b |= d->plr->cbm;
        unused_b = used_b ^ (BIT_MASK(r->cache.cbm_len) - 1);
        unused_b &= BIT_MASK(r->cache.cbm_len) - 1;
-       d->new_ctrl |= unused_b;
+       cfg->new_ctrl |= unused_b;
        /*
         * Force the initial CBM to be valid, user can
         * modify the CBM based on system availability.
         */
-       d->new_ctrl = cbm_ensure_valid(d->new_ctrl, r);
+       cfg->new_ctrl = cbm_ensure_valid(cfg->new_ctrl, r);
        /*
         * Assign the u32 CBM to an unsigned long to ensure that
         * bitmap_weight() does not access out-of-bound memory.
         */
-       tmp_cbm = d->new_ctrl;
+       tmp_cbm = cfg->new_ctrl;
        if (bitmap_weight(&tmp_cbm, r->cache.cbm_len) < r->cache.min_cbm_bits) {
                rdt_last_cmd_printf("No space on %s:%d\n", s->name, d->id);
                return -ENOSPC;
        }
-       d->have_new_ctrl = true;
+       cfg->have_new_ctrl = true;
 
        return 0;
 }
@@ -2840,11 +2842,13 @@ static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid)
 /* Initialize MBA resource with default values. */
 static void rdtgroup_init_mba(struct rdt_resource *r)
 {
+       struct resctrl_staged_config *cfg;
        struct rdt_domain *d;
 
        list_for_each_entry(d, &r->domains, list) {
-               d->new_ctrl = is_mba_sc(r) ? MBA_MAX_MBPS : r->default_ctrl;
-               d->have_new_ctrl = true;
+               cfg = &d->staged_config;
+               cfg->new_ctrl = is_mba_sc(r) ? MBA_MAX_MBPS : r->default_ctrl;
+               cfg->have_new_ctrl = true;
        }
 }
 
index e482ce7..ff7f7d7 100644 (file)
@@ -28,12 +28,20 @@ enum resctrl_conf_type {
 };
 
 /**
+ * struct resctrl_staged_config - parsed configuration to be applied
+ * @new_ctrl:          new ctrl value to be loaded
+ * @have_new_ctrl:     whether the user provided new_ctrl is valid
+ */
+struct resctrl_staged_config {
+       u32                     new_ctrl;
+       bool                    have_new_ctrl;
+};
+
+/**
  * struct rdt_domain - group of CPUs sharing a resctrl resource
  * @list:              all instances of this resource
  * @id:                        unique id for this instance
  * @cpu_mask:          which CPUs share this resource
- * @new_ctrl:          new ctrl value to be loaded
- * @have_new_ctrl:     did user provide new_ctrl for this domain
  * @rmid_busy_llc:     bitmap of which limbo RMIDs are above threshold
  * @mbm_total:         saved state for MBM total bandwidth
  * @mbm_local:         saved state for MBM local bandwidth
@@ -42,13 +50,12 @@ enum resctrl_conf_type {
  * @mbm_work_cpu:      worker CPU for MBM h/w counters
  * @cqm_work_cpu:      worker CPU for CQM h/w counters
  * @plr:               pseudo-locked region (if any) associated with domain
+ * @staged_config:     parsed configuration to be applied
  */
 struct rdt_domain {
        struct list_head                list;
        int                             id;
        struct cpumask                  cpu_mask;
-       u32                             new_ctrl;
-       bool                            have_new_ctrl;
        unsigned long                   *rmid_busy_llc;
        struct mbm_state                *mbm_total;
        struct mbm_state                *mbm_local;
@@ -57,6 +64,7 @@ struct rdt_domain {
        int                             mbm_work_cpu;
        int                             cqm_work_cpu;
        struct pseudo_lock_region       *plr;
+       struct resctrl_staged_config    staged_config;
 };
 
 /**