[PATCH v2 17/17] x86/resctrl: Update RMID assignments on event configuration changes

From: Babu Moger
Date: Fri Jan 19 2024 - 13:27:18 EST


When ABMC (Assignable Bandwidth Monitoring Counters) feature is enabled,
bandwidth events can be read in following methods.

1. The contents of a specific counter can be read by setting the following
fields in QM_EVTSEL: [ExtendedEvtID]=1, [EvtID]=L3CacheABMC and setting
[RMID] to the desired counter ID. Reading QM_CTR will then return the
contents of the specified counter. The E bit will be set if the counter
configuration was invalid, or if an invalid counter ID was set in the
QM_EVTSEL[RMID] field. The rmid_read interface (resctrl_arch_rmid_read)
does not support this method currently. Supporting this method will
require changes in rmid_read interface.

2. Alternatively, the contents of a counter may be read by specifying an
RMID and setting the [EvtID] to L3BWMonEvtn where n= {0,1}. If an
assignable bandwidth counter is monitoring that RMID with a BwType bitmask
that matches a QOS_EVT_CFG_n, that counter’s value will be returned when
reading QM_CTR. However, if multiple counters have the same configuration,
QM_CTR will return the value of the counter with the lowest CtrID.

Method 2 can be supported without any changes to rmid_read interface.
However, this requires the contents of the MSR QOS_EVT_CFG_[0,1] to match
the BwType while assigning total and local events respectively. So,
whenever event configuration changes, the ABMC assignment needs to be
updated to match the event configuration.

The feature details are documented in APM listed below [1].
[1] AMD64 Architecture Programmer's Manual Volume 2: System Programming
Publication # 24593 Revision 3.41 section 19.3.3.3 Assignable Bandwidth
Monitoring (ABMC).

Signed-off-by: Babu Moger <babu.moger@xxxxxxx>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537
---
v2: Minor text changes.
---
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 40 ++++++++++++++++++++++++++
1 file changed, 40 insertions(+)

diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index 869fab878087..91a20e601ffd 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -1828,6 +1828,38 @@ static ssize_t rdtgroup_monitor_state_write(struct kernfs_open_file *of,
return ret ?: nbytes;
}

+static void rdtgroup_update_abmc(struct rdt_resource *r,
+ struct rdt_domain *d, u32 evtid)
+{
+ struct rdtgroup *prgrp, *crgrp;
+ int index, mon_state;
+
+ if (evtid == QOS_L3_MBM_TOTAL_EVENT_ID)
+ mon_state = TOTAL_ASSIGN;
+ else
+ mon_state = LOCAL_ASSIGN;
+
+ index = mon_event_config_index_get(evtid);
+ if (index == INVALID_CONFIG_INDEX) {
+ pr_warn_once("Invalid event id %d\n", evtid);
+ return;
+ }
+
+ /*
+ * Update the assignment for all the monitor groups if the group
+ * is configured with ABMC assignment.
+ */
+ list_for_each_entry(prgrp, &rdt_all_groups, rdtgroup_list) {
+ if (prgrp->mon.monitor_state & mon_state)
+ rdtgroup_abmc_domain(d, prgrp, evtid, index, 1);
+
+ list_for_each_entry(crgrp, &prgrp->mon.crdtgrp_list, mon.crdtgrp_list) {
+ if (crgrp->mon.monitor_state & mon_state)
+ rdtgroup_abmc_domain(d, crgrp, evtid, index, 1);
+ }
+ }
+}
+
static void mon_event_config_read(void *info)
{
struct mon_config_info *mon_info = info;
@@ -1912,6 +1944,7 @@ static void mon_event_config_write(void *info)
static int mbm_config_write_domain(struct rdt_resource *r,
struct rdt_domain *d, u32 evtid, u32 val)
{
+ struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
struct mon_config_info mon_info = {0};
int ret = 0;
@@ -1952,6 +1985,13 @@ static int mbm_config_write_domain(struct rdt_resource *r,
else
goto out;

+ /*
+ * Event configuration changed for the domain, so Update
+ * the ABMC assignment.
+ */
+ if (hw_res->abmc_enabled)
+ rdtgroup_update_abmc(r, d, evtid);
+
/*
* When an Event Configuration is changed, the bandwidth counters
* for all RMIDs and Events will be cleared by the hardware. The
--
2.34.1