xref: /openbmc/linux/tools/testing/selftests/resctrl/resctrl_tests.c (revision b97d6790d03b763eca08847a9a5869a4291b9f9a)
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