[PATCH v5 14/20] x86/resctrl: Add the interface to unassign hardware counter

Babu Moger
2024-07-03T21:50:39Z

The ABMC feature provides an option to the user to assign a hardware
counter to an RMID and monitor the bandwidth as long as it is assigned.
The assigned RMID will be tracked by the hardware until the user unassigns
it manually.

Hardware provides only limited number of counters. If the system runs out
of assignable counters, kernel will display an error when a new assignment
is requested. Users need to unassign a already assigned counter to make
space for new assignment.

Provide the interface to unassign the counter ids from the group.

The feature details are documented in the 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@amd.com>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537
---
v5: Few name changes to match cntr_id.
Changed the function names to
rdtgroup_unassign_cntr
More comments on commit log.

v4: Added domain specific unassign feature.
Few name changes.

v3: Removed the static from the prototype of rdtgroup_unassign_abmc.
The function is not called directly from user anymore. These
changes are related to global assignment interface.

v2: No changes.
---
arch/x86/kernel/cpu/resctrl/internal.h | 2 ++
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 33 ++++++++++++++++++++++++++
2 files changed, 35 insertions(+)

diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index 66460375056c..beb005775fe4 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -711,6 +711,8 @@ unsigned int mon_event_config_index_get(u32 evtid);
int resctrl_arch_assign_cntr(struct rdt_mon_domain *d, u32 evtid, u32 rmid,
u32 cntr_id, u32 closid, bool enable);
int rdtgroup_assign_cntr(struct rdtgroup *rdtgrp, u32 evtid);
+int rdtgroup_unassign_cntr(struct rdtgroup *rdtgrp, u32 evtid);
+void mbm_cntr_free(u32 cntr_id);
void rdt_staged_configs_clear(void);
bool closid_allocated(unsigned int closid);
int resctrl_find_cleanest_closid(void);
diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index 44f6eff42c30..ffde30b36c1a 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -215,6 +215,11 @@ static int mbm_cntr_alloc(void)
return cntr_id;
}

+void mbm_cntr_free(u32 cntr_id)
+{
+ __set_bit(cntr_id, &mbm_cntrs_free_map);
+}
+
/**
* rdtgroup_mode_by_closid - Return mode of resource group with closid
* @closid: closid if the resource group
@@ -1956,6 +1961,34 @@ int rdtgroup_assign_cntr(struct rdtgroup *rdtgrp, u32 evtid)
return 0;
}

+/* Unassign a hardware counter id from the group. */
+int rdtgroup_unassign_cntr(struct rdtgroup *rdtgrp, u32 evtid)
+{
+ struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
+ struct rdt_mon_domain *d;
+ int index;
+
+ index = mon_event_config_index_get(evtid);
+ if (index == INVALID_CONFIG_INDEX) {
+ pr_warn_once("Invalid event id %d\n", evtid);
+ return -EINVAL;
+ }
+
+ if (rdtgrp->mon.cntr_id[index] != MON_CNTR_UNSET) {
+ list_for_each_entry(d, &r->mon_domains, hdr.list)
+ resctrl_arch_assign_cntr(d, evtid,
+ rdtgrp->mon.rmid,
+ rdtgrp->mon.cntr_id[index],
+ rdtgrp->closid, 0);
+
+ /* Update the counter bitmap */
+ mbm_cntr_free(rdtgrp->mon.cntr_id[index]);
+ rdtgrp->mon.cntr_id[index] = MON_CNTR_UNSET;
+ }
+
+ return 0;
+}
+
/* rdtgroup information files for one cache resource. */
static struct rftype res_common_files[] = {
{
--
2.34.1