Skip to content

Commit 5186ba3

Browse files
committed
Merge tag 'x86_cache_for_v6.10_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 resource control updates from Borislav Petkov: - Add a tracepoint to read out LLC occupancy of resource monitor IDs with the goal of freeing them sooner rather than later - Other code improvements and cleanups * tag 'x86_cache_for_v6.10_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/resctrl: Add tracepoint for llc_occupancy tracking x86/resctrl: Rename pseudo_lock_event.h to trace.h x86/resctrl: Simplify call convention for MSR update functions x86/resctrl: Pass domain to target CPU
2 parents 25c7cb0 + 931be44 commit 5186ba3

File tree

8 files changed

+72
-83
lines changed

8 files changed

+72
-83
lines changed

Documentation/arch/x86/resctrl.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,12 @@ during mkdir.
446446
max_threshold_occupancy is a user configurable value to determine the
447447
occupancy at which an RMID can be freed.
448448

449+
The mon_llc_occupancy_limbo tracepoint gives the precise occupancy in bytes
450+
for a subset of RMID that are not immediately available for allocation.
451+
This can't be relied on to produce output every second, it may be necessary
452+
to attempt to create an empty monitor group to force an update. Output may
453+
only be produced if creation of a control or monitor group fails.
454+
449455
Schemata files - general concepts
450456
---------------------------------
451457
Each line in the file describes one resource. The line starts with

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

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,9 @@ int max_name_width, max_data_width;
5656
*/
5757
bool rdt_alloc_capable;
5858

59-
static void
60-
mba_wrmsr_intel(struct rdt_domain *d, struct msr_param *m,
61-
struct rdt_resource *r);
62-
static void
63-
cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r);
64-
static void
65-
mba_wrmsr_amd(struct rdt_domain *d, struct msr_param *m,
66-
struct rdt_resource *r);
59+
static void mba_wrmsr_intel(struct msr_param *m);
60+
static void cat_wrmsr(struct msr_param *m);
61+
static void mba_wrmsr_amd(struct msr_param *m);
6762

6863
#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].r_resctrl.domains)
6964

@@ -309,12 +304,11 @@ static void rdt_get_cdp_l2_config(void)
309304
rdt_get_cdp_config(RDT_RESOURCE_L2);
310305
}
311306

312-
static void
313-
mba_wrmsr_amd(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r)
307+
static void mba_wrmsr_amd(struct msr_param *m)
314308
{
309+
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
310+
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
315311
unsigned int i;
316-
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
317-
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
318312

319313
for (i = m->low; i < m->high; i++)
320314
wrmsrl(hw_res->msr_base + i, hw_dom->ctrl_val[i]);
@@ -334,25 +328,22 @@ static u32 delay_bw_map(unsigned long bw, struct rdt_resource *r)
334328
return r->default_ctrl;
335329
}
336330

337-
static void
338-
mba_wrmsr_intel(struct rdt_domain *d, struct msr_param *m,
339-
struct rdt_resource *r)
331+
static void mba_wrmsr_intel(struct msr_param *m)
340332
{
333+
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
334+
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
341335
unsigned int i;
342-
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
343-
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
344336

345337
/* Write the delay values for mba. */
346338
for (i = m->low; i < m->high; i++)
347-
wrmsrl(hw_res->msr_base + i, delay_bw_map(hw_dom->ctrl_val[i], r));
339+
wrmsrl(hw_res->msr_base + i, delay_bw_map(hw_dom->ctrl_val[i], m->res));
348340
}
349341

350-
static void
351-
cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r)
342+
static void cat_wrmsr(struct msr_param *m)
352343
{
344+
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
345+
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
353346
unsigned int i;
354-
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
355-
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
356347

357348
for (i = m->low; i < m->high; i++)
358349
wrmsrl(hw_res->msr_base + i, hw_dom->ctrl_val[i]);
@@ -362,6 +353,8 @@ struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r)
362353
{
363354
struct rdt_domain *d;
364355

356+
lockdep_assert_cpus_held();
357+
365358
list_for_each_entry(d, &r->domains, list) {
366359
/* Find the domain that contains this CPU */
367360
if (cpumask_test_cpu(cpu, &d->cpu_mask))
@@ -378,19 +371,11 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *r)
378371

379372
void rdt_ctrl_update(void *arg)
380373
{
374+
struct rdt_hw_resource *hw_res;
381375
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;
386376

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);
377+
hw_res = resctrl_to_arch_res(m->res);
378+
hw_res->msr_update(m);
394379
}
395380

396381
/*
@@ -463,9 +448,11 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
463448
hw_dom->ctrl_val = dc;
464449
setup_default_ctrlval(r, dc);
465450

451+
m.res = r;
452+
m.dom = d;
466453
m.low = 0;
467454
m.high = hw_res->num_closid;
468-
hw_res->msr_update(d, &m, r);
455+
hw_res->msr_update(&m);
469456
return 0;
470457
}
471458

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

Lines changed: 8 additions & 32 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,9 +286,10 @@ 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;
307-
hw_res->msr_update(d, &msr_param, r);
292+
hw_res->msr_update(&msr_param);
308293

309294
return 0;
310295
}
@@ -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: 3 additions & 2 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
};
@@ -443,8 +445,7 @@ struct rdt_hw_resource {
443445
struct rdt_resource r_resctrl;
444446
u32 num_closid;
445447
unsigned int msr_base;
446-
void (*msr_update) (struct rdt_domain *d, struct msr_param *m,
447-
struct rdt_resource *r);
448+
void (*msr_update)(struct msr_param *m);
448449
unsigned int mon_scale;
449450
unsigned int mbm_width;
450451
unsigned int mbm_cfg_mask;

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <asm/resctrl.h>
2525

2626
#include "internal.h"
27+
#include "trace.h"
2728

2829
/**
2930
* struct rmid_entry - dirty tracking for all RMID.
@@ -354,6 +355,16 @@ void __check_limbo(struct rdt_domain *d, bool force_free)
354355
rmid_dirty = true;
355356
} else {
356357
rmid_dirty = (val >= resctrl_rmid_realloc_threshold);
358+
359+
/*
360+
* x86's CLOSID and RMID are independent numbers, so the entry's
361+
* CLOSID is an empty CLOSID (X86_RESCTRL_EMPTY_CLOSID). On Arm the
362+
* RMID (PMG) extends the CLOSID (PARTID) space with bits that aren't
363+
* used to select the configuration. It is thus necessary to track both
364+
* CLOSID and RMID because there may be dependencies between them
365+
* on some architectures.
366+
*/
367+
trace_mon_llc_occupancy_limbo(entry->closid, entry->rmid, d->id, val);
357368
}
358369

359370
if (force_free || !rmid_dirty) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include "internal.h"
3232

3333
#define CREATE_TRACE_POINTS
34-
#include "pseudo_lock_event.h"
34+
#include "trace.h"
3535

3636
/*
3737
* The bits needed to disable hardware prefetching varies based on the

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

arch/x86/kernel/cpu/resctrl/pseudo_lock_event.h renamed to arch/x86/kernel/cpu/resctrl/trace.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
#undef TRACE_SYSTEM
33
#define TRACE_SYSTEM resctrl
44

5-
#if !defined(_TRACE_PSEUDO_LOCK_H) || defined(TRACE_HEADER_MULTI_READ)
6-
#define _TRACE_PSEUDO_LOCK_H
5+
#if !defined(_TRACE_RESCTRL_H) || defined(TRACE_HEADER_MULTI_READ)
6+
#define _TRACE_RESCTRL_H
77

88
#include <linux/tracepoint.h>
99

@@ -35,9 +35,25 @@ TRACE_EVENT(pseudo_lock_l3,
3535
TP_printk("hits=%llu miss=%llu",
3636
__entry->l3_hits, __entry->l3_miss));
3737

38-
#endif /* _TRACE_PSEUDO_LOCK_H */
38+
TRACE_EVENT(mon_llc_occupancy_limbo,
39+
TP_PROTO(u32 ctrl_hw_id, u32 mon_hw_id, int domain_id, u64 llc_occupancy_bytes),
40+
TP_ARGS(ctrl_hw_id, mon_hw_id, domain_id, llc_occupancy_bytes),
41+
TP_STRUCT__entry(__field(u32, ctrl_hw_id)
42+
__field(u32, mon_hw_id)
43+
__field(int, domain_id)
44+
__field(u64, llc_occupancy_bytes)),
45+
TP_fast_assign(__entry->ctrl_hw_id = ctrl_hw_id;
46+
__entry->mon_hw_id = mon_hw_id;
47+
__entry->domain_id = domain_id;
48+
__entry->llc_occupancy_bytes = llc_occupancy_bytes;),
49+
TP_printk("ctrl_hw_id=%u mon_hw_id=%u domain_id=%d llc_occupancy_bytes=%llu",
50+
__entry->ctrl_hw_id, __entry->mon_hw_id, __entry->domain_id,
51+
__entry->llc_occupancy_bytes)
52+
);
53+
54+
#endif /* _TRACE_RESCTRL_H */
3955

4056
#undef TRACE_INCLUDE_PATH
4157
#define TRACE_INCLUDE_PATH .
42-
#define TRACE_INCLUDE_FILE pseudo_lock_event
58+
#define TRACE_INCLUDE_FILE trace
4359
#include <trace/define_trace.h>

0 commit comments

Comments
 (0)