[PATCH v10 22/24] x86/resctrl: Update assignments on event configuration changes
From: Babu Moger
Date: Thu Dec 12 2024 - 15:22:16 EST
Resctrl provides option to configure events by writing to the interfaces
/sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config or
/sys/fs/resctrl/info/L3_MON/mbm_local_bytes_config when BMEC (Bandwidth
Monitoring Event Configuration) is supported.
Whenever the event configuration is updated, MBM assignments must be
revised across all monitor groups within the impacted domains.
Signed-off-by: Babu Moger <babu.moger@xxxxxxx>
---
v10: Code changed completely with domain specific counter assignment.
Rewrite the commit message.
Added few more code comments.
v9: Again patch changed completely based on the comment.
https://lore.kernel.org/lkml/03b278b5-6c15-4d09-9ab7-3317e84a409e@xxxxxxxxx/
Introduced resctrl_mon_event_config_set to handle IPI.
But sending another IPI inside IPI causes problem. Kernel reports SMP
warning. So, introduced resctrl_arch_update_cntr() to send the command directly.
v8: Patch changed completely.
Updated the assignment on same IPI as the event is updated.
Could not do the way we discussed in the thread.
https://lore.kernel.org/lkml/f77737ac-d3f6-3e4b-3565-564f79c86ca8@xxxxxxx/
Needed to figure out event type to update the configuration.
v7: New patch to update the assignments. Missed it earlier.
---
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 67 ++++++++++++++++++++++----
include/linux/resctrl.h | 4 +-
2 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index 65b3556978ad..6b5c886b7e99 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -1704,26 +1704,26 @@ u32 resctrl_arch_mon_event_config_get(struct rdt_mon_domain *d,
return INVALID_CONFIG_VALUE;
}
-void resctrl_arch_mon_event_config_set(void *info)
+void resctrl_arch_mon_event_config_set(struct rdt_mon_domain *d,
+ enum resctrl_event_id eventid, u32 val)
{
- struct mon_config_info *mon_info = info;
struct rdt_hw_mon_domain *hw_dom;
unsigned int index;
- index = mon_event_config_index_get(mon_info->evtid);
+ index = mon_event_config_index_get(eventid);
if (index == INVALID_CONFIG_INDEX)
return;
- wrmsr(MSR_IA32_EVT_CFG_BASE + index, mon_info->mon_config, 0);
+ wrmsr(MSR_IA32_EVT_CFG_BASE + index, val, 0);
- hw_dom = resctrl_to_arch_mon_dom(mon_info->d);
+ hw_dom = resctrl_to_arch_mon_dom(d);
- switch (mon_info->evtid) {
+ switch (eventid) {
case QOS_L3_MBM_TOTAL_EVENT_ID:
- hw_dom->mbm_total_cfg = mon_info->mon_config;
+ hw_dom->mbm_total_cfg = val;
break;
case QOS_L3_MBM_LOCAL_EVENT_ID:
- hw_dom->mbm_local_cfg = mon_info->mon_config;
+ hw_dom->mbm_local_cfg = val;
break;
default:
break;
@@ -1825,6 +1825,54 @@ static int mbm_local_bytes_config_show(struct kernfs_open_file *of,
return 0;
}
+/*
+ * Review the cntr_cfg domain configuration. If a matching assignment is found,
+ * update the counter assignment accordingly. This is within the IPI Context,
+ * so call resctrl_abmc_config_one_amd directly.
+ */
+static void resctrl_arch_update_cntr(struct rdt_resource *r, struct rdt_mon_domain *d,
+ enum resctrl_event_id evtid, u32 val)
+{
+ struct cntr_config config;
+ struct rdtgroup *rdtgrp;
+ struct mbm_state *m;
+ u32 cntr_id;
+
+ for (cntr_id = 0; cntr_id < r->mon.num_mbm_cntrs; cntr_id++) {
+ rdtgrp = d->cntr_cfg[cntr_id].rdtgrp;
+ if (rdtgrp && d->cntr_cfg[cntr_id].evtid == evtid) {
+ memset(&config, 0, sizeof(struct cntr_config));
+ config.r = r;
+ config.d = d;
+ config.evtid = evtid;
+ config.rmid = rdtgrp->mon.rmid;
+ config.closid = rdtgrp->closid;
+ config.cntr_id = cntr_id;
+ config.val = val;
+ config.assign = 1;
+
+ resctrl_abmc_config_one_amd(&config);
+
+ m = get_mbm_state(d, rdtgrp->closid, rdtgrp->mon.rmid, evtid);
+ if (m)
+ memset(m, 0, sizeof(struct mbm_state));
+ }
+ }
+}
+
+static void resctrl_mon_event_config_set(void *info)
+{
+ struct mon_config_info *mon_info = info;
+ struct rdt_mon_domain *d = mon_info->d;
+ struct rdt_resource *r = mon_info->r;
+
+ resctrl_arch_mon_event_config_set(d, mon_info->evtid, mon_info->mon_config);
+
+ /* Check if assignments needs to be updated */
+ if (resctrl_arch_mbm_cntr_assign_enabled(r))
+ resctrl_arch_update_cntr(r, d, mon_info->evtid,
+ mon_info->mon_config);
+}
static void mbm_config_write_domain(struct rdt_resource *r,
struct rdt_mon_domain *d, u32 evtid, u32 val)
@@ -1840,6 +1888,7 @@ static void mbm_config_write_domain(struct rdt_resource *r,
if (config_val == INVALID_CONFIG_VALUE || config_val == val)
return;
+ mon_info.r = r;
mon_info.d = d;
mon_info.evtid = evtid;
mon_info.mon_config = val;
@@ -1851,7 +1900,7 @@ static void mbm_config_write_domain(struct rdt_resource *r,
* on one CPU is observed by all the CPUs in the domain.
*/
smp_call_function_any(&d->hdr.cpu_mask,
- resctrl_arch_mon_event_config_set,
+ resctrl_mon_event_config_set,
&mon_info, 1);
/*
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 03c67d9156f3..2bf461179680 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -137,6 +137,7 @@ struct rdt_mon_domain {
* @mon_config: Event configuration value
*/
struct mon_config_info {
+ struct rdt_resource *r;
struct rdt_mon_domain *d;
enum resctrl_event_id evtid;
u32 mon_config;
@@ -376,7 +377,8 @@ void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_mon_domain *d,
*/
void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain *d);
-void resctrl_arch_mon_event_config_set(void *info);
+void resctrl_arch_mon_event_config_set(struct rdt_mon_domain *d,
+ enum resctrl_event_id eventid, u32 val);
u32 resctrl_arch_mon_event_config_get(struct rdt_mon_domain *d,
enum resctrl_event_id eventid);
--
2.34.1