0001
0002
0003 #include <stdint.h>
0004 #include "resctrl.h"
0005
0006 struct read_format {
0007 __u64 nr;
0008 struct {
0009 __u64 value;
0010 } values[2];
0011 };
0012
0013 static struct perf_event_attr pea_llc_miss;
0014 static struct read_format rf_cqm;
0015 static int fd_lm;
0016 char llc_occup_path[1024];
0017
0018 static void initialize_perf_event_attr(void)
0019 {
0020 pea_llc_miss.type = PERF_TYPE_HARDWARE;
0021 pea_llc_miss.size = sizeof(struct perf_event_attr);
0022 pea_llc_miss.read_format = PERF_FORMAT_GROUP;
0023 pea_llc_miss.exclude_kernel = 1;
0024 pea_llc_miss.exclude_hv = 1;
0025 pea_llc_miss.exclude_idle = 1;
0026 pea_llc_miss.exclude_callchain_kernel = 1;
0027 pea_llc_miss.inherit = 1;
0028 pea_llc_miss.exclude_guest = 1;
0029 pea_llc_miss.disabled = 1;
0030 }
0031
0032 static void ioctl_perf_event_ioc_reset_enable(void)
0033 {
0034 ioctl(fd_lm, PERF_EVENT_IOC_RESET, 0);
0035 ioctl(fd_lm, PERF_EVENT_IOC_ENABLE, 0);
0036 }
0037
0038 static int perf_event_open_llc_miss(pid_t pid, int cpu_no)
0039 {
0040 fd_lm = perf_event_open(&pea_llc_miss, pid, cpu_no, -1,
0041 PERF_FLAG_FD_CLOEXEC);
0042 if (fd_lm == -1) {
0043 perror("Error opening leader");
0044 ctrlc_handler(0, NULL, NULL);
0045 return -1;
0046 }
0047
0048 return 0;
0049 }
0050
0051 static int initialize_llc_perf(void)
0052 {
0053 memset(&pea_llc_miss, 0, sizeof(struct perf_event_attr));
0054 memset(&rf_cqm, 0, sizeof(struct read_format));
0055
0056
0057 initialize_perf_event_attr();
0058
0059 pea_llc_miss.config = PERF_COUNT_HW_CACHE_MISSES;
0060
0061 rf_cqm.nr = 1;
0062
0063 return 0;
0064 }
0065
0066 static int reset_enable_llc_perf(pid_t pid, int cpu_no)
0067 {
0068 int ret = 0;
0069
0070 ret = perf_event_open_llc_miss(pid, cpu_no);
0071 if (ret < 0)
0072 return ret;
0073
0074
0075 ioctl_perf_event_ioc_reset_enable();
0076
0077 return 0;
0078 }
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 static int get_llc_perf(unsigned long *llc_perf_miss)
0090 {
0091 __u64 total_misses;
0092
0093
0094
0095 ioctl(fd_lm, PERF_EVENT_IOC_DISABLE, 0);
0096
0097 if (read(fd_lm, &rf_cqm, sizeof(struct read_format)) == -1) {
0098 perror("Could not get llc misses through perf");
0099
0100 return -1;
0101 }
0102
0103 total_misses = rf_cqm.values[0].value;
0104
0105 close(fd_lm);
0106
0107 *llc_perf_miss = total_misses;
0108
0109 return 0;
0110 }
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 static int get_llc_occu_resctrl(unsigned long *llc_occupancy)
0126 {
0127 FILE *fp;
0128
0129 fp = fopen(llc_occup_path, "r");
0130 if (!fp) {
0131 perror("Failed to open results file");
0132
0133 return errno;
0134 }
0135 if (fscanf(fp, "%lu", llc_occupancy) <= 0) {
0136 perror("Could not get llc occupancy");
0137 fclose(fp);
0138
0139 return -1;
0140 }
0141 fclose(fp);
0142
0143 return 0;
0144 }
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 static int print_results_cache(char *filename, int bm_pid,
0156 unsigned long llc_value)
0157 {
0158 FILE *fp;
0159
0160 if (strcmp(filename, "stdio") == 0 || strcmp(filename, "stderr") == 0) {
0161 printf("Pid: %d \t LLC_value: %lu\n", bm_pid,
0162 llc_value);
0163 } else {
0164 fp = fopen(filename, "a");
0165 if (!fp) {
0166 perror("Cannot open results file");
0167
0168 return errno;
0169 }
0170 fprintf(fp, "Pid: %d \t llc_value: %lu\n", bm_pid, llc_value);
0171 fclose(fp);
0172 }
0173
0174 return 0;
0175 }
0176
0177 int measure_cache_vals(struct resctrl_val_param *param, int bm_pid)
0178 {
0179 unsigned long llc_perf_miss = 0, llc_occu_resc = 0, llc_value = 0;
0180 int ret;
0181
0182
0183
0184
0185 if (!strncmp(param->resctrl_val, CAT_STR, sizeof(CAT_STR))) {
0186 ret = get_llc_perf(&llc_perf_miss);
0187 if (ret < 0)
0188 return ret;
0189 llc_value = llc_perf_miss;
0190 }
0191
0192
0193
0194
0195 if (!strncmp(param->resctrl_val, CMT_STR, sizeof(CMT_STR))) {
0196 ret = get_llc_occu_resctrl(&llc_occu_resc);
0197 if (ret < 0)
0198 return ret;
0199 llc_value = llc_occu_resc;
0200 }
0201 ret = print_results_cache(param->filename, bm_pid, llc_value);
0202 if (ret)
0203 return ret;
0204
0205 return 0;
0206 }
0207
0208
0209
0210
0211
0212
0213
0214
0215 int cat_val(struct resctrl_val_param *param)
0216 {
0217 int malloc_and_init_memory = 1, memflush = 1, operation = 0, ret = 0;
0218 char *resctrl_val = param->resctrl_val;
0219 pid_t bm_pid;
0220
0221 if (strcmp(param->filename, "") == 0)
0222 sprintf(param->filename, "stdio");
0223
0224 bm_pid = getpid();
0225
0226
0227 ret = taskset_benchmark(bm_pid, param->cpu_no);
0228 if (ret)
0229 return ret;
0230
0231
0232 ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp,
0233 resctrl_val);
0234 if (ret)
0235 return ret;
0236
0237 if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) {
0238 ret = initialize_llc_perf();
0239 if (ret)
0240 return ret;
0241 }
0242
0243
0244 while (1) {
0245 if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) {
0246 ret = param->setup(1, param);
0247 if (ret) {
0248 ret = 0;
0249 break;
0250 }
0251 ret = reset_enable_llc_perf(bm_pid, param->cpu_no);
0252 if (ret)
0253 break;
0254
0255 if (run_fill_buf(param->span, malloc_and_init_memory,
0256 memflush, operation, resctrl_val)) {
0257 fprintf(stderr, "Error-running fill buffer\n");
0258 ret = -1;
0259 break;
0260 }
0261
0262 sleep(1);
0263 ret = measure_cache_vals(param, bm_pid);
0264 if (ret)
0265 break;
0266 } else {
0267 break;
0268 }
0269 }
0270
0271 return ret;
0272 }
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 int show_cache_info(unsigned long sum_llc_val, int no_of_bits,
0288 unsigned long cache_span, unsigned long max_diff,
0289 unsigned long max_diff_percent, unsigned long num_of_runs,
0290 bool platform, bool cmt)
0291 {
0292 unsigned long avg_llc_val = 0;
0293 float diff_percent;
0294 long avg_diff = 0;
0295 int ret;
0296
0297 avg_llc_val = sum_llc_val / (num_of_runs - 1);
0298 avg_diff = (long)abs(cache_span - avg_llc_val);
0299 diff_percent = ((float)cache_span - avg_llc_val) / cache_span * 100;
0300
0301 ret = platform && abs((int)diff_percent) > max_diff_percent &&
0302 (cmt ? (abs(avg_diff) > max_diff) : true);
0303
0304 ksft_print_msg("%s Check cache miss rate within %d%%\n",
0305 ret ? "Fail:" : "Pass:", max_diff_percent);
0306
0307 ksft_print_msg("Percent diff=%d\n", abs((int)diff_percent));
0308 ksft_print_msg("Number of bits: %d\n", no_of_bits);
0309 ksft_print_msg("Average LLC val: %lu\n", avg_llc_val);
0310 ksft_print_msg("Cache span (%s): %lu\n", cmt ? "bytes" : "lines",
0311 cache_span);
0312
0313 return ret;
0314 }