1 // SPDX-License-Identifier: GPL-2.0
3 * Memory Bandwidth Allocation (MBA) test
5 * Copyright (C) 2018 Intel Corporation
8 * Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
9 * Fenghua Yu <fenghua.yu@intel.com>
13 #define RESULT_FILE_NAME "result_mba"
15 #define MAX_DIFF_PERCENT 8
16 #define ALLOCATION_MAX 100
17 #define ALLOCATION_MIN 10
18 #define ALLOCATION_STEP 10
20 static int mba_init(const struct resctrl_val_param
*param
, int domain_id
)
24 ret
= initialize_read_mem_bw_imc();
28 initialize_mem_bw_resctrl(param
, domain_id
);
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.
38 static int mba_setup(const struct resctrl_test
*test
,
39 const struct user_params
*uparams
,
40 struct resctrl_val_param
*p
)
42 static unsigned int allocation
= ALLOCATION_MIN
;
43 static int runs_per_allocation
;
44 char allocation_str
[64];
47 if (runs_per_allocation
>= NUM_OF_RUNS
)
48 runs_per_allocation
= 0;
50 /* Only set up schemata once every NUM_OF_RUNS of allocations */
51 if (runs_per_allocation
++ != 0)
54 if (allocation
> ALLOCATION_MAX
)
57 sprintf(allocation_str
, "%d", allocation
);
59 ret
= write_schemata(p
->ctrlgrp
, allocation_str
, uparams
->cpu
, test
->resource
);
63 allocation
+= ALLOCATION_STEP
;
68 static int mba_measure(const struct user_params
*uparams
,
69 struct resctrl_val_param
*param
, pid_t bm_pid
)
71 return measure_read_mem_bw(uparams
, param
, bm_pid
);
74 static bool show_mba_info(unsigned long *bw_imc
, unsigned long *bw_resc
)
76 unsigned int allocation
;
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
;
84 unsigned long sum_bw_imc
= 0, sum_bw_resc
= 0;
85 long avg_bw_imc
, avg_bw_resc
;
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
];
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",
100 ALLOCATION_MIN
+ ALLOCATION_STEP
* allocation
);
104 avg_diff
= (float)labs(avg_bw_resc
- avg_bw_imc
) / avg_bw_imc
;
105 avg_diff_per
= (int)(avg_diff
* 100);
107 ksft_print_msg("%s Check MBA diff within %d%% for schemata %u\n",
108 avg_diff_per
> MAX_DIFF_PERCENT
?
111 ALLOCATION_MIN
+ ALLOCATION_STEP
* allocation
);
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
)
120 ksft_print_msg("%s Check schemata change using MBA\n",
121 ret
? "Fail:" : "Pass:");
123 ksft_print_msg("At least one test failed\n");
128 static int check_results(void)
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];
136 fp
= fopen(output
, "r");
144 while (fgets(temp
, sizeof(temp
), fp
)) {
145 char *token
= strtok(temp
, ":\t");
149 token_array
[fields
++] = token
;
150 token
= strtok(NULL
, ":\t");
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);
162 return show_mba_info(bw_imc
, bw_resc
);
165 static void mba_test_cleanup(void)
167 remove(RESULT_FILE_NAME
);
170 static int mba_run_test(const struct resctrl_test
*test
, const struct user_params
*uparams
)
172 struct resctrl_val_param param
= {
174 .filename
= RESULT_FILE_NAME
,
177 .measure
= mba_measure
,
179 struct fill_buf_param fill_buf
= {};
182 remove(RESULT_FILE_NAME
);
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]) {
191 buf_size
= get_fill_buf_size(uparams
->cpu
, "L3");
194 fill_buf
.buf_size
= buf_size
;
195 fill_buf
.memflush
= true;
196 param
.fill_buf
= &fill_buf
;
199 ret
= resctrl_val(test
, uparams
, ¶m
);
203 ret
= check_results();
208 static bool mba_feature_check(const struct resctrl_test
*test
)
210 return test_resource_feature_check(test
) &&
211 resctrl_mon_feature_exists("L3_MON", "mbm_local_bytes");
214 struct resctrl_test mba_test
= {
217 .vendor_specific
= ARCH_INTEL
,
218 .feature_check
= mba_feature_check
,
219 .run_test
= mba_run_test
,
220 .cleanup
= mba_test_cleanup
,