xref: /linux/tools/testing/selftests/resctrl/resctrl_val.c (revision fd38cbee26944f8f2bcbea23d71a23b4b1813e9e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Memory bandwidth monitoring and allocation library
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 UNCORE_IMC		"uncore_imc"
14 #define READ_FILE_NAME		"cas_count_read"
15 #define DYN_PMU_PATH		"/sys/bus/event_source/devices"
16 #define SCALE			0.00006103515625
17 #define MAX_IMCS		40
18 #define MAX_TOKENS		5
19 
20 #define CON_MBM_LOCAL_BYTES_PATH		\
21 	"%s/%s/mon_data/mon_L3_%02d/mbm_local_bytes"
22 
23 struct membw_read_format {
24 	__u64 value;         /* The value of the event */
25 	__u64 time_enabled;  /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
26 	__u64 time_running;  /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
27 	__u64 id;            /* if PERF_FORMAT_ID */
28 };
29 
30 struct imc_counter_config {
31 	struct list_head entry;
32 	__u32 type;
33 	__u64 event;
34 	__u64 umask;
35 	struct perf_event_attr pe;
36 	int fd;
37 };
38 
39 static char mbm_total_path[1024];
40 static int imcs;
41 static struct imc_counter_config imc_counters_config[MAX_IMCS];
42 LIST_HEAD(imc_counters_list);
43 static const struct resctrl_test *current_test;
44 
45 static void read_mem_bw_initialize_perf_event_attr(int i)
46 {
47 	memset(&imc_counters_config[i].pe, 0,
48 	       sizeof(struct perf_event_attr));
49 	imc_counters_config[i].pe.type = imc_counters_config[i].type;
50 	imc_counters_config[i].pe.size = sizeof(struct perf_event_attr);
51 	imc_counters_config[i].pe.disabled = 1;
52 	imc_counters_config[i].pe.inherit = 1;
53 	imc_counters_config[i].pe.exclude_guest = 0;
54 	imc_counters_config[i].pe.config =
55 		imc_counters_config[i].umask << 8 |
56 		imc_counters_config[i].event;
57 	imc_counters_config[i].pe.sample_type = PERF_SAMPLE_IDENTIFIER;
58 	imc_counters_config[i].pe.read_format =
59 		PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
60 }
61 
62 static void read_mem_bw_ioctl_perf_event_ioc_reset_enable(int i)
63 {
64 	ioctl(imc_counters_config[i].fd, PERF_EVENT_IOC_RESET, 0);
65 	ioctl(imc_counters_config[i].fd, PERF_EVENT_IOC_ENABLE, 0);
66 }
67 
68 static void read_mem_bw_ioctl_perf_event_ioc_disable(int i)
69 {
70 	ioctl(imc_counters_config[i].fd, PERF_EVENT_IOC_DISABLE, 0);
71 }
72 
73 /*
74  * get_read_event_and_umask:	Parse config into event and umask
75  * @cas_count_cfg:	Config
76  * @count:		iMC number
77  */
78 static void get_read_event_and_umask(char *cas_count_cfg, unsigned int count)
79 {
80 	char *token[MAX_TOKENS];
81 	int i = 0;
82 
83 	token[0] = strtok(cas_count_cfg, "=,");
84 
85 	for (i = 1; i < MAX_TOKENS; i++)
86 		token[i] = strtok(NULL, "=,");
87 
88 	for (i = 0; i < MAX_TOKENS - 1; i++) {
89 		if (!token[i])
90 			break;
91 		if (strcmp(token[i], "event") == 0)
92 			imc_counters_config[count].event = strtol(token[i + 1], NULL, 16);
93 		if (strcmp(token[i], "umask") == 0)
94 			imc_counters_config[count].umask = strtol(token[i + 1], NULL, 16);
95 	}
96 }
97 
98 static int open_perf_read_event(int i, int cpu_no)
99 {
100 	imc_counters_config[i].fd =
101 		perf_event_open(&imc_counters_config[i].pe, -1, cpu_no, -1,
102 				PERF_FLAG_FD_CLOEXEC);
103 
104 	if (imc_counters_config[i].fd == -1) {
105 		fprintf(stderr, "Error opening leader %llx\n",
106 			imc_counters_config[i].pe.config);
107 
108 		return -1;
109 	}
110 
111 	return 0;
112 }
113 
114 static int parse_imc_read_bw_events(char *imc_dir, unsigned int type,
115 				    unsigned int *count)
116 {
117 	char imc_events_dir[PATH_MAX], imc_counter_cfg[PATH_MAX];
118 	struct imc_counter_config *imc_counter;
119 	unsigned int orig_count = *count;
120 	char cas_count_cfg[1024];
121 	struct dirent *ep;
122 	int path_len;
123 	int ret = -1;
124 	int num_cfg;
125 	FILE *fp;
126 	DIR *dp;
127 
128 	path_len = snprintf(imc_events_dir, sizeof(imc_events_dir), "%sevents",
129 			    imc_dir);
130 	if (path_len >= sizeof(imc_events_dir)) {
131 		ksft_print_msg("Unable to create path to %sevents\n", imc_dir);
132 		goto out;
133 	}
134 
135 	dp = opendir(imc_events_dir);
136 	if (!dp) {
137 		ksft_perror("Unable to open PMU events directory");
138 		goto out;
139 	}
140 
141 	while ((ep = readdir(dp))) {
142 		/*
143 		 * Parse all event files with READ_FILE_NAME prefix that
144 		 * contain the event number and umask. Skip files containing
145 		 * "." that contain unused properties of event.
146 		 */
147 		if (!strstr(ep->d_name, READ_FILE_NAME) ||
148 		    strchr(ep->d_name, '.'))
149 			continue;
150 
151 		path_len = snprintf(imc_counter_cfg, sizeof(imc_counter_cfg),
152 				    "%s/%s", imc_events_dir, ep->d_name);
153 		if (path_len >= sizeof(imc_counter_cfg)) {
154 			ksft_print_msg("Unable to create path to %s/%s\n",
155 				       imc_events_dir, ep->d_name);
156 			goto out_close;
157 		}
158 		fp = fopen(imc_counter_cfg, "r");
159 		if (!fp) {
160 			ksft_perror("Failed to open iMC config file");
161 			goto out_close;
162 		}
163 		num_cfg = fscanf(fp, "%1023s", cas_count_cfg);
164 		fclose(fp);
165 		if (num_cfg <= 0) {
166 			ksft_perror("Could not get iMC cas count read");
167 			goto out_close;
168 		}
169 		if (*count >= MAX_IMCS) {
170 			ksft_print_msg("Maximum iMC count exceeded\n");
171 			goto out_close;
172 		}
173 		imc_counter = calloc(1, sizeof(*imc_counter));
174 		if (!imc_counter) {
175 			ksft_perror("Unable to allocate memory for iMC counters");
176 			goto out_close;
177 		}
178 
179 		imc_counters_config[*count].type = type;
180 		get_read_event_and_umask(cas_count_cfg, *count);
181 		/* Do not fail after incrementing *count. */
182 		*count += 1;
183 		list_add(&imc_counter->entry, &imc_counters_list);
184 	}
185 	if (*count == orig_count) {
186 		ksft_print_msg("Unable to find events in %s\n", imc_events_dir);
187 		goto out_close;
188 	}
189 	ret = 0;
190 out_close:
191 	closedir(dp);
192 out:
193 	if (ret)
194 		cleanup_read_mem_bw_imc();
195 
196 	return ret;
197 }
198 
199 /* Get type and config of an iMC counter's read event. */
200 static int read_from_imc_dir(char *imc_dir, unsigned int *count)
201 {
202 	char imc_counter_type[PATH_MAX];
203 	unsigned int type;
204 	int path_len;
205 	FILE *fp;
206 	int ret;
207 
208 	/* Get type of iMC counter */
209 	path_len = snprintf(imc_counter_type, sizeof(imc_counter_type),
210 			    "%s%s", imc_dir, "type");
211 	if (path_len >= sizeof(imc_counter_type)) {
212 		ksft_print_msg("Unable to create path to %s%s\n",
213 			       imc_dir, "type");
214 		return -1;
215 	}
216 	fp = fopen(imc_counter_type, "r");
217 	if (!fp) {
218 		ksft_perror("Failed to open iMC counter type file");
219 
220 		return -1;
221 	}
222 	ret = fscanf(fp, "%u", &type);
223 	fclose(fp);
224 	if (ret <= 0) {
225 		ksft_perror("Could not get iMC type");
226 		return -1;
227 	}
228 	ret = parse_imc_read_bw_events(imc_dir, type, count);
229 	if (ret) {
230 		ksft_print_msg("Unable to parse bandwidth event and umask\n");
231 		return ret;
232 	}
233 
234 	return 0;
235 }
236 
237 /*
238  * A system can have 'n' number of iMC (Integrated Memory Controller)
239  * counters, get that 'n'. Discover the properties of the available
240  * counters in support of needed performance measurement via perf.
241  * For each iMC counter get it's type and config. Also obtain each
242  * counter's event and umask for the memory read events that will be
243  * measured.
244  *
245  * Enumerate all these details into an array of structures.
246  *
247  * Return: >= 0 on success. < 0 on failure.
248  */
249 static int num_of_imcs(void)
250 {
251 	char imc_dir[512], *temp;
252 	unsigned int count = 0;
253 	struct dirent *ep;
254 	int ret;
255 	DIR *dp;
256 
257 	dp = opendir(DYN_PMU_PATH);
258 	if (dp) {
259 		while ((ep = readdir(dp))) {
260 			temp = strstr(ep->d_name, UNCORE_IMC);
261 			if (!temp)
262 				continue;
263 
264 			/*
265 			 * imc counters are named as "uncore_imc_<n>", hence
266 			 * increment the pointer to point to <n>. Note that
267 			 * sizeof(UNCORE_IMC) would count for null character as
268 			 * well and hence the last underscore character in
269 			 * uncore_imc'_' need not be counted.
270 			 */
271 			temp = temp + sizeof(UNCORE_IMC);
272 
273 			/*
274 			 * Some directories under "DYN_PMU_PATH" could have
275 			 * names like "uncore_imc_free_running", hence, check if
276 			 * first character is a numerical digit or not.
277 			 */
278 			if (temp[0] >= '0' && temp[0] <= '9') {
279 				sprintf(imc_dir, "%s/%s/", DYN_PMU_PATH,
280 					ep->d_name);
281 				ret = read_from_imc_dir(imc_dir, &count);
282 				if (ret) {
283 					closedir(dp);
284 
285 					return ret;
286 				}
287 			}
288 		}
289 		closedir(dp);
290 		if (count == 0) {
291 			ksft_print_msg("Unable to find iMC counters\n");
292 
293 			return -1;
294 		}
295 	} else {
296 		ksft_perror("Unable to open PMU directory");
297 
298 		return -1;
299 	}
300 
301 	return count;
302 }
303 
304 int initialize_read_mem_bw_imc(void)
305 {
306 	int imc;
307 
308 	imcs = num_of_imcs();
309 	if (imcs <= 0)
310 		return imcs;
311 
312 	/* Initialize perf_event_attr structures for all iMC's */
313 	for (imc = 0; imc < imcs; imc++)
314 		read_mem_bw_initialize_perf_event_attr(imc);
315 
316 	return 0;
317 }
318 
319 void cleanup_read_mem_bw_imc(void)
320 {
321 	struct imc_counter_config *imc_counter, *tmp;
322 
323 	list_for_each_entry_safe(imc_counter, tmp, &imc_counters_list, entry) {
324 		list_del(&imc_counter->entry);
325 		free(imc_counter);
326 	}
327 }
328 
329 static void perf_close_imc_read_mem_bw(void)
330 {
331 	int mc;
332 
333 	for (mc = 0; mc < imcs; mc++) {
334 		if (imc_counters_config[mc].fd != -1)
335 			close(imc_counters_config[mc].fd);
336 	}
337 }
338 
339 /*
340  * perf_open_imc_read_mem_bw - Open perf fds for IMCs
341  * @cpu_no: CPU number that the benchmark PID is bound to
342  *
343  * Return: = 0 on success. < 0 on failure.
344  */
345 static int perf_open_imc_read_mem_bw(int cpu_no)
346 {
347 	int imc, ret;
348 
349 	for (imc = 0; imc < imcs; imc++)
350 		imc_counters_config[imc].fd = -1;
351 
352 	for (imc = 0; imc < imcs; imc++) {
353 		ret = open_perf_read_event(imc, cpu_no);
354 		if (ret)
355 			goto close_fds;
356 	}
357 
358 	return 0;
359 
360 close_fds:
361 	perf_close_imc_read_mem_bw();
362 	return -1;
363 }
364 
365 /*
366  * do_imc_read_mem_bw_test - Perform memory bandwidth test
367  *
368  * Runs memory bandwidth test over one second period. Also, handles starting
369  * and stopping of the IMC perf counters around the test.
370  */
371 static void do_imc_read_mem_bw_test(void)
372 {
373 	int imc;
374 
375 	for (imc = 0; imc < imcs; imc++)
376 		read_mem_bw_ioctl_perf_event_ioc_reset_enable(imc);
377 
378 	sleep(1);
379 
380 	/* Stop counters after a second to get results. */
381 	for (imc = 0; imc < imcs; imc++)
382 		read_mem_bw_ioctl_perf_event_ioc_disable(imc);
383 }
384 
385 /*
386  * get_read_mem_bw_imc - Memory read bandwidth as reported by iMC counters
387  *
388  * Memory read bandwidth utilized by a process on a socket can be calculated
389  * using iMC counters' read events. Perf events are used to read these
390  * counters.
391  *
392  * Return: = 0 on success. < 0 on failure.
393  */
394 static int get_read_mem_bw_imc(float *bw_imc)
395 {
396 	float reads = 0, of_mul_read = 1;
397 	int imc;
398 
399 	/*
400 	 * Log read event values from all iMC counters into
401 	 * struct imc_counter_config.
402 	 * Take overflow into consideration before calculating total bandwidth.
403 	 */
404 	for (imc = 0; imc < imcs; imc++) {
405 		struct membw_read_format measurement;
406 		struct imc_counter_config *r =
407 			&imc_counters_config[imc];
408 
409 		if (read(r->fd, &measurement, sizeof(measurement)) == -1) {
410 			ksft_perror("Couldn't get read bandwidth through iMC");
411 			return -1;
412 		}
413 
414 		__u64 r_time_enabled = measurement.time_enabled;
415 		__u64 r_time_running = measurement.time_running;
416 
417 		if (r_time_enabled != r_time_running)
418 			of_mul_read = (float)r_time_enabled /
419 					(float)r_time_running;
420 
421 		reads += measurement.value * of_mul_read * SCALE;
422 	}
423 
424 	*bw_imc = reads;
425 	return 0;
426 }
427 
428 /*
429  * initialize_mem_bw_resctrl:	Appropriately populate "mbm_total_path"
430  * @param:	Parameters passed to resctrl_val()
431  * @domain_id:	Domain ID (cache ID; for MB, L3 cache ID)
432  */
433 void initialize_mem_bw_resctrl(const struct resctrl_val_param *param,
434 			       int domain_id)
435 {
436 	sprintf(mbm_total_path, CON_MBM_LOCAL_BYTES_PATH, RESCTRL_PATH,
437 		param->ctrlgrp, domain_id);
438 }
439 
440 /*
441  * Open file to read MBM local bytes from resctrl FS
442  */
443 static FILE *open_mem_bw_resctrl(const char *mbm_bw_file)
444 {
445 	FILE *fp;
446 
447 	fp = fopen(mbm_bw_file, "r");
448 	if (!fp)
449 		ksft_perror("Failed to open total memory bandwidth file");
450 
451 	return fp;
452 }
453 
454 /*
455  * Get MBM Local bytes as reported by resctrl FS
456  */
457 static int get_mem_bw_resctrl(FILE *fp, unsigned long *mbm_total)
458 {
459 	if (fscanf(fp, "%lu\n", mbm_total) <= 0) {
460 		ksft_perror("Could not get MBM local bytes");
461 		return -1;
462 	}
463 	return 0;
464 }
465 
466 static pid_t bm_pid;
467 
468 void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
469 {
470 	/* Only kill child after bm_pid is set after fork() */
471 	if (bm_pid)
472 		kill(bm_pid, SIGKILL);
473 	umount_resctrlfs();
474 	if (current_test && current_test->cleanup)
475 		current_test->cleanup();
476 	ksft_print_msg("Ending\n\n");
477 
478 	exit(EXIT_SUCCESS);
479 }
480 
481 /*
482  * Register CTRL-C handler for parent, as it has to kill
483  * child process before exiting.
484  */
485 int signal_handler_register(const struct resctrl_test *test)
486 {
487 	struct sigaction sigact = {};
488 	int ret = 0;
489 
490 	bm_pid = 0;
491 
492 	current_test = test;
493 	sigact.sa_sigaction = ctrlc_handler;
494 	sigemptyset(&sigact.sa_mask);
495 	sigact.sa_flags = SA_SIGINFO;
496 	if (sigaction(SIGINT, &sigact, NULL) ||
497 	    sigaction(SIGTERM, &sigact, NULL) ||
498 	    sigaction(SIGHUP, &sigact, NULL)) {
499 		ksft_perror("sigaction");
500 		ret = -1;
501 	}
502 	return ret;
503 }
504 
505 /*
506  * Reset signal handler to SIG_DFL.
507  * Non-Value return because the caller should keep
508  * the error code of other path even if sigaction fails.
509  */
510 void signal_handler_unregister(void)
511 {
512 	struct sigaction sigact = {};
513 
514 	current_test = NULL;
515 	sigact.sa_handler = SIG_DFL;
516 	sigemptyset(&sigact.sa_mask);
517 	if (sigaction(SIGINT, &sigact, NULL) ||
518 	    sigaction(SIGTERM, &sigact, NULL) ||
519 	    sigaction(SIGHUP, &sigact, NULL)) {
520 		ksft_perror("sigaction");
521 	}
522 }
523 
524 /*
525  * print_results_bw:	the memory bandwidth results are stored in a file
526  * @filename:		file that stores the results
527  * @bm_pid:		child pid that runs benchmark
528  * @bw_imc:		perf imc counter value
529  * @bw_resc:		memory bandwidth value
530  *
531  * Return:		0 on success, < 0 on error.
532  */
533 static int print_results_bw(char *filename, pid_t bm_pid, float bw_imc,
534 			    unsigned long bw_resc)
535 {
536 	unsigned long diff = fabs(bw_imc - bw_resc);
537 	FILE *fp;
538 
539 	if (strcmp(filename, "stdio") == 0 || strcmp(filename, "stderr") == 0) {
540 		printf("Pid: %d \t Mem_BW_iMC: %f \t ", (int)bm_pid, bw_imc);
541 		printf("Mem_BW_resc: %lu \t Difference: %lu\n", bw_resc, diff);
542 	} else {
543 		fp = fopen(filename, "a");
544 		if (!fp) {
545 			ksft_perror("Cannot open results file");
546 
547 			return -1;
548 		}
549 		if (fprintf(fp, "Pid: %d \t Mem_BW_iMC: %f \t Mem_BW_resc: %lu \t Difference: %lu\n",
550 			    (int)bm_pid, bw_imc, bw_resc, diff) <= 0) {
551 			ksft_print_msg("Could not log results\n");
552 			fclose(fp);
553 
554 			return -1;
555 		}
556 		fclose(fp);
557 	}
558 
559 	return 0;
560 }
561 
562 /*
563  * measure_read_mem_bw - Measures read memory bandwidth numbers while benchmark runs
564  * @uparams:		User supplied parameters
565  * @param:		Parameters passed to resctrl_val()
566  * @bm_pid:		PID that runs the benchmark
567  *
568  * Measure memory bandwidth from resctrl and from another source which is
569  * perf imc value or could be something else if perf imc event is not
570  * available. Compare the two values to validate resctrl value. It takes
571  * 1 sec to measure the data.
572  * resctrl does not distinguish between read and write operations so
573  * its data includes all memory operations.
574  */
575 int measure_read_mem_bw(const struct user_params *uparams,
576 			struct resctrl_val_param *param, pid_t bm_pid)
577 {
578 	unsigned long bw_resc, bw_resc_start, bw_resc_end;
579 	FILE *mem_bw_fp;
580 	float bw_imc;
581 	int ret;
582 
583 	mem_bw_fp = open_mem_bw_resctrl(mbm_total_path);
584 	if (!mem_bw_fp)
585 		return -1;
586 
587 	ret = perf_open_imc_read_mem_bw(uparams->cpu);
588 	if (ret < 0)
589 		goto close_fp;
590 
591 	ret = get_mem_bw_resctrl(mem_bw_fp, &bw_resc_start);
592 	if (ret < 0)
593 		goto close_imc;
594 
595 	rewind(mem_bw_fp);
596 
597 	do_imc_read_mem_bw_test();
598 
599 	ret = get_mem_bw_resctrl(mem_bw_fp, &bw_resc_end);
600 	if (ret < 0)
601 		goto close_imc;
602 
603 	ret = get_read_mem_bw_imc(&bw_imc);
604 	if (ret < 0)
605 		goto close_imc;
606 
607 	perf_close_imc_read_mem_bw();
608 	fclose(mem_bw_fp);
609 
610 	bw_resc = (bw_resc_end - bw_resc_start) / MB;
611 
612 	return print_results_bw(param->filename, bm_pid, bw_imc, bw_resc);
613 
614 close_imc:
615 	perf_close_imc_read_mem_bw();
616 close_fp:
617 	fclose(mem_bw_fp);
618 	return ret;
619 }
620 
621 /*
622  * resctrl_val:	execute benchmark and measure memory bandwidth on
623  *			the benchmark
624  * @test:		test information structure
625  * @uparams:		user supplied parameters
626  * @param:		parameters passed to resctrl_val()
627  *
628  * Return:		0 when the test was run, < 0 on error.
629  */
630 int resctrl_val(const struct resctrl_test *test,
631 		const struct user_params *uparams,
632 		struct resctrl_val_param *param)
633 {
634 	unsigned char *buf = NULL;
635 	cpu_set_t old_affinity;
636 	int domain_id;
637 	int ret = 0;
638 	pid_t ppid;
639 
640 	if (strcmp(param->filename, "") == 0)
641 		sprintf(param->filename, "stdio");
642 
643 	ret = get_domain_id(test->resource, uparams->cpu, &domain_id);
644 	if (ret < 0) {
645 		ksft_print_msg("Could not get domain ID\n");
646 		return ret;
647 	}
648 
649 	ppid = getpid();
650 
651 	/* Taskset test to specified CPU. */
652 	ret = taskset_benchmark(ppid, uparams->cpu, &old_affinity);
653 	if (ret)
654 		return ret;
655 
656 	/* Write test to specified control & monitoring group in resctrl FS. */
657 	ret = write_bm_pid_to_resctrl(ppid, param->ctrlgrp, param->mongrp);
658 	if (ret)
659 		goto reset_affinity;
660 
661 	if (param->init) {
662 		ret = param->init(test, uparams, param, domain_id);
663 		if (ret)
664 			goto reset_affinity;
665 	}
666 
667 	/*
668 	 * If not running user provided benchmark, run the default
669 	 * "fill_buf". First phase of "fill_buf" is to prepare the
670 	 * buffer that the benchmark will operate on. No measurements
671 	 * are needed during this phase and prepared memory will be
672 	 * passed to next part of benchmark via copy-on-write thus
673 	 * no impact on the benchmark that relies on reading from
674 	 * memory only.
675 	 */
676 	if (param->fill_buf) {
677 		buf = alloc_buffer(param->fill_buf->buf_size,
678 				   param->fill_buf->memflush);
679 		if (!buf) {
680 			ret = -ENOMEM;
681 			goto reset_affinity;
682 		}
683 	}
684 
685 	fflush(stdout);
686 	bm_pid = fork();
687 	if (bm_pid == -1) {
688 		ret = -errno;
689 		ksft_perror("Unable to fork");
690 		goto free_buf;
691 	}
692 
693 	/*
694 	 * What needs to be measured runs in separate process until
695 	 * terminated.
696 	 */
697 	if (bm_pid == 0) {
698 		if (param->fill_buf)
699 			fill_cache_read(buf, param->fill_buf->buf_size, false);
700 		else if (uparams->benchmark_cmd[0])
701 			execvp(uparams->benchmark_cmd[0], (char **)uparams->benchmark_cmd);
702 		exit(EXIT_SUCCESS);
703 	}
704 
705 	ksft_print_msg("Benchmark PID: %d\n", (int)bm_pid);
706 
707 	/* Give benchmark enough time to fully run. */
708 	sleep(1);
709 
710 	/* Test runs until the callback setup() tells the test to stop. */
711 	while (1) {
712 		ret = param->setup(test, uparams, param);
713 		if (ret == END_OF_TESTS) {
714 			ret = 0;
715 			break;
716 		}
717 		if (ret < 0)
718 			break;
719 
720 		ret = param->measure(uparams, param, bm_pid);
721 		if (ret)
722 			break;
723 	}
724 
725 	kill(bm_pid, SIGKILL);
726 free_buf:
727 	free(buf);
728 reset_affinity:
729 	taskset_restore(ppid, &old_affinity);
730 	return ret;
731 }
732