1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Cache Monitoring Technology (CQM) 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_cqm" 15#define NUM_OF_RUNS 5 16#define MAX_DIFF 2000000 17#define MAX_DIFF_PERCENT 15 18 19static int count_of_bits; 20static char cbm_mask[256]; 21static unsigned long long_mask; 22static unsigned long cache_size; 23 24static int cqm_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 42static void show_cache_info(unsigned long sum_llc_occu_resc, int no_of_bits, 43 unsigned long span) 44{ 45 unsigned long avg_llc_occu_resc = 0; 46 float diff_percent; 47 long avg_diff = 0; 48 bool res; 49 50 avg_llc_occu_resc = sum_llc_occu_resc / (NUM_OF_RUNS - 1); 51 avg_diff = (long)abs(span - avg_llc_occu_resc); 52 53 diff_percent = (((float)span - avg_llc_occu_resc) / span) * 100; 54 55 if ((abs((int)diff_percent) <= MAX_DIFF_PERCENT) || 56 (abs(avg_diff) <= MAX_DIFF)) 57 res = true; 58 else 59 res = false; 60 61 printf("%sok CQM: diff within %d, %d\%%\n", res ? "" : "not", 62 MAX_DIFF, (int)MAX_DIFF_PERCENT); 63 64 printf("# diff: %ld\n", avg_diff); 65 printf("# percent diff=%d\n", abs((int)diff_percent)); 66 printf("# Results are displayed in (Bytes)\n"); 67 printf("# Number of bits: %d\n", no_of_bits); 68 printf("# Avg_llc_occu_resc: %lu\n", avg_llc_occu_resc); 69 printf("# llc_occu_exp (span): %lu\n", span); 70 71 tests_run++; 72} 73 74static int check_results(struct resctrl_val_param *param, int no_of_bits) 75{ 76 char *token_array[8], temp[512]; 77 unsigned long sum_llc_occu_resc = 0; 78 int runs = 0; 79 FILE *fp; 80 81 printf("# checking for pass/fail\n"); 82 fp = fopen(param->filename, "r"); 83 if (!fp) { 84 perror("# Error in opening file\n"); 85 86 return errno; 87 } 88 89 while (fgets(temp, sizeof(temp), fp)) { 90 char *token = strtok(temp, ":\t"); 91 int fields = 0; 92 93 while (token) { 94 token_array[fields++] = token; 95 token = strtok(NULL, ":\t"); 96 } 97 98 /* Field 3 is llc occ resc value */ 99 if (runs > 0) 100 sum_llc_occu_resc += strtoul(token_array[3], NULL, 0); 101 runs++; 102 } 103 fclose(fp); 104 show_cache_info(sum_llc_occu_resc, no_of_bits, param->span); 105 106 return 0; 107} 108 109void cqm_test_cleanup(void) 110{ 111 remove(RESULT_FILE_NAME); 112} 113 114int cqm_resctrl_val(int cpu_no, int n, char **benchmark_cmd) 115{ 116 int ret, mum_resctrlfs; 117 118 cache_size = 0; 119 mum_resctrlfs = 1; 120 121 ret = remount_resctrlfs(mum_resctrlfs); 122 if (ret) 123 return ret; 124 125 if (!validate_resctrl_feature_request("cqm")) 126 return -1; 127 128 ret = get_cbm_mask("L3", cbm_mask); 129 if (ret) 130 return ret; 131 132 long_mask = strtoul(cbm_mask, NULL, 16); 133 134 ret = get_cache_size(cpu_no, "L3", &cache_size); 135 if (ret) 136 return ret; 137 printf("cache size :%lu\n", cache_size); 138 139 count_of_bits = count_bits(long_mask); 140 141 if (n < 1 || n > count_of_bits) { 142 printf("Invalid input value for numbr_of_bits n!\n"); 143 printf("Please Enter value in range 1 to %d\n", count_of_bits); 144 return -1; 145 } 146 147 struct resctrl_val_param param = { 148 .resctrl_val = CQM_STR, 149 .ctrlgrp = "c1", 150 .mongrp = "m1", 151 .cpu_no = cpu_no, 152 .mum_resctrlfs = 0, 153 .filename = RESULT_FILE_NAME, 154 .mask = ~(long_mask << n) & long_mask, 155 .span = cache_size * n / count_of_bits, 156 .num_of_runs = 0, 157 .setup = cqm_setup, 158 }; 159 160 if (strcmp(benchmark_cmd[0], "fill_buf") == 0) 161 sprintf(benchmark_cmd[1], "%lu", param.span); 162 163 remove(RESULT_FILE_NAME); 164 165 ret = resctrl_val(benchmark_cmd, ¶m); 166 if (ret) 167 return ret; 168 169 ret = check_results(¶m, n); 170 if (ret) 171 return ret; 172 173 cqm_test_cleanup(); 174 175 return 0; 176} 177