1591a6e85SSai Praneeth Prakhya // SPDX-License-Identifier: GPL-2.0 2591a6e85SSai Praneeth Prakhya /* 3591a6e85SSai Praneeth Prakhya * Basic resctrl file system operations 4591a6e85SSai Praneeth Prakhya * 5591a6e85SSai Praneeth Prakhya * Copyright (C) 2018 Intel Corporation 6591a6e85SSai Praneeth Prakhya * 7591a6e85SSai Praneeth Prakhya * Authors: 8591a6e85SSai Praneeth Prakhya * Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>, 9591a6e85SSai Praneeth Prakhya * Fenghua Yu <fenghua.yu@intel.com> 10591a6e85SSai Praneeth Prakhya */ 1120d96b25SMaciej Wieczor-Retman #include <fcntl.h> 12d56e5da0SIlpo Järvinen #include <limits.h> 13d56e5da0SIlpo Järvinen 14591a6e85SSai Praneeth Prakhya #include "resctrl.h" 15591a6e85SSai Praneeth Prakhya 16591a6e85SSai Praneeth Prakhya static int find_resctrl_mount(char *buffer) 17591a6e85SSai Praneeth Prakhya { 18591a6e85SSai Praneeth Prakhya FILE *mounts; 19591a6e85SSai Praneeth Prakhya char line[256], *fs, *mntpoint; 20591a6e85SSai Praneeth Prakhya 21591a6e85SSai Praneeth Prakhya mounts = fopen("/proc/mounts", "r"); 22591a6e85SSai Praneeth Prakhya if (!mounts) { 23cc8ff7f5SIlpo Järvinen ksft_perror("/proc/mounts"); 24591a6e85SSai Praneeth Prakhya return -ENXIO; 25591a6e85SSai Praneeth Prakhya } 26591a6e85SSai Praneeth Prakhya while (!feof(mounts)) { 27591a6e85SSai Praneeth Prakhya if (!fgets(line, 256, mounts)) 28591a6e85SSai Praneeth Prakhya break; 29591a6e85SSai Praneeth Prakhya fs = strtok(line, " \t"); 30591a6e85SSai Praneeth Prakhya if (!fs) 31591a6e85SSai Praneeth Prakhya continue; 32591a6e85SSai Praneeth Prakhya mntpoint = strtok(NULL, " \t"); 33591a6e85SSai Praneeth Prakhya if (!mntpoint) 34591a6e85SSai Praneeth Prakhya continue; 35591a6e85SSai Praneeth Prakhya fs = strtok(NULL, " \t"); 36591a6e85SSai Praneeth Prakhya if (!fs) 37591a6e85SSai Praneeth Prakhya continue; 38591a6e85SSai Praneeth Prakhya if (strcmp(fs, "resctrl")) 39591a6e85SSai Praneeth Prakhya continue; 40591a6e85SSai Praneeth Prakhya 41591a6e85SSai Praneeth Prakhya fclose(mounts); 42591a6e85SSai Praneeth Prakhya if (buffer) 43591a6e85SSai Praneeth Prakhya strncpy(buffer, mntpoint, 256); 44591a6e85SSai Praneeth Prakhya 45591a6e85SSai Praneeth Prakhya return 0; 46591a6e85SSai Praneeth Prakhya } 47591a6e85SSai Praneeth Prakhya 48591a6e85SSai Praneeth Prakhya fclose(mounts); 49591a6e85SSai Praneeth Prakhya 50591a6e85SSai Praneeth Prakhya return -ENOENT; 51591a6e85SSai Praneeth Prakhya } 52591a6e85SSai Praneeth Prakhya 53591a6e85SSai Praneeth Prakhya /* 546383851aSIlpo Järvinen * mount_resctrlfs - Mount resctrl FS at /sys/fs/resctrl 55591a6e85SSai Praneeth Prakhya * 566383851aSIlpo Järvinen * Mounts resctrl FS. Fails if resctrl FS is already mounted to avoid 576383851aSIlpo Järvinen * pre-existing settings interfering with the test results. 58591a6e85SSai Praneeth Prakhya * 5934813938SIlpo Järvinen * Return: 0 on success, < 0 on error. 60591a6e85SSai Praneeth Prakhya */ 616383851aSIlpo Järvinen int mount_resctrlfs(void) 62591a6e85SSai Praneeth Prakhya { 63591a6e85SSai Praneeth Prakhya int ret; 64591a6e85SSai Praneeth Prakhya 656383851aSIlpo Järvinen ret = find_resctrl_mount(NULL); 666383851aSIlpo Järvinen if (ret != -ENOENT) 676383851aSIlpo Järvinen return -1; 68591a6e85SSai Praneeth Prakhya 69ca2f4214SFenghua Yu ksft_print_msg("Mounting resctrl to \"%s\"\n", RESCTRL_PATH); 70591a6e85SSai Praneeth Prakhya ret = mount("resctrl", RESCTRL_PATH, "resctrl", 0, NULL); 71591a6e85SSai Praneeth Prakhya if (ret) 72cc8ff7f5SIlpo Järvinen ksft_perror("mount"); 73591a6e85SSai Praneeth Prakhya 74591a6e85SSai Praneeth Prakhya return ret; 75591a6e85SSai Praneeth Prakhya } 76591a6e85SSai Praneeth Prakhya 77591a6e85SSai Praneeth Prakhya int umount_resctrlfs(void) 78591a6e85SSai Praneeth Prakhya { 79ede13008SIlpo Järvinen char mountpoint[256]; 80ede13008SIlpo Järvinen int ret; 814e5cb354SFenghua Yu 82ede13008SIlpo Järvinen ret = find_resctrl_mount(mountpoint); 83ede13008SIlpo Järvinen if (ret == -ENOENT) 84ede13008SIlpo Järvinen return 0; 85ede13008SIlpo Järvinen if (ret) 86ede13008SIlpo Järvinen return ret; 87ede13008SIlpo Järvinen 88ede13008SIlpo Järvinen if (umount(mountpoint)) { 89cc8ff7f5SIlpo Järvinen ksft_perror("Unable to umount resctrl"); 90591a6e85SSai Praneeth Prakhya 91c90fba60SIlpo Järvinen return -1; 92591a6e85SSai Praneeth Prakhya } 93591a6e85SSai Praneeth Prakhya 94591a6e85SSai Praneeth Prakhya return 0; 95591a6e85SSai Praneeth Prakhya } 96591a6e85SSai Praneeth Prakhya 97591a6e85SSai Praneeth Prakhya /* 98591a6e85SSai Praneeth Prakhya * get_resource_id - Get socket number/l3 id for a specified CPU 99591a6e85SSai Praneeth Prakhya * @cpu_no: CPU number 100591a6e85SSai Praneeth Prakhya * @resource_id: Socket number or l3_id 101591a6e85SSai Praneeth Prakhya * 102591a6e85SSai Praneeth Prakhya * Return: >= 0 on success, < 0 on failure. 103591a6e85SSai Praneeth Prakhya */ 104591a6e85SSai Praneeth Prakhya int get_resource_id(int cpu_no, int *resource_id) 105591a6e85SSai Praneeth Prakhya { 106591a6e85SSai Praneeth Prakhya char phys_pkg_path[1024]; 107591a6e85SSai Praneeth Prakhya FILE *fp; 108591a6e85SSai Praneeth Prakhya 1096220f69eSShaopeng Tan if (get_vendor() == ARCH_AMD) 110c0327e1dSBabu Moger sprintf(phys_pkg_path, "%s%d/cache/index3/id", 111c0327e1dSBabu Moger PHYS_ID_PATH, cpu_no); 112c0327e1dSBabu Moger else 113591a6e85SSai Praneeth Prakhya sprintf(phys_pkg_path, "%s%d/topology/physical_package_id", 114591a6e85SSai Praneeth Prakhya PHYS_ID_PATH, cpu_no); 115c0327e1dSBabu Moger 116591a6e85SSai Praneeth Prakhya fp = fopen(phys_pkg_path, "r"); 117591a6e85SSai Praneeth Prakhya if (!fp) { 118cc8ff7f5SIlpo Järvinen ksft_perror("Failed to open physical_package_id"); 119591a6e85SSai Praneeth Prakhya 120591a6e85SSai Praneeth Prakhya return -1; 121591a6e85SSai Praneeth Prakhya } 122591a6e85SSai Praneeth Prakhya if (fscanf(fp, "%d", resource_id) <= 0) { 123cc8ff7f5SIlpo Järvinen ksft_perror("Could not get socket number or l3 id"); 124591a6e85SSai Praneeth Prakhya fclose(fp); 125591a6e85SSai Praneeth Prakhya 126591a6e85SSai Praneeth Prakhya return -1; 127591a6e85SSai Praneeth Prakhya } 128591a6e85SSai Praneeth Prakhya fclose(fp); 129591a6e85SSai Praneeth Prakhya 130591a6e85SSai Praneeth Prakhya return 0; 131591a6e85SSai Praneeth Prakhya } 132591a6e85SSai Praneeth Prakhya 133591a6e85SSai Praneeth Prakhya /* 13478941183SFenghua Yu * get_cache_size - Get cache size for a specified CPU 13578941183SFenghua Yu * @cpu_no: CPU number 13678941183SFenghua Yu * @cache_type: Cache level L2/L3 13778941183SFenghua Yu * @cache_size: pointer to cache_size 13878941183SFenghua Yu * 13978941183SFenghua Yu * Return: = 0 on success, < 0 on failure. 14078941183SFenghua Yu */ 14178941183SFenghua Yu int get_cache_size(int cpu_no, char *cache_type, unsigned long *cache_size) 14278941183SFenghua Yu { 14378941183SFenghua Yu char cache_path[1024], cache_str[64]; 14478941183SFenghua Yu int length, i, cache_num; 14578941183SFenghua Yu FILE *fp; 14678941183SFenghua Yu 14778941183SFenghua Yu if (!strcmp(cache_type, "L3")) { 14878941183SFenghua Yu cache_num = 3; 14978941183SFenghua Yu } else if (!strcmp(cache_type, "L2")) { 15078941183SFenghua Yu cache_num = 2; 15178941183SFenghua Yu } else { 152cc8ff7f5SIlpo Järvinen ksft_print_msg("Invalid cache level\n"); 15378941183SFenghua Yu return -1; 15478941183SFenghua Yu } 15578941183SFenghua Yu 15678941183SFenghua Yu sprintf(cache_path, "/sys/bus/cpu/devices/cpu%d/cache/index%d/size", 15778941183SFenghua Yu cpu_no, cache_num); 15878941183SFenghua Yu fp = fopen(cache_path, "r"); 15978941183SFenghua Yu if (!fp) { 160cc8ff7f5SIlpo Järvinen ksft_perror("Failed to open cache size"); 16178941183SFenghua Yu 16278941183SFenghua Yu return -1; 16378941183SFenghua Yu } 16478941183SFenghua Yu if (fscanf(fp, "%s", cache_str) <= 0) { 165cc8ff7f5SIlpo Järvinen ksft_perror("Could not get cache_size"); 16678941183SFenghua Yu fclose(fp); 16778941183SFenghua Yu 16878941183SFenghua Yu return -1; 16978941183SFenghua Yu } 17078941183SFenghua Yu fclose(fp); 17178941183SFenghua Yu 17278941183SFenghua Yu length = (int)strlen(cache_str); 17378941183SFenghua Yu 17478941183SFenghua Yu *cache_size = 0; 17578941183SFenghua Yu 17678941183SFenghua Yu for (i = 0; i < length; i++) { 17778941183SFenghua Yu if ((cache_str[i] >= '0') && (cache_str[i] <= '9')) 17878941183SFenghua Yu 17978941183SFenghua Yu *cache_size = *cache_size * 10 + (cache_str[i] - '0'); 18078941183SFenghua Yu 18178941183SFenghua Yu else if (cache_str[i] == 'K') 18278941183SFenghua Yu 18378941183SFenghua Yu *cache_size = *cache_size * 1024; 18478941183SFenghua Yu 18578941183SFenghua Yu else if (cache_str[i] == 'M') 18678941183SFenghua Yu 18778941183SFenghua Yu *cache_size = *cache_size * 1024 * 1024; 18878941183SFenghua Yu 18978941183SFenghua Yu else 19078941183SFenghua Yu break; 19178941183SFenghua Yu } 19278941183SFenghua Yu 19378941183SFenghua Yu return 0; 19478941183SFenghua Yu } 19578941183SFenghua Yu 19678941183SFenghua Yu #define CORE_SIBLINGS_PATH "/sys/bus/cpu/devices/cpu" 19778941183SFenghua Yu 19878941183SFenghua Yu /* 199*4b357e2aSIlpo Järvinen * get_bit_mask - Get bit mask from given file 200*4b357e2aSIlpo Järvinen * @filename: File containing the mask 201*4b357e2aSIlpo Järvinen * @mask: The bit mask returned as unsigned long 20278941183SFenghua Yu * 20378941183SFenghua Yu * Return: = 0 on success, < 0 on failure. 20478941183SFenghua Yu */ 205*4b357e2aSIlpo Järvinen static int get_bit_mask(const char *filename, unsigned long *mask) 20678941183SFenghua Yu { 20778941183SFenghua Yu FILE *fp; 20878941183SFenghua Yu 209*4b357e2aSIlpo Järvinen if (!filename || !mask) 2108236c51dSFenghua Yu return -1; 2118236c51dSFenghua Yu 212*4b357e2aSIlpo Järvinen fp = fopen(filename, "r"); 21378941183SFenghua Yu if (!fp) { 214*4b357e2aSIlpo Järvinen ksft_print_msg("Failed to open bit mask file '%s': %s\n", 215*4b357e2aSIlpo Järvinen filename, strerror(errno)); 21678941183SFenghua Yu return -1; 21778941183SFenghua Yu } 218*4b357e2aSIlpo Järvinen 219*4b357e2aSIlpo Järvinen if (fscanf(fp, "%lx", mask) <= 0) { 220*4b357e2aSIlpo Järvinen ksft_print_msg("Could not read bit mask file '%s': %s\n", 221*4b357e2aSIlpo Järvinen filename, strerror(errno)); 22278941183SFenghua Yu fclose(fp); 22378941183SFenghua Yu 22478941183SFenghua Yu return -1; 22578941183SFenghua Yu } 22678941183SFenghua Yu fclose(fp); 22778941183SFenghua Yu 22878941183SFenghua Yu return 0; 22978941183SFenghua Yu } 23078941183SFenghua Yu 23178941183SFenghua Yu /* 232*4b357e2aSIlpo Järvinen * get_full_cbm - Get full Cache Bit Mask (CBM) 233*4b357e2aSIlpo Järvinen * @cache_type: Cache type as "L2" or "L3" 234*4b357e2aSIlpo Järvinen * @mask: Full cache bit mask representing the maximal portion of cache 235*4b357e2aSIlpo Järvinen * available for allocation, returned as unsigned long. 236*4b357e2aSIlpo Järvinen * 237*4b357e2aSIlpo Järvinen * Return: = 0 on success, < 0 on failure. 238*4b357e2aSIlpo Järvinen */ 239*4b357e2aSIlpo Järvinen int get_full_cbm(const char *cache_type, unsigned long *mask) 240*4b357e2aSIlpo Järvinen { 241*4b357e2aSIlpo Järvinen char cbm_path[PATH_MAX]; 242*4b357e2aSIlpo Järvinen int ret; 243*4b357e2aSIlpo Järvinen 244*4b357e2aSIlpo Järvinen if (!cache_type) 245*4b357e2aSIlpo Järvinen return -1; 246*4b357e2aSIlpo Järvinen 247*4b357e2aSIlpo Järvinen snprintf(cbm_path, sizeof(cbm_path), "%s/%s/cbm_mask", 248*4b357e2aSIlpo Järvinen INFO_PATH, cache_type); 249*4b357e2aSIlpo Järvinen 250*4b357e2aSIlpo Järvinen ret = get_bit_mask(cbm_path, mask); 251*4b357e2aSIlpo Järvinen if (ret || !*mask) 252*4b357e2aSIlpo Järvinen return -1; 253*4b357e2aSIlpo Järvinen 254*4b357e2aSIlpo Järvinen return 0; 255*4b357e2aSIlpo Järvinen } 256*4b357e2aSIlpo Järvinen 257*4b357e2aSIlpo Järvinen /* 25878941183SFenghua Yu * get_core_sibling - Get sibling core id from the same socket for given CPU 25978941183SFenghua Yu * @cpu_no: CPU number 26078941183SFenghua Yu * 26178941183SFenghua Yu * Return: > 0 on success, < 0 on failure. 26278941183SFenghua Yu */ 26378941183SFenghua Yu int get_core_sibling(int cpu_no) 26478941183SFenghua Yu { 26578941183SFenghua Yu char core_siblings_path[1024], cpu_list_str[64]; 26678941183SFenghua Yu int sibling_cpu_no = -1; 26778941183SFenghua Yu FILE *fp; 26878941183SFenghua Yu 26978941183SFenghua Yu sprintf(core_siblings_path, "%s%d/topology/core_siblings_list", 27078941183SFenghua Yu CORE_SIBLINGS_PATH, cpu_no); 27178941183SFenghua Yu 27278941183SFenghua Yu fp = fopen(core_siblings_path, "r"); 27378941183SFenghua Yu if (!fp) { 274cc8ff7f5SIlpo Järvinen ksft_perror("Failed to open core siblings path"); 27578941183SFenghua Yu 27678941183SFenghua Yu return -1; 27778941183SFenghua Yu } 27878941183SFenghua Yu if (fscanf(fp, "%s", cpu_list_str) <= 0) { 279cc8ff7f5SIlpo Järvinen ksft_perror("Could not get core_siblings list"); 28078941183SFenghua Yu fclose(fp); 28178941183SFenghua Yu 28278941183SFenghua Yu return -1; 28378941183SFenghua Yu } 28478941183SFenghua Yu fclose(fp); 28578941183SFenghua Yu 28678941183SFenghua Yu char *token = strtok(cpu_list_str, "-,"); 28778941183SFenghua Yu 28878941183SFenghua Yu while (token) { 28978941183SFenghua Yu sibling_cpu_no = atoi(token); 29078941183SFenghua Yu /* Skipping core 0 as we don't want to run test on core 0 */ 291f5f16ae4SReinette Chatre if (sibling_cpu_no != 0 && sibling_cpu_no != cpu_no) 29278941183SFenghua Yu break; 29378941183SFenghua Yu token = strtok(NULL, "-,"); 29478941183SFenghua Yu } 29578941183SFenghua Yu 29678941183SFenghua Yu return sibling_cpu_no; 29778941183SFenghua Yu } 29878941183SFenghua Yu 29978941183SFenghua Yu /* 300591a6e85SSai Praneeth Prakhya * taskset_benchmark - Taskset PID (i.e. benchmark) to a specified cpu 301591a6e85SSai Praneeth Prakhya * @bm_pid: PID that should be binded 302591a6e85SSai Praneeth Prakhya * @cpu_no: CPU number at which the PID would be binded 303591a6e85SSai Praneeth Prakhya * 30434813938SIlpo Järvinen * Return: 0 on success, < 0 on error. 305591a6e85SSai Praneeth Prakhya */ 306591a6e85SSai Praneeth Prakhya int taskset_benchmark(pid_t bm_pid, int cpu_no) 307591a6e85SSai Praneeth Prakhya { 308591a6e85SSai Praneeth Prakhya cpu_set_t my_set; 309591a6e85SSai Praneeth Prakhya 310591a6e85SSai Praneeth Prakhya CPU_ZERO(&my_set); 311591a6e85SSai Praneeth Prakhya CPU_SET(cpu_no, &my_set); 312591a6e85SSai Praneeth Prakhya 313591a6e85SSai Praneeth Prakhya if (sched_setaffinity(bm_pid, sizeof(cpu_set_t), &my_set)) { 314cc8ff7f5SIlpo Järvinen ksft_perror("Unable to taskset benchmark"); 315591a6e85SSai Praneeth Prakhya 316591a6e85SSai Praneeth Prakhya return -1; 317591a6e85SSai Praneeth Prakhya } 318591a6e85SSai Praneeth Prakhya 319591a6e85SSai Praneeth Prakhya return 0; 320591a6e85SSai Praneeth Prakhya } 321591a6e85SSai Praneeth Prakhya 322591a6e85SSai Praneeth Prakhya /* 323591a6e85SSai Praneeth Prakhya * create_grp - Create a group only if one doesn't exist 324591a6e85SSai Praneeth Prakhya * @grp_name: Name of the group 325591a6e85SSai Praneeth Prakhya * @grp: Full path and name of the group 326591a6e85SSai Praneeth Prakhya * @parent_grp: Full path and name of the parent group 327591a6e85SSai Praneeth Prakhya * 32834813938SIlpo Järvinen * Return: 0 on success, < 0 on error. 329591a6e85SSai Praneeth Prakhya */ 330591a6e85SSai Praneeth Prakhya static int create_grp(const char *grp_name, char *grp, const char *parent_grp) 331591a6e85SSai Praneeth Prakhya { 332591a6e85SSai Praneeth Prakhya int found_grp = 0; 333591a6e85SSai Praneeth Prakhya struct dirent *ep; 334591a6e85SSai Praneeth Prakhya DIR *dp; 335591a6e85SSai Praneeth Prakhya 33678941183SFenghua Yu /* 33778941183SFenghua Yu * At this point, we are guaranteed to have resctrl FS mounted and if 33878941183SFenghua Yu * length of grp_name == 0, it means, user wants to use root con_mon 33978941183SFenghua Yu * grp, so do nothing 34078941183SFenghua Yu */ 34178941183SFenghua Yu if (strlen(grp_name) == 0) 34278941183SFenghua Yu return 0; 34378941183SFenghua Yu 344591a6e85SSai Praneeth Prakhya /* Check if requested grp exists or not */ 345591a6e85SSai Praneeth Prakhya dp = opendir(parent_grp); 346591a6e85SSai Praneeth Prakhya if (dp) { 347591a6e85SSai Praneeth Prakhya while ((ep = readdir(dp)) != NULL) { 348591a6e85SSai Praneeth Prakhya if (strcmp(ep->d_name, grp_name) == 0) 349591a6e85SSai Praneeth Prakhya found_grp = 1; 350591a6e85SSai Praneeth Prakhya } 351591a6e85SSai Praneeth Prakhya closedir(dp); 352591a6e85SSai Praneeth Prakhya } else { 353cc8ff7f5SIlpo Järvinen ksft_perror("Unable to open resctrl for group"); 354591a6e85SSai Praneeth Prakhya 355591a6e85SSai Praneeth Prakhya return -1; 356591a6e85SSai Praneeth Prakhya } 357591a6e85SSai Praneeth Prakhya 358591a6e85SSai Praneeth Prakhya /* Requested grp doesn't exist, hence create it */ 359591a6e85SSai Praneeth Prakhya if (found_grp == 0) { 360591a6e85SSai Praneeth Prakhya if (mkdir(grp, 0) == -1) { 361cc8ff7f5SIlpo Järvinen ksft_perror("Unable to create group"); 362591a6e85SSai Praneeth Prakhya 363591a6e85SSai Praneeth Prakhya return -1; 364591a6e85SSai Praneeth Prakhya } 365591a6e85SSai Praneeth Prakhya } 366591a6e85SSai Praneeth Prakhya 367591a6e85SSai Praneeth Prakhya return 0; 368591a6e85SSai Praneeth Prakhya } 369591a6e85SSai Praneeth Prakhya 370591a6e85SSai Praneeth Prakhya static int write_pid_to_tasks(char *tasks, pid_t pid) 371591a6e85SSai Praneeth Prakhya { 372591a6e85SSai Praneeth Prakhya FILE *fp; 373591a6e85SSai Praneeth Prakhya 374591a6e85SSai Praneeth Prakhya fp = fopen(tasks, "w"); 375591a6e85SSai Praneeth Prakhya if (!fp) { 376cc8ff7f5SIlpo Järvinen ksft_perror("Failed to open tasks file"); 377591a6e85SSai Praneeth Prakhya 378591a6e85SSai Praneeth Prakhya return -1; 379591a6e85SSai Praneeth Prakhya } 380591a6e85SSai Praneeth Prakhya if (fprintf(fp, "%d\n", pid) < 0) { 381cc8ff7f5SIlpo Järvinen ksft_print_msg("Failed to write pid to tasks file\n"); 382591a6e85SSai Praneeth Prakhya fclose(fp); 383591a6e85SSai Praneeth Prakhya 384591a6e85SSai Praneeth Prakhya return -1; 385591a6e85SSai Praneeth Prakhya } 386591a6e85SSai Praneeth Prakhya fclose(fp); 387591a6e85SSai Praneeth Prakhya 388591a6e85SSai Praneeth Prakhya return 0; 389591a6e85SSai Praneeth Prakhya } 390591a6e85SSai Praneeth Prakhya 391591a6e85SSai Praneeth Prakhya /* 392591a6e85SSai Praneeth Prakhya * write_bm_pid_to_resctrl - Write a PID (i.e. benchmark) to resctrl FS 393591a6e85SSai Praneeth Prakhya * @bm_pid: PID that should be written 394591a6e85SSai Praneeth Prakhya * @ctrlgrp: Name of the control monitor group (con_mon grp) 395591a6e85SSai Praneeth Prakhya * @mongrp: Name of the monitor group (mon grp) 396591a6e85SSai Praneeth Prakhya * @resctrl_val: Resctrl feature (Eg: mbm, mba.. etc) 397591a6e85SSai Praneeth Prakhya * 398591a6e85SSai Praneeth Prakhya * If a con_mon grp is requested, create it and write pid to it, otherwise 399591a6e85SSai Praneeth Prakhya * write pid to root con_mon grp. 400591a6e85SSai Praneeth Prakhya * If a mon grp is requested, create it and write pid to it, otherwise 401591a6e85SSai Praneeth Prakhya * pid is not written, this means that pid is in con_mon grp and hence 402591a6e85SSai Praneeth Prakhya * should consult con_mon grp's mon_data directory for results. 403591a6e85SSai Praneeth Prakhya * 40434813938SIlpo Järvinen * Return: 0 on success, < 0 on error. 405591a6e85SSai Praneeth Prakhya */ 406591a6e85SSai Praneeth Prakhya int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp, 407591a6e85SSai Praneeth Prakhya char *resctrl_val) 408591a6e85SSai Praneeth Prakhya { 409591a6e85SSai Praneeth Prakhya char controlgroup[128], monitorgroup[512], monitorgroup_p[256]; 410591a6e85SSai Praneeth Prakhya char tasks[1024]; 411591a6e85SSai Praneeth Prakhya int ret = 0; 412591a6e85SSai Praneeth Prakhya 413591a6e85SSai Praneeth Prakhya if (strlen(ctrlgrp)) 414591a6e85SSai Praneeth Prakhya sprintf(controlgroup, "%s/%s", RESCTRL_PATH, ctrlgrp); 415591a6e85SSai Praneeth Prakhya else 416591a6e85SSai Praneeth Prakhya sprintf(controlgroup, "%s", RESCTRL_PATH); 417591a6e85SSai Praneeth Prakhya 418591a6e85SSai Praneeth Prakhya /* Create control and monitoring group and write pid into it */ 419591a6e85SSai Praneeth Prakhya ret = create_grp(ctrlgrp, controlgroup, RESCTRL_PATH); 420591a6e85SSai Praneeth Prakhya if (ret) 421591a6e85SSai Praneeth Prakhya goto out; 422591a6e85SSai Praneeth Prakhya sprintf(tasks, "%s/tasks", controlgroup); 423591a6e85SSai Praneeth Prakhya ret = write_pid_to_tasks(tasks, bm_pid); 424591a6e85SSai Praneeth Prakhya if (ret) 425591a6e85SSai Praneeth Prakhya goto out; 426591a6e85SSai Praneeth Prakhya 4272f320911SFenghua Yu /* Create mon grp and write pid into it for "mbm" and "cmt" test */ 4282f320911SFenghua Yu if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)) || 42924286736SFenghua Yu !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) { 43078941183SFenghua Yu if (strlen(mongrp)) { 431591a6e85SSai Praneeth Prakhya sprintf(monitorgroup_p, "%s/mon_groups", controlgroup); 432591a6e85SSai Praneeth Prakhya sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp); 433591a6e85SSai Praneeth Prakhya ret = create_grp(mongrp, monitorgroup, monitorgroup_p); 434591a6e85SSai Praneeth Prakhya if (ret) 435591a6e85SSai Praneeth Prakhya goto out; 436591a6e85SSai Praneeth Prakhya 437591a6e85SSai Praneeth Prakhya sprintf(tasks, "%s/mon_groups/%s/tasks", 438591a6e85SSai Praneeth Prakhya controlgroup, mongrp); 439591a6e85SSai Praneeth Prakhya ret = write_pid_to_tasks(tasks, bm_pid); 440591a6e85SSai Praneeth Prakhya if (ret) 441591a6e85SSai Praneeth Prakhya goto out; 442591a6e85SSai Praneeth Prakhya } 443591a6e85SSai Praneeth Prakhya } 444591a6e85SSai Praneeth Prakhya 445591a6e85SSai Praneeth Prakhya out: 446ca2f4214SFenghua Yu ksft_print_msg("Writing benchmark parameters to resctrl FS\n"); 447591a6e85SSai Praneeth Prakhya if (ret) 448cc8ff7f5SIlpo Järvinen ksft_print_msg("Failed writing to resctrlfs\n"); 449591a6e85SSai Praneeth Prakhya 450591a6e85SSai Praneeth Prakhya return ret; 451591a6e85SSai Praneeth Prakhya } 452591a6e85SSai Praneeth Prakhya 453591a6e85SSai Praneeth Prakhya /* 454591a6e85SSai Praneeth Prakhya * write_schemata - Update schemata of a con_mon grp 455591a6e85SSai Praneeth Prakhya * @ctrlgrp: Name of the con_mon grp 456591a6e85SSai Praneeth Prakhya * @schemata: Schemata that should be updated to 457591a6e85SSai Praneeth Prakhya * @cpu_no: CPU number that the benchmark PID is binded to 458591a6e85SSai Praneeth Prakhya * @resctrl_val: Resctrl feature (Eg: mbm, mba.. etc) 459591a6e85SSai Praneeth Prakhya * 460591a6e85SSai Praneeth Prakhya * Update schemata of a con_mon grp *only* if requested resctrl feature is 461591a6e85SSai Praneeth Prakhya * allocation type 462591a6e85SSai Praneeth Prakhya * 46334813938SIlpo Järvinen * Return: 0 on success, < 0 on error. 464591a6e85SSai Praneeth Prakhya */ 465591a6e85SSai Praneeth Prakhya int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val) 466591a6e85SSai Praneeth Prakhya { 46720d96b25SMaciej Wieczor-Retman char controlgroup[1024], reason[128], schema[1024] = {}; 46820d96b25SMaciej Wieczor-Retman int resource_id, fd, schema_len = -1, ret = 0; 469591a6e85SSai Praneeth Prakhya 47024286736SFenghua Yu if (strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) && 47142e3b093SShaopeng Tan strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) && 47224286736SFenghua Yu strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) && 4732f320911SFenghua Yu strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) 474591a6e85SSai Praneeth Prakhya return -ENOENT; 475591a6e85SSai Praneeth Prakhya 476591a6e85SSai Praneeth Prakhya if (!schemata) { 477ca2f4214SFenghua Yu ksft_print_msg("Skipping empty schemata update\n"); 478591a6e85SSai Praneeth Prakhya 479591a6e85SSai Praneeth Prakhya return -1; 480591a6e85SSai Praneeth Prakhya } 481591a6e85SSai Praneeth Prakhya 482591a6e85SSai Praneeth Prakhya if (get_resource_id(cpu_no, &resource_id) < 0) { 483591a6e85SSai Praneeth Prakhya sprintf(reason, "Failed to get resource id"); 484591a6e85SSai Praneeth Prakhya ret = -1; 485591a6e85SSai Praneeth Prakhya 486591a6e85SSai Praneeth Prakhya goto out; 487591a6e85SSai Praneeth Prakhya } 488591a6e85SSai Praneeth Prakhya 489591a6e85SSai Praneeth Prakhya if (strlen(ctrlgrp) != 0) 490591a6e85SSai Praneeth Prakhya sprintf(controlgroup, "%s/%s/schemata", RESCTRL_PATH, ctrlgrp); 491591a6e85SSai Praneeth Prakhya else 492591a6e85SSai Praneeth Prakhya sprintf(controlgroup, "%s/schemata", RESCTRL_PATH); 493591a6e85SSai Praneeth Prakhya 49424286736SFenghua Yu if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) || 4952f320911SFenghua Yu !strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) 49620d96b25SMaciej Wieczor-Retman schema_len = snprintf(schema, sizeof(schema), "%s%d%c%s\n", 49720d96b25SMaciej Wieczor-Retman "L3:", resource_id, '=', schemata); 49842e3b093SShaopeng Tan if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) || 49942e3b093SShaopeng Tan !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) 50020d96b25SMaciej Wieczor-Retman schema_len = snprintf(schema, sizeof(schema), "%s%d%c%s\n", 50120d96b25SMaciej Wieczor-Retman "MB:", resource_id, '=', schemata); 50220d96b25SMaciej Wieczor-Retman if (schema_len < 0 || schema_len >= sizeof(schema)) { 50320d96b25SMaciej Wieczor-Retman snprintf(reason, sizeof(reason), 50420d96b25SMaciej Wieczor-Retman "snprintf() failed with return value : %d", schema_len); 505591a6e85SSai Praneeth Prakhya ret = -1; 506591a6e85SSai Praneeth Prakhya goto out; 507591a6e85SSai Praneeth Prakhya } 508591a6e85SSai Praneeth Prakhya 50920d96b25SMaciej Wieczor-Retman fd = open(controlgroup, O_WRONLY); 51020d96b25SMaciej Wieczor-Retman if (fd < 0) { 51120d96b25SMaciej Wieczor-Retman snprintf(reason, sizeof(reason), 51220d96b25SMaciej Wieczor-Retman "open() failed : %s", strerror(errno)); 513591a6e85SSai Praneeth Prakhya ret = -1; 514591a6e85SSai Praneeth Prakhya 51520d96b25SMaciej Wieczor-Retman goto err_schema_not_empty; 516591a6e85SSai Praneeth Prakhya } 51720d96b25SMaciej Wieczor-Retman if (write(fd, schema, schema_len) < 0) { 51820d96b25SMaciej Wieczor-Retman snprintf(reason, sizeof(reason), 51920d96b25SMaciej Wieczor-Retman "write() failed : %s", strerror(errno)); 52020d96b25SMaciej Wieczor-Retman close(fd); 52120d96b25SMaciej Wieczor-Retman ret = -1; 522591a6e85SSai Praneeth Prakhya 52320d96b25SMaciej Wieczor-Retman goto err_schema_not_empty; 52420d96b25SMaciej Wieczor-Retman } 52520d96b25SMaciej Wieczor-Retman close(fd); 52620d96b25SMaciej Wieczor-Retman 52720d96b25SMaciej Wieczor-Retman err_schema_not_empty: 52820d96b25SMaciej Wieczor-Retman schema[schema_len - 1] = 0; 529591a6e85SSai Praneeth Prakhya out: 530ca2f4214SFenghua Yu ksft_print_msg("Write schema \"%s\" to resctrl FS%s%s\n", 531ca2f4214SFenghua Yu schema, ret ? " # " : "", 532591a6e85SSai Praneeth Prakhya ret ? reason : ""); 533591a6e85SSai Praneeth Prakhya 534591a6e85SSai Praneeth Prakhya return ret; 535591a6e85SSai Praneeth Prakhya } 536591a6e85SSai Praneeth Prakhya 537ecdbb911SFenghua Yu bool check_resctrlfs_support(void) 538ecdbb911SFenghua Yu { 539ecdbb911SFenghua Yu FILE *inf = fopen("/proc/filesystems", "r"); 540ecdbb911SFenghua Yu DIR *dp; 541ecdbb911SFenghua Yu char *res; 542ecdbb911SFenghua Yu bool ret = false; 543ecdbb911SFenghua Yu 544ecdbb911SFenghua Yu if (!inf) 545ecdbb911SFenghua Yu return false; 546ecdbb911SFenghua Yu 547ecdbb911SFenghua Yu res = fgrep(inf, "nodev\tresctrl\n"); 548ecdbb911SFenghua Yu 549ecdbb911SFenghua Yu if (res) { 550ecdbb911SFenghua Yu ret = true; 551ecdbb911SFenghua Yu free(res); 552ecdbb911SFenghua Yu } 553ecdbb911SFenghua Yu 554ecdbb911SFenghua Yu fclose(inf); 555ecdbb911SFenghua Yu 556e7507478SFenghua Yu ksft_print_msg("%s Check kernel supports resctrl filesystem\n", 557ca2f4214SFenghua Yu ret ? "Pass:" : "Fail:"); 558ecdbb911SFenghua Yu 559a3611fbcSFenghua Yu if (!ret) 560a3611fbcSFenghua Yu return ret; 561a3611fbcSFenghua Yu 562ecdbb911SFenghua Yu dp = opendir(RESCTRL_PATH); 563e7507478SFenghua Yu ksft_print_msg("%s Check resctrl mountpoint \"%s\" exists\n", 564ca2f4214SFenghua Yu dp ? "Pass:" : "Fail:", RESCTRL_PATH); 565ecdbb911SFenghua Yu if (dp) 566ecdbb911SFenghua Yu closedir(dp); 567ecdbb911SFenghua Yu 568ca2f4214SFenghua Yu ksft_print_msg("resctrl filesystem %s mounted\n", 569ecdbb911SFenghua Yu find_resctrl_mount(NULL) ? "not" : "is"); 570ecdbb911SFenghua Yu 571ecdbb911SFenghua Yu return ret; 572ecdbb911SFenghua Yu } 573ecdbb911SFenghua Yu 574591a6e85SSai Praneeth Prakhya char *fgrep(FILE *inf, const char *str) 575591a6e85SSai Praneeth Prakhya { 576591a6e85SSai Praneeth Prakhya char line[256]; 577591a6e85SSai Praneeth Prakhya int slen = strlen(str); 578591a6e85SSai Praneeth Prakhya 579591a6e85SSai Praneeth Prakhya while (!feof(inf)) { 580591a6e85SSai Praneeth Prakhya if (!fgets(line, 256, inf)) 581591a6e85SSai Praneeth Prakhya break; 582591a6e85SSai Praneeth Prakhya if (strncmp(line, str, slen)) 583591a6e85SSai Praneeth Prakhya continue; 584591a6e85SSai Praneeth Prakhya 585591a6e85SSai Praneeth Prakhya return strdup(line); 586591a6e85SSai Praneeth Prakhya } 587591a6e85SSai Praneeth Prakhya 588591a6e85SSai Praneeth Prakhya return NULL; 589591a6e85SSai Praneeth Prakhya } 590591a6e85SSai Praneeth Prakhya 591591a6e85SSai Praneeth Prakhya /* 592591a6e85SSai Praneeth Prakhya * validate_resctrl_feature_request - Check if requested feature is valid. 593d56e5da0SIlpo Järvinen * @resource: Required resource (e.g., MB, L3, L2, L3_MON, etc.) 594d56e5da0SIlpo Järvinen * @feature: Required monitor feature (in mon_features file). Can only be 595d56e5da0SIlpo Järvinen * set for L3_MON. Must be NULL for all other resources. 596591a6e85SSai Praneeth Prakhya * 597d56e5da0SIlpo Järvinen * Return: True if the resource/feature is supported, else false. False is 598d56e5da0SIlpo Järvinen * also returned if resctrl FS is not mounted. 599591a6e85SSai Praneeth Prakhya */ 600d56e5da0SIlpo Järvinen bool validate_resctrl_feature_request(const char *resource, const char *feature) 601591a6e85SSai Praneeth Prakhya { 602d56e5da0SIlpo Järvinen char res_path[PATH_MAX]; 603ee041568SFenghua Yu struct stat statbuf; 604591a6e85SSai Praneeth Prakhya char *res; 605ee041568SFenghua Yu FILE *inf; 606caddc0fbSIlpo Järvinen int ret; 607591a6e85SSai Praneeth Prakhya 608d56e5da0SIlpo Järvinen if (!resource) 609ee041568SFenghua Yu return false; 610ee041568SFenghua Yu 611caddc0fbSIlpo Järvinen ret = find_resctrl_mount(NULL); 612caddc0fbSIlpo Järvinen if (ret) 613ee041568SFenghua Yu return false; 614ee041568SFenghua Yu 615d56e5da0SIlpo Järvinen snprintf(res_path, sizeof(res_path), "%s/%s", INFO_PATH, resource); 616d56e5da0SIlpo Järvinen 617d56e5da0SIlpo Järvinen if (stat(res_path, &statbuf)) 618d56e5da0SIlpo Järvinen return false; 619d56e5da0SIlpo Järvinen 620d56e5da0SIlpo Järvinen if (!feature) 621ee041568SFenghua Yu return true; 622d56e5da0SIlpo Järvinen 623d56e5da0SIlpo Järvinen snprintf(res_path, sizeof(res_path), "%s/%s/mon_features", INFO_PATH, resource); 624d56e5da0SIlpo Järvinen inf = fopen(res_path, "r"); 625591a6e85SSai Praneeth Prakhya if (!inf) 626591a6e85SSai Praneeth Prakhya return false; 627591a6e85SSai Praneeth Prakhya 628d56e5da0SIlpo Järvinen res = fgrep(inf, feature); 629591a6e85SSai Praneeth Prakhya free(res); 630591a6e85SSai Praneeth Prakhya fclose(inf); 631591a6e85SSai Praneeth Prakhya 632d56e5da0SIlpo Järvinen return !!res; 633591a6e85SSai Praneeth Prakhya } 634591a6e85SSai Praneeth Prakhya 635ecdbb911SFenghua Yu int filter_dmesg(void) 636ecdbb911SFenghua Yu { 637ecdbb911SFenghua Yu char line[1024]; 638ecdbb911SFenghua Yu FILE *fp; 639ecdbb911SFenghua Yu int pipefds[2]; 640ecdbb911SFenghua Yu pid_t pid; 641ecdbb911SFenghua Yu int ret; 642ecdbb911SFenghua Yu 643ecdbb911SFenghua Yu ret = pipe(pipefds); 644ecdbb911SFenghua Yu if (ret) { 645cc8ff7f5SIlpo Järvinen ksft_perror("pipe"); 646ecdbb911SFenghua Yu return ret; 647ecdbb911SFenghua Yu } 648a080b6e7SShaopeng Tan fflush(stdout); 649ecdbb911SFenghua Yu pid = fork(); 650ecdbb911SFenghua Yu if (pid == 0) { 651ecdbb911SFenghua Yu close(pipefds[0]); 652ecdbb911SFenghua Yu dup2(pipefds[1], STDOUT_FILENO); 653ecdbb911SFenghua Yu execlp("dmesg", "dmesg", NULL); 654cc8ff7f5SIlpo Järvinen ksft_perror("Executing dmesg"); 655ecdbb911SFenghua Yu exit(1); 656ecdbb911SFenghua Yu } 657ecdbb911SFenghua Yu close(pipefds[1]); 658ecdbb911SFenghua Yu fp = fdopen(pipefds[0], "r"); 659ecdbb911SFenghua Yu if (!fp) { 660cc8ff7f5SIlpo Järvinen ksft_perror("fdopen(pipe)"); 661ecdbb911SFenghua Yu kill(pid, SIGTERM); 662ecdbb911SFenghua Yu 663ecdbb911SFenghua Yu return -1; 664ecdbb911SFenghua Yu } 665ecdbb911SFenghua Yu 666ecdbb911SFenghua Yu while (fgets(line, 1024, fp)) { 667ecdbb911SFenghua Yu if (strstr(line, "intel_rdt:")) 668ca2f4214SFenghua Yu ksft_print_msg("dmesg: %s", line); 669ecdbb911SFenghua Yu if (strstr(line, "resctrl:")) 670ca2f4214SFenghua Yu ksft_print_msg("dmesg: %s", line); 671ecdbb911SFenghua Yu } 672ecdbb911SFenghua Yu fclose(fp); 673ecdbb911SFenghua Yu waitpid(pid, NULL, 0); 674ecdbb911SFenghua Yu 675ecdbb911SFenghua Yu return 0; 676ecdbb911SFenghua Yu } 677ecdbb911SFenghua Yu 678591a6e85SSai Praneeth Prakhya int validate_bw_report_request(char *bw_report) 679591a6e85SSai Praneeth Prakhya { 680591a6e85SSai Praneeth Prakhya if (strcmp(bw_report, "reads") == 0) 681591a6e85SSai Praneeth Prakhya return 0; 682591a6e85SSai Praneeth Prakhya if (strcmp(bw_report, "writes") == 0) 683591a6e85SSai Praneeth Prakhya return 0; 684591a6e85SSai Praneeth Prakhya if (strcmp(bw_report, "nt-writes") == 0) { 685591a6e85SSai Praneeth Prakhya strcpy(bw_report, "writes"); 686591a6e85SSai Praneeth Prakhya return 0; 687591a6e85SSai Praneeth Prakhya } 688591a6e85SSai Praneeth Prakhya if (strcmp(bw_report, "total") == 0) 689591a6e85SSai Praneeth Prakhya return 0; 690591a6e85SSai Praneeth Prakhya 691591a6e85SSai Praneeth Prakhya fprintf(stderr, "Requested iMC B/W report type unavailable\n"); 692591a6e85SSai Praneeth Prakhya 693591a6e85SSai Praneeth Prakhya return -1; 694591a6e85SSai Praneeth Prakhya } 695591a6e85SSai Praneeth Prakhya 696591a6e85SSai Praneeth Prakhya int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, 697591a6e85SSai Praneeth Prakhya int group_fd, unsigned long flags) 698591a6e85SSai Praneeth Prakhya { 699591a6e85SSai Praneeth Prakhya int ret; 700591a6e85SSai Praneeth Prakhya 701591a6e85SSai Praneeth Prakhya ret = syscall(__NR_perf_event_open, hw_event, pid, cpu, 702591a6e85SSai Praneeth Prakhya group_fd, flags); 703591a6e85SSai Praneeth Prakhya return ret; 704591a6e85SSai Praneeth Prakhya } 70578941183SFenghua Yu 70678941183SFenghua Yu unsigned int count_bits(unsigned long n) 70778941183SFenghua Yu { 70878941183SFenghua Yu unsigned int count = 0; 70978941183SFenghua Yu 71078941183SFenghua Yu while (n) { 71178941183SFenghua Yu count += n & 1; 71278941183SFenghua Yu n >>= 1; 71378941183SFenghua Yu } 71478941183SFenghua Yu 71578941183SFenghua Yu return count; 71678941183SFenghua Yu } 717