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

selftests/resctrl: Use resctrl/info for feature detection

Resctrl test suite before running any unit test (like cmt, cat, mbm and
mba) should first check if the feature is enabled (by kernel and not just
supported by H/W) on the platform or not.
validate_resctrl_feature_request() is supposed to do that. This function
intends to grep for relevant flags in /proc/cpuinfo but there are several
issues here

1. validate_resctrl_feature_request() calls fgrep() to get flags from
/proc/cpuinfo. But, fgrep() can only return a string with maximum of 255
characters and hence the complete cpu flags are never returned.
2. The substring search logic is also busted. If strstr() finds requested
resctrl feature in the cpu flags, it returns pointer to the first
occurrence. But, the logic negates the return value of strstr() and
hence validate_resctrl_feature_request() returns false if the feature is
present in the cpu flags and returns true if the feature is not present.
3. validate_resctrl_feature_request() checks if a resctrl feature is
reported in /proc/cpuinfo flags or not. Having a cpu flag means that the
H/W supports the feature, but it doesn't mean that the kernel enabled
it. A user could selectively enable only a subset of resctrl features
using kernel command line arguments. Hence, /proc/cpuinfo isn't a
reliable source to check if a feature is enabled or not.

The 3rd issue being the major one and fixing it requires changing the way
validate_resctrl_feature_request() works. Since, /proc/cpuinfo isn't the
right place to check if a resctrl feature is enabled or not, a more
appropriate place is /sys/fs/resctrl/info directory. Change
validate_resctrl_feature_request() such that,

1. For cat, check if /sys/fs/resctrl/info/L3 directory is present or not
2. For mba, check if /sys/fs/resctrl/info/MB directory is present or not
3. For cmt, check if /sys/fs/resctrl/info/L3_MON directory is present and
check if /sys/fs/resctrl/info/L3_MON/mon_features has llc_occupancy
4. For mbm, check if /sys/fs/resctrl/info/L3_MON directory is present and
check if /sys/fs/resctrl/info/L3_MON/mon_features has
mbm_<total/local>_bytes

Please note that only L3_CAT, L3_CMT, MBA and MBM are supported. CDP and L2
variants can be added later.

Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

authored by

Fenghua Yu and committed by
Shuah Khan
ee041568 a3611fbc

+45 -11
+5 -1
tools/testing/selftests/resctrl/resctrl.h
··· 29 29 #define RESCTRL_PATH "/sys/fs/resctrl" 30 30 #define PHYS_ID_PATH "/sys/devices/system/cpu/cpu" 31 31 #define CBM_MASK_PATH "/sys/fs/resctrl/info" 32 + #define L3_PATH "/sys/fs/resctrl/info/L3" 33 + #define MB_PATH "/sys/fs/resctrl/info/MB" 34 + #define L3_MON_PATH "/sys/fs/resctrl/info/L3_MON" 35 + #define L3_MON_FEATURES_PATH "/sys/fs/resctrl/info/L3_MON/mon_features" 32 36 33 37 #define PARENT_EXIT(err_msg) \ 34 38 do { \ ··· 83 79 int get_resource_id(int cpu_no, int *resource_id); 84 80 int umount_resctrlfs(void); 85 81 int validate_bw_report_request(char *bw_report); 86 - bool validate_resctrl_feature_request(char *resctrl_val); 82 + bool validate_resctrl_feature_request(const char *resctrl_val); 87 83 char *fgrep(FILE *inf, const char *str); 88 84 int taskset_benchmark(pid_t bm_pid, int cpu_no); 89 85 void run_benchmark(int signum, siginfo_t *info, void *ucontext);
+40 -10
tools/testing/selftests/resctrl/resctrlfs.c
··· 606 606 * validate_resctrl_feature_request - Check if requested feature is valid. 607 607 * @resctrl_val: Requested feature 608 608 * 609 - * Return: 0 on success, non-zero on failure 609 + * Return: True if the feature is supported, else false 610 610 */ 611 - bool validate_resctrl_feature_request(char *resctrl_val) 611 + bool validate_resctrl_feature_request(const char *resctrl_val) 612 612 { 613 - FILE *inf = fopen("/proc/cpuinfo", "r"); 613 + struct stat statbuf; 614 614 bool found = false; 615 615 char *res; 616 + FILE *inf; 616 617 617 - if (!inf) 618 + if (!resctrl_val) 618 619 return false; 619 620 620 - res = fgrep(inf, "flags"); 621 + if (remount_resctrlfs(false)) 622 + return false; 621 623 622 - if (res) { 623 - char *s = strchr(res, ':'); 624 + if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) { 625 + if (!stat(L3_PATH, &statbuf)) 626 + return true; 627 + } else if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { 628 + if (!stat(MB_PATH, &statbuf)) 629 + return true; 630 + } else if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || 631 + !strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { 632 + if (!stat(L3_MON_PATH, &statbuf)) { 633 + inf = fopen(L3_MON_FEATURES_PATH, "r"); 634 + if (!inf) 635 + return false; 624 636 625 - found = s && !strstr(s, resctrl_val); 626 - free(res); 637 + if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { 638 + res = fgrep(inf, "llc_occupancy"); 639 + if (res) { 640 + found = true; 641 + free(res); 642 + } 643 + } 644 + 645 + if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) { 646 + res = fgrep(inf, "mbm_total_bytes"); 647 + if (res) { 648 + free(res); 649 + res = fgrep(inf, "mbm_local_bytes"); 650 + if (res) { 651 + found = true; 652 + free(res); 653 + } 654 + } 655 + } 656 + fclose(inf); 657 + } 627 658 } 628 - fclose(inf); 629 659 630 660 return found; 631 661 }