xref: /openbmc/linux/tools/testing/selftests/resctrl/resctrlfs.c (revision 278002edb19bce2c628fafb0af936e77000f3a5b)
1591a6e85SSai Praneeth Prakhya // SPDX-License-Identifier: GPL-2.0
2591a6e85SSai Praneeth Prakhya /*
3591a6e85SSai Praneeth Prakhya  * Basic resctrl file system operations
4591a6e85SSai Praneeth Prakhya  *
5591a6e85SSai Praneeth Prakhya  * Copyright (C) 2018 Intel Corporation
6591a6e85SSai Praneeth Prakhya  *
7591a6e85SSai Praneeth Prakhya  * Authors:
8591a6e85SSai Praneeth Prakhya  *    Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
9591a6e85SSai Praneeth Prakhya  *    Fenghua Yu <fenghua.yu@intel.com>
10591a6e85SSai Praneeth Prakhya  */
1107717178SIlpo Järvinen #include <limits.h>
1207717178SIlpo Järvinen 
13591a6e85SSai Praneeth Prakhya #include "resctrl.h"
14591a6e85SSai Praneeth Prakhya 
find_resctrl_mount(char * buffer)15591a6e85SSai Praneeth Prakhya static int find_resctrl_mount(char *buffer)
16591a6e85SSai Praneeth Prakhya {
17591a6e85SSai Praneeth Prakhya 	FILE *mounts;
18591a6e85SSai Praneeth Prakhya 	char line[256], *fs, *mntpoint;
19591a6e85SSai Praneeth Prakhya 
20591a6e85SSai Praneeth Prakhya 	mounts = fopen("/proc/mounts", "r");
21591a6e85SSai Praneeth Prakhya 	if (!mounts) {
22384dc568SIlpo Järvinen 		ksft_perror("/proc/mounts");
23591a6e85SSai Praneeth Prakhya 		return -ENXIO;
24591a6e85SSai Praneeth Prakhya 	}
25591a6e85SSai Praneeth Prakhya 	while (!feof(mounts)) {
26591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, mounts))
27591a6e85SSai Praneeth Prakhya 			break;
28591a6e85SSai Praneeth Prakhya 		fs = strtok(line, " \t");
29591a6e85SSai Praneeth Prakhya 		if (!fs)
30591a6e85SSai Praneeth Prakhya 			continue;
31591a6e85SSai Praneeth Prakhya 		mntpoint = strtok(NULL, " \t");
32591a6e85SSai Praneeth Prakhya 		if (!mntpoint)
33591a6e85SSai Praneeth Prakhya 			continue;
34591a6e85SSai Praneeth Prakhya 		fs = strtok(NULL, " \t");
35591a6e85SSai Praneeth Prakhya 		if (!fs)
36591a6e85SSai Praneeth Prakhya 			continue;
37591a6e85SSai Praneeth Prakhya 		if (strcmp(fs, "resctrl"))
38591a6e85SSai Praneeth Prakhya 			continue;
39591a6e85SSai Praneeth Prakhya 
40591a6e85SSai Praneeth Prakhya 		fclose(mounts);
41591a6e85SSai Praneeth Prakhya 		if (buffer)
42591a6e85SSai Praneeth Prakhya 			strncpy(buffer, mntpoint, 256);
43591a6e85SSai Praneeth Prakhya 
44591a6e85SSai Praneeth Prakhya 		return 0;
45591a6e85SSai Praneeth Prakhya 	}
46591a6e85SSai Praneeth Prakhya 
47591a6e85SSai Praneeth Prakhya 	fclose(mounts);
48591a6e85SSai Praneeth Prakhya 
49591a6e85SSai Praneeth Prakhya 	return -ENOENT;
50591a6e85SSai Praneeth Prakhya }
51591a6e85SSai Praneeth Prakhya 
52591a6e85SSai Praneeth Prakhya /*
536383851aSIlpo Järvinen  * mount_resctrlfs - Mount resctrl FS at /sys/fs/resctrl
54591a6e85SSai Praneeth Prakhya  *
556383851aSIlpo Järvinen  * Mounts resctrl FS. Fails if resctrl FS is already mounted to avoid
566383851aSIlpo Järvinen  * pre-existing settings interfering with the test results.
57591a6e85SSai Praneeth Prakhya  *
58591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
59591a6e85SSai Praneeth Prakhya  */
mount_resctrlfs(void)606383851aSIlpo Järvinen int mount_resctrlfs(void)
61591a6e85SSai Praneeth Prakhya {
62591a6e85SSai Praneeth Prakhya 	int ret;
63591a6e85SSai Praneeth Prakhya 
646383851aSIlpo Järvinen 	ret = find_resctrl_mount(NULL);
656383851aSIlpo Järvinen 	if (ret != -ENOENT)
666383851aSIlpo Järvinen 		return -1;
67591a6e85SSai Praneeth Prakhya 
68ca2f4214SFenghua Yu 	ksft_print_msg("Mounting resctrl to \"%s\"\n", RESCTRL_PATH);
69591a6e85SSai Praneeth Prakhya 	ret = mount("resctrl", RESCTRL_PATH, "resctrl", 0, NULL);
70591a6e85SSai Praneeth Prakhya 	if (ret)
71384dc568SIlpo Järvinen 		ksft_perror("mount");
72591a6e85SSai Praneeth Prakhya 
73591a6e85SSai Praneeth Prakhya 	return ret;
74591a6e85SSai Praneeth Prakhya }
75591a6e85SSai Praneeth Prakhya 
umount_resctrlfs(void)76591a6e85SSai Praneeth Prakhya int umount_resctrlfs(void)
77591a6e85SSai Praneeth Prakhya {
78ede13008SIlpo Järvinen 	char mountpoint[256];
79ede13008SIlpo Järvinen 	int ret;
804e5cb354SFenghua Yu 
81ede13008SIlpo Järvinen 	ret = find_resctrl_mount(mountpoint);
82ede13008SIlpo Järvinen 	if (ret == -ENOENT)
83ede13008SIlpo Järvinen 		return 0;
84ede13008SIlpo Järvinen 	if (ret)
85ede13008SIlpo Järvinen 		return ret;
86ede13008SIlpo Järvinen 
87ede13008SIlpo Järvinen 	if (umount(mountpoint)) {
88384dc568SIlpo Järvinen 		ksft_perror("Unable to umount resctrl");
89591a6e85SSai Praneeth Prakhya 
90591a6e85SSai Praneeth Prakhya 		return errno;
91591a6e85SSai Praneeth Prakhya 	}
92591a6e85SSai Praneeth Prakhya 
93591a6e85SSai Praneeth Prakhya 	return 0;
94591a6e85SSai Praneeth Prakhya }
95591a6e85SSai Praneeth Prakhya 
96591a6e85SSai Praneeth Prakhya /*
97591a6e85SSai Praneeth Prakhya  * get_resource_id - Get socket number/l3 id for a specified CPU
98591a6e85SSai Praneeth Prakhya  * @cpu_no:	CPU number
99591a6e85SSai Praneeth Prakhya  * @resource_id: Socket number or l3_id
100591a6e85SSai Praneeth Prakhya  *
101591a6e85SSai Praneeth Prakhya  * Return: >= 0 on success, < 0 on failure.
102591a6e85SSai Praneeth Prakhya  */
get_resource_id(int cpu_no,int * resource_id)103591a6e85SSai Praneeth Prakhya int get_resource_id(int cpu_no, int *resource_id)
104591a6e85SSai Praneeth Prakhya {
105591a6e85SSai Praneeth Prakhya 	char phys_pkg_path[1024];
106591a6e85SSai Praneeth Prakhya 	FILE *fp;
107591a6e85SSai Praneeth Prakhya 
1086220f69eSShaopeng Tan 	if (get_vendor() == ARCH_AMD)
109c0327e1dSBabu Moger 		sprintf(phys_pkg_path, "%s%d/cache/index3/id",
110c0327e1dSBabu Moger 			PHYS_ID_PATH, cpu_no);
111c0327e1dSBabu Moger 	else
112591a6e85SSai Praneeth Prakhya 		sprintf(phys_pkg_path, "%s%d/topology/physical_package_id",
113591a6e85SSai Praneeth Prakhya 			PHYS_ID_PATH, cpu_no);
114c0327e1dSBabu Moger 
115591a6e85SSai Praneeth Prakhya 	fp = fopen(phys_pkg_path, "r");
116591a6e85SSai Praneeth Prakhya 	if (!fp) {
117384dc568SIlpo Järvinen 		ksft_perror("Failed to open physical_package_id");
118591a6e85SSai Praneeth Prakhya 
119591a6e85SSai Praneeth Prakhya 		return -1;
120591a6e85SSai Praneeth Prakhya 	}
121591a6e85SSai Praneeth Prakhya 	if (fscanf(fp, "%d", resource_id) <= 0) {
122384dc568SIlpo Järvinen 		ksft_perror("Could not get socket number or l3 id");
123591a6e85SSai Praneeth Prakhya 		fclose(fp);
124591a6e85SSai Praneeth Prakhya 
125591a6e85SSai Praneeth Prakhya 		return -1;
126591a6e85SSai Praneeth Prakhya 	}
127591a6e85SSai Praneeth Prakhya 	fclose(fp);
128591a6e85SSai Praneeth Prakhya 
129591a6e85SSai Praneeth Prakhya 	return 0;
130591a6e85SSai Praneeth Prakhya }
131591a6e85SSai Praneeth Prakhya 
132591a6e85SSai Praneeth Prakhya /*
13378941183SFenghua Yu  * get_cache_size - Get cache size for a specified CPU
13478941183SFenghua Yu  * @cpu_no:	CPU number
13578941183SFenghua Yu  * @cache_type:	Cache level L2/L3
13678941183SFenghua Yu  * @cache_size:	pointer to cache_size
13778941183SFenghua Yu  *
13878941183SFenghua Yu  * Return: = 0 on success, < 0 on failure.
13978941183SFenghua Yu  */
get_cache_size(int cpu_no,char * cache_type,unsigned long * cache_size)14078941183SFenghua Yu int get_cache_size(int cpu_no, char *cache_type, unsigned long *cache_size)
14178941183SFenghua Yu {
14278941183SFenghua Yu 	char cache_path[1024], cache_str[64];
14378941183SFenghua Yu 	int length, i, cache_num;
14478941183SFenghua Yu 	FILE *fp;
14578941183SFenghua Yu 
14678941183SFenghua Yu 	if (!strcmp(cache_type, "L3")) {
14778941183SFenghua Yu 		cache_num = 3;
14878941183SFenghua Yu 	} else if (!strcmp(cache_type, "L2")) {
14978941183SFenghua Yu 		cache_num = 2;
15078941183SFenghua Yu 	} else {
151384dc568SIlpo Järvinen 		ksft_print_msg("Invalid cache level\n");
15278941183SFenghua Yu 		return -1;
15378941183SFenghua Yu 	}
15478941183SFenghua Yu 
15578941183SFenghua Yu 	sprintf(cache_path, "/sys/bus/cpu/devices/cpu%d/cache/index%d/size",
15678941183SFenghua Yu 		cpu_no, cache_num);
15778941183SFenghua Yu 	fp = fopen(cache_path, "r");
15878941183SFenghua Yu 	if (!fp) {
159384dc568SIlpo Järvinen 		ksft_perror("Failed to open cache size");
16078941183SFenghua Yu 
16178941183SFenghua Yu 		return -1;
16278941183SFenghua Yu 	}
163*66ab5385SReinette Chatre 	if (fscanf(fp, "%63s", cache_str) <= 0) {
164384dc568SIlpo Järvinen 		ksft_perror("Could not get cache_size");
16578941183SFenghua Yu 		fclose(fp);
16678941183SFenghua Yu 
16778941183SFenghua Yu 		return -1;
16878941183SFenghua Yu 	}
16978941183SFenghua Yu 	fclose(fp);
17078941183SFenghua Yu 
17178941183SFenghua Yu 	length = (int)strlen(cache_str);
17278941183SFenghua Yu 
17378941183SFenghua Yu 	*cache_size = 0;
17478941183SFenghua Yu 
17578941183SFenghua Yu 	for (i = 0; i < length; i++) {
17678941183SFenghua Yu 		if ((cache_str[i] >= '0') && (cache_str[i] <= '9'))
17778941183SFenghua Yu 
17878941183SFenghua Yu 			*cache_size = *cache_size * 10 + (cache_str[i] - '0');
17978941183SFenghua Yu 
18078941183SFenghua Yu 		else if (cache_str[i] == 'K')
18178941183SFenghua Yu 
18278941183SFenghua Yu 			*cache_size = *cache_size * 1024;
18378941183SFenghua Yu 
18478941183SFenghua Yu 		else if (cache_str[i] == 'M')
18578941183SFenghua Yu 
18678941183SFenghua Yu 			*cache_size = *cache_size * 1024 * 1024;
18778941183SFenghua Yu 
18878941183SFenghua Yu 		else
18978941183SFenghua Yu 			break;
19078941183SFenghua Yu 	}
19178941183SFenghua Yu 
19278941183SFenghua Yu 	return 0;
19378941183SFenghua Yu }
19478941183SFenghua Yu 
19578941183SFenghua Yu #define CORE_SIBLINGS_PATH	"/sys/bus/cpu/devices/cpu"
19678941183SFenghua Yu 
19778941183SFenghua Yu /*
19878941183SFenghua Yu  * get_cbm_mask - Get cbm mask for given cache
19978941183SFenghua Yu  * @cache_type:	Cache level L2/L3
2008236c51dSFenghua Yu  * @cbm_mask:	cbm_mask returned as a string
20178941183SFenghua Yu  *
20278941183SFenghua Yu  * Return: = 0 on success, < 0 on failure.
20378941183SFenghua Yu  */
get_cbm_mask(char * cache_type,char * cbm_mask)2048236c51dSFenghua Yu int get_cbm_mask(char *cache_type, char *cbm_mask)
20578941183SFenghua Yu {
20678941183SFenghua Yu 	char cbm_mask_path[1024];
20778941183SFenghua Yu 	FILE *fp;
20878941183SFenghua Yu 
2098236c51dSFenghua Yu 	if (!cbm_mask)
2108236c51dSFenghua Yu 		return -1;
2118236c51dSFenghua Yu 
212e48c3230SFenghua Yu 	sprintf(cbm_mask_path, "%s/%s/cbm_mask", INFO_PATH, cache_type);
21378941183SFenghua Yu 
21478941183SFenghua Yu 	fp = fopen(cbm_mask_path, "r");
21578941183SFenghua Yu 	if (!fp) {
216384dc568SIlpo Järvinen 		ksft_perror("Failed to open cache level");
21778941183SFenghua Yu 
21878941183SFenghua Yu 		return -1;
21978941183SFenghua Yu 	}
22078941183SFenghua Yu 	if (fscanf(fp, "%s", cbm_mask) <= 0) {
221384dc568SIlpo Järvinen 		ksft_perror("Could not get max cbm_mask");
22278941183SFenghua Yu 		fclose(fp);
22378941183SFenghua Yu 
22478941183SFenghua Yu 		return -1;
22578941183SFenghua Yu 	}
22678941183SFenghua Yu 	fclose(fp);
22778941183SFenghua Yu 
22878941183SFenghua Yu 	return 0;
22978941183SFenghua Yu }
23078941183SFenghua Yu 
23178941183SFenghua Yu /*
23278941183SFenghua Yu  * get_core_sibling - Get sibling core id from the same socket for given CPU
23378941183SFenghua Yu  * @cpu_no:	CPU number
23478941183SFenghua Yu  *
23578941183SFenghua Yu  * Return:	> 0 on success, < 0 on failure.
23678941183SFenghua Yu  */
get_core_sibling(int cpu_no)23778941183SFenghua Yu int get_core_sibling(int cpu_no)
23878941183SFenghua Yu {
23978941183SFenghua Yu 	char core_siblings_path[1024], cpu_list_str[64];
24078941183SFenghua Yu 	int sibling_cpu_no = -1;
24178941183SFenghua Yu 	FILE *fp;
24278941183SFenghua Yu 
24378941183SFenghua Yu 	sprintf(core_siblings_path, "%s%d/topology/core_siblings_list",
24478941183SFenghua Yu 		CORE_SIBLINGS_PATH, cpu_no);
24578941183SFenghua Yu 
24678941183SFenghua Yu 	fp = fopen(core_siblings_path, "r");
24778941183SFenghua Yu 	if (!fp) {
248384dc568SIlpo Järvinen 		ksft_perror("Failed to open core siblings path");
24978941183SFenghua Yu 
25078941183SFenghua Yu 		return -1;
25178941183SFenghua Yu 	}
25278941183SFenghua Yu 	if (fscanf(fp, "%s", cpu_list_str) <= 0) {
253384dc568SIlpo Järvinen 		ksft_perror("Could not get core_siblings list");
25478941183SFenghua Yu 		fclose(fp);
25578941183SFenghua Yu 
25678941183SFenghua Yu 		return -1;
25778941183SFenghua Yu 	}
25878941183SFenghua Yu 	fclose(fp);
25978941183SFenghua Yu 
26078941183SFenghua Yu 	char *token = strtok(cpu_list_str, "-,");
26178941183SFenghua Yu 
26278941183SFenghua Yu 	while (token) {
26378941183SFenghua Yu 		sibling_cpu_no = atoi(token);
26478941183SFenghua Yu 		/* Skipping core 0 as we don't want to run test on core 0 */
265f5f16ae4SReinette Chatre 		if (sibling_cpu_no != 0 && sibling_cpu_no != cpu_no)
26678941183SFenghua Yu 			break;
26778941183SFenghua Yu 		token = strtok(NULL, "-,");
26878941183SFenghua Yu 	}
26978941183SFenghua Yu 
27078941183SFenghua Yu 	return sibling_cpu_no;
27178941183SFenghua Yu }
27278941183SFenghua Yu 
27378941183SFenghua Yu /*
274591a6e85SSai Praneeth Prakhya  * taskset_benchmark - Taskset PID (i.e. benchmark) to a specified cpu
275591a6e85SSai Praneeth Prakhya  * @bm_pid:	PID that should be binded
276591a6e85SSai Praneeth Prakhya  * @cpu_no:	CPU number at which the PID would be binded
277591a6e85SSai Praneeth Prakhya  *
278591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
279591a6e85SSai Praneeth Prakhya  */
taskset_benchmark(pid_t bm_pid,int cpu_no)280591a6e85SSai Praneeth Prakhya int taskset_benchmark(pid_t bm_pid, int cpu_no)
281591a6e85SSai Praneeth Prakhya {
282591a6e85SSai Praneeth Prakhya 	cpu_set_t my_set;
283591a6e85SSai Praneeth Prakhya 
284591a6e85SSai Praneeth Prakhya 	CPU_ZERO(&my_set);
285591a6e85SSai Praneeth Prakhya 	CPU_SET(cpu_no, &my_set);
286591a6e85SSai Praneeth Prakhya 
287591a6e85SSai Praneeth Prakhya 	if (sched_setaffinity(bm_pid, sizeof(cpu_set_t), &my_set)) {
288384dc568SIlpo Järvinen 		ksft_perror("Unable to taskset benchmark");
289591a6e85SSai Praneeth Prakhya 
290591a6e85SSai Praneeth Prakhya 		return -1;
291591a6e85SSai Praneeth Prakhya 	}
292591a6e85SSai Praneeth Prakhya 
293591a6e85SSai Praneeth Prakhya 	return 0;
294591a6e85SSai Praneeth Prakhya }
295591a6e85SSai Praneeth Prakhya 
296591a6e85SSai Praneeth Prakhya /*
297591a6e85SSai Praneeth Prakhya  * create_grp - Create a group only if one doesn't exist
298591a6e85SSai Praneeth Prakhya  * @grp_name:	Name of the group
299591a6e85SSai Praneeth Prakhya  * @grp:	Full path and name of the group
300591a6e85SSai Praneeth Prakhya  * @parent_grp:	Full path and name of the parent group
301591a6e85SSai Praneeth Prakhya  *
302591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
303591a6e85SSai Praneeth Prakhya  */
create_grp(const char * grp_name,char * grp,const char * parent_grp)304591a6e85SSai Praneeth Prakhya static int create_grp(const char *grp_name, char *grp, const char *parent_grp)
305591a6e85SSai Praneeth Prakhya {
306591a6e85SSai Praneeth Prakhya 	int found_grp = 0;
307591a6e85SSai Praneeth Prakhya 	struct dirent *ep;
308591a6e85SSai Praneeth Prakhya 	DIR *dp;
309591a6e85SSai Praneeth Prakhya 
31078941183SFenghua Yu 	/*
31178941183SFenghua Yu 	 * At this point, we are guaranteed to have resctrl FS mounted and if
31278941183SFenghua Yu 	 * length of grp_name == 0, it means, user wants to use root con_mon
31378941183SFenghua Yu 	 * grp, so do nothing
31478941183SFenghua Yu 	 */
31578941183SFenghua Yu 	if (strlen(grp_name) == 0)
31678941183SFenghua Yu 		return 0;
31778941183SFenghua Yu 
318591a6e85SSai Praneeth Prakhya 	/* Check if requested grp exists or not */
319591a6e85SSai Praneeth Prakhya 	dp = opendir(parent_grp);
320591a6e85SSai Praneeth Prakhya 	if (dp) {
321591a6e85SSai Praneeth Prakhya 		while ((ep = readdir(dp)) != NULL) {
322591a6e85SSai Praneeth Prakhya 			if (strcmp(ep->d_name, grp_name) == 0)
323591a6e85SSai Praneeth Prakhya 				found_grp = 1;
324591a6e85SSai Praneeth Prakhya 		}
325591a6e85SSai Praneeth Prakhya 		closedir(dp);
326591a6e85SSai Praneeth Prakhya 	} else {
327384dc568SIlpo Järvinen 		ksft_perror("Unable to open resctrl for group");
328591a6e85SSai Praneeth Prakhya 
329591a6e85SSai Praneeth Prakhya 		return -1;
330591a6e85SSai Praneeth Prakhya 	}
331591a6e85SSai Praneeth Prakhya 
332591a6e85SSai Praneeth Prakhya 	/* Requested grp doesn't exist, hence create it */
333591a6e85SSai Praneeth Prakhya 	if (found_grp == 0) {
334591a6e85SSai Praneeth Prakhya 		if (mkdir(grp, 0) == -1) {
335384dc568SIlpo Järvinen 			ksft_perror("Unable to create group");
336591a6e85SSai Praneeth Prakhya 
337591a6e85SSai Praneeth Prakhya 			return -1;
338591a6e85SSai Praneeth Prakhya 		}
339591a6e85SSai Praneeth Prakhya 	}
340591a6e85SSai Praneeth Prakhya 
341591a6e85SSai Praneeth Prakhya 	return 0;
342591a6e85SSai Praneeth Prakhya }
343591a6e85SSai Praneeth Prakhya 
write_pid_to_tasks(char * tasks,pid_t pid)344591a6e85SSai Praneeth Prakhya static int write_pid_to_tasks(char *tasks, pid_t pid)
345591a6e85SSai Praneeth Prakhya {
346591a6e85SSai Praneeth Prakhya 	FILE *fp;
347591a6e85SSai Praneeth Prakhya 
348591a6e85SSai Praneeth Prakhya 	fp = fopen(tasks, "w");
349591a6e85SSai Praneeth Prakhya 	if (!fp) {
350384dc568SIlpo Järvinen 		ksft_perror("Failed to open tasks file");
351591a6e85SSai Praneeth Prakhya 
352591a6e85SSai Praneeth Prakhya 		return -1;
353591a6e85SSai Praneeth Prakhya 	}
354591a6e85SSai Praneeth Prakhya 	if (fprintf(fp, "%d\n", pid) < 0) {
355384dc568SIlpo Järvinen 		ksft_print_msg("Failed to write pid to tasks file\n");
356591a6e85SSai Praneeth Prakhya 		fclose(fp);
357591a6e85SSai Praneeth Prakhya 
358591a6e85SSai Praneeth Prakhya 		return -1;
359591a6e85SSai Praneeth Prakhya 	}
360591a6e85SSai Praneeth Prakhya 	fclose(fp);
361591a6e85SSai Praneeth Prakhya 
362591a6e85SSai Praneeth Prakhya 	return 0;
363591a6e85SSai Praneeth Prakhya }
364591a6e85SSai Praneeth Prakhya 
365591a6e85SSai Praneeth Prakhya /*
366591a6e85SSai Praneeth Prakhya  * write_bm_pid_to_resctrl - Write a PID (i.e. benchmark) to resctrl FS
367591a6e85SSai Praneeth Prakhya  * @bm_pid:		PID that should be written
368591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the control monitor group (con_mon grp)
369591a6e85SSai Praneeth Prakhya  * @mongrp:		Name of the monitor group (mon grp)
370591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Resctrl feature (Eg: mbm, mba.. etc)
371591a6e85SSai Praneeth Prakhya  *
372591a6e85SSai Praneeth Prakhya  * If a con_mon grp is requested, create it and write pid to it, otherwise
373591a6e85SSai Praneeth Prakhya  * write pid to root con_mon grp.
374591a6e85SSai Praneeth Prakhya  * If a mon grp is requested, create it and write pid to it, otherwise
375591a6e85SSai Praneeth Prakhya  * pid is not written, this means that pid is in con_mon grp and hence
376591a6e85SSai Praneeth Prakhya  * should consult con_mon grp's mon_data directory for results.
377591a6e85SSai Praneeth Prakhya  *
378591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
379591a6e85SSai Praneeth Prakhya  */
write_bm_pid_to_resctrl(pid_t bm_pid,char * ctrlgrp,char * mongrp,char * resctrl_val)380591a6e85SSai Praneeth Prakhya int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
381591a6e85SSai Praneeth Prakhya 			    char *resctrl_val)
382591a6e85SSai Praneeth Prakhya {
383591a6e85SSai Praneeth Prakhya 	char controlgroup[128], monitorgroup[512], monitorgroup_p[256];
384591a6e85SSai Praneeth Prakhya 	char tasks[1024];
385591a6e85SSai Praneeth Prakhya 	int ret = 0;
386591a6e85SSai Praneeth Prakhya 
387591a6e85SSai Praneeth Prakhya 	if (strlen(ctrlgrp))
388591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s", RESCTRL_PATH, ctrlgrp);
389591a6e85SSai Praneeth Prakhya 	else
390591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s", RESCTRL_PATH);
391591a6e85SSai Praneeth Prakhya 
392591a6e85SSai Praneeth Prakhya 	/* Create control and monitoring group and write pid into it */
393591a6e85SSai Praneeth Prakhya 	ret = create_grp(ctrlgrp, controlgroup, RESCTRL_PATH);
394591a6e85SSai Praneeth Prakhya 	if (ret)
395591a6e85SSai Praneeth Prakhya 		goto out;
396591a6e85SSai Praneeth Prakhya 	sprintf(tasks, "%s/tasks", controlgroup);
397591a6e85SSai Praneeth Prakhya 	ret = write_pid_to_tasks(tasks, bm_pid);
398591a6e85SSai Praneeth Prakhya 	if (ret)
399591a6e85SSai Praneeth Prakhya 		goto out;
400591a6e85SSai Praneeth Prakhya 
4012f320911SFenghua Yu 	/* Create mon grp and write pid into it for "mbm" and "cmt" test */
4022f320911SFenghua Yu 	if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)) ||
40324286736SFenghua Yu 	    !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) {
40478941183SFenghua Yu 		if (strlen(mongrp)) {
405591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup_p, "%s/mon_groups", controlgroup);
406591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp);
407591a6e85SSai Praneeth Prakhya 			ret = create_grp(mongrp, monitorgroup, monitorgroup_p);
408591a6e85SSai Praneeth Prakhya 			if (ret)
409591a6e85SSai Praneeth Prakhya 				goto out;
410591a6e85SSai Praneeth Prakhya 
411591a6e85SSai Praneeth Prakhya 			sprintf(tasks, "%s/mon_groups/%s/tasks",
412591a6e85SSai Praneeth Prakhya 				controlgroup, mongrp);
413591a6e85SSai Praneeth Prakhya 			ret = write_pid_to_tasks(tasks, bm_pid);
414591a6e85SSai Praneeth Prakhya 			if (ret)
415591a6e85SSai Praneeth Prakhya 				goto out;
416591a6e85SSai Praneeth Prakhya 		}
417591a6e85SSai Praneeth Prakhya 	}
418591a6e85SSai Praneeth Prakhya 
419591a6e85SSai Praneeth Prakhya out:
420ca2f4214SFenghua Yu 	ksft_print_msg("Writing benchmark parameters to resctrl FS\n");
421591a6e85SSai Praneeth Prakhya 	if (ret)
422384dc568SIlpo Järvinen 		ksft_print_msg("Failed writing to resctrlfs\n");
423591a6e85SSai Praneeth Prakhya 
424591a6e85SSai Praneeth Prakhya 	return ret;
425591a6e85SSai Praneeth Prakhya }
426591a6e85SSai Praneeth Prakhya 
427591a6e85SSai Praneeth Prakhya /*
428591a6e85SSai Praneeth Prakhya  * write_schemata - Update schemata of a con_mon grp
429591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the con_mon grp
430591a6e85SSai Praneeth Prakhya  * @schemata:		Schemata that should be updated to
431591a6e85SSai Praneeth Prakhya  * @cpu_no:		CPU number that the benchmark PID is binded to
432591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Resctrl feature (Eg: mbm, mba.. etc)
433591a6e85SSai Praneeth Prakhya  *
434591a6e85SSai Praneeth Prakhya  * Update schemata of a con_mon grp *only* if requested resctrl feature is
435591a6e85SSai Praneeth Prakhya  * allocation type
436591a6e85SSai Praneeth Prakhya  *
437591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
438591a6e85SSai Praneeth Prakhya  */
write_schemata(char * ctrlgrp,char * schemata,int cpu_no,char * resctrl_val)439591a6e85SSai Praneeth Prakhya int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
440591a6e85SSai Praneeth Prakhya {
441591a6e85SSai Praneeth Prakhya 	char controlgroup[1024], schema[1024], reason[64];
442591a6e85SSai Praneeth Prakhya 	int resource_id, ret = 0;
443591a6e85SSai Praneeth Prakhya 	FILE *fp;
444591a6e85SSai Praneeth Prakhya 
44524286736SFenghua Yu 	if (strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) &&
44642e3b093SShaopeng Tan 	    strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) &&
44724286736SFenghua Yu 	    strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) &&
4482f320911SFenghua Yu 	    strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
449591a6e85SSai Praneeth Prakhya 		return -ENOENT;
450591a6e85SSai Praneeth Prakhya 
451591a6e85SSai Praneeth Prakhya 	if (!schemata) {
452ca2f4214SFenghua Yu 		ksft_print_msg("Skipping empty schemata update\n");
453591a6e85SSai Praneeth Prakhya 
454591a6e85SSai Praneeth Prakhya 		return -1;
455591a6e85SSai Praneeth Prakhya 	}
456591a6e85SSai Praneeth Prakhya 
457591a6e85SSai Praneeth Prakhya 	if (get_resource_id(cpu_no, &resource_id) < 0) {
458591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to get resource id");
459591a6e85SSai Praneeth Prakhya 		ret = -1;
460591a6e85SSai Praneeth Prakhya 
461591a6e85SSai Praneeth Prakhya 		goto out;
462591a6e85SSai Praneeth Prakhya 	}
463591a6e85SSai Praneeth Prakhya 
464591a6e85SSai Praneeth Prakhya 	if (strlen(ctrlgrp) != 0)
465591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s/schemata", RESCTRL_PATH, ctrlgrp);
466591a6e85SSai Praneeth Prakhya 	else
467591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/schemata", RESCTRL_PATH);
468591a6e85SSai Praneeth Prakhya 
46924286736SFenghua Yu 	if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) ||
4702f320911SFenghua Yu 	    !strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
47178941183SFenghua Yu 		sprintf(schema, "%s%d%c%s", "L3:", resource_id, '=', schemata);
47242e3b093SShaopeng Tan 	if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) ||
47342e3b093SShaopeng Tan 	    !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)))
474591a6e85SSai Praneeth Prakhya 		sprintf(schema, "%s%d%c%s", "MB:", resource_id, '=', schemata);
475591a6e85SSai Praneeth Prakhya 
476591a6e85SSai Praneeth Prakhya 	fp = fopen(controlgroup, "w");
477591a6e85SSai Praneeth Prakhya 	if (!fp) {
478591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to open control group");
479591a6e85SSai Praneeth Prakhya 		ret = -1;
480591a6e85SSai Praneeth Prakhya 
481591a6e85SSai Praneeth Prakhya 		goto out;
482591a6e85SSai Praneeth Prakhya 	}
483591a6e85SSai Praneeth Prakhya 
484591a6e85SSai Praneeth Prakhya 	if (fprintf(fp, "%s\n", schema) < 0) {
485591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to write schemata in control group");
486591a6e85SSai Praneeth Prakhya 		fclose(fp);
487591a6e85SSai Praneeth Prakhya 		ret = -1;
488591a6e85SSai Praneeth Prakhya 
489591a6e85SSai Praneeth Prakhya 		goto out;
490591a6e85SSai Praneeth Prakhya 	}
491591a6e85SSai Praneeth Prakhya 	fclose(fp);
492591a6e85SSai Praneeth Prakhya 
493591a6e85SSai Praneeth Prakhya out:
494ca2f4214SFenghua Yu 	ksft_print_msg("Write schema \"%s\" to resctrl FS%s%s\n",
495ca2f4214SFenghua Yu 		       schema, ret ? " # " : "",
496591a6e85SSai Praneeth Prakhya 		       ret ? reason : "");
497591a6e85SSai Praneeth Prakhya 
498591a6e85SSai Praneeth Prakhya 	return ret;
499591a6e85SSai Praneeth Prakhya }
500591a6e85SSai Praneeth Prakhya 
check_resctrlfs_support(void)501ecdbb911SFenghua Yu bool check_resctrlfs_support(void)
502ecdbb911SFenghua Yu {
503ecdbb911SFenghua Yu 	FILE *inf = fopen("/proc/filesystems", "r");
504ecdbb911SFenghua Yu 	DIR *dp;
505ecdbb911SFenghua Yu 	char *res;
506ecdbb911SFenghua Yu 	bool ret = false;
507ecdbb911SFenghua Yu 
508ecdbb911SFenghua Yu 	if (!inf)
509ecdbb911SFenghua Yu 		return false;
510ecdbb911SFenghua Yu 
511ecdbb911SFenghua Yu 	res = fgrep(inf, "nodev\tresctrl\n");
512ecdbb911SFenghua Yu 
513ecdbb911SFenghua Yu 	if (res) {
514ecdbb911SFenghua Yu 		ret = true;
515ecdbb911SFenghua Yu 		free(res);
516ecdbb911SFenghua Yu 	}
517ecdbb911SFenghua Yu 
518ecdbb911SFenghua Yu 	fclose(inf);
519ecdbb911SFenghua Yu 
520e7507478SFenghua Yu 	ksft_print_msg("%s Check kernel supports resctrl filesystem\n",
521ca2f4214SFenghua Yu 		       ret ? "Pass:" : "Fail:");
522ecdbb911SFenghua Yu 
523a3611fbcSFenghua Yu 	if (!ret)
524a3611fbcSFenghua Yu 		return ret;
525a3611fbcSFenghua Yu 
526ecdbb911SFenghua Yu 	dp = opendir(RESCTRL_PATH);
527e7507478SFenghua Yu 	ksft_print_msg("%s Check resctrl mountpoint \"%s\" exists\n",
528ca2f4214SFenghua Yu 		       dp ? "Pass:" : "Fail:", RESCTRL_PATH);
529ecdbb911SFenghua Yu 	if (dp)
530ecdbb911SFenghua Yu 		closedir(dp);
531ecdbb911SFenghua Yu 
532ca2f4214SFenghua Yu 	ksft_print_msg("resctrl filesystem %s mounted\n",
533ecdbb911SFenghua Yu 		       find_resctrl_mount(NULL) ? "not" : "is");
534ecdbb911SFenghua Yu 
535ecdbb911SFenghua Yu 	return ret;
536ecdbb911SFenghua Yu }
537ecdbb911SFenghua Yu 
fgrep(FILE * inf,const char * str)538591a6e85SSai Praneeth Prakhya char *fgrep(FILE *inf, const char *str)
539591a6e85SSai Praneeth Prakhya {
540591a6e85SSai Praneeth Prakhya 	char line[256];
541591a6e85SSai Praneeth Prakhya 	int slen = strlen(str);
542591a6e85SSai Praneeth Prakhya 
543591a6e85SSai Praneeth Prakhya 	while (!feof(inf)) {
544591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, inf))
545591a6e85SSai Praneeth Prakhya 			break;
546591a6e85SSai Praneeth Prakhya 		if (strncmp(line, str, slen))
547591a6e85SSai Praneeth Prakhya 			continue;
548591a6e85SSai Praneeth Prakhya 
549591a6e85SSai Praneeth Prakhya 		return strdup(line);
550591a6e85SSai Praneeth Prakhya 	}
551591a6e85SSai Praneeth Prakhya 
552591a6e85SSai Praneeth Prakhya 	return NULL;
553591a6e85SSai Praneeth Prakhya }
554591a6e85SSai Praneeth Prakhya 
555591a6e85SSai Praneeth Prakhya /*
556591a6e85SSai Praneeth Prakhya  * validate_resctrl_feature_request - Check if requested feature is valid.
55707717178SIlpo Järvinen  * @resource:	Required resource (e.g., MB, L3, L2, L3_MON, etc.)
55807717178SIlpo Järvinen  * @feature:	Required monitor feature (in mon_features file). Can only be
55907717178SIlpo Järvinen  *		set for L3_MON. Must be NULL for all other resources.
560591a6e85SSai Praneeth Prakhya  *
56107717178SIlpo Järvinen  * Return: True if the resource/feature is supported, else false. False is
56207717178SIlpo Järvinen  *         also returned if resctrl FS is not mounted.
563591a6e85SSai Praneeth Prakhya  */
validate_resctrl_feature_request(const char * resource,const char * feature)56407717178SIlpo Järvinen bool validate_resctrl_feature_request(const char *resource, const char *feature)
565591a6e85SSai Praneeth Prakhya {
56607717178SIlpo Järvinen 	char res_path[PATH_MAX];
567ee041568SFenghua Yu 	struct stat statbuf;
568591a6e85SSai Praneeth Prakhya 	char *res;
569ee041568SFenghua Yu 	FILE *inf;
570caddc0fbSIlpo Järvinen 	int ret;
571591a6e85SSai Praneeth Prakhya 
57207717178SIlpo Järvinen 	if (!resource)
573ee041568SFenghua Yu 		return false;
574ee041568SFenghua Yu 
575caddc0fbSIlpo Järvinen 	ret = find_resctrl_mount(NULL);
576caddc0fbSIlpo Järvinen 	if (ret)
577ee041568SFenghua Yu 		return false;
578ee041568SFenghua Yu 
57907717178SIlpo Järvinen 	snprintf(res_path, sizeof(res_path), "%s/%s", INFO_PATH, resource);
58007717178SIlpo Järvinen 
58107717178SIlpo Järvinen 	if (stat(res_path, &statbuf))
58207717178SIlpo Järvinen 		return false;
58307717178SIlpo Järvinen 
58407717178SIlpo Järvinen 	if (!feature)
585ee041568SFenghua Yu 		return true;
58607717178SIlpo Järvinen 
58707717178SIlpo Järvinen 	snprintf(res_path, sizeof(res_path), "%s/%s/mon_features", INFO_PATH, resource);
58807717178SIlpo Järvinen 	inf = fopen(res_path, "r");
589591a6e85SSai Praneeth Prakhya 	if (!inf)
590591a6e85SSai Praneeth Prakhya 		return false;
591591a6e85SSai Praneeth Prakhya 
59207717178SIlpo Järvinen 	res = fgrep(inf, feature);
593591a6e85SSai Praneeth Prakhya 	free(res);
594591a6e85SSai Praneeth Prakhya 	fclose(inf);
595591a6e85SSai Praneeth Prakhya 
59607717178SIlpo Järvinen 	return !!res;
597591a6e85SSai Praneeth Prakhya }
598591a6e85SSai Praneeth Prakhya 
filter_dmesg(void)599ecdbb911SFenghua Yu int filter_dmesg(void)
600ecdbb911SFenghua Yu {
601ecdbb911SFenghua Yu 	char line[1024];
602ecdbb911SFenghua Yu 	FILE *fp;
603ecdbb911SFenghua Yu 	int pipefds[2];
604ecdbb911SFenghua Yu 	pid_t pid;
605ecdbb911SFenghua Yu 	int ret;
606ecdbb911SFenghua Yu 
607ecdbb911SFenghua Yu 	ret = pipe(pipefds);
608ecdbb911SFenghua Yu 	if (ret) {
609384dc568SIlpo Järvinen 		ksft_perror("pipe");
610ecdbb911SFenghua Yu 		return ret;
611ecdbb911SFenghua Yu 	}
612a080b6e7SShaopeng Tan 	fflush(stdout);
613ecdbb911SFenghua Yu 	pid = fork();
614ecdbb911SFenghua Yu 	if (pid == 0) {
615ecdbb911SFenghua Yu 		close(pipefds[0]);
616ecdbb911SFenghua Yu 		dup2(pipefds[1], STDOUT_FILENO);
617ecdbb911SFenghua Yu 		execlp("dmesg", "dmesg", NULL);
618384dc568SIlpo Järvinen 		ksft_perror("Executing dmesg");
619ecdbb911SFenghua Yu 		exit(1);
620ecdbb911SFenghua Yu 	}
621ecdbb911SFenghua Yu 	close(pipefds[1]);
622ecdbb911SFenghua Yu 	fp = fdopen(pipefds[0], "r");
623ecdbb911SFenghua Yu 	if (!fp) {
624384dc568SIlpo Järvinen 		ksft_perror("fdopen(pipe)");
625ecdbb911SFenghua Yu 		kill(pid, SIGTERM);
626ecdbb911SFenghua Yu 
627ecdbb911SFenghua Yu 		return -1;
628ecdbb911SFenghua Yu 	}
629ecdbb911SFenghua Yu 
630ecdbb911SFenghua Yu 	while (fgets(line, 1024, fp)) {
631ecdbb911SFenghua Yu 		if (strstr(line, "intel_rdt:"))
632ca2f4214SFenghua Yu 			ksft_print_msg("dmesg: %s", line);
633ecdbb911SFenghua Yu 		if (strstr(line, "resctrl:"))
634ca2f4214SFenghua Yu 			ksft_print_msg("dmesg: %s", line);
635ecdbb911SFenghua Yu 	}
636ecdbb911SFenghua Yu 	fclose(fp);
637ecdbb911SFenghua Yu 	waitpid(pid, NULL, 0);
638ecdbb911SFenghua Yu 
639ecdbb911SFenghua Yu 	return 0;
640ecdbb911SFenghua Yu }
641ecdbb911SFenghua Yu 
validate_bw_report_request(char * bw_report)642591a6e85SSai Praneeth Prakhya int validate_bw_report_request(char *bw_report)
643591a6e85SSai Praneeth Prakhya {
644591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "reads") == 0)
645591a6e85SSai Praneeth Prakhya 		return 0;
646591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "writes") == 0)
647591a6e85SSai Praneeth Prakhya 		return 0;
648591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "nt-writes") == 0) {
649591a6e85SSai Praneeth Prakhya 		strcpy(bw_report, "writes");
650591a6e85SSai Praneeth Prakhya 		return 0;
651591a6e85SSai Praneeth Prakhya 	}
652591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "total") == 0)
653591a6e85SSai Praneeth Prakhya 		return 0;
654591a6e85SSai Praneeth Prakhya 
655591a6e85SSai Praneeth Prakhya 	fprintf(stderr, "Requested iMC B/W report type unavailable\n");
656591a6e85SSai Praneeth Prakhya 
657591a6e85SSai Praneeth Prakhya 	return -1;
658591a6e85SSai Praneeth Prakhya }
659591a6e85SSai Praneeth Prakhya 
perf_event_open(struct perf_event_attr * hw_event,pid_t pid,int cpu,int group_fd,unsigned long flags)660591a6e85SSai Praneeth Prakhya int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
661591a6e85SSai Praneeth Prakhya 		    int group_fd, unsigned long flags)
662591a6e85SSai Praneeth Prakhya {
663591a6e85SSai Praneeth Prakhya 	int ret;
664591a6e85SSai Praneeth Prakhya 
665591a6e85SSai Praneeth Prakhya 	ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
666591a6e85SSai Praneeth Prakhya 		      group_fd, flags);
667591a6e85SSai Praneeth Prakhya 	return ret;
668591a6e85SSai Praneeth Prakhya }
66978941183SFenghua Yu 
count_bits(unsigned long n)67078941183SFenghua Yu unsigned int count_bits(unsigned long n)
67178941183SFenghua Yu {
67278941183SFenghua Yu 	unsigned int count = 0;
67378941183SFenghua Yu 
67478941183SFenghua Yu 	while (n) {
67578941183SFenghua Yu 		count += n & 1;
67678941183SFenghua Yu 		n >>= 1;
67778941183SFenghua Yu 	}
67878941183SFenghua Yu 
67978941183SFenghua Yu 	return count;
68078941183SFenghua Yu }
681