Skip to content

Commit e3ca96e

Browse files
aeglbp3tk0v
authored andcommitted
x86/resctrl: Pass domain to target CPU
reset_all_ctrls() and resctrl_arch_update_domains() use on_each_cpu_mask() to call rdt_ctrl_update() on potentially one CPU from each domain. But this means rdt_ctrl_update() needs to figure out which domain to apply changes to. Doing so requires a search of all domains in a resource, which can only be done safely if cpus_lock is held. Both callers do hold this lock, but there isn't a way for a function called on another CPU via IPI to verify this. Commit c0d848f ("x86/resctrl: Remove lockdep annotation that triggers false positive") removed the incorrect assertions. Add the target domain to the msr_param structure and call rdt_ctrl_update() for each domain separately using smp_call_function_single(). This means that rdt_ctrl_update() doesn't need to search for the domain and get_domain_from_cpu() can safely assert that the cpus_lock is held since the remaining callers do not use IPI. Signed-off-by: Tony Luck <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Reviewed-by: Reinette Chatre <[email protected]> Reviewed-by: James Morse <[email protected]> Reviewed-by: Babu Moger <[email protected]> Tested-by: Maciej Wieczor-Retman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent ed30a4a commit e3ca96e

File tree

4 files changed

+17
-52
lines changed

4 files changed

+17
-52
lines changed

arch/x86/kernel/cpu/resctrl/core.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r)
362362
{
363363
struct rdt_domain *d;
364364

365+
lockdep_assert_cpus_held();
366+
365367
list_for_each_entry(d, &r->domains, list) {
366368
/* Find the domain that contains this CPU */
367369
if (cpumask_test_cpu(cpu, &d->cpu_mask))
@@ -378,19 +380,11 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *r)
378380

379381
void rdt_ctrl_update(void *arg)
380382
{
383+
struct rdt_hw_resource *hw_res;
381384
struct msr_param *m = arg;
382-
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
383-
struct rdt_resource *r = m->res;
384-
int cpu = smp_processor_id();
385-
struct rdt_domain *d;
386385

387-
d = get_domain_from_cpu(cpu, r);
388-
if (d) {
389-
hw_res->msr_update(d, m, r);
390-
return;
391-
}
392-
pr_warn_once("cpu %d not found in any domain for resource %s\n",
393-
cpu, r->name);
386+
hw_res = resctrl_to_arch_res(m->res);
387+
hw_res->msr_update(m->dom, m, m->res);
394388
}
395389

396390
/*
@@ -463,6 +457,7 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
463457
hw_dom->ctrl_val = dc;
464458
setup_default_ctrlval(r, dc);
465459

460+
m.dom = d;
466461
m.low = 0;
467462
m.high = hw_res->num_closid;
468463
hw_res->msr_update(d, &m, r);

arch/x86/kernel/cpu/resctrl/ctrlmondata.c

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -272,22 +272,6 @@ static u32 get_config_index(u32 closid, enum resctrl_conf_type type)
272272
}
273273
}
274274

275-
static bool apply_config(struct rdt_hw_domain *hw_dom,
276-
struct resctrl_staged_config *cfg, u32 idx,
277-
cpumask_var_t cpu_mask)
278-
{
279-
struct rdt_domain *dom = &hw_dom->d_resctrl;
280-
281-
if (cfg->new_ctrl != hw_dom->ctrl_val[idx]) {
282-
cpumask_set_cpu(cpumask_any(&dom->cpu_mask), cpu_mask);
283-
hw_dom->ctrl_val[idx] = cfg->new_ctrl;
284-
285-
return true;
286-
}
287-
288-
return false;
289-
}
290-
291275
int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
292276
u32 closid, enum resctrl_conf_type t, u32 cfg_val)
293277
{
@@ -302,6 +286,7 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
302286
hw_dom->ctrl_val[idx] = cfg_val;
303287

304288
msr_param.res = r;
289+
msr_param.dom = d;
305290
msr_param.low = idx;
306291
msr_param.high = idx + 1;
307292
hw_res->msr_update(d, &msr_param, r);
@@ -315,48 +300,39 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
315300
struct rdt_hw_domain *hw_dom;
316301
struct msr_param msr_param;
317302
enum resctrl_conf_type t;
318-
cpumask_var_t cpu_mask;
319303
struct rdt_domain *d;
320304
u32 idx;
321305

322306
/* Walking r->domains, ensure it can't race with cpuhp */
323307
lockdep_assert_cpus_held();
324308

325-
if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
326-
return -ENOMEM;
327-
328-
msr_param.res = NULL;
329309
list_for_each_entry(d, &r->domains, list) {
330310
hw_dom = resctrl_to_arch_dom(d);
311+
msr_param.res = NULL;
331312
for (t = 0; t < CDP_NUM_TYPES; t++) {
332313
cfg = &hw_dom->d_resctrl.staged_config[t];
333314
if (!cfg->have_new_ctrl)
334315
continue;
335316

336317
idx = get_config_index(closid, t);
337-
if (!apply_config(hw_dom, cfg, idx, cpu_mask))
318+
if (cfg->new_ctrl == hw_dom->ctrl_val[idx])
338319
continue;
320+
hw_dom->ctrl_val[idx] = cfg->new_ctrl;
339321

340322
if (!msr_param.res) {
341323
msr_param.low = idx;
342324
msr_param.high = msr_param.low + 1;
343325
msr_param.res = r;
326+
msr_param.dom = d;
344327
} else {
345328
msr_param.low = min(msr_param.low, idx);
346329
msr_param.high = max(msr_param.high, idx + 1);
347330
}
348331
}
332+
if (msr_param.res)
333+
smp_call_function_any(&d->cpu_mask, rdt_ctrl_update, &msr_param, 1);
349334
}
350335

351-
if (cpumask_empty(cpu_mask))
352-
goto done;
353-
354-
/* Update resource control msr on all the CPUs. */
355-
on_each_cpu_mask(cpu_mask, rdt_ctrl_update, &msr_param, 1);
356-
357-
done:
358-
free_cpumask_var(cpu_mask);
359-
360336
return 0;
361337
}
362338

arch/x86/kernel/cpu/resctrl/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,11 +379,13 @@ static inline struct rdt_hw_domain *resctrl_to_arch_dom(struct rdt_domain *r)
379379
/**
380380
* struct msr_param - set a range of MSRs from a domain
381381
* @res: The resource to use
382+
* @dom: The domain to update
382383
* @low: Beginning index from base MSR
383384
* @high: End index
384385
*/
385386
struct msr_param {
386387
struct rdt_resource *res;
388+
struct rdt_domain *dom;
387389
u32 low;
388390
u32 high;
389391
};

arch/x86/kernel/cpu/resctrl/rdtgroup.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2813,16 +2813,12 @@ static int reset_all_ctrls(struct rdt_resource *r)
28132813
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
28142814
struct rdt_hw_domain *hw_dom;
28152815
struct msr_param msr_param;
2816-
cpumask_var_t cpu_mask;
28172816
struct rdt_domain *d;
28182817
int i;
28192818

28202819
/* Walking r->domains, ensure it can't race with cpuhp */
28212820
lockdep_assert_cpus_held();
28222821

2823-
if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
2824-
return -ENOMEM;
2825-
28262822
msr_param.res = r;
28272823
msr_param.low = 0;
28282824
msr_param.high = hw_res->num_closid;
@@ -2834,17 +2830,13 @@ static int reset_all_ctrls(struct rdt_resource *r)
28342830
*/
28352831
list_for_each_entry(d, &r->domains, list) {
28362832
hw_dom = resctrl_to_arch_dom(d);
2837-
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
28382833

28392834
for (i = 0; i < hw_res->num_closid; i++)
28402835
hw_dom->ctrl_val[i] = r->default_ctrl;
2836+
msr_param.dom = d;
2837+
smp_call_function_any(&d->cpu_mask, rdt_ctrl_update, &msr_param, 1);
28412838
}
28422839

2843-
/* Update CBM on all the CPUs in cpu_mask */
2844-
on_each_cpu_mask(cpu_mask, rdt_ctrl_update, &msr_param, 1);
2845-
2846-
free_cpumask_var(cpu_mask);
2847-
28482840
return 0;
28492841
}
28502842

0 commit comments

Comments
 (0)