Hi Babu, On 7/8/25 3:17 PM, Babu Moger wrote: > When "mbm_event" counter assignment mode is supported, users can modify > the event configuration by writing to the 'event_filter' resctrl file. > The event configurations for mbm_event mode are located in > /sys/fs/resctrl/info/L3_MON/event_configs/. > > Update the assignments of all CTRL_MON and MON resource groups when the > event configuration is modified. > > Example: > $ mount -t resctrl resctrl /sys/fs/resctrl > > $ cd /sys/fs/resctrl/ > > $ cat info/L3_MON/event_configs/mbm_local_bytes/event_filter > local_reads,local_non_temporal_writes,local_reads_slow_memory > > $ echo "local_reads,local_non_temporal_writes" > > info/L3_MON/event_configs/mbm_total_bytes/event_filter > > $ cat info/L3_MON/event_configs/mbm_total_bytes/event_filter > local_reads,local_non_temporal_writes > > Signed-off-by: Babu Moger <babu.moger@xxxxxxx> > --- ... > --- > Documentation/filesystems/resctrl.rst | 12 +++++ > fs/resctrl/internal.h | 1 + > fs/resctrl/monitor.c | 44 ++++++++++++++++ > fs/resctrl/rdtgroup.c | 74 ++++++++++++++++++++++++++- > 4 files changed, 130 insertions(+), 1 deletion(-) > > diff --git a/Documentation/filesystems/resctrl.rst b/Documentation/filesystems/resctrl.rst > index 57fd12f0aeca..06c8c08d0341 100644 > --- a/Documentation/filesystems/resctrl.rst > +++ b/Documentation/filesystems/resctrl.rst > @@ -342,6 +342,18 @@ with the following files: > # cat /sys/fs/resctrl/info/L3_MON/event_configs/mbm_local_bytes/event_filter > local_reads,local_non_temporal_writes,local_reads_slow_memory > > + Modify the event configuration by writing to the "event_filter" file within > + the "event_configs" directory. The read/write "event_filter" file contains the > + configuration of the event that reflects which memory transactions are counted by it. > + > + For example:: > + > + # echo "local_reads, local_non_temporal_writes" > > + /sys/fs/resctrl/info/L3_MON/event_configs/mbm_total_bytes/event_filter > + > + # cat /sys/fs/resctrl/info/L3_MON/event_configs/mbm_total_bytes/event_filter > + local_reads,local_non_temporal_writes > + > "max_threshold_occupancy": > Read/write file provides the largest value (in > bytes) at which a previously used LLC_occupancy > diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h > index b107874407b2..b42890fd937a 100644 > --- a/fs/resctrl/internal.h > +++ b/fs/resctrl/internal.h > @@ -409,6 +409,7 @@ void rdtgroup_unassign_cntr_event(struct rdt_mon_domain *d, struct rdtgroup *rdt > struct mon_evt *mevt); > int mbm_cntr_get(struct rdt_resource *r, struct rdt_mon_domain *d, > struct rdtgroup *rdtgrp, enum resctrl_event_id evtid); > +void resctrl_update_cntr_allrdtgrp(struct mon_evt *mevt); > > #ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK > int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp); > diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c > index 787dce934903..0722e72f6cb1 100644 > --- a/fs/resctrl/monitor.c > +++ b/fs/resctrl/monitor.c > @@ -1173,3 +1173,47 @@ void rdtgroup_unassign_cntr_event(struct rdt_mon_domain *d, struct rdtgroup *rdt > rdtgroup_free_config_cntr(r, d, rdtgrp, mevt->evtid); > } > } > + > +/* > + * rdtgroup_update_cntr_event - Update the counter assignments for the event > + * in a group. > + * @r: Resource to which update needs to be done. > + * @rdtgrp: Resctrl group. > + * @mevt: MBM monitor event. @mevt needs update match actual parameter > + */ > +static void rdtgroup_update_cntr_event(struct rdt_resource *r, struct rdtgroup *rdtgrp, > + enum resctrl_event_id evtid) > +{ > + struct rdt_mon_domain *d; > + int cntr_id; > + > + list_for_each_entry(d, &r->mon_domains, hdr.list) { > + cntr_id = mbm_cntr_get(r, d, rdtgrp, evtid); > + if (cntr_id >= 0) > + resctrl_arch_config_cntr(r, d, evtid, rdtgrp->mon.rmid, > + rdtgrp->closid, cntr_id, true); > + } > +} > + > +/* > + * resctrl_update_cntr_allrdtgrp - Update the counter assignments for the event > + * for all the groups. > + * @r: Resource to which update needs to be done. @r no longer a parameter > + * @mevt MBM Monitor event. > + */ > +void resctrl_update_cntr_allrdtgrp(struct mon_evt *mevt) > +{ > + struct rdt_resource *r = resctrl_arch_get_resource(mevt->rid); > + struct rdtgroup *prgrp, *crgrp; > + > + /* > + * Find all the groups where the event is assigned and update > + * the assignment "update the assignment" -> "update the configuration of existing assignments" ? > + */ > + list_for_each_entry(prgrp, &rdt_all_groups, rdtgroup_list) { > + rdtgroup_update_cntr_event(r, prgrp, mevt->evtid); > + > + list_for_each_entry(crgrp, &prgrp->mon.crdtgrp_list, mon.crdtgrp_list) > + rdtgroup_update_cntr_event(r, crgrp, mevt->evtid); > + } > +} > diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c > index bb28ef7e4600..4889e7556cc7 100644 > --- a/fs/resctrl/rdtgroup.c > +++ b/fs/resctrl/rdtgroup.c > @@ -1916,6 +1916,77 @@ static int event_filter_show(struct kernfs_open_file *of, struct seq_file *seq, > return 0; > } > > +static int resctrl_process_configs(char *tok, u32 *val) Please move to monitor.c and give more specific name. Perhaps resctrl_parse_mem_transactions()? Open to ideas. > +{ > + u32 temp_val = 0; > + char *evt_str; > + bool found; > + int i; > + > +next_config: > + if (!tok || tok[0] == '\0') { > + *val = temp_val; > + return 0; > + } > + > + /* Start processing the strings for each memory transaction type */ > + evt_str = strim(strsep(&tok, ",")); > + found = false; > + for (i = 0; i < NUM_MBM_TRANSACTIONS; i++) { > + if (!strcmp(mbm_transactions[i].name, evt_str)) { > + temp_val |= mbm_transactions[i].val; > + found = true; > + break; > + } > + } > + > + if (!found) { > + rdt_last_cmd_printf("Invalid memory transaction type %s\n", evt_str); > + return -EINVAL; > + } > + > + goto next_config; > +} > + > +static ssize_t event_filter_write(struct kernfs_open_file *of, char *buf, > + size_t nbytes, loff_t off) > +{ > + struct mon_evt *mevt = rdt_kn_parent_priv(of->kn); > + struct rdt_resource *r; > + u32 evt_cfg = 0; > + int ret = 0; > + > + /* Valid input requires a trailing newline */ > + if (nbytes == 0 || buf[nbytes - 1] != '\n') > + return -EINVAL; > + > + buf[nbytes - 1] = '\0'; > + > + cpus_read_lock(); > + mutex_lock(&rdtgroup_mutex); > + > + rdt_last_cmd_clear(); > + > + r = resctrl_arch_get_resource(mevt->rid); > + if (!resctrl_arch_mbm_cntr_assign_enabled(r)) { > + rdt_last_cmd_puts("mbm_event counter assignment mode is not enabled\n"); > + ret = -EINVAL; > + goto out_unlock; > + } > + > + ret = resctrl_process_configs(buf, &evt_cfg); > + if (!ret && mevt->evt_cfg != evt_cfg) { > + mevt->evt_cfg = evt_cfg; > + resctrl_update_cntr_allrdtgrp(mevt); > + } > + > +out_unlock: > + mutex_unlock(&rdtgroup_mutex); > + cpus_read_unlock(); > + > + return ret ?: nbytes; > +} > + > /* rdtgroup information files for one cache resource. */ > static struct rftype res_common_files[] = { > { > @@ -2042,9 +2113,10 @@ static struct rftype res_common_files[] = { > }, > { > .name = "event_filter", > - .mode = 0444, > + .mode = 0644, > .kf_ops = &rdtgroup_kf_single_ops, > .seq_show = event_filter_show, > + .write = event_filter_write, > }, > { > .name = "mbm_assign_mode", Reinette