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 static int count_of_bits; 20 static char cbm_mask[256]; 21 static unsigned long long_mask; 22 static unsigned long cache_size; 23 24 static int cmt_setup(int num, ...) 25 { 26 struct resctrl_val_param *p; 27 va_list param; 28 29 va_start(param, num); 30 p = va_arg(param, struct resctrl_val_param *); 31 va_end(param); 32 33 /* Run NUM_OF_RUNS times */ 34 if (p->num_of_runs >= NUM_OF_RUNS) 35 return -1; 36 37 p->num_of_runs++; 38 39 return 0; 40 } 41 42 static int check_results(struct resctrl_val_param *param, int no_of_bits) 43 { 44 char *token_array[8], temp[512]; 45 unsigned long sum_llc_occu_resc = 0; 46 int runs = 0; 47 FILE *fp; 48 49 ksft_print_msg("Checking for pass/fail\n"); 50 fp = fopen(param->filename, "r"); 51 if (!fp) { 52 perror("# Error in opening file\n"); 53 54 return errno; 55 } 56 57 while (fgets(temp, sizeof(temp), fp)) { 58 char *token = strtok(temp, ":\t"); 59 int fields = 0; 60 61 while (token) { 62 token_array[fields++] = token; 63 token = strtok(NULL, ":\t"); 64 } 65 66 /* Field 3 is llc occ resc value */ 67 if (runs > 0) 68 sum_llc_occu_resc += strtoul(token_array[3], NULL, 0); 69 runs++; 70 } 71 fclose(fp); 72 73 return show_cache_info(sum_llc_occu_resc, no_of_bits, param->span, 74 MAX_DIFF, MAX_DIFF_PERCENT, NUM_OF_RUNS, 75 true, true); 76 } 77 78 void cmt_test_cleanup(void) 79 { 80 remove(RESULT_FILE_NAME); 81 } 82 83 int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd) 84 { 85 int ret, mum_resctrlfs; 86 87 cache_size = 0; 88 mum_resctrlfs = 1; 89 90 ret = remount_resctrlfs(mum_resctrlfs); 91 if (ret) 92 return ret; 93 94 if (!validate_resctrl_feature_request(CMT_STR)) 95 return -1; 96 97 ret = get_cbm_mask("L3", cbm_mask); 98 if (ret) 99 return ret; 100 101 long_mask = strtoul(cbm_mask, NULL, 16); 102 103 ret = get_cache_size(cpu_no, "L3", &cache_size); 104 if (ret) 105 return ret; 106 ksft_print_msg("Cache size :%lu\n", cache_size); 107 108 count_of_bits = count_bits(long_mask); 109 110 if (n < 1 || n > count_of_bits) { 111 ksft_print_msg("Invalid input value for numbr_of_bits n!\n"); 112 ksft_print_msg("Please enter value in range 1 to %d\n", count_of_bits); 113 return -1; 114 } 115 116 struct resctrl_val_param param = { 117 .resctrl_val = CMT_STR, 118 .ctrlgrp = "c1", 119 .mongrp = "m1", 120 .cpu_no = cpu_no, 121 .mum_resctrlfs = 0, 122 .filename = RESULT_FILE_NAME, 123 .mask = ~(long_mask << n) & long_mask, 124 .span = cache_size * n / count_of_bits, 125 .num_of_runs = 0, 126 .setup = cmt_setup, 127 }; 128 129 if (strcmp(benchmark_cmd[0], "fill_buf") == 0) 130 sprintf(benchmark_cmd[1], "%lu", param.span); 131 132 remove(RESULT_FILE_NAME); 133 134 ret = resctrl_val(benchmark_cmd, ¶m); 135 if (ret) 136 return ret; 137 138 ret = check_results(¶m, n); 139 if (ret) 140 return ret; 141 142 cmt_test_cleanup(); 143 144 return 0; 145 } 146