Cqm3 support based on resctrl along with MBM
v4 cover Cqm3 support based on resctrl along with MBM
Sending some fixes to V3 as per discussions with Thomas. This is on top of the merged patches in tip and contains the following:
- a fix to MBM hot cpu handling to avoid doubling of the overflow timer interval.
- some changes to the limbo RMID processing patch to make corrections to handle the rmid->busy correctly in case of domain going offline and to use the correct work_cpu.
Vikas Shivappa (2):
x86/intel_rdt/mbm: Fix MBM overflow handler during hot cpu x86/intel_rdt/cqm: Improve limbo list processing
arch/x86/kernel/cpu/intel_rdt.c | 34 ++++- arch/x86/kernel/cpu/intel_rdt.h | 14 +- arch/x86/kernel/cpu/intel_rdt_monitor.c | 213 ++++++++++++++----------------- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 2 +- 4 files changed, 136 insertions(+), 127 deletions(-)
Signature · 1 line
1.9.1
PATCH v4 1/2 x86/intel_rdt/mbm: Fix MBM overflow handler during hot cpu
When a CPU is dying, we cancel the worker and schedule a new worker on a different CPU on the same domain. But if the timer is already about to expire (say 0.99s) then we essentially double the interval.
We modify the hot cpu handling to cancel the delayed work on the dying cpu and run the worker immediately on a different cpu in same domain. We donot flush the worker because the MBM overflow worker reschedules the worker on same CPU and scans the domain->cpu_mask to get the domain pointer.
--- arch/x86/kernel/cpu/intel_rdt.c | 4 ++-- arch/x86/kernel/cpu/intel_rdt.h | 2 +- arch/x86/kernel/cpu/intel_rdt_monitor.c | 4 ++-- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +2 -2
@@ -447,7 +447,7 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)if (is_mbm_enabled ()) {INIT_DELAYED_WORK (&d->mbm_over, mbm_handle_overflow); -mbm_setup_overflow_handler (d); +mbm_setup_overflow_handler (d,MBM_OVERFLOW_INTERVAL ); }return 0 ;
@@ -540,7 +540,7 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) }else if (r == &rdt_resources_all[RDT_RESOURCE_L3 ] && cpu == d->mbm_work_cpu &&is_mbm_enabled ()) {cancel_delayed_work (&d->mbm_over); -mbm_setup_overflow_handler (d); +mbm_setup_overflow_handler (d,0 ); } }
arch/x86/kernel/cpu/intel_rdt.h +1 -1
@@ -422,7 +422,7 @@ void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r, struct rdt_domain *d);void mon_event_read (struct rmid_read *rr,struct rdt_domain *d,struct rdtgroup *rdtgrp,int evtid,int first); -void mbm_setup_overflow_handler (struct rdt_domain *dom); +void mbm_setup_overflow_handler (struct rdt_domain *dom,unsigned long delay_ms);void mbm_handle_overflow (struct work_struct *work);#endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_monitor.c +2 -2
@@ -417,9 +417,9 @@ void mbm_handle_overflow(struct work_struct *work)mutex_unlock (&rdtgroup_mutex); } -void mbm_setup_overflow_handler (struct rdt_domain *dom) +void mbm_setup_overflow_handler (struct rdt_domain *dom,unsigned long delay_ms) { -unsigned long delay =msecs_to_jiffies (MBM_OVERFLOW_INTERVAL ); +unsigned long delay =msecs_to_jiffies (delay_ms);int cpu;if (!static_branch_likely (&rdt_enable_key))
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +1 -1
@@ -1140,7 +1140,7 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,if (is_mbm_enabled ()) { r = &rdt_resources_all[RDT_RESOURCE_L3 ];list_for_each_entry (dom, &r->domains, list) -mbm_setup_overflow_handler (dom); +mbm_setup_overflow_handler (dom,MBM_OVERFLOW_INTERVAL ); } goto out;
Signature · 1 line
1.9.1
Re: [PATCH 1/2] x86/intel_rdt/mbm: Fix MBM overflow handler during hot cpu
Quoted 9 lines · Vikas Shivappa
When a CPU is dying, we cancel the worker and schedule a new worker on a different CPU on the same domain. But if the timer is already about to expire (say 0.99s) then we essentially double the interval.
We modify the hot cpu handling to cancel the delayed work on the dying cpu and run the worker immediately on a different cpu in same domain. We donot flush the worker because the MBM overflow worker reschedules the worker on same CPU and scans the
domain->cpu_maskto get the domain pointer.
You could alternatively use flush and make the worker code schedule the work on a still online CPU in the domain instead of blindly rescheduling it on the same CPU.
Thanks,
tglx
RE: [PATCH 1/2] x86/intel_rdt/mbm: Fix MBM overflow handler during hot cpu
Quoted 3 lines
You could alternatively use flush and make the worker code schedule the work on a still online CPU in the domain instead of blindly rescheduling it on the same CPU.
We looked at that when you suggested flush. The problem is that we have already deleted the current cpu from the bitmask for the domain. So the worker code doesn't know which domain it is running on, so can't pick another.
If we try to do the flush before dropping the cpu from the bitmask, then the worker code doesn't have any reason to pick a different CPU.
Is there is some cheap "I'm running on a CPU that is in the process of going offline" test that we could make in the worker code?
-Tony
RE: [PATCH 1/2] x86/intel_rdt/mbm: Fix MBM overflow handler during hot cpu
Quoted 9 lines · Tony
Quoted 3 lines
You could alternatively use flush and make the worker code schedule the work on a still online CPU in the domain instead of blindly rescheduling it on the same CPU.
We looked at that when you suggested flush. The problem is that we have already deleted the current cpu from the bitmask for the domain. So the worker code doesn't know which domain it is running on, so can't pick another.
Quoted 5 lines
If we try to do the flush before dropping the cpu from the bitmask, then the worker code doesn't have any reason to pick a different CPU.
Is there is some cheap "I'm running on a CPU that is in the process of going offline" test that we could make in the worker code?
Don't think so. It was just a thought, but the code as provided is fine and merged as is.
Thanks,
tglx
tip-bot for Vikas Shivappa
merge bot[tip:x86/cache] x86/intel_rdt/mbm: Fix MBM overflow handler during CPU hotplug
In reply to Vikas Shivappax86/intel_rdt/mbm: Fix MBM overflow handler during CPU hotplug
Commit-ID: bbc4615e0b7df5e21d0991adb4b2798508354924 Gitweb: http://git.kernel.org/tip/bbc4615e0b7df5e21d0991adb4b2798508354924 Author: Vikas Shivappa <[email protected]> AuthorDate: Tue, 15 Aug 2017 18:00:42 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 16 Aug 2017 12:05:41 +0200
x86/intel_rdt/mbm: Fix MBM overflow handler during CPU hotplug
When a CPU is dying, the overflow worker is canceled and rescheduled on a different CPU in the same domain. But if the timer is already about to expire this essentially doubles the interval which might result in a non detected overflow.
Cancel the overflow worker and reschedule it immediately on a different CPU in same domain. The work could be flushed as well, but that would reschedule it on the same CPU.
[ tglx: Rewrote changelog once again ]
--- arch/x86/kernel/cpu/intel_rdt.c | 4 ++-- arch/x86/kernel/cpu/intel_rdt.h | 2 +- arch/x86/kernel/cpu/intel_rdt_monitor.c | 4 ++-- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +2 -2
@@ -447,7 +447,7 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)if (is_mbm_enabled ()) {INIT_DELAYED_WORK (&d->mbm_over, mbm_handle_overflow); -mbm_setup_overflow_handler (d); +mbm_setup_overflow_handler (d,MBM_OVERFLOW_INTERVAL ); }return 0 ;
@@ -540,7 +540,7 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) }else if (r == &rdt_resources_all[RDT_RESOURCE_L3 ] && cpu == d->mbm_work_cpu &&is_mbm_enabled ()) {cancel_delayed_work (&d->mbm_over); -mbm_setup_overflow_handler (d); +mbm_setup_overflow_handler (d,0 ); } }
arch/x86/kernel/cpu/intel_rdt.h +1 -1
@@ -422,7 +422,7 @@ void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r, struct rdt_domain *d);void mon_event_read (struct rmid_read *rr,struct rdt_domain *d,struct rdtgroup *rdtgrp,int evtid,int first); -void mbm_setup_overflow_handler (struct rdt_domain *dom); +void mbm_setup_overflow_handler (struct rdt_domain *dom,unsigned long delay_ms);void mbm_handle_overflow (struct work_struct *work);#endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_monitor.c +2 -2
@@ -417,9 +417,9 @@ out_unlock:mutex_unlock (&rdtgroup_mutex); } -void mbm_setup_overflow_handler (struct rdt_domain *dom) +void mbm_setup_overflow_handler (struct rdt_domain *dom,unsigned long delay_ms) { -unsigned long delay =msecs_to_jiffies (MBM_OVERFLOW_INTERVAL ); +unsigned long delay =msecs_to_jiffies (delay_ms);int cpu;if (!static_branch_likely (&rdt_enable_key))
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +1 -1
@@ -1140,7 +1140,7 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,if (is_mbm_enabled ()) { r = &rdt_resources_all[RDT_RESOURCE_L3 ];list_for_each_entry (dom, &r->domains, list) -mbm_setup_overflow_handler (dom); +mbm_setup_overflow_handler (dom,MBM_OVERFLOW_INTERVAL ); } goto out;
PATCH v4 2/2 x86/intel_rdt/cqm: Improve limbo list processing
In reply to Vikas ShivappaDuring a mkdir, we synchronously check the entire limbo list on each package for free RMIDs by sending IPIs and the worst case would end up taking more than tolerable amount of time in IPIs. For ex: On SKL we could end up reading all 192 RMIDs for llc_occupancy.
Modify this to make some improvements mainly avoiding the use of IPIs. We use asynchronous worker threads on each package which would periodically scan the limbo list and move the RMIDs that have:
llc_occupancy < threshold_occupancy
on all packages to free list. The mkdir would simply return -ENOSPC if the limbo list is empty or would return -EBUSY if there are RMIDs on limbo but not on free list. As a side effect of not accessing the limbo list in parallel on IPIs we simplify some of the related data structures.
--- arch/x86/kernel/cpu/intel_rdt.c | 32 ++++- arch/x86/kernel/cpu/intel_rdt.h | 14 ++- arch/x86/kernel/cpu/intel_rdt_monitor.c | 209 ++++++++++++++------------------ 3 files changed, 132 insertions(+), 123 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +28 -4
@@ -426,6 +426,7 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d) GFP_KERNEL);if (!d->rmid_busy_llc)return -ENOMEM ; +INIT_DELAYED_WORK (&d->cqm_limbo, cqm_handle_limbo); }if (is_mbm_total_enabled ()) { tsize =sizeof (*d->mbm_total);
@@ -536,11 +537,34 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)list_del (&d->list);if (is_mbm_enabled ())cancel_delayed_work (&d->mbm_over); +if (is_llc_occupancy_enabled () && +has_busy_rmid (r, d)) { +/* +* When a package is going down, we forcefully +* decrement rmid->ebusy. There is no way to +* know that the L3 was flushed and hence may +* lead to incorrect counts in rare scenarios, +* but leaving the RMID as busy creates RMID +* leaks if the package never comes back. +*/ +__check_limbo (d, true); +cancel_delayed_work (&d->cqm_limbo); + } +kfree (d); - }else if (r == &rdt_resources_all[RDT_RESOURCE_L3 ] && - cpu == d->mbm_work_cpu &&is_mbm_enabled ()) { -cancel_delayed_work (&d->mbm_over); -mbm_setup_overflow_handler (d,0 ); +return ; + } + +if (r == &rdt_resources_all[RDT_RESOURCE_L3 ]) { +if (is_mbm_enabled () && cpu == d->mbm_work_cpu) { +cancel_delayed_work (&d->mbm_over); +mbm_setup_overflow_handler (d,0 ); + } +if (is_llc_occupancy_enabled () && cpu == d->cqm_work_cpu && +has_busy_rmid (r, d)) { +cancel_delayed_work (&d->cqm_limbo); +cqm_setup_limbo_handler (d,0 ); + } } }
arch/x86/kernel/cpu/intel_rdt.h +13 -1
@@ -20,6 +20,8 @@#define QOS_L3_MBM_TOTAL_EVENT_ID 0x02#define QOS_L3_MBM_LOCAL_EVENT_ID 0x03 +#define CQM_LIMBOCHECK_INTERVAL 1000 +#define MBM_CNTR_WIDTH 24#define MBM_OVERFLOW_INTERVAL 1000
@@ -187,8 +189,11 @@ struct mbm_state {* @mbm_total: saved state for MBM total bandwidth * @mbm_local: saved state for MBM local bandwidth * @mbm_over: worker to periodically read MBM h/w counters +* @cqm_limbo: worker to periodically read CQM h/w counters * @mbm_work_cpu: * worker cpu for MBM h/w counters +* @cqm_work_cpu: +* worker cpu for CQM h/w counters * @ctrl_val: array of cache or mem ctrl values (indexed by CLOSID) * @new_ctrl: new ctrl value to be loaded * @have_new_ctrl: did user provide new_ctrl for this domain
@@ -201,7 +206,9 @@ struct rdt_domain {struct mbm_state *mbm_total;struct mbm_state *mbm_local;struct delayed_work mbm_over; +struct delayed_work cqm_limbo;int mbm_work_cpu; +int cqm_work_cpu;u32 *ctrl_val;u32 new_ctrl;bool have_new_ctrl;
@@ -422,7 +429,12 @@ void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r, struct rdt_domain *d);void mon_event_read (struct rmid_read *rr,struct rdt_domain *d,struct rdtgroup *rdtgrp,int evtid,int first); -void mbm_setup_overflow_handler (struct rdt_domain *dom,unsigned long delay_ms); +void mbm_setup_overflow_handler (struct rdt_domain *dom, +unsigned long delay_ms);void mbm_handle_overflow (struct work_struct *work); +void cqm_setup_limbo_handler (struct rdt_domain *dom,unsigned long delay_ms); +void cqm_handle_limbo (struct work_struct *work); +bool has_busy_rmid (struct rdt_resource *r,struct rdt_domain *d); +void __check_limbo (struct rdt_domain *d,bool force_free);#endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_monitor.c +91 -118
284 lines not on this page · raw message
Signature · 1 line
1.9.1
tip-bot for Vikas Shivappa
merge bot[tip:x86/cache] x86/intel_rdt/cqm: Improve limbo list processing
x86/intel_rdt/cqm: Improve limbo list processing
Commit-ID: 24247aeeabe99eab13b798ccccc2dec066dd6f07 Gitweb: http://git.kernel.org/tip/24247aeeabe99eab13b798ccccc2dec066dd6f07 Author: Vikas Shivappa <[email protected]> AuthorDate: Tue, 15 Aug 2017 18:00:43 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Wed, 16 Aug 2017 12:05:41 +0200
x86/intel_rdt/cqm: Improve limbo list processing
During a mkdir, the entire limbo list is synchronously checked on each package for free RMIDs by sending IPIs. With a large number of RMIDs (SKL has 192) this creates a intolerable amount of work in IPIs.
Replace the IPI based checking of the limbo list with asynchronous worker threads on each package which periodically scan the limbo list and move the RMIDs that have:
llc_occupancy < threshold_occupancy
on all packages to the free list.
mkdir now returns -ENOSPC if the free list and the limbo list ere empty or returns -EBUSY if there are RMIDs on the limbo list and the free list is empty.
Getting rid of the IPIs also simplifies the data structures and the serialization required for handling the lists.
[ tglx: Rewrote changelog ... ]
--- arch/x86/kernel/cpu/intel_rdt.c | 31 ++++- arch/x86/kernel/cpu/intel_rdt.h | 14 ++- arch/x86/kernel/cpu/intel_rdt_monitor.c | 210 ++++++++++++++------------------ 3 files changed, 133 insertions(+), 122 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +27 -4
@@ -426,6 +426,7 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d) GFP_KERNEL);if (!d->rmid_busy_llc)return -ENOMEM ; +INIT_DELAYED_WORK (&d->cqm_limbo, cqm_handle_limbo); }if (is_mbm_total_enabled ()) { tsize =sizeof (*d->mbm_total);
@@ -536,11 +537,33 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)list_del (&d->list);if (is_mbm_enabled ())cancel_delayed_work (&d->mbm_over); +if (is_llc_occupancy_enabled () &&has_busy_rmid (r, d)) { +/* +* When a package is going down, forcefully +* decrement rmid->ebusy. There is no way to know +* that the L3 was flushed and hence may lead to +* incorrect counts in rare scenarios, but leaving +* the RMID as busy creates RMID leaks if the +* package never comes back. +*/ +__check_limbo (d, true); +cancel_delayed_work (&d->cqm_limbo); + } +kfree (d); - }else if (r == &rdt_resources_all[RDT_RESOURCE_L3 ] && - cpu == d->mbm_work_cpu &&is_mbm_enabled ()) { -cancel_delayed_work (&d->mbm_over); -mbm_setup_overflow_handler (d,0 ); +return ; + } + +if (r == &rdt_resources_all[RDT_RESOURCE_L3 ]) { +if (is_mbm_enabled () && cpu == d->mbm_work_cpu) { +cancel_delayed_work (&d->mbm_over); +mbm_setup_overflow_handler (d,0 ); + } +if (is_llc_occupancy_enabled () && cpu == d->cqm_work_cpu && +has_busy_rmid (r, d)) { +cancel_delayed_work (&d->cqm_limbo); +cqm_setup_limbo_handler (d,0 ); + } } }
arch/x86/kernel/cpu/intel_rdt.h +13 -1
@@ -20,6 +20,8 @@#define QOS_L3_MBM_TOTAL_EVENT_ID 0x02#define QOS_L3_MBM_LOCAL_EVENT_ID 0x03 +#define CQM_LIMBOCHECK_INTERVAL 1000 +#define MBM_CNTR_WIDTH 24#define MBM_OVERFLOW_INTERVAL 1000
@@ -187,8 +189,11 @@ struct mbm_state {* @mbm_total: saved state for MBM total bandwidth * @mbm_local: saved state for MBM local bandwidth * @mbm_over: worker to periodically read MBM h/w counters +* @cqm_limbo: worker to periodically read CQM h/w counters * @mbm_work_cpu: * worker cpu for MBM h/w counters +* @cqm_work_cpu: +* worker cpu for CQM h/w counters * @ctrl_val: array of cache or mem ctrl values (indexed by CLOSID) * @new_ctrl: new ctrl value to be loaded * @have_new_ctrl: did user provide new_ctrl for this domain
@@ -201,7 +206,9 @@ struct rdt_domain {struct mbm_state *mbm_total;struct mbm_state *mbm_local;struct delayed_work mbm_over; +struct delayed_work cqm_limbo;int mbm_work_cpu; +int cqm_work_cpu;u32 *ctrl_val;u32 new_ctrl;bool have_new_ctrl;
@@ -422,7 +429,12 @@ void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r, struct rdt_domain *d);void mon_event_read (struct rmid_read *rr,struct rdt_domain *d,struct rdtgroup *rdtgrp,int evtid,int first); -void mbm_setup_overflow_handler (struct rdt_domain *dom,unsigned long delay_ms); +void mbm_setup_overflow_handler (struct rdt_domain *dom, +unsigned long delay_ms);void mbm_handle_overflow (struct work_struct *work); +void cqm_setup_limbo_handler (struct rdt_domain *dom,unsigned long delay_ms); +void cqm_handle_limbo (struct work_struct *work); +bool has_busy_rmid (struct rdt_resource *r,struct rdt_domain *d); +void __check_limbo (struct rdt_domain *d,bool force_free);#endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_monitor.c +93 -117
292 lines not on this page · raw message