mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 23:46:49 +08:00
fs/resctrl: Add the functionality to assign MBM events
When supported, "mbm_event" counter assignment mode offers "num_mbm_cntrs" number of counters that can be assigned to RMID, event pairs and monitor bandwidth usage as long as it is assigned. Add the functionality to allocate and assign a counter to an RMID, event pair in the domain. Also, add the helper rdtgroup_assign_cntrs() to assign counters in the group. Log the error message "Failed to allocate counter for <event> in domain <id>" in /sys/fs/resctrl/info/last_cmd_status if all the counters are in use. Exit on the first failure when assigning counters across all the domains. Signed-off-by: Babu Moger <babu.moger@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Link: https://lore.kernel.org/cover.1757108044.git.babu.moger@amd.com
This commit is contained in:
committed by
Borislav Petkov (AMD)
parent
f7a4fb2231
commit
bd85310efd
@@ -396,6 +396,8 @@ int resctrl_num_mbm_cntrs_show(struct kernfs_open_file *of, struct seq_file *s,
|
||||
int resctrl_available_mbm_cntrs_show(struct kernfs_open_file *of, struct seq_file *s,
|
||||
void *v);
|
||||
|
||||
void rdtgroup_assign_cntrs(struct rdtgroup *rdtgrp);
|
||||
|
||||
#ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK
|
||||
int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
|
||||
|
||||
|
||||
@@ -356,6 +356,55 @@ static struct mbm_state *get_mbm_state(struct rdt_mon_domain *d, u32 closid,
|
||||
return state ? &state[idx] : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* mbm_cntr_get() - Return the counter ID for the matching @evtid and @rdtgrp.
|
||||
*
|
||||
* Return:
|
||||
* Valid counter ID on success, or -ENOENT on failure.
|
||||
*/
|
||||
static int mbm_cntr_get(struct rdt_resource *r, struct rdt_mon_domain *d,
|
||||
struct rdtgroup *rdtgrp, enum resctrl_event_id evtid)
|
||||
{
|
||||
int cntr_id;
|
||||
|
||||
if (!r->mon.mbm_cntr_assignable)
|
||||
return -ENOENT;
|
||||
|
||||
if (!resctrl_is_mbm_event(evtid))
|
||||
return -ENOENT;
|
||||
|
||||
for (cntr_id = 0; cntr_id < r->mon.num_mbm_cntrs; cntr_id++) {
|
||||
if (d->cntr_cfg[cntr_id].rdtgrp == rdtgrp &&
|
||||
d->cntr_cfg[cntr_id].evtid == evtid)
|
||||
return cntr_id;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* mbm_cntr_alloc() - Initialize and return a new counter ID in the domain @d.
|
||||
* Caller must ensure that the specified event is not assigned already.
|
||||
*
|
||||
* Return:
|
||||
* Valid counter ID on success, or -ENOSPC on failure.
|
||||
*/
|
||||
static int mbm_cntr_alloc(struct rdt_resource *r, struct rdt_mon_domain *d,
|
||||
struct rdtgroup *rdtgrp, enum resctrl_event_id evtid)
|
||||
{
|
||||
int cntr_id;
|
||||
|
||||
for (cntr_id = 0; cntr_id < r->mon.num_mbm_cntrs; cntr_id++) {
|
||||
if (!d->cntr_cfg[cntr_id].rdtgrp) {
|
||||
d->cntr_cfg[cntr_id].rdtgrp = rdtgrp;
|
||||
d->cntr_cfg[cntr_id].evtid = evtid;
|
||||
return cntr_id;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
static int __mon_event_count(u32 closid, u32 rmid, struct rmid_read *rr)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
@@ -887,6 +936,113 @@ u32 resctrl_get_mon_evt_cfg(enum resctrl_event_id evtid)
|
||||
return mon_event_all[evtid].evt_cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* rdtgroup_assign_cntr() - Assign/unassign the counter ID for the event, RMID
|
||||
* pair in the domain.
|
||||
*
|
||||
* Assign the counter if @assign is true else unassign the counter. Reset the
|
||||
* associated non-architectural state.
|
||||
*/
|
||||
static void rdtgroup_assign_cntr(struct rdt_resource *r, struct rdt_mon_domain *d,
|
||||
enum resctrl_event_id evtid, u32 rmid, u32 closid,
|
||||
u32 cntr_id, bool assign)
|
||||
{
|
||||
struct mbm_state *m;
|
||||
|
||||
resctrl_arch_config_cntr(r, d, evtid, rmid, closid, cntr_id, assign);
|
||||
|
||||
m = get_mbm_state(d, closid, rmid, evtid);
|
||||
if (m)
|
||||
memset(m, 0, sizeof(*m));
|
||||
}
|
||||
|
||||
/*
|
||||
* rdtgroup_alloc_assign_cntr() - Allocate a counter ID and assign it to the event
|
||||
* pointed to by @mevt and the resctrl group @rdtgrp within the domain @d.
|
||||
*
|
||||
* Return:
|
||||
* 0 on success, < 0 on failure.
|
||||
*/
|
||||
static int rdtgroup_alloc_assign_cntr(struct rdt_resource *r, struct rdt_mon_domain *d,
|
||||
struct rdtgroup *rdtgrp, struct mon_evt *mevt)
|
||||
{
|
||||
int cntr_id;
|
||||
|
||||
/* No action required if the counter is assigned already. */
|
||||
cntr_id = mbm_cntr_get(r, d, rdtgrp, mevt->evtid);
|
||||
if (cntr_id >= 0)
|
||||
return 0;
|
||||
|
||||
cntr_id = mbm_cntr_alloc(r, d, rdtgrp, mevt->evtid);
|
||||
if (cntr_id < 0) {
|
||||
rdt_last_cmd_printf("Failed to allocate counter for %s in domain %d\n",
|
||||
mevt->name, d->hdr.id);
|
||||
return cntr_id;
|
||||
}
|
||||
|
||||
rdtgroup_assign_cntr(r, d, mevt->evtid, rdtgrp->mon.rmid, rdtgrp->closid, cntr_id, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* rdtgroup_assign_cntr_event() - Assign a hardware counter for the event in
|
||||
* @mevt to the resctrl group @rdtgrp. Assign counters to all domains if @d is
|
||||
* NULL; otherwise, assign the counter to the specified domain @d.
|
||||
*
|
||||
* If all counters in a domain are already in use, rdtgroup_alloc_assign_cntr()
|
||||
* will fail. The assignment process will abort at the first failure encountered
|
||||
* during domain traversal, which may result in the event being only partially
|
||||
* assigned.
|
||||
*
|
||||
* Return:
|
||||
* 0 on success, < 0 on failure.
|
||||
*/
|
||||
static int rdtgroup_assign_cntr_event(struct rdt_mon_domain *d, struct rdtgroup *rdtgrp,
|
||||
struct mon_evt *mevt)
|
||||
{
|
||||
struct rdt_resource *r = resctrl_arch_get_resource(mevt->rid);
|
||||
int ret = 0;
|
||||
|
||||
if (!d) {
|
||||
list_for_each_entry(d, &r->mon_domains, hdr.list) {
|
||||
ret = rdtgroup_alloc_assign_cntr(r, d, rdtgrp, mevt);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = rdtgroup_alloc_assign_cntr(r, d, rdtgrp, mevt);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* rdtgroup_assign_cntrs() - Assign counters to MBM events. Called when
|
||||
* a new group is created.
|
||||
*
|
||||
* Each group can accommodate two counters per domain: one for the total
|
||||
* event and one for the local event. Assignments may fail due to the limited
|
||||
* number of counters. However, it is not necessary to fail the group creation
|
||||
* and thus no failure is returned. Users have the option to modify the
|
||||
* counter assignments after the group has been created.
|
||||
*/
|
||||
void rdtgroup_assign_cntrs(struct rdtgroup *rdtgrp)
|
||||
{
|
||||
struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
|
||||
|
||||
if (!r->mon_capable || !resctrl_arch_mbm_cntr_assign_enabled(r))
|
||||
return;
|
||||
|
||||
if (resctrl_is_mon_event_enabled(QOS_L3_MBM_TOTAL_EVENT_ID))
|
||||
rdtgroup_assign_cntr_event(NULL, rdtgrp,
|
||||
&mon_event_all[QOS_L3_MBM_TOTAL_EVENT_ID]);
|
||||
|
||||
if (resctrl_is_mon_event_enabled(QOS_L3_MBM_LOCAL_EVENT_ID))
|
||||
rdtgroup_assign_cntr_event(NULL, rdtgrp,
|
||||
&mon_event_all[QOS_L3_MBM_LOCAL_EVENT_ID]);
|
||||
}
|
||||
|
||||
int resctrl_mbm_assign_mode_show(struct kernfs_open_file *of,
|
||||
struct seq_file *s, void *v)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user