11d3f0868SSai Praneeth Prakhya // SPDX-License-Identifier: GPL-2.0 21d3f0868SSai Praneeth Prakhya /* 31d3f0868SSai Praneeth Prakhya * Memory bandwidth monitoring and allocation library 41d3f0868SSai Praneeth Prakhya * 51d3f0868SSai Praneeth Prakhya * Copyright (C) 2018 Intel Corporation 61d3f0868SSai Praneeth Prakhya * 71d3f0868SSai Praneeth Prakhya * Authors: 81d3f0868SSai Praneeth Prakhya * Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>, 91d3f0868SSai Praneeth Prakhya * Fenghua Yu <fenghua.yu@intel.com> 101d3f0868SSai Praneeth Prakhya */ 111d3f0868SSai Praneeth Prakhya #include "resctrl.h" 121d3f0868SSai Praneeth Prakhya 131d3f0868SSai Praneeth Prakhya #define UNCORE_IMC "uncore_imc" 141d3f0868SSai Praneeth Prakhya #define READ_FILE_NAME "events/cas_count_read" 151d3f0868SSai Praneeth Prakhya #define WRITE_FILE_NAME "events/cas_count_write" 161d3f0868SSai Praneeth Prakhya #define DYN_PMU_PATH "/sys/bus/event_source/devices" 171d3f0868SSai Praneeth Prakhya #define SCALE 0.00006103515625 181d3f0868SSai Praneeth Prakhya #define MAX_IMCS 20 191d3f0868SSai Praneeth Prakhya #define MAX_TOKENS 5 201d3f0868SSai Praneeth Prakhya #define READ 0 211d3f0868SSai Praneeth Prakhya #define WRITE 1 221d3f0868SSai Praneeth Prakhya #define CON_MON_MBM_LOCAL_BYTES_PATH \ 231d3f0868SSai Praneeth Prakhya "%s/%s/mon_groups/%s/mon_data/mon_L3_%02d/mbm_local_bytes" 241d3f0868SSai Praneeth Prakhya 251d3f0868SSai Praneeth Prakhya #define CON_MBM_LOCAL_BYTES_PATH \ 261d3f0868SSai Praneeth Prakhya "%s/%s/mon_data/mon_L3_%02d/mbm_local_bytes" 271d3f0868SSai Praneeth Prakhya 281d3f0868SSai Praneeth Prakhya #define MON_MBM_LOCAL_BYTES_PATH \ 291d3f0868SSai Praneeth Prakhya "%s/mon_groups/%s/mon_data/mon_L3_%02d/mbm_local_bytes" 301d3f0868SSai Praneeth Prakhya 311d3f0868SSai Praneeth Prakhya #define MBM_LOCAL_BYTES_PATH \ 321d3f0868SSai Praneeth Prakhya "%s/mon_data/mon_L3_%02d/mbm_local_bytes" 331d3f0868SSai Praneeth Prakhya 3478941183SFenghua Yu #define CON_MON_LCC_OCCUP_PATH \ 3578941183SFenghua Yu "%s/%s/mon_groups/%s/mon_data/mon_L3_%02d/llc_occupancy" 3678941183SFenghua Yu 3778941183SFenghua Yu #define CON_LCC_OCCUP_PATH \ 3878941183SFenghua Yu "%s/%s/mon_data/mon_L3_%02d/llc_occupancy" 3978941183SFenghua Yu 4078941183SFenghua Yu #define MON_LCC_OCCUP_PATH \ 4178941183SFenghua Yu "%s/mon_groups/%s/mon_data/mon_L3_%02d/llc_occupancy" 4278941183SFenghua Yu 4378941183SFenghua Yu #define LCC_OCCUP_PATH \ 4478941183SFenghua Yu "%s/mon_data/mon_L3_%02d/llc_occupancy" 4578941183SFenghua Yu 461d3f0868SSai Praneeth Prakhya struct membw_read_format { 471d3f0868SSai Praneeth Prakhya __u64 value; /* The value of the event */ 481d3f0868SSai Praneeth Prakhya __u64 time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */ 491d3f0868SSai Praneeth Prakhya __u64 time_running; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */ 501d3f0868SSai Praneeth Prakhya __u64 id; /* if PERF_FORMAT_ID */ 511d3f0868SSai Praneeth Prakhya }; 521d3f0868SSai Praneeth Prakhya 531d3f0868SSai Praneeth Prakhya struct imc_counter_config { 541d3f0868SSai Praneeth Prakhya __u32 type; 551d3f0868SSai Praneeth Prakhya __u64 event; 561d3f0868SSai Praneeth Prakhya __u64 umask; 571d3f0868SSai Praneeth Prakhya struct perf_event_attr pe; 581d3f0868SSai Praneeth Prakhya struct membw_read_format return_value; 591d3f0868SSai Praneeth Prakhya int fd; 601d3f0868SSai Praneeth Prakhya }; 611d3f0868SSai Praneeth Prakhya 627f4d257eSSai Praneeth Prakhya static char mbm_total_path[1024]; 637f4d257eSSai Praneeth Prakhya static int imcs; 641d3f0868SSai Praneeth Prakhya static struct imc_counter_config imc_counters_config[MAX_IMCS][2]; 651d3f0868SSai Praneeth Prakhya 661d3f0868SSai Praneeth Prakhya void membw_initialize_perf_event_attr(int i, int j) 671d3f0868SSai Praneeth Prakhya { 681d3f0868SSai Praneeth Prakhya memset(&imc_counters_config[i][j].pe, 0, 691d3f0868SSai Praneeth Prakhya sizeof(struct perf_event_attr)); 701d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].pe.type = imc_counters_config[i][j].type; 711d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].pe.size = sizeof(struct perf_event_attr); 721d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].pe.disabled = 1; 731d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].pe.inherit = 1; 741d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].pe.exclude_guest = 0; 751d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].pe.config = 761d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].umask << 8 | 771d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].event; 781d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].pe.sample_type = PERF_SAMPLE_IDENTIFIER; 791d3f0868SSai Praneeth Prakhya imc_counters_config[i][j].pe.read_format = 801d3f0868SSai Praneeth Prakhya PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; 811d3f0868SSai Praneeth Prakhya } 821d3f0868SSai Praneeth Prakhya 831d3f0868SSai Praneeth Prakhya void membw_ioctl_perf_event_ioc_reset_enable(int i, int j) 841d3f0868SSai Praneeth Prakhya { 851d3f0868SSai Praneeth Prakhya ioctl(imc_counters_config[i][j].fd, PERF_EVENT_IOC_RESET, 0); 861d3f0868SSai Praneeth Prakhya ioctl(imc_counters_config[i][j].fd, PERF_EVENT_IOC_ENABLE, 0); 871d3f0868SSai Praneeth Prakhya } 881d3f0868SSai Praneeth Prakhya 891d3f0868SSai Praneeth Prakhya void membw_ioctl_perf_event_ioc_disable(int i, int j) 901d3f0868SSai Praneeth Prakhya { 911d3f0868SSai Praneeth Prakhya ioctl(imc_counters_config[i][j].fd, PERF_EVENT_IOC_DISABLE, 0); 921d3f0868SSai Praneeth Prakhya } 931d3f0868SSai Praneeth Prakhya 941d3f0868SSai Praneeth Prakhya /* 951d3f0868SSai Praneeth Prakhya * get_event_and_umask: Parse config into event and umask 961d3f0868SSai Praneeth Prakhya * @cas_count_cfg: Config 971d3f0868SSai Praneeth Prakhya * @count: iMC number 981d3f0868SSai Praneeth Prakhya * @op: Operation (read/write) 991d3f0868SSai Praneeth Prakhya */ 1001d3f0868SSai Praneeth Prakhya void get_event_and_umask(char *cas_count_cfg, int count, bool op) 1011d3f0868SSai Praneeth Prakhya { 1021d3f0868SSai Praneeth Prakhya char *token[MAX_TOKENS]; 1031d3f0868SSai Praneeth Prakhya int i = 0; 1041d3f0868SSai Praneeth Prakhya 1051d3f0868SSai Praneeth Prakhya strcat(cas_count_cfg, ","); 1061d3f0868SSai Praneeth Prakhya token[0] = strtok(cas_count_cfg, "=,"); 1071d3f0868SSai Praneeth Prakhya 1081d3f0868SSai Praneeth Prakhya for (i = 1; i < MAX_TOKENS; i++) 1091d3f0868SSai Praneeth Prakhya token[i] = strtok(NULL, "=,"); 1101d3f0868SSai Praneeth Prakhya 1111d3f0868SSai Praneeth Prakhya for (i = 0; i < MAX_TOKENS; i++) { 1121d3f0868SSai Praneeth Prakhya if (!token[i]) 1131d3f0868SSai Praneeth Prakhya break; 1141d3f0868SSai Praneeth Prakhya if (strcmp(token[i], "event") == 0) { 1151d3f0868SSai Praneeth Prakhya if (op == READ) 1161d3f0868SSai Praneeth Prakhya imc_counters_config[count][READ].event = 1171d3f0868SSai Praneeth Prakhya strtol(token[i + 1], NULL, 16); 1181d3f0868SSai Praneeth Prakhya else 1191d3f0868SSai Praneeth Prakhya imc_counters_config[count][WRITE].event = 1201d3f0868SSai Praneeth Prakhya strtol(token[i + 1], NULL, 16); 1211d3f0868SSai Praneeth Prakhya } 1221d3f0868SSai Praneeth Prakhya if (strcmp(token[i], "umask") == 0) { 1231d3f0868SSai Praneeth Prakhya if (op == READ) 1241d3f0868SSai Praneeth Prakhya imc_counters_config[count][READ].umask = 1251d3f0868SSai Praneeth Prakhya strtol(token[i + 1], NULL, 16); 1261d3f0868SSai Praneeth Prakhya else 1271d3f0868SSai Praneeth Prakhya imc_counters_config[count][WRITE].umask = 1281d3f0868SSai Praneeth Prakhya strtol(token[i + 1], NULL, 16); 1291d3f0868SSai Praneeth Prakhya } 1301d3f0868SSai Praneeth Prakhya } 1311d3f0868SSai Praneeth Prakhya } 1327f4d257eSSai Praneeth Prakhya 1337f4d257eSSai Praneeth Prakhya static int open_perf_event(int i, int cpu_no, int j) 1347f4d257eSSai Praneeth Prakhya { 1357f4d257eSSai Praneeth Prakhya imc_counters_config[i][j].fd = 1367f4d257eSSai Praneeth Prakhya perf_event_open(&imc_counters_config[i][j].pe, -1, cpu_no, -1, 1377f4d257eSSai Praneeth Prakhya PERF_FLAG_FD_CLOEXEC); 1387f4d257eSSai Praneeth Prakhya 1397f4d257eSSai Praneeth Prakhya if (imc_counters_config[i][j].fd == -1) { 1407f4d257eSSai Praneeth Prakhya fprintf(stderr, "Error opening leader %llx\n", 1417f4d257eSSai Praneeth Prakhya imc_counters_config[i][j].pe.config); 1427f4d257eSSai Praneeth Prakhya 1437f4d257eSSai Praneeth Prakhya return -1; 1447f4d257eSSai Praneeth Prakhya } 1457f4d257eSSai Praneeth Prakhya 1467f4d257eSSai Praneeth Prakhya return 0; 1477f4d257eSSai Praneeth Prakhya } 1487f4d257eSSai Praneeth Prakhya 1497f4d257eSSai Praneeth Prakhya /* Get type and config (read and write) of an iMC counter */ 1507f4d257eSSai Praneeth Prakhya static int read_from_imc_dir(char *imc_dir, int count) 1517f4d257eSSai Praneeth Prakhya { 1527f4d257eSSai Praneeth Prakhya char cas_count_cfg[1024], imc_counter_cfg[1024], imc_counter_type[1024]; 1537f4d257eSSai Praneeth Prakhya FILE *fp; 1547f4d257eSSai Praneeth Prakhya 1557f4d257eSSai Praneeth Prakhya /* Get type of iMC counter */ 1567f4d257eSSai Praneeth Prakhya sprintf(imc_counter_type, "%s%s", imc_dir, "type"); 1577f4d257eSSai Praneeth Prakhya fp = fopen(imc_counter_type, "r"); 1587f4d257eSSai Praneeth Prakhya if (!fp) { 1597f4d257eSSai Praneeth Prakhya perror("Failed to open imc counter type file"); 1607f4d257eSSai Praneeth Prakhya 1617f4d257eSSai Praneeth Prakhya return -1; 1627f4d257eSSai Praneeth Prakhya } 1637f4d257eSSai Praneeth Prakhya if (fscanf(fp, "%u", &imc_counters_config[count][READ].type) <= 0) { 1647f4d257eSSai Praneeth Prakhya perror("Could not get imc type"); 1657f4d257eSSai Praneeth Prakhya fclose(fp); 1667f4d257eSSai Praneeth Prakhya 1677f4d257eSSai Praneeth Prakhya return -1; 1687f4d257eSSai Praneeth Prakhya } 1697f4d257eSSai Praneeth Prakhya fclose(fp); 1707f4d257eSSai Praneeth Prakhya 1717f4d257eSSai Praneeth Prakhya imc_counters_config[count][WRITE].type = 1727f4d257eSSai Praneeth Prakhya imc_counters_config[count][READ].type; 1737f4d257eSSai Praneeth Prakhya 1747f4d257eSSai Praneeth Prakhya /* Get read config */ 1757f4d257eSSai Praneeth Prakhya sprintf(imc_counter_cfg, "%s%s", imc_dir, READ_FILE_NAME); 1767f4d257eSSai Praneeth Prakhya fp = fopen(imc_counter_cfg, "r"); 1777f4d257eSSai Praneeth Prakhya if (!fp) { 1787f4d257eSSai Praneeth Prakhya perror("Failed to open imc config file"); 1797f4d257eSSai Praneeth Prakhya 1807f4d257eSSai Praneeth Prakhya return -1; 1817f4d257eSSai Praneeth Prakhya } 1827f4d257eSSai Praneeth Prakhya if (fscanf(fp, "%s", cas_count_cfg) <= 0) { 1837f4d257eSSai Praneeth Prakhya perror("Could not get imc cas count read"); 1847f4d257eSSai Praneeth Prakhya fclose(fp); 1857f4d257eSSai Praneeth Prakhya 1867f4d257eSSai Praneeth Prakhya return -1; 1877f4d257eSSai Praneeth Prakhya } 1887f4d257eSSai Praneeth Prakhya fclose(fp); 1897f4d257eSSai Praneeth Prakhya 1907f4d257eSSai Praneeth Prakhya get_event_and_umask(cas_count_cfg, count, READ); 1917f4d257eSSai Praneeth Prakhya 1927f4d257eSSai Praneeth Prakhya /* Get write config */ 1937f4d257eSSai Praneeth Prakhya sprintf(imc_counter_cfg, "%s%s", imc_dir, WRITE_FILE_NAME); 1947f4d257eSSai Praneeth Prakhya fp = fopen(imc_counter_cfg, "r"); 1957f4d257eSSai Praneeth Prakhya if (!fp) { 1967f4d257eSSai Praneeth Prakhya perror("Failed to open imc config file"); 1977f4d257eSSai Praneeth Prakhya 1987f4d257eSSai Praneeth Prakhya return -1; 1997f4d257eSSai Praneeth Prakhya } 2007f4d257eSSai Praneeth Prakhya if (fscanf(fp, "%s", cas_count_cfg) <= 0) { 2017f4d257eSSai Praneeth Prakhya perror("Could not get imc cas count write"); 2027f4d257eSSai Praneeth Prakhya fclose(fp); 2037f4d257eSSai Praneeth Prakhya 2047f4d257eSSai Praneeth Prakhya return -1; 2057f4d257eSSai Praneeth Prakhya } 2067f4d257eSSai Praneeth Prakhya fclose(fp); 2077f4d257eSSai Praneeth Prakhya 2087f4d257eSSai Praneeth Prakhya get_event_and_umask(cas_count_cfg, count, WRITE); 2097f4d257eSSai Praneeth Prakhya 2107f4d257eSSai Praneeth Prakhya return 0; 2117f4d257eSSai Praneeth Prakhya } 2127f4d257eSSai Praneeth Prakhya 2137f4d257eSSai Praneeth Prakhya /* 2147f4d257eSSai Praneeth Prakhya * A system can have 'n' number of iMC (Integrated Memory Controller) 2157f4d257eSSai Praneeth Prakhya * counters, get that 'n'. For each iMC counter get it's type and config. 2167f4d257eSSai Praneeth Prakhya * Also, each counter has two configs, one for read and the other for write. 2177f4d257eSSai Praneeth Prakhya * A config again has two parts, event and umask. 2187f4d257eSSai Praneeth Prakhya * Enumerate all these details into an array of structures. 2197f4d257eSSai Praneeth Prakhya * 2207f4d257eSSai Praneeth Prakhya * Return: >= 0 on success. < 0 on failure. 2217f4d257eSSai Praneeth Prakhya */ 2227f4d257eSSai Praneeth Prakhya static int num_of_imcs(void) 2237f4d257eSSai Praneeth Prakhya { 224d81343b5SFenghua Yu char imc_dir[512], *temp; 2257f4d257eSSai Praneeth Prakhya unsigned int count = 0; 2267f4d257eSSai Praneeth Prakhya struct dirent *ep; 2277f4d257eSSai Praneeth Prakhya int ret; 2287f4d257eSSai Praneeth Prakhya DIR *dp; 2297f4d257eSSai Praneeth Prakhya 2307f4d257eSSai Praneeth Prakhya dp = opendir(DYN_PMU_PATH); 2317f4d257eSSai Praneeth Prakhya if (dp) { 2327f4d257eSSai Praneeth Prakhya while ((ep = readdir(dp))) { 233d81343b5SFenghua Yu temp = strstr(ep->d_name, UNCORE_IMC); 234d81343b5SFenghua Yu if (!temp) 235d81343b5SFenghua Yu continue; 236d81343b5SFenghua Yu 237d81343b5SFenghua Yu /* 238d81343b5SFenghua Yu * imc counters are named as "uncore_imc_<n>", hence 239d81343b5SFenghua Yu * increment the pointer to point to <n>. Note that 240d81343b5SFenghua Yu * sizeof(UNCORE_IMC) would count for null character as 241d81343b5SFenghua Yu * well and hence the last underscore character in 242d81343b5SFenghua Yu * uncore_imc'_' need not be counted. 243d81343b5SFenghua Yu */ 244d81343b5SFenghua Yu temp = temp + sizeof(UNCORE_IMC); 245d81343b5SFenghua Yu 246d81343b5SFenghua Yu /* 247d81343b5SFenghua Yu * Some directories under "DYN_PMU_PATH" could have 248d81343b5SFenghua Yu * names like "uncore_imc_free_running", hence, check if 249d81343b5SFenghua Yu * first character is a numerical digit or not. 250d81343b5SFenghua Yu */ 251d81343b5SFenghua Yu if (temp[0] >= '0' && temp[0] <= '9') { 2527f4d257eSSai Praneeth Prakhya sprintf(imc_dir, "%s/%s/", DYN_PMU_PATH, 2537f4d257eSSai Praneeth Prakhya ep->d_name); 2547f4d257eSSai Praneeth Prakhya ret = read_from_imc_dir(imc_dir, count); 2557f4d257eSSai Praneeth Prakhya if (ret) { 2567f4d257eSSai Praneeth Prakhya closedir(dp); 2577f4d257eSSai Praneeth Prakhya 2587f4d257eSSai Praneeth Prakhya return ret; 2597f4d257eSSai Praneeth Prakhya } 2607f4d257eSSai Praneeth Prakhya count++; 2617f4d257eSSai Praneeth Prakhya } 2627f4d257eSSai Praneeth Prakhya } 2637f4d257eSSai Praneeth Prakhya closedir(dp); 2647f4d257eSSai Praneeth Prakhya if (count == 0) { 2657f4d257eSSai Praneeth Prakhya perror("Unable find iMC counters!\n"); 2667f4d257eSSai Praneeth Prakhya 2677f4d257eSSai Praneeth Prakhya return -1; 2687f4d257eSSai Praneeth Prakhya } 2697f4d257eSSai Praneeth Prakhya } else { 2707f4d257eSSai Praneeth Prakhya perror("Unable to open PMU directory!\n"); 2717f4d257eSSai Praneeth Prakhya 2727f4d257eSSai Praneeth Prakhya return -1; 2737f4d257eSSai Praneeth Prakhya } 2747f4d257eSSai Praneeth Prakhya 2757f4d257eSSai Praneeth Prakhya return count; 2767f4d257eSSai Praneeth Prakhya } 2777f4d257eSSai Praneeth Prakhya 2787f4d257eSSai Praneeth Prakhya static int initialize_mem_bw_imc(void) 2797f4d257eSSai Praneeth Prakhya { 2807f4d257eSSai Praneeth Prakhya int imc, j; 2817f4d257eSSai Praneeth Prakhya 2827f4d257eSSai Praneeth Prakhya imcs = num_of_imcs(); 2837f4d257eSSai Praneeth Prakhya if (imcs <= 0) 2847f4d257eSSai Praneeth Prakhya return imcs; 2857f4d257eSSai Praneeth Prakhya 2867f4d257eSSai Praneeth Prakhya /* Initialize perf_event_attr structures for all iMC's */ 2877f4d257eSSai Praneeth Prakhya for (imc = 0; imc < imcs; imc++) { 2887f4d257eSSai Praneeth Prakhya for (j = 0; j < 2; j++) 2897f4d257eSSai Praneeth Prakhya membw_initialize_perf_event_attr(imc, j); 2907f4d257eSSai Praneeth Prakhya } 2917f4d257eSSai Praneeth Prakhya 2927f4d257eSSai Praneeth Prakhya return 0; 2937f4d257eSSai Praneeth Prakhya } 2947f4d257eSSai Praneeth Prakhya 2957f4d257eSSai Praneeth Prakhya /* 2967f4d257eSSai Praneeth Prakhya * get_mem_bw_imc: Memory band width as reported by iMC counters 2977f4d257eSSai Praneeth Prakhya * @cpu_no: CPU number that the benchmark PID is binded to 2987f4d257eSSai Praneeth Prakhya * @bw_report: Bandwidth report type (reads, writes) 2997f4d257eSSai Praneeth Prakhya * 3007f4d257eSSai Praneeth Prakhya * Memory B/W utilized by a process on a socket can be calculated using 3017f4d257eSSai Praneeth Prakhya * iMC counters. Perf events are used to read these counters. 3027f4d257eSSai Praneeth Prakhya * 3031205b688SFenghua Yu * Return: = 0 on success. < 0 on failure. 3047f4d257eSSai Praneeth Prakhya */ 3051205b688SFenghua Yu static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) 3067f4d257eSSai Praneeth Prakhya { 3077f4d257eSSai Praneeth Prakhya float reads, writes, of_mul_read, of_mul_write; 3087f4d257eSSai Praneeth Prakhya int imc, j, ret; 3097f4d257eSSai Praneeth Prakhya 3107f4d257eSSai Praneeth Prakhya /* Start all iMC counters to log values (both read and write) */ 3117f4d257eSSai Praneeth Prakhya reads = 0, writes = 0, of_mul_read = 1, of_mul_write = 1; 3127f4d257eSSai Praneeth Prakhya for (imc = 0; imc < imcs; imc++) { 3137f4d257eSSai Praneeth Prakhya for (j = 0; j < 2; j++) { 3147f4d257eSSai Praneeth Prakhya ret = open_perf_event(imc, cpu_no, j); 3157f4d257eSSai Praneeth Prakhya if (ret) 3167f4d257eSSai Praneeth Prakhya return -1; 3177f4d257eSSai Praneeth Prakhya } 3187f4d257eSSai Praneeth Prakhya for (j = 0; j < 2; j++) 3197f4d257eSSai Praneeth Prakhya membw_ioctl_perf_event_ioc_reset_enable(imc, j); 3207f4d257eSSai Praneeth Prakhya } 3217f4d257eSSai Praneeth Prakhya 3227f4d257eSSai Praneeth Prakhya sleep(1); 3237f4d257eSSai Praneeth Prakhya 3247f4d257eSSai Praneeth Prakhya /* Stop counters after a second to get results (both read and write) */ 3257f4d257eSSai Praneeth Prakhya for (imc = 0; imc < imcs; imc++) { 3267f4d257eSSai Praneeth Prakhya for (j = 0; j < 2; j++) 3277f4d257eSSai Praneeth Prakhya membw_ioctl_perf_event_ioc_disable(imc, j); 3287f4d257eSSai Praneeth Prakhya } 3297f4d257eSSai Praneeth Prakhya 3307f4d257eSSai Praneeth Prakhya /* 3317f4d257eSSai Praneeth Prakhya * Get results which are stored in struct type imc_counter_config 3327f4d257eSSai Praneeth Prakhya * Take over flow into consideration before calculating total b/w 3337f4d257eSSai Praneeth Prakhya */ 3347f4d257eSSai Praneeth Prakhya for (imc = 0; imc < imcs; imc++) { 3357f4d257eSSai Praneeth Prakhya struct imc_counter_config *r = 3367f4d257eSSai Praneeth Prakhya &imc_counters_config[imc][READ]; 3377f4d257eSSai Praneeth Prakhya struct imc_counter_config *w = 3387f4d257eSSai Praneeth Prakhya &imc_counters_config[imc][WRITE]; 3397f4d257eSSai Praneeth Prakhya 3407f4d257eSSai Praneeth Prakhya if (read(r->fd, &r->return_value, 3417f4d257eSSai Praneeth Prakhya sizeof(struct membw_read_format)) == -1) { 3427f4d257eSSai Praneeth Prakhya perror("Couldn't get read b/w through iMC"); 3437f4d257eSSai Praneeth Prakhya 3447f4d257eSSai Praneeth Prakhya return -1; 3457f4d257eSSai Praneeth Prakhya } 3467f4d257eSSai Praneeth Prakhya 3477f4d257eSSai Praneeth Prakhya if (read(w->fd, &w->return_value, 3487f4d257eSSai Praneeth Prakhya sizeof(struct membw_read_format)) == -1) { 3497f4d257eSSai Praneeth Prakhya perror("Couldn't get write bw through iMC"); 3507f4d257eSSai Praneeth Prakhya 3517f4d257eSSai Praneeth Prakhya return -1; 3527f4d257eSSai Praneeth Prakhya } 3537f4d257eSSai Praneeth Prakhya 3547f4d257eSSai Praneeth Prakhya __u64 r_time_enabled = r->return_value.time_enabled; 3557f4d257eSSai Praneeth Prakhya __u64 r_time_running = r->return_value.time_running; 3567f4d257eSSai Praneeth Prakhya 3577f4d257eSSai Praneeth Prakhya if (r_time_enabled != r_time_running) 3587f4d257eSSai Praneeth Prakhya of_mul_read = (float)r_time_enabled / 3597f4d257eSSai Praneeth Prakhya (float)r_time_running; 3607f4d257eSSai Praneeth Prakhya 3617f4d257eSSai Praneeth Prakhya __u64 w_time_enabled = w->return_value.time_enabled; 3627f4d257eSSai Praneeth Prakhya __u64 w_time_running = w->return_value.time_running; 3637f4d257eSSai Praneeth Prakhya 3647f4d257eSSai Praneeth Prakhya if (w_time_enabled != w_time_running) 3657f4d257eSSai Praneeth Prakhya of_mul_write = (float)w_time_enabled / 3667f4d257eSSai Praneeth Prakhya (float)w_time_running; 3677f4d257eSSai Praneeth Prakhya reads += r->return_value.value * of_mul_read * SCALE; 3687f4d257eSSai Praneeth Prakhya writes += w->return_value.value * of_mul_write * SCALE; 3697f4d257eSSai Praneeth Prakhya } 3707f4d257eSSai Praneeth Prakhya 3717f4d257eSSai Praneeth Prakhya for (imc = 0; imc < imcs; imc++) { 3727f4d257eSSai Praneeth Prakhya close(imc_counters_config[imc][READ].fd); 3737f4d257eSSai Praneeth Prakhya close(imc_counters_config[imc][WRITE].fd); 3747f4d257eSSai Praneeth Prakhya } 3757f4d257eSSai Praneeth Prakhya 3761205b688SFenghua Yu if (strcmp(bw_report, "reads") == 0) { 3771205b688SFenghua Yu *bw_imc = reads; 3781205b688SFenghua Yu return 0; 3791205b688SFenghua Yu } 3807f4d257eSSai Praneeth Prakhya 3811205b688SFenghua Yu if (strcmp(bw_report, "writes") == 0) { 3821205b688SFenghua Yu *bw_imc = writes; 3831205b688SFenghua Yu return 0; 3841205b688SFenghua Yu } 3857f4d257eSSai Praneeth Prakhya 3861205b688SFenghua Yu *bw_imc = reads + writes; 3871205b688SFenghua Yu return 0; 3887f4d257eSSai Praneeth Prakhya } 3897f4d257eSSai Praneeth Prakhya 3907f4d257eSSai Praneeth Prakhya void set_mbm_path(const char *ctrlgrp, const char *mongrp, int resource_id) 3917f4d257eSSai Praneeth Prakhya { 3927f4d257eSSai Praneeth Prakhya if (ctrlgrp && mongrp) 3937f4d257eSSai Praneeth Prakhya sprintf(mbm_total_path, CON_MON_MBM_LOCAL_BYTES_PATH, 3947f4d257eSSai Praneeth Prakhya RESCTRL_PATH, ctrlgrp, mongrp, resource_id); 3957f4d257eSSai Praneeth Prakhya else if (!ctrlgrp && mongrp) 3967f4d257eSSai Praneeth Prakhya sprintf(mbm_total_path, MON_MBM_LOCAL_BYTES_PATH, RESCTRL_PATH, 3977f4d257eSSai Praneeth Prakhya mongrp, resource_id); 3987f4d257eSSai Praneeth Prakhya else if (ctrlgrp && !mongrp) 3997f4d257eSSai Praneeth Prakhya sprintf(mbm_total_path, CON_MBM_LOCAL_BYTES_PATH, RESCTRL_PATH, 4007f4d257eSSai Praneeth Prakhya ctrlgrp, resource_id); 4017f4d257eSSai Praneeth Prakhya else if (!ctrlgrp && !mongrp) 4027f4d257eSSai Praneeth Prakhya sprintf(mbm_total_path, MBM_LOCAL_BYTES_PATH, RESCTRL_PATH, 4037f4d257eSSai Praneeth Prakhya resource_id); 4047f4d257eSSai Praneeth Prakhya } 4057f4d257eSSai Praneeth Prakhya 4067f4d257eSSai Praneeth Prakhya /* 4077f4d257eSSai Praneeth Prakhya * initialize_mem_bw_resctrl: Appropriately populate "mbm_total_path" 4087f4d257eSSai Praneeth Prakhya * @ctrlgrp: Name of the control monitor group (con_mon grp) 4097f4d257eSSai Praneeth Prakhya * @mongrp: Name of the monitor group (mon grp) 4107f4d257eSSai Praneeth Prakhya * @cpu_no: CPU number that the benchmark PID is binded to 4117f4d257eSSai Praneeth Prakhya * @resctrl_val: Resctrl feature (Eg: mbm, mba.. etc) 4127f4d257eSSai Praneeth Prakhya */ 4137f4d257eSSai Praneeth Prakhya static void initialize_mem_bw_resctrl(const char *ctrlgrp, const char *mongrp, 4147f4d257eSSai Praneeth Prakhya int cpu_no, char *resctrl_val) 4157f4d257eSSai Praneeth Prakhya { 4167f4d257eSSai Praneeth Prakhya int resource_id; 4177f4d257eSSai Praneeth Prakhya 4187f4d257eSSai Praneeth Prakhya if (get_resource_id(cpu_no, &resource_id) < 0) { 4197f4d257eSSai Praneeth Prakhya perror("Could not get resource_id"); 4207f4d257eSSai Praneeth Prakhya return; 4217f4d257eSSai Praneeth Prakhya } 4227f4d257eSSai Praneeth Prakhya 42324286736SFenghua Yu if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) 4247f4d257eSSai Praneeth Prakhya set_mbm_path(ctrlgrp, mongrp, resource_id); 4257f4d257eSSai Praneeth Prakhya 42624286736SFenghua Yu if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { 4277f4d257eSSai Praneeth Prakhya if (ctrlgrp) 4287f4d257eSSai Praneeth Prakhya sprintf(mbm_total_path, CON_MBM_LOCAL_BYTES_PATH, 4297f4d257eSSai Praneeth Prakhya RESCTRL_PATH, ctrlgrp, resource_id); 4307f4d257eSSai Praneeth Prakhya else 4317f4d257eSSai Praneeth Prakhya sprintf(mbm_total_path, MBM_LOCAL_BYTES_PATH, 4327f4d257eSSai Praneeth Prakhya RESCTRL_PATH, resource_id); 4337f4d257eSSai Praneeth Prakhya } 4347f4d257eSSai Praneeth Prakhya } 4357f4d257eSSai Praneeth Prakhya 4367f4d257eSSai Praneeth Prakhya /* 4377f4d257eSSai Praneeth Prakhya * Get MBM Local bytes as reported by resctrl FS 4387f4d257eSSai Praneeth Prakhya * For MBM, 4397f4d257eSSai Praneeth Prakhya * 1. If con_mon grp and mon grp are given, then read from con_mon grp's mon grp 4407f4d257eSSai Praneeth Prakhya * 2. If only con_mon grp is given, then read from con_mon grp 4417f4d257eSSai Praneeth Prakhya * 3. If both are not given, then read from root con_mon grp 4427f4d257eSSai Praneeth Prakhya * For MBA, 4437f4d257eSSai Praneeth Prakhya * 1. If con_mon grp is given, then read from it 4447f4d257eSSai Praneeth Prakhya * 2. If con_mon grp is not given, then read from root con_mon grp 4457f4d257eSSai Praneeth Prakhya */ 4461205b688SFenghua Yu static int get_mem_bw_resctrl(unsigned long *mbm_total) 4477f4d257eSSai Praneeth Prakhya { 4487f4d257eSSai Praneeth Prakhya FILE *fp; 4497f4d257eSSai Praneeth Prakhya 4507f4d257eSSai Praneeth Prakhya fp = fopen(mbm_total_path, "r"); 4517f4d257eSSai Praneeth Prakhya if (!fp) { 4527f4d257eSSai Praneeth Prakhya perror("Failed to open total bw file"); 4537f4d257eSSai Praneeth Prakhya 4547f4d257eSSai Praneeth Prakhya return -1; 4557f4d257eSSai Praneeth Prakhya } 4561205b688SFenghua Yu if (fscanf(fp, "%lu", mbm_total) <= 0) { 4577f4d257eSSai Praneeth Prakhya perror("Could not get mbm local bytes"); 4587f4d257eSSai Praneeth Prakhya fclose(fp); 4597f4d257eSSai Praneeth Prakhya 4607f4d257eSSai Praneeth Prakhya return -1; 4617f4d257eSSai Praneeth Prakhya } 4627f4d257eSSai Praneeth Prakhya fclose(fp); 4637f4d257eSSai Praneeth Prakhya 4641205b688SFenghua Yu return 0; 4657f4d257eSSai Praneeth Prakhya } 4667f4d257eSSai Praneeth Prakhya 4677f4d257eSSai Praneeth Prakhya pid_t bm_pid, ppid; 4687f4d257eSSai Praneeth Prakhya 46978941183SFenghua Yu void ctrlc_handler(int signum, siginfo_t *info, void *ptr) 4707f4d257eSSai Praneeth Prakhya { 4717f4d257eSSai Praneeth Prakhya kill(bm_pid, SIGKILL); 472ecdbb911SFenghua Yu umount_resctrlfs(); 473ecdbb911SFenghua Yu tests_cleanup(); 474ca2f4214SFenghua Yu ksft_print_msg("Ending\n\n"); 4757f4d257eSSai Praneeth Prakhya 4767f4d257eSSai Praneeth Prakhya exit(EXIT_SUCCESS); 4777f4d257eSSai Praneeth Prakhya } 4787f4d257eSSai Praneeth Prakhya 4797f4d257eSSai Praneeth Prakhya /* 48073c55fa5SShaopeng Tan * Register CTRL-C handler for parent, as it has to kill 48173c55fa5SShaopeng Tan * child process before exiting. 48273c55fa5SShaopeng Tan */ 48373c55fa5SShaopeng Tan int signal_handler_register(void) 48473c55fa5SShaopeng Tan { 48573c55fa5SShaopeng Tan struct sigaction sigact; 48673c55fa5SShaopeng Tan int ret = 0; 48773c55fa5SShaopeng Tan 48873c55fa5SShaopeng Tan sigact.sa_sigaction = ctrlc_handler; 48973c55fa5SShaopeng Tan sigemptyset(&sigact.sa_mask); 49073c55fa5SShaopeng Tan sigact.sa_flags = SA_SIGINFO; 49173c55fa5SShaopeng Tan if (sigaction(SIGINT, &sigact, NULL) || 49273c55fa5SShaopeng Tan sigaction(SIGTERM, &sigact, NULL) || 49373c55fa5SShaopeng Tan sigaction(SIGHUP, &sigact, NULL)) { 49473c55fa5SShaopeng Tan perror("# sigaction"); 49573c55fa5SShaopeng Tan ret = -1; 49673c55fa5SShaopeng Tan } 49773c55fa5SShaopeng Tan return ret; 49873c55fa5SShaopeng Tan } 49973c55fa5SShaopeng Tan 50073c55fa5SShaopeng Tan /* 50173c55fa5SShaopeng Tan * Reset signal handler to SIG_DFL. 50273c55fa5SShaopeng Tan * Non-Value return because the caller should keep 50373c55fa5SShaopeng Tan * the error code of other path even if sigaction fails. 50473c55fa5SShaopeng Tan */ 50573c55fa5SShaopeng Tan void signal_handler_unregister(void) 50673c55fa5SShaopeng Tan { 50773c55fa5SShaopeng Tan struct sigaction sigact; 50873c55fa5SShaopeng Tan 50973c55fa5SShaopeng Tan sigact.sa_handler = SIG_DFL; 51073c55fa5SShaopeng Tan sigemptyset(&sigact.sa_mask); 51173c55fa5SShaopeng Tan if (sigaction(SIGINT, &sigact, NULL) || 51273c55fa5SShaopeng Tan sigaction(SIGTERM, &sigact, NULL) || 51373c55fa5SShaopeng Tan sigaction(SIGHUP, &sigact, NULL)) { 51473c55fa5SShaopeng Tan perror("# sigaction"); 51573c55fa5SShaopeng Tan } 51673c55fa5SShaopeng Tan } 51773c55fa5SShaopeng Tan 51873c55fa5SShaopeng Tan /* 5197f4d257eSSai Praneeth Prakhya * print_results_bw: the memory bandwidth results are stored in a file 5207f4d257eSSai Praneeth Prakhya * @filename: file that stores the results 5217f4d257eSSai Praneeth Prakhya * @bm_pid: child pid that runs benchmark 5227f4d257eSSai Praneeth Prakhya * @bw_imc: perf imc counter value 5237f4d257eSSai Praneeth Prakhya * @bw_resc: memory bandwidth value 5247f4d257eSSai Praneeth Prakhya * 5257f4d257eSSai Praneeth Prakhya * Return: 0 on success. non-zero on failure. 5267f4d257eSSai Praneeth Prakhya */ 5277f4d257eSSai Praneeth Prakhya static int print_results_bw(char *filename, int bm_pid, float bw_imc, 5287f4d257eSSai Praneeth Prakhya unsigned long bw_resc) 5297f4d257eSSai Praneeth Prakhya { 5307f4d257eSSai Praneeth Prakhya unsigned long diff = fabs(bw_imc - bw_resc); 5317f4d257eSSai Praneeth Prakhya FILE *fp; 5327f4d257eSSai Praneeth Prakhya 5337f4d257eSSai Praneeth Prakhya if (strcmp(filename, "stdio") == 0 || strcmp(filename, "stderr") == 0) { 5347f4d257eSSai Praneeth Prakhya printf("Pid: %d \t Mem_BW_iMC: %f \t ", bm_pid, bw_imc); 5357f4d257eSSai Praneeth Prakhya printf("Mem_BW_resc: %lu \t Difference: %lu\n", bw_resc, diff); 5367f4d257eSSai Praneeth Prakhya } else { 5377f4d257eSSai Praneeth Prakhya fp = fopen(filename, "a"); 5387f4d257eSSai Praneeth Prakhya if (!fp) { 5397f4d257eSSai Praneeth Prakhya perror("Cannot open results file"); 5407f4d257eSSai Praneeth Prakhya 5417f4d257eSSai Praneeth Prakhya return errno; 5427f4d257eSSai Praneeth Prakhya } 5437f4d257eSSai Praneeth Prakhya if (fprintf(fp, "Pid: %d \t Mem_BW_iMC: %f \t Mem_BW_resc: %lu \t Difference: %lu\n", 5447f4d257eSSai Praneeth Prakhya bm_pid, bw_imc, bw_resc, diff) <= 0) { 5457f4d257eSSai Praneeth Prakhya fclose(fp); 5467f4d257eSSai Praneeth Prakhya perror("Could not log results."); 5477f4d257eSSai Praneeth Prakhya 5487f4d257eSSai Praneeth Prakhya return errno; 5497f4d257eSSai Praneeth Prakhya } 5507f4d257eSSai Praneeth Prakhya fclose(fp); 5517f4d257eSSai Praneeth Prakhya } 5527f4d257eSSai Praneeth Prakhya 5537f4d257eSSai Praneeth Prakhya return 0; 5547f4d257eSSai Praneeth Prakhya } 5557f4d257eSSai Praneeth Prakhya 5562f320911SFenghua Yu static void set_cmt_path(const char *ctrlgrp, const char *mongrp, char sock_num) 55778941183SFenghua Yu { 55878941183SFenghua Yu if (strlen(ctrlgrp) && strlen(mongrp)) 55978941183SFenghua Yu sprintf(llc_occup_path, CON_MON_LCC_OCCUP_PATH, RESCTRL_PATH, 56078941183SFenghua Yu ctrlgrp, mongrp, sock_num); 56178941183SFenghua Yu else if (!strlen(ctrlgrp) && strlen(mongrp)) 56278941183SFenghua Yu sprintf(llc_occup_path, MON_LCC_OCCUP_PATH, RESCTRL_PATH, 56378941183SFenghua Yu mongrp, sock_num); 56478941183SFenghua Yu else if (strlen(ctrlgrp) && !strlen(mongrp)) 56578941183SFenghua Yu sprintf(llc_occup_path, CON_LCC_OCCUP_PATH, RESCTRL_PATH, 56678941183SFenghua Yu ctrlgrp, sock_num); 56778941183SFenghua Yu else if (!strlen(ctrlgrp) && !strlen(mongrp)) 56878941183SFenghua Yu sprintf(llc_occup_path, LCC_OCCUP_PATH, RESCTRL_PATH, sock_num); 56978941183SFenghua Yu } 57078941183SFenghua Yu 57178941183SFenghua Yu /* 57278941183SFenghua Yu * initialize_llc_occu_resctrl: Appropriately populate "llc_occup_path" 57378941183SFenghua Yu * @ctrlgrp: Name of the control monitor group (con_mon grp) 57478941183SFenghua Yu * @mongrp: Name of the monitor group (mon grp) 57578941183SFenghua Yu * @cpu_no: CPU number that the benchmark PID is binded to 5762f320911SFenghua Yu * @resctrl_val: Resctrl feature (Eg: cat, cmt.. etc) 57778941183SFenghua Yu */ 57878941183SFenghua Yu static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp, 57978941183SFenghua Yu int cpu_no, char *resctrl_val) 58078941183SFenghua Yu { 58178941183SFenghua Yu int resource_id; 58278941183SFenghua Yu 58378941183SFenghua Yu if (get_resource_id(cpu_no, &resource_id) < 0) { 58478941183SFenghua Yu perror("# Unable to resource_id"); 58578941183SFenghua Yu return; 58678941183SFenghua Yu } 58778941183SFenghua Yu 5882f320911SFenghua Yu if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) 5892f320911SFenghua Yu set_cmt_path(ctrlgrp, mongrp, resource_id); 59078941183SFenghua Yu } 59178941183SFenghua Yu 5927f4d257eSSai Praneeth Prakhya static int 5937f4d257eSSai Praneeth Prakhya measure_vals(struct resctrl_val_param *param, unsigned long *bw_resc_start) 5947f4d257eSSai Praneeth Prakhya { 5951205b688SFenghua Yu unsigned long bw_resc, bw_resc_end; 5961205b688SFenghua Yu float bw_imc; 5977f4d257eSSai Praneeth Prakhya int ret; 5987f4d257eSSai Praneeth Prakhya 5997f4d257eSSai Praneeth Prakhya /* 6007f4d257eSSai Praneeth Prakhya * Measure memory bandwidth from resctrl and from 6017f4d257eSSai Praneeth Prakhya * another source which is perf imc value or could 6027f4d257eSSai Praneeth Prakhya * be something else if perf imc event is not available. 6037f4d257eSSai Praneeth Prakhya * Compare the two values to validate resctrl value. 6047f4d257eSSai Praneeth Prakhya * It takes 1sec to measure the data. 6057f4d257eSSai Praneeth Prakhya */ 6061205b688SFenghua Yu ret = get_mem_bw_imc(param->cpu_no, param->bw_report, &bw_imc); 6071205b688SFenghua Yu if (ret < 0) 6081205b688SFenghua Yu return ret; 6097f4d257eSSai Praneeth Prakhya 6101205b688SFenghua Yu ret = get_mem_bw_resctrl(&bw_resc_end); 6111205b688SFenghua Yu if (ret < 0) 6121205b688SFenghua Yu return ret; 6137f4d257eSSai Praneeth Prakhya 6147f4d257eSSai Praneeth Prakhya bw_resc = (bw_resc_end - *bw_resc_start) / MB; 6157f4d257eSSai Praneeth Prakhya ret = print_results_bw(param->filename, bm_pid, bw_imc, bw_resc); 6167f4d257eSSai Praneeth Prakhya if (ret) 6177f4d257eSSai Praneeth Prakhya return ret; 6187f4d257eSSai Praneeth Prakhya 6197f4d257eSSai Praneeth Prakhya *bw_resc_start = bw_resc_end; 6207f4d257eSSai Praneeth Prakhya 6217f4d257eSSai Praneeth Prakhya return 0; 6227f4d257eSSai Praneeth Prakhya } 6237f4d257eSSai Praneeth Prakhya 6247f4d257eSSai Praneeth Prakhya /* 6257f4d257eSSai Praneeth Prakhya * resctrl_val: execute benchmark and measure memory bandwidth on 6267f4d257eSSai Praneeth Prakhya * the benchmark 6277f4d257eSSai Praneeth Prakhya * @benchmark_cmd: benchmark command and its arguments 6287f4d257eSSai Praneeth Prakhya * @param: parameters passed to resctrl_val() 6297f4d257eSSai Praneeth Prakhya * 6307f4d257eSSai Praneeth Prakhya * Return: 0 on success. non-zero on failure. 6317f4d257eSSai Praneeth Prakhya */ 6327f4d257eSSai Praneeth Prakhya int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param) 6337f4d257eSSai Praneeth Prakhya { 6347f4d257eSSai Praneeth Prakhya char *resctrl_val = param->resctrl_val; 6357f4d257eSSai Praneeth Prakhya unsigned long bw_resc_start = 0; 6367f4d257eSSai Praneeth Prakhya struct sigaction sigact; 6377f4d257eSSai Praneeth Prakhya int ret = 0, pipefd[2]; 6387f4d257eSSai Praneeth Prakhya char pipe_message = 0; 6397f4d257eSSai Praneeth Prakhya union sigval value; 6407f4d257eSSai Praneeth Prakhya 6417f4d257eSSai Praneeth Prakhya if (strcmp(param->filename, "") == 0) 6427f4d257eSSai Praneeth Prakhya sprintf(param->filename, "stdio"); 6437f4d257eSSai Praneeth Prakhya 64424286736SFenghua Yu if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) || 64524286736SFenghua Yu !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) { 6467f4d257eSSai Praneeth Prakhya ret = validate_bw_report_request(param->bw_report); 6477f4d257eSSai Praneeth Prakhya if (ret) 6487f4d257eSSai Praneeth Prakhya return ret; 6497f4d257eSSai Praneeth Prakhya } 6507f4d257eSSai Praneeth Prakhya 6517f4d257eSSai Praneeth Prakhya /* 6527f4d257eSSai Praneeth Prakhya * If benchmark wasn't successfully started by child, then child should 6537f4d257eSSai Praneeth Prakhya * kill parent, so save parent's pid 6547f4d257eSSai Praneeth Prakhya */ 6557f4d257eSSai Praneeth Prakhya ppid = getpid(); 6567f4d257eSSai Praneeth Prakhya 6577f4d257eSSai Praneeth Prakhya if (pipe(pipefd)) { 6587f4d257eSSai Praneeth Prakhya perror("# Unable to create pipe"); 6597f4d257eSSai Praneeth Prakhya 6607f4d257eSSai Praneeth Prakhya return -1; 6617f4d257eSSai Praneeth Prakhya } 6627f4d257eSSai Praneeth Prakhya 6637f4d257eSSai Praneeth Prakhya /* 6647f4d257eSSai Praneeth Prakhya * Fork to start benchmark, save child's pid so that it can be killed 6657f4d257eSSai Praneeth Prakhya * when needed 6667f4d257eSSai Praneeth Prakhya */ 667a080b6e7SShaopeng Tan fflush(stdout); 6687f4d257eSSai Praneeth Prakhya bm_pid = fork(); 6697f4d257eSSai Praneeth Prakhya if (bm_pid == -1) { 6707f4d257eSSai Praneeth Prakhya perror("# Unable to fork"); 6717f4d257eSSai Praneeth Prakhya 6727f4d257eSSai Praneeth Prakhya return -1; 6737f4d257eSSai Praneeth Prakhya } 6747f4d257eSSai Praneeth Prakhya 6757f4d257eSSai Praneeth Prakhya if (bm_pid == 0) { 6767f4d257eSSai Praneeth Prakhya /* 6777f4d257eSSai Praneeth Prakhya * Mask all signals except SIGUSR1, parent uses SIGUSR1 to 6787f4d257eSSai Praneeth Prakhya * start benchmark 6797f4d257eSSai Praneeth Prakhya */ 6807f4d257eSSai Praneeth Prakhya sigfillset(&sigact.sa_mask); 6817f4d257eSSai Praneeth Prakhya sigdelset(&sigact.sa_mask, SIGUSR1); 6827f4d257eSSai Praneeth Prakhya 6837f4d257eSSai Praneeth Prakhya sigact.sa_sigaction = run_benchmark; 6847f4d257eSSai Praneeth Prakhya sigact.sa_flags = SA_SIGINFO; 6857f4d257eSSai Praneeth Prakhya 6867f4d257eSSai Praneeth Prakhya /* Register for "SIGUSR1" signal from parent */ 6877f4d257eSSai Praneeth Prakhya if (sigaction(SIGUSR1, &sigact, NULL)) 6887f4d257eSSai Praneeth Prakhya PARENT_EXIT("Can't register child for signal"); 6897f4d257eSSai Praneeth Prakhya 6907f4d257eSSai Praneeth Prakhya /* Tell parent that child is ready */ 6917f4d257eSSai Praneeth Prakhya close(pipefd[0]); 6927f4d257eSSai Praneeth Prakhya pipe_message = 1; 6937f4d257eSSai Praneeth Prakhya if (write(pipefd[1], &pipe_message, sizeof(pipe_message)) < 6947f4d257eSSai Praneeth Prakhya sizeof(pipe_message)) { 6957f4d257eSSai Praneeth Prakhya perror("# failed signaling parent process"); 6967f4d257eSSai Praneeth Prakhya close(pipefd[1]); 6977f4d257eSSai Praneeth Prakhya return -1; 6987f4d257eSSai Praneeth Prakhya } 6997f4d257eSSai Praneeth Prakhya close(pipefd[1]); 7007f4d257eSSai Praneeth Prakhya 7017f4d257eSSai Praneeth Prakhya /* Suspend child until delivery of "SIGUSR1" from parent */ 7027f4d257eSSai Praneeth Prakhya sigsuspend(&sigact.sa_mask); 7037f4d257eSSai Praneeth Prakhya 7047f4d257eSSai Praneeth Prakhya PARENT_EXIT("Child is done"); 7057f4d257eSSai Praneeth Prakhya } 7067f4d257eSSai Praneeth Prakhya 707ca2f4214SFenghua Yu ksft_print_msg("Benchmark PID: %d\n", bm_pid); 7087f4d257eSSai Praneeth Prakhya 70973c55fa5SShaopeng Tan ret = signal_handler_register(); 71073c55fa5SShaopeng Tan if (ret) 7117f4d257eSSai Praneeth Prakhya goto out; 7127f4d257eSSai Praneeth Prakhya 7137f4d257eSSai Praneeth Prakhya value.sival_ptr = benchmark_cmd; 7147f4d257eSSai Praneeth Prakhya 7157f4d257eSSai Praneeth Prakhya /* Taskset benchmark to specified cpu */ 7167f4d257eSSai Praneeth Prakhya ret = taskset_benchmark(bm_pid, param->cpu_no); 7177f4d257eSSai Praneeth Prakhya if (ret) 71873c55fa5SShaopeng Tan goto unregister; 7197f4d257eSSai Praneeth Prakhya 7207f4d257eSSai Praneeth Prakhya /* Write benchmark to specified control&monitoring grp in resctrl FS */ 7217f4d257eSSai Praneeth Prakhya ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp, 7227f4d257eSSai Praneeth Prakhya resctrl_val); 7237f4d257eSSai Praneeth Prakhya if (ret) 72473c55fa5SShaopeng Tan goto unregister; 7257f4d257eSSai Praneeth Prakhya 72624286736SFenghua Yu if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || 72724286736SFenghua Yu !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { 7287f4d257eSSai Praneeth Prakhya ret = initialize_mem_bw_imc(); 7297f4d257eSSai Praneeth Prakhya if (ret) 73073c55fa5SShaopeng Tan goto unregister; 7317f4d257eSSai Praneeth Prakhya 7327f4d257eSSai Praneeth Prakhya initialize_mem_bw_resctrl(param->ctrlgrp, param->mongrp, 7337f4d257eSSai Praneeth Prakhya param->cpu_no, resctrl_val); 7342f320911SFenghua Yu } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) 73578941183SFenghua Yu initialize_llc_occu_resctrl(param->ctrlgrp, param->mongrp, 73678941183SFenghua Yu param->cpu_no, resctrl_val); 7377f4d257eSSai Praneeth Prakhya 7387f4d257eSSai Praneeth Prakhya /* Parent waits for child to be ready. */ 7397f4d257eSSai Praneeth Prakhya close(pipefd[1]); 7407f4d257eSSai Praneeth Prakhya while (pipe_message != 1) { 7417f4d257eSSai Praneeth Prakhya if (read(pipefd[0], &pipe_message, sizeof(pipe_message)) < 7427f4d257eSSai Praneeth Prakhya sizeof(pipe_message)) { 7437f4d257eSSai Praneeth Prakhya perror("# failed reading message from child process"); 7447f4d257eSSai Praneeth Prakhya close(pipefd[0]); 74573c55fa5SShaopeng Tan goto unregister; 7467f4d257eSSai Praneeth Prakhya } 7477f4d257eSSai Praneeth Prakhya } 7487f4d257eSSai Praneeth Prakhya close(pipefd[0]); 7497f4d257eSSai Praneeth Prakhya 7507f4d257eSSai Praneeth Prakhya /* Signal child to start benchmark */ 7517f4d257eSSai Praneeth Prakhya if (sigqueue(bm_pid, SIGUSR1, value) == -1) { 7527f4d257eSSai Praneeth Prakhya perror("# sigqueue SIGUSR1 to child"); 7537f4d257eSSai Praneeth Prakhya ret = errno; 75473c55fa5SShaopeng Tan goto unregister; 7557f4d257eSSai Praneeth Prakhya } 7567f4d257eSSai Praneeth Prakhya 7577f4d257eSSai Praneeth Prakhya /* Give benchmark enough time to fully run */ 7587f4d257eSSai Praneeth Prakhya sleep(1); 7597f4d257eSSai Praneeth Prakhya 7607f4d257eSSai Praneeth Prakhya /* Test runs until the callback setup() tells the test to stop. */ 7617f4d257eSSai Praneeth Prakhya while (1) { 762*8ee592a6SIlpo Järvinen ret = param->setup(param); 763fa10366cSIlpo Järvinen if (ret == END_OF_TESTS) { 7647f4d257eSSai Praneeth Prakhya ret = 0; 7657f4d257eSSai Praneeth Prakhya break; 7667f4d257eSSai Praneeth Prakhya } 767fa10366cSIlpo Järvinen if (ret < 0) 768fa10366cSIlpo Järvinen break; 7697f4d257eSSai Praneeth Prakhya 770c90b3b58SIlpo Järvinen if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || 771c90b3b58SIlpo Järvinen !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { 7727f4d257eSSai Praneeth Prakhya ret = measure_vals(param, &bw_resc_start); 7737f4d257eSSai Praneeth Prakhya if (ret) 7747f4d257eSSai Praneeth Prakhya break; 7752f320911SFenghua Yu } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { 77678941183SFenghua Yu sleep(1); 77778941183SFenghua Yu ret = measure_cache_vals(param, bm_pid); 7787f4d257eSSai Praneeth Prakhya if (ret) 7797f4d257eSSai Praneeth Prakhya break; 7807f4d257eSSai Praneeth Prakhya } 7817f4d257eSSai Praneeth Prakhya } 7827f4d257eSSai Praneeth Prakhya 78373c55fa5SShaopeng Tan unregister: 78473c55fa5SShaopeng Tan signal_handler_unregister(); 7857f4d257eSSai Praneeth Prakhya out: 7867f4d257eSSai Praneeth Prakhya kill(bm_pid, SIGKILL); 7877f4d257eSSai Praneeth Prakhya 7887f4d257eSSai Praneeth Prakhya return ret; 7897f4d257eSSai Praneeth Prakhya } 790