Loading...
Note: File does not exist in v4.10.11.
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_PERCENT 8
16#define ALLOCATION_MAX 100
17#define ALLOCATION_MIN 10
18#define ALLOCATION_STEP 10
19
20static int mba_init(const struct resctrl_val_param *param, int domain_id)
21{
22 int ret;
23
24 ret = initialize_read_mem_bw_imc();
25 if (ret)
26 return ret;
27
28 initialize_mem_bw_resctrl(param, domain_id);
29
30 return 0;
31}
32
33/*
34 * Change schemata percentage from 100 to 10%. Write schemata to specified
35 * con_mon grp, mon_grp in resctrl FS.
36 * For each allocation, run 5 times in order to get average values.
37 */
38static int mba_setup(const struct resctrl_test *test,
39 const struct user_params *uparams,
40 struct resctrl_val_param *p)
41{
42 static unsigned int allocation = ALLOCATION_MIN;
43 static int runs_per_allocation;
44 char allocation_str[64];
45 int ret;
46
47 if (runs_per_allocation >= NUM_OF_RUNS)
48 runs_per_allocation = 0;
49
50 /* Only set up schemata once every NUM_OF_RUNS of allocations */
51 if (runs_per_allocation++ != 0)
52 return 0;
53
54 if (allocation > ALLOCATION_MAX)
55 return END_OF_TESTS;
56
57 sprintf(allocation_str, "%d", allocation);
58
59 ret = write_schemata(p->ctrlgrp, allocation_str, uparams->cpu, test->resource);
60 if (ret < 0)
61 return ret;
62
63 allocation += ALLOCATION_STEP;
64
65 return 0;
66}
67
68static int mba_measure(const struct user_params *uparams,
69 struct resctrl_val_param *param, pid_t bm_pid)
70{
71 return measure_read_mem_bw(uparams, param, bm_pid);
72}
73
74static bool show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc)
75{
76 unsigned int allocation;
77 bool ret = false;
78 int runs;
79
80 ksft_print_msg("Results are displayed in (MB)\n");
81 /* Memory bandwidth from 100% down to 10% */
82 for (allocation = 0; allocation < ALLOCATION_MAX / ALLOCATION_STEP;
83 allocation++) {
84 unsigned long sum_bw_imc = 0, sum_bw_resc = 0;
85 long avg_bw_imc, avg_bw_resc;
86 int avg_diff_per;
87 float avg_diff;
88
89 for (runs = NUM_OF_RUNS * allocation;
90 runs < NUM_OF_RUNS * allocation + NUM_OF_RUNS ; runs++) {
91 sum_bw_imc += bw_imc[runs];
92 sum_bw_resc += bw_resc[runs];
93 }
94
95 avg_bw_imc = sum_bw_imc / NUM_OF_RUNS;
96 avg_bw_resc = sum_bw_resc / NUM_OF_RUNS;
97 if (avg_bw_imc < THROTTLE_THRESHOLD || avg_bw_resc < THROTTLE_THRESHOLD) {
98 ksft_print_msg("Bandwidth below threshold (%d MiB). Dropping results from MBA schemata %u.\n",
99 THROTTLE_THRESHOLD,
100 ALLOCATION_MIN + ALLOCATION_STEP * allocation);
101 continue;
102 }
103
104 avg_diff = (float)labs(avg_bw_resc - avg_bw_imc) / avg_bw_imc;
105 avg_diff_per = (int)(avg_diff * 100);
106
107 ksft_print_msg("%s Check MBA diff within %d%% for schemata %u\n",
108 avg_diff_per > MAX_DIFF_PERCENT ?
109 "Fail:" : "Pass:",
110 MAX_DIFF_PERCENT,
111 ALLOCATION_MIN + ALLOCATION_STEP * allocation);
112
113 ksft_print_msg("avg_diff_per: %d%%\n", avg_diff_per);
114 ksft_print_msg("avg_bw_imc: %lu\n", avg_bw_imc);
115 ksft_print_msg("avg_bw_resc: %lu\n", avg_bw_resc);
116 if (avg_diff_per > MAX_DIFF_PERCENT)
117 ret = true;
118 }
119
120 ksft_print_msg("%s Check schemata change using MBA\n",
121 ret ? "Fail:" : "Pass:");
122 if (ret)
123 ksft_print_msg("At least one test failed\n");
124
125 return ret;
126}
127
128static int check_results(void)
129{
130 unsigned long bw_resc[NUM_OF_RUNS * ALLOCATION_MAX / ALLOCATION_STEP];
131 unsigned long bw_imc[NUM_OF_RUNS * ALLOCATION_MAX / ALLOCATION_STEP];
132 char *token_array[8], output[] = RESULT_FILE_NAME, temp[512];
133 int runs;
134 FILE *fp;
135
136 fp = fopen(output, "r");
137 if (!fp) {
138 ksft_perror(output);
139
140 return -1;
141 }
142
143 runs = 0;
144 while (fgets(temp, sizeof(temp), fp)) {
145 char *token = strtok(temp, ":\t");
146 int fields = 0;
147
148 while (token) {
149 token_array[fields++] = token;
150 token = strtok(NULL, ":\t");
151 }
152
153 /* Field 3 is perf imc value */
154 bw_imc[runs] = strtoul(token_array[3], NULL, 0);
155 /* Field 5 is resctrl value */
156 bw_resc[runs] = strtoul(token_array[5], NULL, 0);
157 runs++;
158 }
159
160 fclose(fp);
161
162 return show_mba_info(bw_imc, bw_resc);
163}
164
165static void mba_test_cleanup(void)
166{
167 remove(RESULT_FILE_NAME);
168}
169
170static int mba_run_test(const struct resctrl_test *test, const struct user_params *uparams)
171{
172 struct resctrl_val_param param = {
173 .ctrlgrp = "c1",
174 .filename = RESULT_FILE_NAME,
175 .init = mba_init,
176 .setup = mba_setup,
177 .measure = mba_measure,
178 };
179 struct fill_buf_param fill_buf = {};
180 int ret;
181
182 remove(RESULT_FILE_NAME);
183
184 if (uparams->fill_buf) {
185 fill_buf.buf_size = uparams->fill_buf->buf_size;
186 fill_buf.memflush = uparams->fill_buf->memflush;
187 param.fill_buf = &fill_buf;
188 } else if (!uparams->benchmark_cmd[0]) {
189 ssize_t buf_size;
190
191 buf_size = get_fill_buf_size(uparams->cpu, "L3");
192 if (buf_size < 0)
193 return buf_size;
194 fill_buf.buf_size = buf_size;
195 fill_buf.memflush = true;
196 param.fill_buf = &fill_buf;
197 }
198
199 ret = resctrl_val(test, uparams, ¶m);
200 if (ret)
201 return ret;
202
203 ret = check_results();
204
205 return ret;
206}
207
208static bool mba_feature_check(const struct resctrl_test *test)
209{
210 return test_resource_feature_check(test) &&
211 resctrl_mon_feature_exists("L3_MON", "mbm_local_bytes");
212}
213
214struct resctrl_test mba_test = {
215 .name = "MBA",
216 .resource = "MB",
217 .vendor_specific = ARCH_INTEL,
218 .feature_check = mba_feature_check,
219 .run_test = mba_run_test,
220 .cleanup = mba_test_cleanup,
221};