1ecdbb911SFenghua Yu // SPDX-License-Identifier: GPL-2.0
2ecdbb911SFenghua Yu /*
3ecdbb911SFenghua Yu * Resctrl tests
4ecdbb911SFenghua Yu *
5ecdbb911SFenghua Yu * Copyright (C) 2018 Intel Corporation
6ecdbb911SFenghua Yu *
7ecdbb911SFenghua Yu * Authors:
8ecdbb911SFenghua Yu * Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
9ecdbb911SFenghua Yu * Fenghua Yu <fenghua.yu@intel.com>
10ecdbb911SFenghua Yu */
11ecdbb911SFenghua Yu #include "resctrl.h"
12ecdbb911SFenghua Yu
detect_vendor(void)136220f69eSShaopeng Tan static int detect_vendor(void)
1453f74fbeSBabu Moger {
1553f74fbeSBabu Moger FILE *inf = fopen("/proc/cpuinfo", "r");
166220f69eSShaopeng Tan int vendor_id = 0;
176220f69eSShaopeng Tan char *s = NULL;
1853f74fbeSBabu Moger char *res;
1953f74fbeSBabu Moger
2053f74fbeSBabu Moger if (!inf)
216220f69eSShaopeng Tan return vendor_id;
2253f74fbeSBabu Moger
2353f74fbeSBabu Moger res = fgrep(inf, "vendor_id");
2453f74fbeSBabu Moger
256220f69eSShaopeng Tan if (res)
266220f69eSShaopeng Tan s = strchr(res, ':');
2753f74fbeSBabu Moger
286220f69eSShaopeng Tan if (s && !strcmp(s, ": GenuineIntel\n"))
296220f69eSShaopeng Tan vendor_id = ARCH_INTEL;
306220f69eSShaopeng Tan else if (s && !strcmp(s, ": AuthenticAMD\n"))
316220f69eSShaopeng Tan vendor_id = ARCH_AMD;
326220f69eSShaopeng Tan
3353f74fbeSBabu Moger fclose(inf);
346220f69eSShaopeng Tan free(res);
356220f69eSShaopeng Tan return vendor_id;
366220f69eSShaopeng Tan }
376220f69eSShaopeng Tan
get_vendor(void)386220f69eSShaopeng Tan int get_vendor(void)
396220f69eSShaopeng Tan {
406220f69eSShaopeng Tan static int vendor = -1;
416220f69eSShaopeng Tan
426220f69eSShaopeng Tan if (vendor == -1)
436220f69eSShaopeng Tan vendor = detect_vendor();
446220f69eSShaopeng Tan if (vendor == 0)
456220f69eSShaopeng Tan ksft_print_msg("Can not get vendor info...\n");
466220f69eSShaopeng Tan
476220f69eSShaopeng Tan return vendor;
4853f74fbeSBabu Moger }
4953f74fbeSBabu Moger
cmd_help(void)50ecdbb911SFenghua Yu static void cmd_help(void)
51ecdbb911SFenghua Yu {
5278941183SFenghua Yu printf("usage: resctrl_tests [-h] [-b \"benchmark_cmd [options]\"] [-t test list] [-n no_of_bits]\n");
53f29838e6SReinette Chatre printf("\t-b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CMT\n");
54ecdbb911SFenghua Yu printf("\t default benchmark is builtin fill_buf\n");
55ecdbb911SFenghua Yu printf("\t-t test list: run tests specified in the test list, ");
562f320911SFenghua Yu printf("e.g. -t mbm,mba,cmt,cat\n");
5778941183SFenghua Yu printf("\t-n no_of_bits: run cache tests using specified no of bits in cache bit mask\n");
5878941183SFenghua Yu printf("\t-p cpu_no: specify CPU number to run the test. 1 is default\n");
59ecdbb911SFenghua Yu printf("\t-h: help\n");
60ecdbb911SFenghua Yu }
61ecdbb911SFenghua Yu
tests_cleanup(void)62ecdbb911SFenghua Yu void tests_cleanup(void)
63ecdbb911SFenghua Yu {
64ecdbb911SFenghua Yu mbm_test_cleanup();
6501fee6b4SFenghua Yu mba_test_cleanup();
662f320911SFenghua Yu cmt_test_cleanup();
67790bf585SFenghua Yu cat_test_cleanup();
68ecdbb911SFenghua Yu }
69ecdbb911SFenghua Yu
test_prepare(void)70*7989f7adSIlpo Järvinen static int test_prepare(void)
71*7989f7adSIlpo Järvinen {
72*7989f7adSIlpo Järvinen int res;
73*7989f7adSIlpo Järvinen
74*7989f7adSIlpo Järvinen res = signal_handler_register();
75*7989f7adSIlpo Järvinen if (res) {
76*7989f7adSIlpo Järvinen ksft_print_msg("Failed to register signal handler\n");
77*7989f7adSIlpo Järvinen return res;
78*7989f7adSIlpo Järvinen }
79*7989f7adSIlpo Järvinen
80*7989f7adSIlpo Järvinen res = mount_resctrlfs();
81*7989f7adSIlpo Järvinen if (res) {
82*7989f7adSIlpo Järvinen signal_handler_unregister();
83*7989f7adSIlpo Järvinen ksft_print_msg("Failed to mount resctrl FS\n");
84*7989f7adSIlpo Järvinen return res;
85*7989f7adSIlpo Järvinen }
86*7989f7adSIlpo Järvinen return 0;
87*7989f7adSIlpo Järvinen }
88*7989f7adSIlpo Järvinen
test_cleanup(void)89*7989f7adSIlpo Järvinen static void test_cleanup(void)
90*7989f7adSIlpo Järvinen {
91*7989f7adSIlpo Järvinen umount_resctrlfs();
92*7989f7adSIlpo Järvinen signal_handler_unregister();
93*7989f7adSIlpo Järvinen }
94*7989f7adSIlpo Järvinen
run_mbm_test(const char * const * benchmark_cmd,int cpu_no)95b1d34cb5SIlpo Järvinen static void run_mbm_test(const char * const *benchmark_cmd, int cpu_no)
96c9fb4e7cSFenghua Yu {
97c9fb4e7cSFenghua Yu int res;
98c9fb4e7cSFenghua Yu
99c9fb4e7cSFenghua Yu ksft_print_msg("Starting MBM BW change ...\n");
100f1dd7198SFenghua Yu
101*7989f7adSIlpo Järvinen if (test_prepare()) {
102*7989f7adSIlpo Järvinen ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
103caddc0fbSIlpo Järvinen return;
104caddc0fbSIlpo Järvinen }
105caddc0fbSIlpo Järvinen
10607717178SIlpo Järvinen if (!validate_resctrl_feature_request("L3_MON", "mbm_total_bytes") ||
10707717178SIlpo Järvinen !validate_resctrl_feature_request("L3_MON", "mbm_local_bytes") ||
10807717178SIlpo Järvinen (get_vendor() != ARCH_INTEL)) {
109f1dd7198SFenghua Yu ksft_test_result_skip("Hardware does not support MBM or MBM is disabled\n");
110*7989f7adSIlpo Järvinen goto cleanup;
111f1dd7198SFenghua Yu }
112f1dd7198SFenghua Yu
113ef8454afSIlpo Järvinen res = mbm_bw_change(cpu_no, benchmark_cmd);
114c9fb4e7cSFenghua Yu ksft_test_result(!res, "MBM: bw change\n");
115d577380dSShaopeng Tan if ((get_vendor() == ARCH_INTEL) && res)
116d577380dSShaopeng Tan ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
117caddc0fbSIlpo Järvinen
118*7989f7adSIlpo Järvinen cleanup:
119*7989f7adSIlpo Järvinen test_cleanup();
120c9fb4e7cSFenghua Yu }
121c9fb4e7cSFenghua Yu
run_mba_test(const char * const * benchmark_cmd,int cpu_no)122b1d34cb5SIlpo Järvinen static void run_mba_test(const char * const *benchmark_cmd, int cpu_no)
123c9fb4e7cSFenghua Yu {
124c9fb4e7cSFenghua Yu int res;
125c9fb4e7cSFenghua Yu
126c9fb4e7cSFenghua Yu ksft_print_msg("Starting MBA Schemata change ...\n");
127f1dd7198SFenghua Yu
128*7989f7adSIlpo Järvinen if (test_prepare()) {
129*7989f7adSIlpo Järvinen ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
130caddc0fbSIlpo Järvinen return;
131caddc0fbSIlpo Järvinen }
132caddc0fbSIlpo Järvinen
133a8eba047SIlpo Järvinen if (!validate_resctrl_feature_request("MB", NULL) ||
134a8eba047SIlpo Järvinen !validate_resctrl_feature_request("L3_MON", "mbm_local_bytes") ||
135a8eba047SIlpo Järvinen (get_vendor() != ARCH_INTEL)) {
136f1dd7198SFenghua Yu ksft_test_result_skip("Hardware does not support MBA or MBA is disabled\n");
137*7989f7adSIlpo Järvinen goto cleanup;
138f1dd7198SFenghua Yu }
139f1dd7198SFenghua Yu
140fd7a4c55SIlpo Järvinen res = mba_schemata_change(cpu_no, benchmark_cmd);
141c9fb4e7cSFenghua Yu ksft_test_result(!res, "MBA: schemata change\n");
142caddc0fbSIlpo Järvinen
143*7989f7adSIlpo Järvinen cleanup:
144*7989f7adSIlpo Järvinen test_cleanup();
145c9fb4e7cSFenghua Yu }
146c9fb4e7cSFenghua Yu
run_cmt_test(const char * const * benchmark_cmd,int cpu_no)147b1d34cb5SIlpo Järvinen static void run_cmt_test(const char * const *benchmark_cmd, int cpu_no)
148c9fb4e7cSFenghua Yu {
149c9fb4e7cSFenghua Yu int res;
150c9fb4e7cSFenghua Yu
151c9fb4e7cSFenghua Yu ksft_print_msg("Starting CMT test ...\n");
152caddc0fbSIlpo Järvinen
153*7989f7adSIlpo Järvinen if (test_prepare()) {
154*7989f7adSIlpo Järvinen ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
155caddc0fbSIlpo Järvinen return;
156caddc0fbSIlpo Järvinen }
157caddc0fbSIlpo Järvinen
158a8eba047SIlpo Järvinen if (!validate_resctrl_feature_request("L3_MON", "llc_occupancy") ||
159a8eba047SIlpo Järvinen !validate_resctrl_feature_request("L3", NULL)) {
160f1dd7198SFenghua Yu ksft_test_result_skip("Hardware does not support CMT or CMT is disabled\n");
161*7989f7adSIlpo Järvinen goto cleanup;
162f1dd7198SFenghua Yu }
163f1dd7198SFenghua Yu
164c9fb4e7cSFenghua Yu res = cmt_resctrl_val(cpu_no, 5, benchmark_cmd);
165c9fb4e7cSFenghua Yu ksft_test_result(!res, "CMT: test\n");
166d577380dSShaopeng Tan if ((get_vendor() == ARCH_INTEL) && res)
167d577380dSShaopeng Tan ksft_print_msg("Intel CMT may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
168caddc0fbSIlpo Järvinen
169*7989f7adSIlpo Järvinen cleanup:
170*7989f7adSIlpo Järvinen test_cleanup();
171c9fb4e7cSFenghua Yu }
172c9fb4e7cSFenghua Yu
run_cat_test(int cpu_no,int no_of_bits)173c9fb4e7cSFenghua Yu static void run_cat_test(int cpu_no, int no_of_bits)
174c9fb4e7cSFenghua Yu {
175c9fb4e7cSFenghua Yu int res;
176c9fb4e7cSFenghua Yu
177c9fb4e7cSFenghua Yu ksft_print_msg("Starting CAT test ...\n");
178f1dd7198SFenghua Yu
179*7989f7adSIlpo Järvinen if (test_prepare()) {
180*7989f7adSIlpo Järvinen ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
181caddc0fbSIlpo Järvinen return;
182caddc0fbSIlpo Järvinen }
183caddc0fbSIlpo Järvinen
18407717178SIlpo Järvinen if (!validate_resctrl_feature_request("L3", NULL)) {
185f1dd7198SFenghua Yu ksft_test_result_skip("Hardware does not support CAT or CAT is disabled\n");
186*7989f7adSIlpo Järvinen goto cleanup;
187f1dd7198SFenghua Yu }
188f1dd7198SFenghua Yu
189c9fb4e7cSFenghua Yu res = cat_perf_miss_val(cpu_no, no_of_bits, "L3");
190c9fb4e7cSFenghua Yu ksft_test_result(!res, "CAT: test\n");
191caddc0fbSIlpo Järvinen
192*7989f7adSIlpo Järvinen cleanup:
193*7989f7adSIlpo Järvinen test_cleanup();
194c9fb4e7cSFenghua Yu }
195c9fb4e7cSFenghua Yu
main(int argc,char ** argv)196ecdbb911SFenghua Yu int main(int argc, char **argv)
197ecdbb911SFenghua Yu {
1982f320911SFenghua Yu bool has_ben = false, mbm_test = true, mba_test = true, cmt_test = true;
19967a86643SIlpo Järvinen int c, cpu_no = 1, argc_new = argc, i, no_of_bits = 0;
200b1d34cb5SIlpo Järvinen const char *benchmark_cmd[BENCHMARK_ARGS];
201ca2f4214SFenghua Yu int ben_ind, ben_count, tests = 0;
202b1d34cb5SIlpo Järvinen char *span_str = NULL;
203790bf585SFenghua Yu bool cat_test = true;
204b1d34cb5SIlpo Järvinen int ret;
205ecdbb911SFenghua Yu
206ecdbb911SFenghua Yu for (i = 0; i < argc; i++) {
207ecdbb911SFenghua Yu if (strcmp(argv[i], "-b") == 0) {
208ecdbb911SFenghua Yu ben_ind = i + 1;
209ecdbb911SFenghua Yu ben_count = argc - ben_ind;
210ecdbb911SFenghua Yu argc_new = ben_ind - 1;
211ecdbb911SFenghua Yu has_ben = true;
212ecdbb911SFenghua Yu break;
213ecdbb911SFenghua Yu }
214ecdbb911SFenghua Yu }
215ecdbb911SFenghua Yu
216d7af3d0dSFenghua Yu while ((c = getopt(argc_new, argv, "ht:b:n:p:")) != -1) {
217ecdbb911SFenghua Yu char *token;
218ecdbb911SFenghua Yu
219ecdbb911SFenghua Yu switch (c) {
220ecdbb911SFenghua Yu case 't':
221ecdbb911SFenghua Yu token = strtok(optarg, ",");
222ecdbb911SFenghua Yu
223ecdbb911SFenghua Yu mbm_test = false;
22401fee6b4SFenghua Yu mba_test = false;
2252f320911SFenghua Yu cmt_test = false;
226790bf585SFenghua Yu cat_test = false;
227ecdbb911SFenghua Yu while (token) {
22824286736SFenghua Yu if (!strncmp(token, MBM_STR, sizeof(MBM_STR))) {
229ecdbb911SFenghua Yu mbm_test = true;
230ca2f4214SFenghua Yu tests++;
23124286736SFenghua Yu } else if (!strncmp(token, MBA_STR, sizeof(MBA_STR))) {
23201fee6b4SFenghua Yu mba_test = true;
233ca2f4214SFenghua Yu tests++;
2342f320911SFenghua Yu } else if (!strncmp(token, CMT_STR, sizeof(CMT_STR))) {
2352f320911SFenghua Yu cmt_test = true;
236ca2f4214SFenghua Yu tests++;
23724286736SFenghua Yu } else if (!strncmp(token, CAT_STR, sizeof(CAT_STR))) {
238790bf585SFenghua Yu cat_test = true;
239ca2f4214SFenghua Yu tests++;
240ecdbb911SFenghua Yu } else {
241ecdbb911SFenghua Yu printf("invalid argument\n");
242ecdbb911SFenghua Yu
243ecdbb911SFenghua Yu return -1;
244ecdbb911SFenghua Yu }
2451421ec68SXiaochen Shen token = strtok(NULL, ",");
246ecdbb911SFenghua Yu }
247ecdbb911SFenghua Yu break;
248ecdbb911SFenghua Yu case 'p':
249ecdbb911SFenghua Yu cpu_no = atoi(optarg);
250ecdbb911SFenghua Yu break;
25178941183SFenghua Yu case 'n':
25278941183SFenghua Yu no_of_bits = atoi(optarg);
25309a67934SFenghua Yu if (no_of_bits <= 0) {
25409a67934SFenghua Yu printf("Bail out! invalid argument for no_of_bits\n");
25509a67934SFenghua Yu return -1;
25609a67934SFenghua Yu }
25778941183SFenghua Yu break;
258ecdbb911SFenghua Yu case 'h':
259ecdbb911SFenghua Yu cmd_help();
260ecdbb911SFenghua Yu
261ecdbb911SFenghua Yu return 0;
262ecdbb911SFenghua Yu default:
263ecdbb911SFenghua Yu printf("invalid argument\n");
264ecdbb911SFenghua Yu
265ecdbb911SFenghua Yu return -1;
266ecdbb911SFenghua Yu }
267ecdbb911SFenghua Yu }
268ecdbb911SFenghua Yu
269ca2f4214SFenghua Yu ksft_print_header();
270ecdbb911SFenghua Yu
271ecdbb911SFenghua Yu /*
272ecdbb911SFenghua Yu * Typically we need root privileges, because:
273ecdbb911SFenghua Yu * 1. We write to resctrl FS
274ecdbb911SFenghua Yu * 2. We execute perf commands
275ecdbb911SFenghua Yu */
276ecdbb911SFenghua Yu if (geteuid() != 0)
2773531d930SShaopeng Tan return ksft_exit_skip("Not running as root. Skipping...\n");
278ecdbb911SFenghua Yu
279ecdbb911SFenghua Yu if (has_ben) {
280d41a4550SIlpo Järvinen if (argc - ben_ind >= BENCHMARK_ARGS)
281d41a4550SIlpo Järvinen ksft_exit_fail_msg("Too long benchmark command.\n");
282d41a4550SIlpo Järvinen
283ecdbb911SFenghua Yu /* Extract benchmark command from command line. */
284b1d34cb5SIlpo Järvinen for (i = 0; i < argc - ben_ind; i++)
285b1d34cb5SIlpo Järvinen benchmark_cmd[i] = argv[i + ben_ind];
286ecdbb911SFenghua Yu benchmark_cmd[ben_count] = NULL;
287ecdbb911SFenghua Yu } else {
288ecdbb911SFenghua Yu /* If no benchmark is given by "-b" argument, use fill_buf. */
289b1d34cb5SIlpo Järvinen benchmark_cmd[0] = "fill_buf";
290b1d34cb5SIlpo Järvinen ret = asprintf(&span_str, "%u", DEFAULT_SPAN);
291b1d34cb5SIlpo Järvinen if (ret < 0)
292b1d34cb5SIlpo Järvinen ksft_exit_fail_msg("Out of memory!\n");
293b1d34cb5SIlpo Järvinen benchmark_cmd[1] = span_str;
294b1d34cb5SIlpo Järvinen benchmark_cmd[2] = "1";
295b1d34cb5SIlpo Järvinen benchmark_cmd[3] = "0";
296b1d34cb5SIlpo Järvinen benchmark_cmd[4] = "false";
297326baed2SIlpo Järvinen benchmark_cmd[5] = NULL;
298ecdbb911SFenghua Yu }
299ecdbb911SFenghua Yu
300ca2f4214SFenghua Yu if (!check_resctrlfs_support())
3013531d930SShaopeng Tan return ksft_exit_skip("resctrl FS does not exist. Enable X86_CPU_RESCTRL config option.\n");
302ca2f4214SFenghua Yu
303ede13008SIlpo Järvinen if (umount_resctrlfs())
304ede13008SIlpo Järvinen return ksft_exit_skip("resctrl FS unmount failed.\n");
305ede13008SIlpo Järvinen
306ecdbb911SFenghua Yu filter_dmesg();
307ecdbb911SFenghua Yu
308ca2f4214SFenghua Yu ksft_set_plan(tests ? : 4);
309ca2f4214SFenghua Yu
310c2b17907SPeter Newman if (mbm_test)
311ef8454afSIlpo Järvinen run_mbm_test(benchmark_cmd, cpu_no);
312ecdbb911SFenghua Yu
313c2b17907SPeter Newman if (mba_test)
314fd7a4c55SIlpo Järvinen run_mba_test(benchmark_cmd, cpu_no);
31501fee6b4SFenghua Yu
316c9fb4e7cSFenghua Yu if (cmt_test)
3177f3c980cSIlpo Järvinen run_cmt_test(benchmark_cmd, cpu_no);
31878941183SFenghua Yu
319c9fb4e7cSFenghua Yu if (cat_test)
320c9fb4e7cSFenghua Yu run_cat_test(cpu_no, no_of_bits);
321790bf585SFenghua Yu
322b1d34cb5SIlpo Järvinen free(span_str);
323c2b17907SPeter Newman ksft_finished();
324ecdbb911SFenghua Yu }
325