0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "resctrl.h"
0012 #include <unistd.h>
0013
0014 #define RESULT_FILE_NAME1 "result_cat1"
0015 #define RESULT_FILE_NAME2 "result_cat2"
0016 #define NUM_OF_RUNS 5
0017 #define MAX_DIFF_PERCENT 4
0018 #define MAX_DIFF 1000000
0019
0020 static int count_of_bits;
0021 static char cbm_mask[256];
0022 static unsigned long long_mask;
0023 static unsigned long cache_size;
0024
0025
0026
0027
0028
0029
0030 static int cat_setup(int num, ...)
0031 {
0032 struct resctrl_val_param *p;
0033 char schemata[64];
0034 va_list param;
0035 int ret = 0;
0036
0037 va_start(param, num);
0038 p = va_arg(param, struct resctrl_val_param *);
0039 va_end(param);
0040
0041
0042 if (p->num_of_runs >= NUM_OF_RUNS)
0043 return -1;
0044
0045 if (p->num_of_runs == 0) {
0046 sprintf(schemata, "%lx", p->mask);
0047 ret = write_schemata(p->ctrlgrp, schemata, p->cpu_no,
0048 p->resctrl_val);
0049 }
0050 p->num_of_runs++;
0051
0052 return ret;
0053 }
0054
0055 static int check_results(struct resctrl_val_param *param)
0056 {
0057 char *token_array[8], temp[512];
0058 unsigned long sum_llc_perf_miss = 0;
0059 int runs = 0, no_of_bits = 0;
0060 FILE *fp;
0061
0062 ksft_print_msg("Checking for pass/fail\n");
0063 fp = fopen(param->filename, "r");
0064 if (!fp) {
0065 perror("# Cannot open file");
0066
0067 return errno;
0068 }
0069
0070 while (fgets(temp, sizeof(temp), fp)) {
0071 char *token = strtok(temp, ":\t");
0072 int fields = 0;
0073
0074 while (token) {
0075 token_array[fields++] = token;
0076 token = strtok(NULL, ":\t");
0077 }
0078
0079
0080
0081
0082 if (runs > 0)
0083 sum_llc_perf_miss += strtoul(token_array[3], NULL, 0);
0084 runs++;
0085 }
0086
0087 fclose(fp);
0088 no_of_bits = count_bits(param->mask);
0089
0090 return show_cache_info(sum_llc_perf_miss, no_of_bits, param->span / 64,
0091 MAX_DIFF, MAX_DIFF_PERCENT, NUM_OF_RUNS,
0092 get_vendor() == ARCH_INTEL, false);
0093 }
0094
0095 void cat_test_cleanup(void)
0096 {
0097 remove(RESULT_FILE_NAME1);
0098 remove(RESULT_FILE_NAME2);
0099 }
0100
0101 int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
0102 {
0103 unsigned long l_mask, l_mask_1;
0104 int ret, pipefd[2], sibling_cpu_no;
0105 char pipe_message;
0106 pid_t bm_pid;
0107
0108 cache_size = 0;
0109
0110 ret = remount_resctrlfs(true);
0111 if (ret)
0112 return ret;
0113
0114
0115 ret = get_cbm_mask(cache_type, cbm_mask);
0116 if (ret)
0117 return ret;
0118
0119 long_mask = strtoul(cbm_mask, NULL, 16);
0120
0121
0122 ret = get_cache_size(cpu_no, cache_type, &cache_size);
0123 if (ret)
0124 return ret;
0125 ksft_print_msg("Cache size :%lu\n", cache_size);
0126
0127
0128 count_of_bits = count_bits(long_mask);
0129
0130 if (!n)
0131 n = count_of_bits / 2;
0132
0133 if (n > count_of_bits - 1) {
0134 ksft_print_msg("Invalid input value for no_of_bits n!\n");
0135 ksft_print_msg("Please enter value in range 1 to %d\n",
0136 count_of_bits - 1);
0137 return -1;
0138 }
0139
0140
0141 sibling_cpu_no = get_core_sibling(cpu_no);
0142 if (sibling_cpu_no < 0)
0143 return -1;
0144
0145 struct resctrl_val_param param = {
0146 .resctrl_val = CAT_STR,
0147 .cpu_no = cpu_no,
0148 .mum_resctrlfs = 0,
0149 .setup = cat_setup,
0150 };
0151
0152 l_mask = long_mask >> n;
0153 l_mask_1 = ~l_mask & long_mask;
0154
0155
0156
0157
0158 param.span = cache_size * (count_of_bits - n) / count_of_bits;
0159 strcpy(param.ctrlgrp, "c2");
0160 strcpy(param.mongrp, "m2");
0161 strcpy(param.filename, RESULT_FILE_NAME2);
0162 param.mask = l_mask;
0163 param.num_of_runs = 0;
0164
0165 if (pipe(pipefd)) {
0166 perror("# Unable to create pipe");
0167 return errno;
0168 }
0169
0170 bm_pid = fork();
0171
0172
0173
0174
0175 if (bm_pid == 0) {
0176 param.mask = l_mask_1;
0177 strcpy(param.ctrlgrp, "c1");
0178 strcpy(param.mongrp, "m1");
0179 param.span = cache_size * n / count_of_bits;
0180 strcpy(param.filename, RESULT_FILE_NAME1);
0181 param.num_of_runs = 0;
0182 param.cpu_no = sibling_cpu_no;
0183 }
0184
0185 remove(param.filename);
0186
0187 ret = cat_val(¶m);
0188 if (ret)
0189 return ret;
0190
0191 ret = check_results(¶m);
0192 if (ret)
0193 return ret;
0194
0195 if (bm_pid == 0) {
0196
0197 close(pipefd[0]);
0198 pipe_message = 1;
0199 if (write(pipefd[1], &pipe_message, sizeof(pipe_message)) <
0200 sizeof(pipe_message)) {
0201 close(pipefd[1]);
0202 perror("# failed signaling parent process");
0203 return errno;
0204 }
0205
0206 close(pipefd[1]);
0207 while (1)
0208 ;
0209 } else {
0210
0211 close(pipefd[1]);
0212 pipe_message = 0;
0213 while (pipe_message != 1) {
0214 if (read(pipefd[0], &pipe_message,
0215 sizeof(pipe_message)) < sizeof(pipe_message)) {
0216 perror("# failed reading from child process");
0217 break;
0218 }
0219 }
0220 close(pipefd[0]);
0221 kill(bm_pid, SIGKILL);
0222 }
0223
0224 cat_test_cleanup();
0225 if (bm_pid)
0226 umount_resctrlfs();
0227
0228 return 0;
0229 }