Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Babu Moger and committed by
Borislav Petkov (AMD)
bd85310e f7a4fb22

+158
+2
fs/resctrl/internal.h
··· 396 396 int resctrl_available_mbm_cntrs_show(struct kernfs_open_file *of, struct seq_file *s, 397 397 void *v); 398 398 399 + void rdtgroup_assign_cntrs(struct rdtgroup *rdtgrp); 400 + 399 401 #ifdef CONFIG_RESCTRL_FS_PSEUDO_LOCK 400 402 int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp); 401 403
+156
fs/resctrl/monitor.c
··· 356 356 return state ? &state[idx] : NULL; 357 357 } 358 358 359 + /* 360 + * mbm_cntr_get() - Return the counter ID for the matching @evtid and @rdtgrp. 361 + * 362 + * Return: 363 + * Valid counter ID on success, or -ENOENT on failure. 364 + */ 365 + static int mbm_cntr_get(struct rdt_resource *r, struct rdt_mon_domain *d, 366 + struct rdtgroup *rdtgrp, enum resctrl_event_id evtid) 367 + { 368 + int cntr_id; 369 + 370 + if (!r->mon.mbm_cntr_assignable) 371 + return -ENOENT; 372 + 373 + if (!resctrl_is_mbm_event(evtid)) 374 + return -ENOENT; 375 + 376 + for (cntr_id = 0; cntr_id < r->mon.num_mbm_cntrs; cntr_id++) { 377 + if (d->cntr_cfg[cntr_id].rdtgrp == rdtgrp && 378 + d->cntr_cfg[cntr_id].evtid == evtid) 379 + return cntr_id; 380 + } 381 + 382 + return -ENOENT; 383 + } 384 + 385 + /* 386 + * mbm_cntr_alloc() - Initialize and return a new counter ID in the domain @d. 387 + * Caller must ensure that the specified event is not assigned already. 388 + * 389 + * Return: 390 + * Valid counter ID on success, or -ENOSPC on failure. 391 + */ 392 + static int mbm_cntr_alloc(struct rdt_resource *r, struct rdt_mon_domain *d, 393 + struct rdtgroup *rdtgrp, enum resctrl_event_id evtid) 394 + { 395 + int cntr_id; 396 + 397 + for (cntr_id = 0; cntr_id < r->mon.num_mbm_cntrs; cntr_id++) { 398 + if (!d->cntr_cfg[cntr_id].rdtgrp) { 399 + d->cntr_cfg[cntr_id].rdtgrp = rdtgrp; 400 + d->cntr_cfg[cntr_id].evtid = evtid; 401 + return cntr_id; 402 + } 403 + } 404 + 405 + return -ENOSPC; 406 + } 407 + 359 408 static int __mon_event_count(u32 closid, u32 rmid, struct rmid_read *rr) 360 409 { 361 410 int cpu = smp_processor_id(); ··· 934 885 u32 resctrl_get_mon_evt_cfg(enum resctrl_event_id evtid) 935 886 { 936 887 return mon_event_all[evtid].evt_cfg; 888 + } 889 + 890 + /* 891 + * rdtgroup_assign_cntr() - Assign/unassign the counter ID for the event, RMID 892 + * pair in the domain. 893 + * 894 + * Assign the counter if @assign is true else unassign the counter. Reset the 895 + * associated non-architectural state. 896 + */ 897 + static void rdtgroup_assign_cntr(struct rdt_resource *r, struct rdt_mon_domain *d, 898 + enum resctrl_event_id evtid, u32 rmid, u32 closid, 899 + u32 cntr_id, bool assign) 900 + { 901 + struct mbm_state *m; 902 + 903 + resctrl_arch_config_cntr(r, d, evtid, rmid, closid, cntr_id, assign); 904 + 905 + m = get_mbm_state(d, closid, rmid, evtid); 906 + if (m) 907 + memset(m, 0, sizeof(*m)); 908 + } 909 + 910 + /* 911 + * rdtgroup_alloc_assign_cntr() - Allocate a counter ID and assign it to the event 912 + * pointed to by @mevt and the resctrl group @rdtgrp within the domain @d. 913 + * 914 + * Return: 915 + * 0 on success, < 0 on failure. 916 + */ 917 + static int rdtgroup_alloc_assign_cntr(struct rdt_resource *r, struct rdt_mon_domain *d, 918 + struct rdtgroup *rdtgrp, struct mon_evt *mevt) 919 + { 920 + int cntr_id; 921 + 922 + /* No action required if the counter is assigned already. */ 923 + cntr_id = mbm_cntr_get(r, d, rdtgrp, mevt->evtid); 924 + if (cntr_id >= 0) 925 + return 0; 926 + 927 + cntr_id = mbm_cntr_alloc(r, d, rdtgrp, mevt->evtid); 928 + if (cntr_id < 0) { 929 + rdt_last_cmd_printf("Failed to allocate counter for %s in domain %d\n", 930 + mevt->name, d->hdr.id); 931 + return cntr_id; 932 + } 933 + 934 + rdtgroup_assign_cntr(r, d, mevt->evtid, rdtgrp->mon.rmid, rdtgrp->closid, cntr_id, true); 935 + 936 + return 0; 937 + } 938 + 939 + /* 940 + * rdtgroup_assign_cntr_event() - Assign a hardware counter for the event in 941 + * @mevt to the resctrl group @rdtgrp. Assign counters to all domains if @d is 942 + * NULL; otherwise, assign the counter to the specified domain @d. 943 + * 944 + * If all counters in a domain are already in use, rdtgroup_alloc_assign_cntr() 945 + * will fail. The assignment process will abort at the first failure encountered 946 + * during domain traversal, which may result in the event being only partially 947 + * assigned. 948 + * 949 + * Return: 950 + * 0 on success, < 0 on failure. 951 + */ 952 + static int rdtgroup_assign_cntr_event(struct rdt_mon_domain *d, struct rdtgroup *rdtgrp, 953 + struct mon_evt *mevt) 954 + { 955 + struct rdt_resource *r = resctrl_arch_get_resource(mevt->rid); 956 + int ret = 0; 957 + 958 + if (!d) { 959 + list_for_each_entry(d, &r->mon_domains, hdr.list) { 960 + ret = rdtgroup_alloc_assign_cntr(r, d, rdtgrp, mevt); 961 + if (ret) 962 + return ret; 963 + } 964 + } else { 965 + ret = rdtgroup_alloc_assign_cntr(r, d, rdtgrp, mevt); 966 + } 967 + 968 + return ret; 969 + } 970 + 971 + /* 972 + * rdtgroup_assign_cntrs() - Assign counters to MBM events. Called when 973 + * a new group is created. 974 + * 975 + * Each group can accommodate two counters per domain: one for the total 976 + * event and one for the local event. Assignments may fail due to the limited 977 + * number of counters. However, it is not necessary to fail the group creation 978 + * and thus no failure is returned. Users have the option to modify the 979 + * counter assignments after the group has been created. 980 + */ 981 + void rdtgroup_assign_cntrs(struct rdtgroup *rdtgrp) 982 + { 983 + struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3); 984 + 985 + if (!r->mon_capable || !resctrl_arch_mbm_cntr_assign_enabled(r)) 986 + return; 987 + 988 + if (resctrl_is_mon_event_enabled(QOS_L3_MBM_TOTAL_EVENT_ID)) 989 + rdtgroup_assign_cntr_event(NULL, rdtgrp, 990 + &mon_event_all[QOS_L3_MBM_TOTAL_EVENT_ID]); 991 + 992 + if (resctrl_is_mon_event_enabled(QOS_L3_MBM_LOCAL_EVENT_ID)) 993 + rdtgroup_assign_cntr_event(NULL, rdtgrp, 994 + &mon_event_all[QOS_L3_MBM_LOCAL_EVENT_ID]); 937 995 } 938 996 939 997 int resctrl_mbm_assign_mode_show(struct kernfs_open_file *of,