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 END_OF_TESTS; 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; 86 87 cache_size = 0; 88 89 ret = remount_resctrlfs(true); 90 if (ret) 91 return ret; 92 93 if (!validate_resctrl_feature_request(CMT_STR)) 94 return -1; 95 96 ret = get_cbm_mask("L3", cbm_mask); 97 if (ret) 98 return ret; 99 100 long_mask = strtoul(cbm_mask, NULL, 16); 101 102 ret = get_cache_size(cpu_no, "L3", &cache_size); 103 if (ret) 104 return ret; 105 ksft_print_msg("Cache size :%lu\n", cache_size); 106 107 count_of_bits = count_bits(long_mask); 108 109 if (n < 1 || n > count_of_bits) { 110 ksft_print_msg("Invalid input value for numbr_of_bits n!\n"); 111 ksft_print_msg("Please enter value in range 1 to %d\n", count_of_bits); 112 return -1; 113 } 114 115 struct resctrl_val_param param = { 116 .resctrl_val = CMT_STR, 117 .ctrlgrp = "c1", 118 .mongrp = "m1", 119 .cpu_no = cpu_no, 120 .mum_resctrlfs = false, 121 .filename = RESULT_FILE_NAME, 122 .mask = ~(long_mask << n) & long_mask, 123 .span = cache_size * n / count_of_bits, 124 .num_of_runs = 0, 125 .setup = cmt_setup, 126 }; 127 128 if (strcmp(benchmark_cmd[0], "fill_buf") == 0) 129 sprintf(benchmark_cmd[1], "%lu", param.span); 130 131 remove(RESULT_FILE_NAME); 132 133 ret = resctrl_val(benchmark_cmd, ¶m); 134 if (ret) 135 goto out; 136 137 ret = check_results(¶m, n); 138 139 out: 140 cmt_test_cleanup(); 141 142 return ret; 143 } 144