at master 190 lines 4.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Cache Monitoring Technology (CMT) test 4 * 5 * Copyright (C) 2018 Intel Corporation 6 * 7 * Authors: 8 * Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>, 9 * Fenghua Yu <fenghua.yu@intel.com> 10 */ 11#include "resctrl.h" 12#include <unistd.h> 13 14#define RESULT_FILE_NAME "result_cmt" 15#define NUM_OF_RUNS 5 16#define MAX_DIFF 2000000 17#define MAX_DIFF_PERCENT 15 18 19#define CON_MON_LCC_OCCUP_PATH \ 20 "%s/%s/mon_data/mon_L3_%02d/llc_occupancy" 21 22static int cmt_init(const struct resctrl_val_param *param, int domain_id) 23{ 24 sprintf(llc_occup_path, CON_MON_LCC_OCCUP_PATH, RESCTRL_PATH, 25 param->ctrlgrp, domain_id); 26 27 return 0; 28} 29 30static int cmt_setup(const struct resctrl_test *test, 31 const struct user_params *uparams, 32 struct resctrl_val_param *p) 33{ 34 /* Run NUM_OF_RUNS times */ 35 if (p->num_of_runs >= NUM_OF_RUNS) 36 return END_OF_TESTS; 37 38 p->num_of_runs++; 39 40 return 0; 41} 42 43static int cmt_measure(const struct user_params *uparams, 44 struct resctrl_val_param *param, pid_t bm_pid) 45{ 46 sleep(1); 47 return measure_llc_resctrl(param->filename, bm_pid); 48} 49 50static int show_results_info(unsigned long sum_llc_val, int no_of_bits, 51 unsigned long cache_span, unsigned long max_diff, 52 unsigned long max_diff_percent, unsigned long num_of_runs, 53 bool platform) 54{ 55 unsigned long avg_llc_val = 0; 56 float diff_percent; 57 long avg_diff = 0; 58 int ret; 59 60 avg_llc_val = sum_llc_val / num_of_runs; 61 avg_diff = (long)(cache_span - avg_llc_val); 62 diff_percent = ((float)cache_span - avg_llc_val) / cache_span * 100; 63 64 ret = platform && abs((int)diff_percent) > max_diff_percent && 65 labs(avg_diff) > max_diff; 66 67 ksft_print_msg("%s Check cache miss rate within %lu%%\n", 68 ret ? "Fail:" : "Pass:", max_diff_percent); 69 70 ksft_print_msg("Percent diff=%d\n", abs((int)diff_percent)); 71 72 show_cache_info(no_of_bits, avg_llc_val, cache_span, false); 73 74 return ret; 75} 76 77static int check_results(struct resctrl_val_param *param, size_t span, int no_of_bits) 78{ 79 char *token_array[8], temp[512]; 80 unsigned long sum_llc_occu_resc = 0; 81 int runs = 0; 82 FILE *fp; 83 84 ksft_print_msg("Checking for pass/fail\n"); 85 fp = fopen(param->filename, "r"); 86 if (!fp) { 87 ksft_perror("Error in opening file"); 88 89 return -1; 90 } 91 92 while (fgets(temp, sizeof(temp), fp)) { 93 char *token = strtok(temp, ":\t"); 94 int fields = 0; 95 96 while (token) { 97 token_array[fields++] = token; 98 token = strtok(NULL, ":\t"); 99 } 100 101 /* Field 3 is llc occ resc value */ 102 sum_llc_occu_resc += strtoul(token_array[3], NULL, 0); 103 runs++; 104 } 105 fclose(fp); 106 107 return show_results_info(sum_llc_occu_resc, no_of_bits, span, 108 MAX_DIFF, MAX_DIFF_PERCENT, runs, true); 109} 110 111static void cmt_test_cleanup(void) 112{ 113 remove(RESULT_FILE_NAME); 114} 115 116static int cmt_run_test(const struct resctrl_test *test, const struct user_params *uparams) 117{ 118 struct fill_buf_param fill_buf = {}; 119 unsigned long cache_total_size = 0; 120 int n = uparams->bits ? : 5; 121 unsigned long long_mask; 122 int count_of_bits; 123 size_t span; 124 int ret; 125 126 ret = get_full_cbm("L3", &long_mask); 127 if (ret) 128 return ret; 129 130 ret = get_cache_size(uparams->cpu, "L3", &cache_total_size); 131 if (ret) 132 return ret; 133 ksft_print_msg("Cache size :%lu\n", cache_total_size); 134 135 count_of_bits = count_bits(long_mask); 136 137 if (n < 1 || n > count_of_bits) { 138 ksft_print_msg("Invalid input value for numbr_of_bits n!\n"); 139 ksft_print_msg("Please enter value in range 1 to %d\n", count_of_bits); 140 return -1; 141 } 142 143 struct resctrl_val_param param = { 144 .ctrlgrp = "c1", 145 .filename = RESULT_FILE_NAME, 146 .mask = ~(long_mask << n) & long_mask, 147 .num_of_runs = 0, 148 .init = cmt_init, 149 .setup = cmt_setup, 150 .measure = cmt_measure, 151 }; 152 153 span = cache_portion_size(cache_total_size, param.mask, long_mask); 154 155 if (uparams->fill_buf) { 156 fill_buf.buf_size = span; 157 fill_buf.memflush = uparams->fill_buf->memflush; 158 param.fill_buf = &fill_buf; 159 } else if (!uparams->benchmark_cmd[0]) { 160 fill_buf.buf_size = span; 161 fill_buf.memflush = true; 162 param.fill_buf = &fill_buf; 163 } 164 165 remove(RESULT_FILE_NAME); 166 167 ret = resctrl_val(test, uparams, &param); 168 if (ret) 169 return ret; 170 171 ret = check_results(&param, span, n); 172 if (ret && (get_vendor() == ARCH_INTEL) && !snc_kernel_support()) 173 ksft_print_msg("Kernel doesn't support Sub-NUMA Clustering but it is enabled on the system.\n"); 174 175 return ret; 176} 177 178static bool cmt_feature_check(const struct resctrl_test *test) 179{ 180 return test_resource_feature_check(test) && 181 resctrl_mon_feature_exists("L3_MON", "llc_occupancy"); 182} 183 184struct resctrl_test cmt_test = { 185 .name = "CMT", 186 .resource = "L3", 187 .feature_check = cmt_feature_check, 188 .run_test = cmt_run_test, 189 .cleanup = cmt_test_cleanup, 190};