1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Memory Bandwidth Allocation (MBA) 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 13#define RESULT_FILE_NAME "result_mba" 14#define NUM_OF_RUNS 5 15#define MAX_DIFF 300 16#define ALLOCATION_MAX 100 17#define ALLOCATION_MIN 10 18#define ALLOCATION_STEP 10 19 20/* 21 * Change schemata percentage from 100 to 10%. Write schemata to specified 22 * con_mon grp, mon_grp in resctrl FS. 23 * For each allocation, run 5 times in order to get average values. 24 */ 25static int mba_setup(int num, ...) 26{ 27 static int runs_per_allocation, allocation = 100; 28 struct resctrl_val_param *p; 29 char allocation_str[64]; 30 va_list param; 31 int ret; 32 33 va_start(param, num); 34 p = va_arg(param, struct resctrl_val_param *); 35 va_end(param); 36 37 if (runs_per_allocation >= NUM_OF_RUNS) 38 runs_per_allocation = 0; 39 40 /* Only set up schemata once every NUM_OF_RUNS of allocations */ 41 if (runs_per_allocation++ != 0) 42 return 0; 43 44 if (allocation < ALLOCATION_MIN || allocation > ALLOCATION_MAX) 45 return -1; 46 47 sprintf(allocation_str, "%d", allocation); 48 49 ret = write_schemata(p->ctrlgrp, allocation_str, p->cpu_no, 50 p->resctrl_val); 51 if (ret < 0) 52 return ret; 53 54 allocation -= ALLOCATION_STEP; 55 56 return 0; 57} 58 59static void show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc) 60{ 61 int allocation, runs; 62 bool failed = false; 63 64 printf("# Results are displayed in (MB)\n"); 65 /* Memory bandwidth from 100% down to 10% */ 66 for (allocation = 0; allocation < ALLOCATION_MAX / ALLOCATION_STEP; 67 allocation++) { 68 unsigned long avg_bw_imc, avg_bw_resc; 69 unsigned long sum_bw_imc = 0, sum_bw_resc = 0; 70 unsigned long avg_diff; 71 72 /* 73 * The first run is discarded due to inaccurate value from 74 * phase transition. 75 */ 76 for (runs = NUM_OF_RUNS * allocation + 1; 77 runs < NUM_OF_RUNS * allocation + NUM_OF_RUNS ; runs++) { 78 sum_bw_imc += bw_imc[runs]; 79 sum_bw_resc += bw_resc[runs]; 80 } 81 82 avg_bw_imc = sum_bw_imc / (NUM_OF_RUNS - 1); 83 avg_bw_resc = sum_bw_resc / (NUM_OF_RUNS - 1); 84 avg_diff = labs((long)(avg_bw_resc - avg_bw_imc)); 85 86 printf("%sok MBA schemata percentage %u smaller than %d %%\n", 87 avg_diff > MAX_DIFF ? "not " : "", 88 ALLOCATION_MAX - ALLOCATION_STEP * allocation, 89 MAX_DIFF); 90 tests_run++; 91 printf("# avg_diff: %lu\n", avg_diff); 92 printf("# avg_bw_imc: %lu\n", avg_bw_imc); 93 printf("# avg_bw_resc: %lu\n", avg_bw_resc); 94 if (avg_diff > MAX_DIFF) 95 failed = true; 96 } 97 98 printf("%sok schemata change using MBA%s\n", failed ? "not " : "", 99 failed ? " # at least one test failed" : ""); 100 tests_run++; 101} 102 103static int check_results(void) 104{ 105 char *token_array[8], output[] = RESULT_FILE_NAME, temp[512]; 106 unsigned long bw_imc[1024], bw_resc[1024]; 107 int runs; 108 FILE *fp; 109 110 fp = fopen(output, "r"); 111 if (!fp) { 112 perror(output); 113 114 return errno; 115 } 116 117 runs = 0; 118 while (fgets(temp, sizeof(temp), fp)) { 119 char *token = strtok(temp, ":\t"); 120 int fields = 0; 121 122 while (token) { 123 token_array[fields++] = token; 124 token = strtok(NULL, ":\t"); 125 } 126 127 /* Field 3 is perf imc value */ 128 bw_imc[runs] = strtoul(token_array[3], NULL, 0); 129 /* Field 5 is resctrl value */ 130 bw_resc[runs] = strtoul(token_array[5], NULL, 0); 131 runs++; 132 } 133 134 fclose(fp); 135 136 show_mba_info(bw_imc, bw_resc); 137 138 return 0; 139} 140 141void mba_test_cleanup(void) 142{ 143 remove(RESULT_FILE_NAME); 144} 145 146int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd) 147{ 148 struct resctrl_val_param param = { 149 .resctrl_val = MBA_STR, 150 .ctrlgrp = "c1", 151 .mongrp = "m1", 152 .cpu_no = cpu_no, 153 .mum_resctrlfs = 1, 154 .filename = RESULT_FILE_NAME, 155 .bw_report = bw_report, 156 .setup = mba_setup 157 }; 158 int ret; 159 160 remove(RESULT_FILE_NAME); 161 162 if (!validate_resctrl_feature_request("mba")) 163 return -1; 164 165 ret = resctrl_val(benchmark_cmd, ¶m); 166 if (ret) 167 return ret; 168 169 ret = check_results(); 170 if (ret) 171 return ret; 172 173 mba_test_cleanup(); 174 175 return 0; 176} 177