x86/resctrl: Group staged configuration into a separate struct
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
This commit is contained in:
Родитель
e198fde3fe
Коммит
e8f7282552
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,13 +27,21 @@ enum resctrl_conf_type {
|
|||
CDP_DATA,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче