1 // SPDX-License-Identifier: GPL-2.0
3 * Memory Bandwidth Monitoring (MBM) 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_mbm"
14 #define MAX_DIFF_PERCENT 8
18 show_bw_info(unsigned long *bw_imc
, unsigned long *bw_resc
, size_t span
)
20 unsigned long sum_bw_imc
= 0, sum_bw_resc
= 0;
21 long avg_bw_imc
= 0, avg_bw_resc
= 0;
22 int runs
, ret
, avg_diff_per
;
25 for (runs
= 0; runs
< NUM_OF_RUNS
; runs
++) {
26 sum_bw_imc
+= bw_imc
[runs
];
27 sum_bw_resc
+= bw_resc
[runs
];
30 avg_bw_imc
= sum_bw_imc
/ NUM_OF_RUNS
;
31 avg_bw_resc
= sum_bw_resc
/ NUM_OF_RUNS
;
32 avg_diff
= (float)labs(avg_bw_resc
- avg_bw_imc
) / avg_bw_imc
;
33 avg_diff_per
= (int)(avg_diff
* 100);
35 ret
= avg_diff_per
> MAX_DIFF_PERCENT
;
36 ksft_print_msg("%s Check MBM diff within %d%%\n",
37 ret
? "Fail:" : "Pass:", MAX_DIFF_PERCENT
);
38 ksft_print_msg("avg_diff_per: %d%%\n", avg_diff_per
);
40 ksft_print_msg("Span (MB): %zu\n", span
/ MB
);
41 ksft_print_msg("avg_bw_imc: %lu\n", avg_bw_imc
);
42 ksft_print_msg("avg_bw_resc: %lu\n", avg_bw_resc
);
47 static int check_results(size_t span
)
49 unsigned long bw_imc
[NUM_OF_RUNS
], bw_resc
[NUM_OF_RUNS
];
50 char temp
[1024], *token_array
[8];
51 char output
[] = RESULT_FILE_NAME
;
55 ksft_print_msg("Checking for pass/fail\n");
57 fp
= fopen(output
, "r");
65 while (fgets(temp
, sizeof(temp
), fp
)) {
66 char *token
= strtok(temp
, ":\t");
70 token_array
[i
++] = token
;
71 token
= strtok(NULL
, ":\t");
74 bw_resc
[runs
] = strtoul(token_array
[5], NULL
, 0);
75 bw_imc
[runs
] = strtoul(token_array
[3], NULL
, 0);
79 ret
= show_bw_info(bw_imc
, bw_resc
, span
);
86 static int mbm_init(const struct resctrl_val_param
*param
, int domain_id
)
90 ret
= initialize_read_mem_bw_imc();
94 initialize_mem_bw_resctrl(param
, domain_id
);
99 static int mbm_setup(const struct resctrl_test
*test
,
100 const struct user_params
*uparams
,
101 struct resctrl_val_param
*p
)
105 /* Run NUM_OF_RUNS times */
106 if (p
->num_of_runs
>= NUM_OF_RUNS
)
109 /* Set up shemata with 100% allocation on the first run. */
110 if (p
->num_of_runs
== 0 && resctrl_resource_exists("MB"))
111 ret
= write_schemata(p
->ctrlgrp
, "100", uparams
->cpu
, test
->resource
);
118 static int mbm_measure(const struct user_params
*uparams
,
119 struct resctrl_val_param
*param
, pid_t bm_pid
)
121 return measure_read_mem_bw(uparams
, param
, bm_pid
);
124 static void mbm_test_cleanup(void)
126 remove(RESULT_FILE_NAME
);
129 static int mbm_run_test(const struct resctrl_test
*test
, const struct user_params
*uparams
)
131 struct resctrl_val_param param
= {
133 .filename
= RESULT_FILE_NAME
,
136 .measure
= mbm_measure
,
138 struct fill_buf_param fill_buf
= {};
141 remove(RESULT_FILE_NAME
);
143 if (uparams
->fill_buf
) {
144 fill_buf
.buf_size
= uparams
->fill_buf
->buf_size
;
145 fill_buf
.memflush
= uparams
->fill_buf
->memflush
;
146 param
.fill_buf
= &fill_buf
;
147 } else if (!uparams
->benchmark_cmd
[0]) {
150 buf_size
= get_fill_buf_size(uparams
->cpu
, "L3");
153 fill_buf
.buf_size
= buf_size
;
154 fill_buf
.memflush
= true;
155 param
.fill_buf
= &fill_buf
;
158 ret
= resctrl_val(test
, uparams
, ¶m
);
162 ret
= check_results(param
.fill_buf
? param
.fill_buf
->buf_size
: 0);
163 if (ret
&& (get_vendor() == ARCH_INTEL
))
164 ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
169 static bool mbm_feature_check(const struct resctrl_test
*test
)
171 return resctrl_mon_feature_exists("L3_MON", "mbm_total_bytes") &&
172 resctrl_mon_feature_exists("L3_MON", "mbm_local_bytes");
175 struct resctrl_test mbm_test
= {
178 .vendor_specific
= ARCH_INTEL
,
179 .feature_check
= mbm_feature_check
,
180 .run_test
= mbm_run_test
,
181 .cleanup
= mbm_test_cleanup
,