Skip to content

Commit e330268

Browse files
Vikas ShivappaKAGA-KOKO
authored andcommitted
x86/intel_rdt/mbm: Handle counter overflow
Set up a delayed work queue for each domain that will read all the MBM counters of active RMIDs once per second to make sure that they don't wrap around between reads from users. [Tony: Added the initializations for the work structure and completed the patch] Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Vikas Shivappa <vikas.shivappa@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: ravi.v.shankar@intel.com Cc: fenghua.yu@intel.com Cc: peterz@infradead.org Cc: eranian@google.com Cc: vikas.shivappa@intel.com Cc: ak@linux.intel.com Cc: davidcc@google.com Cc: reinette.chatre@intel.com Link: http://lkml.kernel.org/r/1501017287-28083-29-git-send-email-vikas.shivappa@linux.intel.com
1 parent a4de1df commit e330268

File tree

4 files changed

+97
-6
lines changed

4 files changed

+97
-6
lines changed

arch/x86/kernel/cpu/intel_rdt.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,10 @@ void rdt_ctrl_update(void *arg)
348348
int cpu = smp_processor_id();
349349
struct rdt_domain *d;
350350

351-
list_for_each_entry(d, &r->domains, list) {
352-
/* Find the domain that contains this CPU */
353-
if (cpumask_test_cpu(cpu, &d->cpu_mask)) {
354-
r->msr_update(d, m, r);
355-
return;
356-
}
351+
d = get_domain_from_cpu(cpu, r);
352+
if (d) {
353+
r->msr_update(d, m, r);
354+
return;
357355
}
358356
pr_warn_once("cpu %d not found in any domain for resource %s\n",
359357
cpu, r->name);
@@ -447,6 +445,11 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
447445
}
448446
}
449447

448+
if (is_mbm_enabled()) {
449+
INIT_DELAYED_WORK(&d->mbm_over, mbm_handle_overflow);
450+
mbm_setup_overflow_handler(d);
451+
}
452+
450453
return 0;
451454
}
452455

@@ -531,7 +534,13 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
531534
kfree(d->mbm_total);
532535
kfree(d->mbm_local);
533536
list_del(&d->list);
537+
if (is_mbm_enabled())
538+
cancel_delayed_work(&d->mbm_over);
534539
kfree(d);
540+
} else if (r == &rdt_resources_all[RDT_RESOURCE_L3] &&
541+
cpu == d->mbm_work_cpu && is_mbm_enabled()) {
542+
cancel_delayed_work(&d->mbm_over);
543+
mbm_setup_overflow_handler(d);
535544
}
536545
}
537546

arch/x86/kernel/cpu/intel_rdt.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@
2121
#define QOS_L3_MBM_LOCAL_EVENT_ID 0x03
2222

2323
#define MBM_CNTR_WIDTH 24
24+
#define MBM_OVERFLOW_INTERVAL 1000
2425

2526
#define RMID_VAL_ERROR BIT_ULL(63)
2627
#define RMID_VAL_UNAVAIL BIT_ULL(62)
2728

29+
DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
30+
2831
/**
2932
* struct mon_evt - Entry in the event list of a resource
3033
* @evtid: event id
@@ -183,6 +186,9 @@ struct mbm_state {
183186
* bitmap of which limbo RMIDs are above threshold
184187
* @mbm_total: saved state for MBM total bandwidth
185188
* @mbm_local: saved state for MBM local bandwidth
189+
* @mbm_over: worker to periodically read MBM h/w counters
190+
* @mbm_work_cpu:
191+
* worker cpu for MBM h/w counters
186192
* @ctrl_val: array of cache or mem ctrl values (indexed by CLOSID)
187193
* @new_ctrl: new ctrl value to be loaded
188194
* @have_new_ctrl: did user provide new_ctrl for this domain
@@ -194,6 +200,8 @@ struct rdt_domain {
194200
unsigned long *rmid_busy_llc;
195201
struct mbm_state *mbm_total;
196202
struct mbm_state *mbm_local;
203+
struct delayed_work mbm_over;
204+
int mbm_work_cpu;
197205
u32 *ctrl_val;
198206
u32 new_ctrl;
199207
bool have_new_ctrl;
@@ -411,5 +419,7 @@ void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
411419
struct rdt_domain *d);
412420
void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
413421
struct rdtgroup *rdtgrp, int evtid, int first);
422+
void mbm_setup_overflow_handler(struct rdt_domain *dom);
423+
void mbm_handle_overflow(struct work_struct *work);
414424

415425
#endif /* _ASM_X86_INTEL_RDT_H */

arch/x86/kernel/cpu/intel_rdt_monitor.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,69 @@ void mon_event_count(void *info)
366366
}
367367
}
368368

369+
static void mbm_update(struct rdt_domain *d, int rmid)
370+
{
371+
struct rmid_read rr;
372+
373+
rr.first = false;
374+
rr.d = d;
375+
376+
/*
377+
* This is protected from concurrent reads from user
378+
* as both the user and we hold the global mutex.
379+
*/
380+
if (is_mbm_total_enabled()) {
381+
rr.evtid = QOS_L3_MBM_TOTAL_EVENT_ID;
382+
__mon_event_count(rmid, &rr);
383+
}
384+
if (is_mbm_local_enabled()) {
385+
rr.evtid = QOS_L3_MBM_LOCAL_EVENT_ID;
386+
__mon_event_count(rmid, &rr);
387+
}
388+
}
389+
390+
void mbm_handle_overflow(struct work_struct *work)
391+
{
392+
unsigned long delay = msecs_to_jiffies(MBM_OVERFLOW_INTERVAL);
393+
struct rdtgroup *prgrp, *crgrp;
394+
int cpu = smp_processor_id();
395+
struct list_head *head;
396+
struct rdt_domain *d;
397+
398+
mutex_lock(&rdtgroup_mutex);
399+
400+
if (!static_branch_likely(&rdt_enable_key))
401+
goto out_unlock;
402+
403+
d = get_domain_from_cpu(cpu, &rdt_resources_all[RDT_RESOURCE_L3]);
404+
if (!d)
405+
goto out_unlock;
406+
407+
list_for_each_entry(prgrp, &rdt_all_groups, rdtgroup_list) {
408+
mbm_update(d, prgrp->mon.rmid);
409+
410+
head = &prgrp->mon.crdtgrp_list;
411+
list_for_each_entry(crgrp, head, mon.crdtgrp_list)
412+
mbm_update(d, crgrp->mon.rmid);
413+
}
414+
415+
schedule_delayed_work_on(cpu, &d->mbm_over, delay);
416+
out_unlock:
417+
mutex_unlock(&rdtgroup_mutex);
418+
}
419+
420+
void mbm_setup_overflow_handler(struct rdt_domain *dom)
421+
{
422+
unsigned long delay = msecs_to_jiffies(MBM_OVERFLOW_INTERVAL);
423+
int cpu;
424+
425+
if (!static_branch_likely(&rdt_enable_key))
426+
return;
427+
cpu = cpumask_any(&dom->cpu_mask);
428+
dom->mbm_work_cpu = cpu;
429+
schedule_delayed_work_on(cpu, &dom->mbm_over, delay);
430+
}
431+
369432
static int dom_data_init(struct rdt_resource *r)
370433
{
371434
struct rmid_entry *entry = NULL;

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,8 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
10601060
int flags, const char *unused_dev_name,
10611061
void *data)
10621062
{
1063+
struct rdt_domain *dom;
1064+
struct rdt_resource *r;
10631065
struct dentry *dentry;
10641066
int ret;
10651067

@@ -1118,6 +1120,13 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
11181120

11191121
if (rdt_alloc_capable || rdt_mon_capable)
11201122
static_branch_enable(&rdt_enable_key);
1123+
1124+
if (is_mbm_enabled()) {
1125+
r = &rdt_resources_all[RDT_RESOURCE_L3];
1126+
list_for_each_entry(dom, &r->domains, list)
1127+
mbm_setup_overflow_handler(dom);
1128+
}
1129+
11211130
goto out;
11221131

11231132
out_mondata:

0 commit comments

Comments
 (0)