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