xref: /linux/tools/testing/selftests/resctrl/resctrlfs.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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  */
1120d96b25SMaciej Wieczor-Retman #include <fcntl.h>
12d56e5da0SIlpo Järvinen #include <limits.h>
13d56e5da0SIlpo Järvinen 
14591a6e85SSai Praneeth Prakhya #include "resctrl.h"
15591a6e85SSai Praneeth Prakhya 
find_resctrl_mount(char * buffer)16591a6e85SSai Praneeth Prakhya static int find_resctrl_mount(char *buffer)
17591a6e85SSai Praneeth Prakhya {
18591a6e85SSai Praneeth Prakhya 	FILE *mounts;
19591a6e85SSai Praneeth Prakhya 	char line[256], *fs, *mntpoint;
20591a6e85SSai Praneeth Prakhya 
21591a6e85SSai Praneeth Prakhya 	mounts = fopen("/proc/mounts", "r");
22591a6e85SSai Praneeth Prakhya 	if (!mounts) {
23cc8ff7f5SIlpo Järvinen 		ksft_perror("/proc/mounts");
24591a6e85SSai Praneeth Prakhya 		return -ENXIO;
25591a6e85SSai Praneeth Prakhya 	}
26591a6e85SSai Praneeth Prakhya 	while (!feof(mounts)) {
27591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, mounts))
28591a6e85SSai Praneeth Prakhya 			break;
29591a6e85SSai Praneeth Prakhya 		fs = strtok(line, " \t");
30591a6e85SSai Praneeth Prakhya 		if (!fs)
31591a6e85SSai Praneeth Prakhya 			continue;
32591a6e85SSai Praneeth Prakhya 		mntpoint = strtok(NULL, " \t");
33591a6e85SSai Praneeth Prakhya 		if (!mntpoint)
34591a6e85SSai Praneeth Prakhya 			continue;
35591a6e85SSai Praneeth Prakhya 		fs = strtok(NULL, " \t");
36591a6e85SSai Praneeth Prakhya 		if (!fs)
37591a6e85SSai Praneeth Prakhya 			continue;
38591a6e85SSai Praneeth Prakhya 		if (strcmp(fs, "resctrl"))
39591a6e85SSai Praneeth Prakhya 			continue;
40591a6e85SSai Praneeth Prakhya 
41591a6e85SSai Praneeth Prakhya 		fclose(mounts);
42591a6e85SSai Praneeth Prakhya 		if (buffer)
43591a6e85SSai Praneeth Prakhya 			strncpy(buffer, mntpoint, 256);
44591a6e85SSai Praneeth Prakhya 
45591a6e85SSai Praneeth Prakhya 		return 0;
46591a6e85SSai Praneeth Prakhya 	}
47591a6e85SSai Praneeth Prakhya 
48591a6e85SSai Praneeth Prakhya 	fclose(mounts);
49591a6e85SSai Praneeth Prakhya 
50591a6e85SSai Praneeth Prakhya 	return -ENOENT;
51591a6e85SSai Praneeth Prakhya }
52591a6e85SSai Praneeth Prakhya 
53591a6e85SSai Praneeth Prakhya /*
546383851aSIlpo Järvinen  * mount_resctrlfs - Mount resctrl FS at /sys/fs/resctrl
55591a6e85SSai Praneeth Prakhya  *
566383851aSIlpo Järvinen  * Mounts resctrl FS. Fails if resctrl FS is already mounted to avoid
576383851aSIlpo Järvinen  * pre-existing settings interfering with the test results.
58591a6e85SSai Praneeth Prakhya  *
5934813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
60591a6e85SSai Praneeth Prakhya  */
mount_resctrlfs(void)616383851aSIlpo Järvinen int mount_resctrlfs(void)
62591a6e85SSai Praneeth Prakhya {
63591a6e85SSai Praneeth Prakhya 	int ret;
64591a6e85SSai Praneeth Prakhya 
656383851aSIlpo Järvinen 	ret = find_resctrl_mount(NULL);
666383851aSIlpo Järvinen 	if (ret != -ENOENT)
676383851aSIlpo Järvinen 		return -1;
68591a6e85SSai Praneeth Prakhya 
69ca2f4214SFenghua Yu 	ksft_print_msg("Mounting resctrl to \"%s\"\n", RESCTRL_PATH);
70591a6e85SSai Praneeth Prakhya 	ret = mount("resctrl", RESCTRL_PATH, "resctrl", 0, NULL);
71591a6e85SSai Praneeth Prakhya 	if (ret)
72cc8ff7f5SIlpo Järvinen 		ksft_perror("mount");
73591a6e85SSai Praneeth Prakhya 
74591a6e85SSai Praneeth Prakhya 	return ret;
75591a6e85SSai Praneeth Prakhya }
76591a6e85SSai Praneeth Prakhya 
umount_resctrlfs(void)77591a6e85SSai Praneeth Prakhya int umount_resctrlfs(void)
78591a6e85SSai Praneeth Prakhya {
79ede13008SIlpo Järvinen 	char mountpoint[256];
80ede13008SIlpo Järvinen 	int ret;
814e5cb354SFenghua Yu 
82ede13008SIlpo Järvinen 	ret = find_resctrl_mount(mountpoint);
83ede13008SIlpo Järvinen 	if (ret == -ENOENT)
84ede13008SIlpo Järvinen 		return 0;
85ede13008SIlpo Järvinen 	if (ret)
86ede13008SIlpo Järvinen 		return ret;
87ede13008SIlpo Järvinen 
88ede13008SIlpo Järvinen 	if (umount(mountpoint)) {
89cc8ff7f5SIlpo Järvinen 		ksft_perror("Unable to umount resctrl");
90591a6e85SSai Praneeth Prakhya 
91c90fba60SIlpo Järvinen 		return -1;
92591a6e85SSai Praneeth Prakhya 	}
93591a6e85SSai Praneeth Prakhya 
94591a6e85SSai Praneeth Prakhya 	return 0;
95591a6e85SSai Praneeth Prakhya }
96591a6e85SSai Praneeth Prakhya 
97591a6e85SSai Praneeth Prakhya /*
98e73dda7fSIlpo Järvinen  * get_cache_level - Convert cache level from string to integer
99e73dda7fSIlpo Järvinen  * @cache_type:		Cache level as string
100e73dda7fSIlpo Järvinen  *
101e73dda7fSIlpo Järvinen  * Return: cache level as integer or -1 if @cache_type is invalid.
102e73dda7fSIlpo Järvinen  */
get_cache_level(const char * cache_type)103e73dda7fSIlpo Järvinen static int get_cache_level(const char *cache_type)
104e73dda7fSIlpo Järvinen {
105e73dda7fSIlpo Järvinen 	if (!strcmp(cache_type, "L3"))
106e73dda7fSIlpo Järvinen 		return 3;
107e73dda7fSIlpo Järvinen 	if (!strcmp(cache_type, "L2"))
108e73dda7fSIlpo Järvinen 		return 2;
109e73dda7fSIlpo Järvinen 
110e73dda7fSIlpo Järvinen 	ksft_print_msg("Invalid cache level\n");
111e73dda7fSIlpo Järvinen 	return -1;
112e73dda7fSIlpo Järvinen }
113e73dda7fSIlpo Järvinen 
get_resource_cache_level(const char * resource)114345e8abeSIlpo Järvinen static int get_resource_cache_level(const char *resource)
115345e8abeSIlpo Järvinen {
116345e8abeSIlpo Järvinen 	/* "MB" use L3 (LLC) as resource */
117345e8abeSIlpo Järvinen 	if (!strcmp(resource, "MB"))
118345e8abeSIlpo Järvinen 		return 3;
119345e8abeSIlpo Järvinen 	return get_cache_level(resource);
120345e8abeSIlpo Järvinen }
121345e8abeSIlpo Järvinen 
122e73dda7fSIlpo Järvinen /*
1236874f6edSIlpo Järvinen  * get_domain_id - Get resctrl domain ID for a specified CPU
124345e8abeSIlpo Järvinen  * @resource:	resource name
125591a6e85SSai Praneeth Prakhya  * @cpu_no:	CPU number
1266874f6edSIlpo Järvinen  * @domain_id:	domain ID (cache ID; for MB, L3 cache ID)
127591a6e85SSai Praneeth Prakhya  *
128591a6e85SSai Praneeth Prakhya  * Return: >= 0 on success, < 0 on failure.
129591a6e85SSai Praneeth Prakhya  */
get_domain_id(const char * resource,int cpu_no,int * domain_id)130345e8abeSIlpo Järvinen int get_domain_id(const char *resource, int cpu_no, int *domain_id)
131591a6e85SSai Praneeth Prakhya {
132591a6e85SSai Praneeth Prakhya 	char phys_pkg_path[1024];
133345e8abeSIlpo Järvinen 	int cache_num;
134591a6e85SSai Praneeth Prakhya 	FILE *fp;
135591a6e85SSai Praneeth Prakhya 
136345e8abeSIlpo Järvinen 	cache_num = get_resource_cache_level(resource);
137345e8abeSIlpo Järvinen 	if (cache_num < 0)
138345e8abeSIlpo Järvinen 		return cache_num;
139345e8abeSIlpo Järvinen 
140345e8abeSIlpo Järvinen 	sprintf(phys_pkg_path, "%s%d/cache/index%d/id", PHYS_ID_PATH, cpu_no, cache_num);
141c0327e1dSBabu Moger 
142591a6e85SSai Praneeth Prakhya 	fp = fopen(phys_pkg_path, "r");
143591a6e85SSai Praneeth Prakhya 	if (!fp) {
144345e8abeSIlpo Järvinen 		ksft_perror("Failed to open cache id file");
145591a6e85SSai Praneeth Prakhya 
146591a6e85SSai Praneeth Prakhya 		return -1;
147591a6e85SSai Praneeth Prakhya 	}
1486874f6edSIlpo Järvinen 	if (fscanf(fp, "%d", domain_id) <= 0) {
1496874f6edSIlpo Järvinen 		ksft_perror("Could not get domain ID");
150591a6e85SSai Praneeth Prakhya 		fclose(fp);
151591a6e85SSai Praneeth Prakhya 
152591a6e85SSai Praneeth Prakhya 		return -1;
153591a6e85SSai Praneeth Prakhya 	}
154591a6e85SSai Praneeth Prakhya 	fclose(fp);
155591a6e85SSai Praneeth Prakhya 
156591a6e85SSai Praneeth Prakhya 	return 0;
157591a6e85SSai Praneeth Prakhya }
158591a6e85SSai Praneeth Prakhya 
159591a6e85SSai Praneeth Prakhya /*
16078941183SFenghua Yu  * get_cache_size - Get cache size for a specified CPU
16178941183SFenghua Yu  * @cpu_no:	CPU number
16278941183SFenghua Yu  * @cache_type:	Cache level L2/L3
16378941183SFenghua Yu  * @cache_size:	pointer to cache_size
16478941183SFenghua Yu  *
16578941183SFenghua Yu  * Return: = 0 on success, < 0 on failure.
16678941183SFenghua Yu  */
get_cache_size(int cpu_no,const char * cache_type,unsigned long * cache_size)16760c2a692SIlpo Järvinen int get_cache_size(int cpu_no, const char *cache_type, unsigned long *cache_size)
16878941183SFenghua Yu {
16978941183SFenghua Yu 	char cache_path[1024], cache_str[64];
17078941183SFenghua Yu 	int length, i, cache_num;
17178941183SFenghua Yu 	FILE *fp;
17278941183SFenghua Yu 
173e73dda7fSIlpo Järvinen 	cache_num = get_cache_level(cache_type);
174e73dda7fSIlpo Järvinen 	if (cache_num < 0)
175e73dda7fSIlpo Järvinen 		return cache_num;
17678941183SFenghua Yu 
17778941183SFenghua Yu 	sprintf(cache_path, "/sys/bus/cpu/devices/cpu%d/cache/index%d/size",
17878941183SFenghua Yu 		cpu_no, cache_num);
17978941183SFenghua Yu 	fp = fopen(cache_path, "r");
18078941183SFenghua Yu 	if (!fp) {
181cc8ff7f5SIlpo Järvinen 		ksft_perror("Failed to open cache size");
18278941183SFenghua Yu 
18378941183SFenghua Yu 		return -1;
18478941183SFenghua Yu 	}
18578941183SFenghua Yu 	if (fscanf(fp, "%s", cache_str) <= 0) {
186cc8ff7f5SIlpo Järvinen 		ksft_perror("Could not get cache_size");
18778941183SFenghua Yu 		fclose(fp);
18878941183SFenghua Yu 
18978941183SFenghua Yu 		return -1;
19078941183SFenghua Yu 	}
19178941183SFenghua Yu 	fclose(fp);
19278941183SFenghua Yu 
19378941183SFenghua Yu 	length = (int)strlen(cache_str);
19478941183SFenghua Yu 
19578941183SFenghua Yu 	*cache_size = 0;
19678941183SFenghua Yu 
19778941183SFenghua Yu 	for (i = 0; i < length; i++) {
19878941183SFenghua Yu 		if ((cache_str[i] >= '0') && (cache_str[i] <= '9'))
19978941183SFenghua Yu 
20078941183SFenghua Yu 			*cache_size = *cache_size * 10 + (cache_str[i] - '0');
20178941183SFenghua Yu 
20278941183SFenghua Yu 		else if (cache_str[i] == 'K')
20378941183SFenghua Yu 
20478941183SFenghua Yu 			*cache_size = *cache_size * 1024;
20578941183SFenghua Yu 
20678941183SFenghua Yu 		else if (cache_str[i] == 'M')
20778941183SFenghua Yu 
20878941183SFenghua Yu 			*cache_size = *cache_size * 1024 * 1024;
20978941183SFenghua Yu 
21078941183SFenghua Yu 		else
21178941183SFenghua Yu 			break;
21278941183SFenghua Yu 	}
21378941183SFenghua Yu 
21478941183SFenghua Yu 	return 0;
21578941183SFenghua Yu }
21678941183SFenghua Yu 
21778941183SFenghua Yu #define CORE_SIBLINGS_PATH	"/sys/bus/cpu/devices/cpu"
21878941183SFenghua Yu 
21978941183SFenghua Yu /*
2204b357e2aSIlpo Järvinen  * get_bit_mask - Get bit mask from given file
2214b357e2aSIlpo Järvinen  * @filename:	File containing the mask
2224b357e2aSIlpo Järvinen  * @mask:	The bit mask returned as unsigned long
22378941183SFenghua Yu  *
22478941183SFenghua Yu  * Return: = 0 on success, < 0 on failure.
22578941183SFenghua Yu  */
get_bit_mask(const char * filename,unsigned long * mask)2264b357e2aSIlpo Järvinen static int get_bit_mask(const char *filename, unsigned long *mask)
22778941183SFenghua Yu {
22878941183SFenghua Yu 	FILE *fp;
22978941183SFenghua Yu 
2304b357e2aSIlpo Järvinen 	if (!filename || !mask)
2318236c51dSFenghua Yu 		return -1;
2328236c51dSFenghua Yu 
2334b357e2aSIlpo Järvinen 	fp = fopen(filename, "r");
23478941183SFenghua Yu 	if (!fp) {
2354b357e2aSIlpo Järvinen 		ksft_print_msg("Failed to open bit mask file '%s': %s\n",
2364b357e2aSIlpo Järvinen 			       filename, strerror(errno));
23778941183SFenghua Yu 		return -1;
23878941183SFenghua Yu 	}
2394b357e2aSIlpo Järvinen 
2404b357e2aSIlpo Järvinen 	if (fscanf(fp, "%lx", mask) <= 0) {
2414b357e2aSIlpo Järvinen 		ksft_print_msg("Could not read bit mask file '%s': %s\n",
2424b357e2aSIlpo Järvinen 			       filename, strerror(errno));
24378941183SFenghua Yu 		fclose(fp);
24478941183SFenghua Yu 
24578941183SFenghua Yu 		return -1;
24678941183SFenghua Yu 	}
24778941183SFenghua Yu 	fclose(fp);
24878941183SFenghua Yu 
24978941183SFenghua Yu 	return 0;
25078941183SFenghua Yu }
25178941183SFenghua Yu 
25278941183SFenghua Yu /*
253e331ac14SMaciej Wieczor-Retman  * resource_info_unsigned_get - Read an unsigned value from
254e331ac14SMaciej Wieczor-Retman  * /sys/fs/resctrl/info/@resource/@filename
255e331ac14SMaciej Wieczor-Retman  * @resource:	Resource name that matches directory name in
256e331ac14SMaciej Wieczor-Retman  *		/sys/fs/resctrl/info
257e331ac14SMaciej Wieczor-Retman  * @filename:	File in /sys/fs/resctrl/info/@resource
258e331ac14SMaciej Wieczor-Retman  * @val:	Contains read value on success.
259e331ac14SMaciej Wieczor-Retman  *
260e331ac14SMaciej Wieczor-Retman  * Return: = 0 on success, < 0 on failure. On success the read
261e331ac14SMaciej Wieczor-Retman  * value is saved into @val.
262e331ac14SMaciej Wieczor-Retman  */
resource_info_unsigned_get(const char * resource,const char * filename,unsigned int * val)263e331ac14SMaciej Wieczor-Retman int resource_info_unsigned_get(const char *resource, const char *filename,
264e331ac14SMaciej Wieczor-Retman 			       unsigned int *val)
265e331ac14SMaciej Wieczor-Retman {
266e331ac14SMaciej Wieczor-Retman 	char file_path[PATH_MAX];
267e331ac14SMaciej Wieczor-Retman 	FILE *fp;
268e331ac14SMaciej Wieczor-Retman 
269e331ac14SMaciej Wieczor-Retman 	snprintf(file_path, sizeof(file_path), "%s/%s/%s", INFO_PATH, resource,
270e331ac14SMaciej Wieczor-Retman 		 filename);
271e331ac14SMaciej Wieczor-Retman 
272e331ac14SMaciej Wieczor-Retman 	fp = fopen(file_path, "r");
273e331ac14SMaciej Wieczor-Retman 	if (!fp) {
274e331ac14SMaciej Wieczor-Retman 		ksft_print_msg("Error opening %s: %m\n", file_path);
275e331ac14SMaciej Wieczor-Retman 		return -1;
276e331ac14SMaciej Wieczor-Retman 	}
277e331ac14SMaciej Wieczor-Retman 
278e331ac14SMaciej Wieczor-Retman 	if (fscanf(fp, "%u", val) <= 0) {
279e331ac14SMaciej Wieczor-Retman 		ksft_print_msg("Could not get contents of %s: %m\n", file_path);
280e331ac14SMaciej Wieczor-Retman 		fclose(fp);
281e331ac14SMaciej Wieczor-Retman 		return -1;
282e331ac14SMaciej Wieczor-Retman 	}
283e331ac14SMaciej Wieczor-Retman 
284e331ac14SMaciej Wieczor-Retman 	fclose(fp);
285e331ac14SMaciej Wieczor-Retman 	return 0;
286e331ac14SMaciej Wieczor-Retman }
287e331ac14SMaciej Wieczor-Retman 
288e331ac14SMaciej Wieczor-Retman /*
289b6dfac94SIlpo Järvinen  * create_bit_mask- Create bit mask from start, len pair
290b6dfac94SIlpo Järvinen  * @start:	LSB of the mask
291b6dfac94SIlpo Järvinen  * @len		Number of bits in the mask
292b6dfac94SIlpo Järvinen  */
create_bit_mask(unsigned int start,unsigned int len)293b6dfac94SIlpo Järvinen unsigned long create_bit_mask(unsigned int start, unsigned int len)
294b6dfac94SIlpo Järvinen {
295b6dfac94SIlpo Järvinen 	return ((1UL << len) - 1UL) << start;
296b6dfac94SIlpo Järvinen }
297b6dfac94SIlpo Järvinen 
298b6dfac94SIlpo Järvinen /*
299b6dfac94SIlpo Järvinen  * count_contiguous_bits - Returns the longest train of bits in a bit mask
300b6dfac94SIlpo Järvinen  * @val		A bit mask
301b6dfac94SIlpo Järvinen  * @start	The location of the least-significant bit of the longest train
302b6dfac94SIlpo Järvinen  *
303b6dfac94SIlpo Järvinen  * Return:	The length of the contiguous bits in the longest train of bits
304b6dfac94SIlpo Järvinen  */
count_contiguous_bits(unsigned long val,unsigned int * start)305205de6ddSIlpo Järvinen unsigned int count_contiguous_bits(unsigned long val, unsigned int *start)
306b6dfac94SIlpo Järvinen {
307b6dfac94SIlpo Järvinen 	unsigned long last_val;
308b6dfac94SIlpo Järvinen 	unsigned int count = 0;
309b6dfac94SIlpo Järvinen 
310b6dfac94SIlpo Järvinen 	while (val) {
311b6dfac94SIlpo Järvinen 		last_val = val;
312b6dfac94SIlpo Järvinen 		val &= (val >> 1);
313b6dfac94SIlpo Järvinen 		count++;
314b6dfac94SIlpo Järvinen 	}
315b6dfac94SIlpo Järvinen 
316b6dfac94SIlpo Järvinen 	if (start) {
317b6dfac94SIlpo Järvinen 		if (count)
318b6dfac94SIlpo Järvinen 			*start = ffsl(last_val) - 1;
319b6dfac94SIlpo Järvinen 		else
320b6dfac94SIlpo Järvinen 			*start = 0;
321b6dfac94SIlpo Järvinen 	}
322b6dfac94SIlpo Järvinen 
323b6dfac94SIlpo Järvinen 	return count;
324b6dfac94SIlpo Järvinen }
325b6dfac94SIlpo Järvinen 
326b6dfac94SIlpo Järvinen /*
3274b357e2aSIlpo Järvinen  * get_full_cbm - Get full Cache Bit Mask (CBM)
3284b357e2aSIlpo Järvinen  * @cache_type:	Cache type as "L2" or "L3"
3294b357e2aSIlpo Järvinen  * @mask:	Full cache bit mask representing the maximal portion of cache
3304b357e2aSIlpo Järvinen  *		available for allocation, returned as unsigned long.
3314b357e2aSIlpo Järvinen  *
3324b357e2aSIlpo Järvinen  * Return: = 0 on success, < 0 on failure.
3334b357e2aSIlpo Järvinen  */
get_full_cbm(const char * cache_type,unsigned long * mask)3344b357e2aSIlpo Järvinen int get_full_cbm(const char *cache_type, unsigned long *mask)
3354b357e2aSIlpo Järvinen {
3364b357e2aSIlpo Järvinen 	char cbm_path[PATH_MAX];
3374b357e2aSIlpo Järvinen 	int ret;
3384b357e2aSIlpo Järvinen 
3394b357e2aSIlpo Järvinen 	if (!cache_type)
3404b357e2aSIlpo Järvinen 		return -1;
3414b357e2aSIlpo Järvinen 
3424b357e2aSIlpo Järvinen 	snprintf(cbm_path, sizeof(cbm_path), "%s/%s/cbm_mask",
3434b357e2aSIlpo Järvinen 		 INFO_PATH, cache_type);
3444b357e2aSIlpo Järvinen 
3454b357e2aSIlpo Järvinen 	ret = get_bit_mask(cbm_path, mask);
3464b357e2aSIlpo Järvinen 	if (ret || !*mask)
3474b357e2aSIlpo Järvinen 		return -1;
3484b357e2aSIlpo Järvinen 
3494b357e2aSIlpo Järvinen 	return 0;
3504b357e2aSIlpo Järvinen }
3514b357e2aSIlpo Järvinen 
3524b357e2aSIlpo Järvinen /*
353b6dfac94SIlpo Järvinen  * get_shareable_mask - Get shareable mask from shareable_bits
354b6dfac94SIlpo Järvinen  * @cache_type:		Cache type as "L2" or "L3"
355b6dfac94SIlpo Järvinen  * @shareable_mask:	Shareable mask returned as unsigned long
356b6dfac94SIlpo Järvinen  *
357b6dfac94SIlpo Järvinen  * Return: = 0 on success, < 0 on failure.
358b6dfac94SIlpo Järvinen  */
get_shareable_mask(const char * cache_type,unsigned long * shareable_mask)359b6dfac94SIlpo Järvinen static int get_shareable_mask(const char *cache_type, unsigned long *shareable_mask)
360b6dfac94SIlpo Järvinen {
361b6dfac94SIlpo Järvinen 	char mask_path[PATH_MAX];
362b6dfac94SIlpo Järvinen 
363b6dfac94SIlpo Järvinen 	if (!cache_type)
364b6dfac94SIlpo Järvinen 		return -1;
365b6dfac94SIlpo Järvinen 
366b6dfac94SIlpo Järvinen 	snprintf(mask_path, sizeof(mask_path), "%s/%s/shareable_bits",
367b6dfac94SIlpo Järvinen 		 INFO_PATH, cache_type);
368b6dfac94SIlpo Järvinen 
369b6dfac94SIlpo Järvinen 	return get_bit_mask(mask_path, shareable_mask);
370b6dfac94SIlpo Järvinen }
371b6dfac94SIlpo Järvinen 
372b6dfac94SIlpo Järvinen /*
373b6dfac94SIlpo Järvinen  * get_mask_no_shareable - Get Cache Bit Mask (CBM) without shareable bits
374b6dfac94SIlpo Järvinen  * @cache_type:		Cache type as "L2" or "L3"
375b6dfac94SIlpo Järvinen  * @mask:		The largest exclusive portion of the cache out of the
376b6dfac94SIlpo Järvinen  *			full CBM, returned as unsigned long
377b6dfac94SIlpo Järvinen  *
378b6dfac94SIlpo Järvinen  * Parts of a cache may be shared with other devices such as GPU. This function
379b6dfac94SIlpo Järvinen  * calculates the largest exclusive portion of the cache where no other devices
380b6dfac94SIlpo Järvinen  * besides CPU have access to the cache portion.
381b6dfac94SIlpo Järvinen  *
382b6dfac94SIlpo Järvinen  * Return: = 0 on success, < 0 on failure.
383b6dfac94SIlpo Järvinen  */
get_mask_no_shareable(const char * cache_type,unsigned long * mask)384b6dfac94SIlpo Järvinen int get_mask_no_shareable(const char *cache_type, unsigned long *mask)
385b6dfac94SIlpo Järvinen {
386b6dfac94SIlpo Järvinen 	unsigned long full_mask, shareable_mask;
387b6dfac94SIlpo Järvinen 	unsigned int start, len;
388b6dfac94SIlpo Järvinen 
389b6dfac94SIlpo Järvinen 	if (get_full_cbm(cache_type, &full_mask) < 0)
390b6dfac94SIlpo Järvinen 		return -1;
391b6dfac94SIlpo Järvinen 	if (get_shareable_mask(cache_type, &shareable_mask) < 0)
392b6dfac94SIlpo Järvinen 		return -1;
393b6dfac94SIlpo Järvinen 
394b6dfac94SIlpo Järvinen 	len = count_contiguous_bits(full_mask & ~shareable_mask, &start);
395b6dfac94SIlpo Järvinen 	if (!len)
396b6dfac94SIlpo Järvinen 		return -1;
397b6dfac94SIlpo Järvinen 
398b6dfac94SIlpo Järvinen 	*mask = create_bit_mask(start, len);
399b6dfac94SIlpo Järvinen 
400b6dfac94SIlpo Järvinen 	return 0;
401b6dfac94SIlpo Järvinen }
402b6dfac94SIlpo Järvinen 
403b6dfac94SIlpo Järvinen /*
404591a6e85SSai Praneeth Prakhya  * taskset_benchmark - Taskset PID (i.e. benchmark) to a specified cpu
405591a6e85SSai Praneeth Prakhya  * @bm_pid:		PID that should be binded
406591a6e85SSai Praneeth Prakhya  * @cpu_no:		CPU number at which the PID would be binded
4076c8cb747SIlpo Järvinen  * @old_affinity:	When not NULL, set to old CPU affinity
408591a6e85SSai Praneeth Prakhya  *
40934813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
410591a6e85SSai Praneeth Prakhya  */
taskset_benchmark(pid_t bm_pid,int cpu_no,cpu_set_t * old_affinity)4116c8cb747SIlpo Järvinen int taskset_benchmark(pid_t bm_pid, int cpu_no, cpu_set_t *old_affinity)
412591a6e85SSai Praneeth Prakhya {
413591a6e85SSai Praneeth Prakhya 	cpu_set_t my_set;
414591a6e85SSai Praneeth Prakhya 
4156c8cb747SIlpo Järvinen 	if (old_affinity) {
4166c8cb747SIlpo Järvinen 		CPU_ZERO(old_affinity);
4176c8cb747SIlpo Järvinen 		if (sched_getaffinity(bm_pid, sizeof(*old_affinity),
4186c8cb747SIlpo Järvinen 				      old_affinity)) {
4196c8cb747SIlpo Järvinen 			ksft_perror("Unable to read CPU affinity");
4206c8cb747SIlpo Järvinen 			return -1;
4216c8cb747SIlpo Järvinen 		}
4226c8cb747SIlpo Järvinen 	}
4236c8cb747SIlpo Järvinen 
424591a6e85SSai Praneeth Prakhya 	CPU_ZERO(&my_set);
425591a6e85SSai Praneeth Prakhya 	CPU_SET(cpu_no, &my_set);
426591a6e85SSai Praneeth Prakhya 
427591a6e85SSai Praneeth Prakhya 	if (sched_setaffinity(bm_pid, sizeof(cpu_set_t), &my_set)) {
428cc8ff7f5SIlpo Järvinen 		ksft_perror("Unable to taskset benchmark");
429591a6e85SSai Praneeth Prakhya 
430591a6e85SSai Praneeth Prakhya 		return -1;
431591a6e85SSai Praneeth Prakhya 	}
432591a6e85SSai Praneeth Prakhya 
433591a6e85SSai Praneeth Prakhya 	return 0;
434591a6e85SSai Praneeth Prakhya }
435591a6e85SSai Praneeth Prakhya 
436591a6e85SSai Praneeth Prakhya /*
4376c8cb747SIlpo Järvinen  * taskset_restore - Taskset PID to the earlier CPU affinity
4386c8cb747SIlpo Järvinen  * @bm_pid:		PID that should be reset
4396c8cb747SIlpo Järvinen  * @old_affinity:	The old CPU affinity to restore
4406c8cb747SIlpo Järvinen  *
4416c8cb747SIlpo Järvinen  * Return: 0 on success, < 0 on error.
4426c8cb747SIlpo Järvinen  */
taskset_restore(pid_t bm_pid,cpu_set_t * old_affinity)4436c8cb747SIlpo Järvinen int taskset_restore(pid_t bm_pid, cpu_set_t *old_affinity)
4446c8cb747SIlpo Järvinen {
4456c8cb747SIlpo Järvinen 	if (sched_setaffinity(bm_pid, sizeof(*old_affinity), old_affinity)) {
4466c8cb747SIlpo Järvinen 		ksft_perror("Unable to restore CPU affinity");
4476c8cb747SIlpo Järvinen 		return -1;
4486c8cb747SIlpo Järvinen 	}
4496c8cb747SIlpo Järvinen 
4506c8cb747SIlpo Järvinen 	return 0;
4516c8cb747SIlpo Järvinen }
4526c8cb747SIlpo Järvinen 
4536c8cb747SIlpo Järvinen /*
454591a6e85SSai Praneeth Prakhya  * create_grp - Create a group only if one doesn't exist
455591a6e85SSai Praneeth Prakhya  * @grp_name:	Name of the group
456591a6e85SSai Praneeth Prakhya  * @grp:	Full path and name of the group
457591a6e85SSai Praneeth Prakhya  * @parent_grp:	Full path and name of the parent group
458591a6e85SSai Praneeth Prakhya  *
459d14d94daSIlpo Järvinen  * Creates a group @grp_name if it does not exist yet. If @grp_name is NULL,
460d14d94daSIlpo Järvinen  * it is interpreted as the root group which always results in success.
461d14d94daSIlpo Järvinen  *
46234813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
463591a6e85SSai Praneeth Prakhya  */
create_grp(const char * grp_name,char * grp,const char * parent_grp)464591a6e85SSai Praneeth Prakhya static int create_grp(const char *grp_name, char *grp, const char *parent_grp)
465591a6e85SSai Praneeth Prakhya {
466591a6e85SSai Praneeth Prakhya 	int found_grp = 0;
467591a6e85SSai Praneeth Prakhya 	struct dirent *ep;
468591a6e85SSai Praneeth Prakhya 	DIR *dp;
469591a6e85SSai Praneeth Prakhya 
470d14d94daSIlpo Järvinen 	if (!grp_name)
47178941183SFenghua Yu 		return 0;
47278941183SFenghua Yu 
473591a6e85SSai Praneeth Prakhya 	/* Check if requested grp exists or not */
474591a6e85SSai Praneeth Prakhya 	dp = opendir(parent_grp);
475591a6e85SSai Praneeth Prakhya 	if (dp) {
476591a6e85SSai Praneeth Prakhya 		while ((ep = readdir(dp)) != NULL) {
477591a6e85SSai Praneeth Prakhya 			if (strcmp(ep->d_name, grp_name) == 0)
478591a6e85SSai Praneeth Prakhya 				found_grp = 1;
479591a6e85SSai Praneeth Prakhya 		}
480591a6e85SSai Praneeth Prakhya 		closedir(dp);
481591a6e85SSai Praneeth Prakhya 	} else {
482cc8ff7f5SIlpo Järvinen 		ksft_perror("Unable to open resctrl for group");
483591a6e85SSai Praneeth Prakhya 
484591a6e85SSai Praneeth Prakhya 		return -1;
485591a6e85SSai Praneeth Prakhya 	}
486591a6e85SSai Praneeth Prakhya 
487591a6e85SSai Praneeth Prakhya 	/* Requested grp doesn't exist, hence create it */
488591a6e85SSai Praneeth Prakhya 	if (found_grp == 0) {
489591a6e85SSai Praneeth Prakhya 		if (mkdir(grp, 0) == -1) {
490cc8ff7f5SIlpo Järvinen 			ksft_perror("Unable to create group");
491591a6e85SSai Praneeth Prakhya 
492591a6e85SSai Praneeth Prakhya 			return -1;
493591a6e85SSai Praneeth Prakhya 		}
494591a6e85SSai Praneeth Prakhya 	}
495591a6e85SSai Praneeth Prakhya 
496591a6e85SSai Praneeth Prakhya 	return 0;
497591a6e85SSai Praneeth Prakhya }
498591a6e85SSai Praneeth Prakhya 
write_pid_to_tasks(char * tasks,pid_t pid)499591a6e85SSai Praneeth Prakhya static int write_pid_to_tasks(char *tasks, pid_t pid)
500591a6e85SSai Praneeth Prakhya {
501591a6e85SSai Praneeth Prakhya 	FILE *fp;
502591a6e85SSai Praneeth Prakhya 
503591a6e85SSai Praneeth Prakhya 	fp = fopen(tasks, "w");
504591a6e85SSai Praneeth Prakhya 	if (!fp) {
505cc8ff7f5SIlpo Järvinen 		ksft_perror("Failed to open tasks file");
506591a6e85SSai Praneeth Prakhya 
507591a6e85SSai Praneeth Prakhya 		return -1;
508591a6e85SSai Praneeth Prakhya 	}
5098245a70eSIlpo Järvinen 	if (fprintf(fp, "%d\n", (int)pid) < 0) {
510cc8ff7f5SIlpo Järvinen 		ksft_print_msg("Failed to write pid to tasks file\n");
511591a6e85SSai Praneeth Prakhya 		fclose(fp);
512591a6e85SSai Praneeth Prakhya 
513591a6e85SSai Praneeth Prakhya 		return -1;
514591a6e85SSai Praneeth Prakhya 	}
515591a6e85SSai Praneeth Prakhya 	fclose(fp);
516591a6e85SSai Praneeth Prakhya 
517591a6e85SSai Praneeth Prakhya 	return 0;
518591a6e85SSai Praneeth Prakhya }
519591a6e85SSai Praneeth Prakhya 
520591a6e85SSai Praneeth Prakhya /*
521591a6e85SSai Praneeth Prakhya  * write_bm_pid_to_resctrl - Write a PID (i.e. benchmark) to resctrl FS
522591a6e85SSai Praneeth Prakhya  * @bm_pid:		PID that should be written
523591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the control monitor group (con_mon grp)
524591a6e85SSai Praneeth Prakhya  * @mongrp:		Name of the monitor group (mon grp)
525591a6e85SSai Praneeth Prakhya  *
526591a6e85SSai Praneeth Prakhya  * If a con_mon grp is requested, create it and write pid to it, otherwise
527591a6e85SSai Praneeth Prakhya  * write pid to root con_mon grp.
528591a6e85SSai Praneeth Prakhya  * If a mon grp is requested, create it and write pid to it, otherwise
529591a6e85SSai Praneeth Prakhya  * pid is not written, this means that pid is in con_mon grp and hence
530591a6e85SSai Praneeth Prakhya  * should consult con_mon grp's mon_data directory for results.
531591a6e85SSai Praneeth Prakhya  *
53234813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
533591a6e85SSai Praneeth Prakhya  */
write_bm_pid_to_resctrl(pid_t bm_pid,const char * ctrlgrp,const char * mongrp)534*0d66ddb2SIlpo Järvinen int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, const char *mongrp)
535591a6e85SSai Praneeth Prakhya {
536591a6e85SSai Praneeth Prakhya 	char controlgroup[128], monitorgroup[512], monitorgroup_p[256];
537591a6e85SSai Praneeth Prakhya 	char tasks[1024];
538591a6e85SSai Praneeth Prakhya 	int ret = 0;
539591a6e85SSai Praneeth Prakhya 
540d14d94daSIlpo Järvinen 	if (ctrlgrp)
541591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s", RESCTRL_PATH, ctrlgrp);
542591a6e85SSai Praneeth Prakhya 	else
543591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s", RESCTRL_PATH);
544591a6e85SSai Praneeth Prakhya 
545591a6e85SSai Praneeth Prakhya 	/* Create control and monitoring group and write pid into it */
546591a6e85SSai Praneeth Prakhya 	ret = create_grp(ctrlgrp, controlgroup, RESCTRL_PATH);
547591a6e85SSai Praneeth Prakhya 	if (ret)
548591a6e85SSai Praneeth Prakhya 		goto out;
549591a6e85SSai Praneeth Prakhya 	sprintf(tasks, "%s/tasks", controlgroup);
550591a6e85SSai Praneeth Prakhya 	ret = write_pid_to_tasks(tasks, bm_pid);
551591a6e85SSai Praneeth Prakhya 	if (ret)
552591a6e85SSai Praneeth Prakhya 		goto out;
553591a6e85SSai Praneeth Prakhya 
554*0d66ddb2SIlpo Järvinen 	/* Create monitor group and write pid into if it is used */
555d14d94daSIlpo Järvinen 	if (mongrp) {
556591a6e85SSai Praneeth Prakhya 		sprintf(monitorgroup_p, "%s/mon_groups", controlgroup);
557591a6e85SSai Praneeth Prakhya 		sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp);
558591a6e85SSai Praneeth Prakhya 		ret = create_grp(mongrp, monitorgroup, monitorgroup_p);
559591a6e85SSai Praneeth Prakhya 		if (ret)
560591a6e85SSai Praneeth Prakhya 			goto out;
561591a6e85SSai Praneeth Prakhya 
562591a6e85SSai Praneeth Prakhya 		sprintf(tasks, "%s/mon_groups/%s/tasks",
563591a6e85SSai Praneeth Prakhya 			controlgroup, mongrp);
564591a6e85SSai Praneeth Prakhya 		ret = write_pid_to_tasks(tasks, bm_pid);
565591a6e85SSai Praneeth Prakhya 		if (ret)
566591a6e85SSai Praneeth Prakhya 			goto out;
567591a6e85SSai Praneeth Prakhya 	}
568591a6e85SSai Praneeth Prakhya 
569591a6e85SSai Praneeth Prakhya out:
570ca2f4214SFenghua Yu 	ksft_print_msg("Writing benchmark parameters to resctrl FS\n");
571591a6e85SSai Praneeth Prakhya 	if (ret)
572cc8ff7f5SIlpo Järvinen 		ksft_print_msg("Failed writing to resctrlfs\n");
573591a6e85SSai Praneeth Prakhya 
574591a6e85SSai Praneeth Prakhya 	return ret;
575591a6e85SSai Praneeth Prakhya }
576591a6e85SSai Praneeth Prakhya 
577591a6e85SSai Praneeth Prakhya /*
578591a6e85SSai Praneeth Prakhya  * write_schemata - Update schemata of a con_mon grp
579591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the con_mon grp
580591a6e85SSai Praneeth Prakhya  * @schemata:		Schemata that should be updated to
581591a6e85SSai Praneeth Prakhya  * @cpu_no:		CPU number that the benchmark PID is binded to
582ca160887SIlpo Järvinen  * @resource:		Resctrl resource (Eg: MB, L3, L2, etc.)
583591a6e85SSai Praneeth Prakhya  *
584ca160887SIlpo Järvinen  * Update schemata of a con_mon grp *only* if requested resctrl resource is
585591a6e85SSai Praneeth Prakhya  * allocation type
586591a6e85SSai Praneeth Prakhya  *
58734813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
588591a6e85SSai Praneeth Prakhya  */
write_schemata(const char * ctrlgrp,char * schemata,int cpu_no,const char * resource)589909592b5SIlpo Järvinen int write_schemata(const char *ctrlgrp, char *schemata, int cpu_no,
590909592b5SIlpo Järvinen 		   const char *resource)
591591a6e85SSai Praneeth Prakhya {
59220d96b25SMaciej Wieczor-Retman 	char controlgroup[1024], reason[128], schema[1024] = {};
5936874f6edSIlpo Järvinen 	int domain_id, fd, schema_len, ret = 0;
594591a6e85SSai Praneeth Prakhya 
595591a6e85SSai Praneeth Prakhya 	if (!schemata) {
596ca2f4214SFenghua Yu 		ksft_print_msg("Skipping empty schemata update\n");
597591a6e85SSai Praneeth Prakhya 
598591a6e85SSai Praneeth Prakhya 		return -1;
599591a6e85SSai Praneeth Prakhya 	}
600591a6e85SSai Praneeth Prakhya 
601345e8abeSIlpo Järvinen 	if (get_domain_id(resource, cpu_no, &domain_id) < 0) {
6026874f6edSIlpo Järvinen 		sprintf(reason, "Failed to get domain ID");
603591a6e85SSai Praneeth Prakhya 		ret = -1;
604591a6e85SSai Praneeth Prakhya 
605591a6e85SSai Praneeth Prakhya 		goto out;
606591a6e85SSai Praneeth Prakhya 	}
607591a6e85SSai Praneeth Prakhya 
608d14d94daSIlpo Järvinen 	if (ctrlgrp)
609591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s/schemata", RESCTRL_PATH, ctrlgrp);
610591a6e85SSai Praneeth Prakhya 	else
611591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/schemata", RESCTRL_PATH);
612591a6e85SSai Praneeth Prakhya 
613ca160887SIlpo Järvinen 	schema_len = snprintf(schema, sizeof(schema), "%s:%d=%s\n",
6146874f6edSIlpo Järvinen 			      resource, domain_id, schemata);
61520d96b25SMaciej Wieczor-Retman 	if (schema_len < 0 || schema_len >= sizeof(schema)) {
61620d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
61720d96b25SMaciej Wieczor-Retman 			 "snprintf() failed with return value : %d", schema_len);
618591a6e85SSai Praneeth Prakhya 		ret = -1;
619591a6e85SSai Praneeth Prakhya 		goto out;
620591a6e85SSai Praneeth Prakhya 	}
621591a6e85SSai Praneeth Prakhya 
62220d96b25SMaciej Wieczor-Retman 	fd = open(controlgroup, O_WRONLY);
62320d96b25SMaciej Wieczor-Retman 	if (fd < 0) {
62420d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
62520d96b25SMaciej Wieczor-Retman 			 "open() failed : %s", strerror(errno));
626591a6e85SSai Praneeth Prakhya 		ret = -1;
627591a6e85SSai Praneeth Prakhya 
62820d96b25SMaciej Wieczor-Retman 		goto err_schema_not_empty;
629591a6e85SSai Praneeth Prakhya 	}
63020d96b25SMaciej Wieczor-Retman 	if (write(fd, schema, schema_len) < 0) {
63120d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
63220d96b25SMaciej Wieczor-Retman 			 "write() failed : %s", strerror(errno));
63320d96b25SMaciej Wieczor-Retman 		close(fd);
63420d96b25SMaciej Wieczor-Retman 		ret = -1;
635591a6e85SSai Praneeth Prakhya 
63620d96b25SMaciej Wieczor-Retman 		goto err_schema_not_empty;
63720d96b25SMaciej Wieczor-Retman 	}
63820d96b25SMaciej Wieczor-Retman 	close(fd);
63920d96b25SMaciej Wieczor-Retman 
64020d96b25SMaciej Wieczor-Retman err_schema_not_empty:
64120d96b25SMaciej Wieczor-Retman 	schema[schema_len - 1] = 0;
642591a6e85SSai Praneeth Prakhya out:
643ca2f4214SFenghua Yu 	ksft_print_msg("Write schema \"%s\" to resctrl FS%s%s\n",
644ca2f4214SFenghua Yu 		       schema, ret ? " # " : "",
645591a6e85SSai Praneeth Prakhya 		       ret ? reason : "");
646591a6e85SSai Praneeth Prakhya 
647591a6e85SSai Praneeth Prakhya 	return ret;
648591a6e85SSai Praneeth Prakhya }
649591a6e85SSai Praneeth Prakhya 
check_resctrlfs_support(void)650ecdbb911SFenghua Yu bool check_resctrlfs_support(void)
651ecdbb911SFenghua Yu {
652ecdbb911SFenghua Yu 	FILE *inf = fopen("/proc/filesystems", "r");
653ecdbb911SFenghua Yu 	DIR *dp;
654ecdbb911SFenghua Yu 	char *res;
655ecdbb911SFenghua Yu 	bool ret = false;
656ecdbb911SFenghua Yu 
657ecdbb911SFenghua Yu 	if (!inf)
658ecdbb911SFenghua Yu 		return false;
659ecdbb911SFenghua Yu 
660ecdbb911SFenghua Yu 	res = fgrep(inf, "nodev\tresctrl\n");
661ecdbb911SFenghua Yu 
662ecdbb911SFenghua Yu 	if (res) {
663ecdbb911SFenghua Yu 		ret = true;
664ecdbb911SFenghua Yu 		free(res);
665ecdbb911SFenghua Yu 	}
666ecdbb911SFenghua Yu 
667ecdbb911SFenghua Yu 	fclose(inf);
668ecdbb911SFenghua Yu 
669e7507478SFenghua Yu 	ksft_print_msg("%s Check kernel supports resctrl filesystem\n",
670ca2f4214SFenghua Yu 		       ret ? "Pass:" : "Fail:");
671ecdbb911SFenghua Yu 
672a3611fbcSFenghua Yu 	if (!ret)
673a3611fbcSFenghua Yu 		return ret;
674a3611fbcSFenghua Yu 
675ecdbb911SFenghua Yu 	dp = opendir(RESCTRL_PATH);
676e7507478SFenghua Yu 	ksft_print_msg("%s Check resctrl mountpoint \"%s\" exists\n",
677ca2f4214SFenghua Yu 		       dp ? "Pass:" : "Fail:", RESCTRL_PATH);
678ecdbb911SFenghua Yu 	if (dp)
679ecdbb911SFenghua Yu 		closedir(dp);
680ecdbb911SFenghua Yu 
681ca2f4214SFenghua Yu 	ksft_print_msg("resctrl filesystem %s mounted\n",
682ecdbb911SFenghua Yu 		       find_resctrl_mount(NULL) ? "not" : "is");
683ecdbb911SFenghua Yu 
684ecdbb911SFenghua Yu 	return ret;
685ecdbb911SFenghua Yu }
686ecdbb911SFenghua Yu 
fgrep(FILE * inf,const char * str)687591a6e85SSai Praneeth Prakhya char *fgrep(FILE *inf, const char *str)
688591a6e85SSai Praneeth Prakhya {
689591a6e85SSai Praneeth Prakhya 	char line[256];
690591a6e85SSai Praneeth Prakhya 	int slen = strlen(str);
691591a6e85SSai Praneeth Prakhya 
692591a6e85SSai Praneeth Prakhya 	while (!feof(inf)) {
693591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, inf))
694591a6e85SSai Praneeth Prakhya 			break;
695591a6e85SSai Praneeth Prakhya 		if (strncmp(line, str, slen))
696591a6e85SSai Praneeth Prakhya 			continue;
697591a6e85SSai Praneeth Prakhya 
698591a6e85SSai Praneeth Prakhya 		return strdup(line);
699591a6e85SSai Praneeth Prakhya 	}
700591a6e85SSai Praneeth Prakhya 
701591a6e85SSai Praneeth Prakhya 	return NULL;
702591a6e85SSai Praneeth Prakhya }
703591a6e85SSai Praneeth Prakhya 
704591a6e85SSai Praneeth Prakhya /*
70500616416SMaciej Wieczor-Retman  * resctrl_resource_exists - Check if a resource is supported.
70600616416SMaciej Wieczor-Retman  * @resource:	Resctrl resource (e.g., MB, L3, L2, L3_MON, etc.)
707591a6e85SSai Praneeth Prakhya  *
70800616416SMaciej Wieczor-Retman  * Return: True if the resource is supported, else false. False is
709d56e5da0SIlpo Järvinen  *         also returned if resctrl FS is not mounted.
710591a6e85SSai Praneeth Prakhya  */
resctrl_resource_exists(const char * resource)71100616416SMaciej Wieczor-Retman bool resctrl_resource_exists(const char *resource)
712591a6e85SSai Praneeth Prakhya {
713d56e5da0SIlpo Järvinen 	char res_path[PATH_MAX];
714ee041568SFenghua Yu 	struct stat statbuf;
715caddc0fbSIlpo Järvinen 	int ret;
716591a6e85SSai Praneeth Prakhya 
717d56e5da0SIlpo Järvinen 	if (!resource)
718ee041568SFenghua Yu 		return false;
719ee041568SFenghua Yu 
720caddc0fbSIlpo Järvinen 	ret = find_resctrl_mount(NULL);
721caddc0fbSIlpo Järvinen 	if (ret)
722ee041568SFenghua Yu 		return false;
723ee041568SFenghua Yu 
724d56e5da0SIlpo Järvinen 	snprintf(res_path, sizeof(res_path), "%s/%s", INFO_PATH, resource);
725d56e5da0SIlpo Järvinen 
726d56e5da0SIlpo Järvinen 	if (stat(res_path, &statbuf))
727d56e5da0SIlpo Järvinen 		return false;
728d56e5da0SIlpo Järvinen 
729ee041568SFenghua Yu 	return true;
73000616416SMaciej Wieczor-Retman }
73100616416SMaciej Wieczor-Retman 
73200616416SMaciej Wieczor-Retman /*
73300616416SMaciej Wieczor-Retman  * resctrl_mon_feature_exists - Check if requested monitoring feature is valid.
73400616416SMaciej Wieczor-Retman  * @resource:	Resource that uses the mon_features file. Currently only L3_MON
73500616416SMaciej Wieczor-Retman  *		is valid.
73600616416SMaciej Wieczor-Retman  * @feature:	Required monitor feature (in mon_features file).
73700616416SMaciej Wieczor-Retman  *
73800616416SMaciej Wieczor-Retman  * Return: True if the feature is supported, else false.
73900616416SMaciej Wieczor-Retman  */
resctrl_mon_feature_exists(const char * resource,const char * feature)74000616416SMaciej Wieczor-Retman bool resctrl_mon_feature_exists(const char *resource, const char *feature)
74100616416SMaciej Wieczor-Retman {
74200616416SMaciej Wieczor-Retman 	char res_path[PATH_MAX];
74300616416SMaciej Wieczor-Retman 	char *res;
74400616416SMaciej Wieczor-Retman 	FILE *inf;
74500616416SMaciej Wieczor-Retman 
74600616416SMaciej Wieczor-Retman 	if (!feature || !resource)
74700616416SMaciej Wieczor-Retman 		return false;
748d56e5da0SIlpo Järvinen 
749d56e5da0SIlpo Järvinen 	snprintf(res_path, sizeof(res_path), "%s/%s/mon_features", INFO_PATH, resource);
750d56e5da0SIlpo Järvinen 	inf = fopen(res_path, "r");
751591a6e85SSai Praneeth Prakhya 	if (!inf)
752591a6e85SSai Praneeth Prakhya 		return false;
753591a6e85SSai Praneeth Prakhya 
754d56e5da0SIlpo Järvinen 	res = fgrep(inf, feature);
755591a6e85SSai Praneeth Prakhya 	free(res);
756591a6e85SSai Praneeth Prakhya 	fclose(inf);
757591a6e85SSai Praneeth Prakhya 
758d56e5da0SIlpo Järvinen 	return !!res;
759591a6e85SSai Praneeth Prakhya }
760591a6e85SSai Praneeth Prakhya 
76174e76cbaSMaciej Wieczor-Retman /*
76274e76cbaSMaciej Wieczor-Retman  * resource_info_file_exists - Check if a file is present inside
76374e76cbaSMaciej Wieczor-Retman  * /sys/fs/resctrl/info/@resource.
76474e76cbaSMaciej Wieczor-Retman  * @resource:	Required resource (Eg: MB, L3, L2, etc.)
76574e76cbaSMaciej Wieczor-Retman  * @file:	Required file.
76674e76cbaSMaciej Wieczor-Retman  *
76774e76cbaSMaciej Wieczor-Retman  * Return: True if the /sys/fs/resctrl/info/@resource/@file exists, else false.
76874e76cbaSMaciej Wieczor-Retman  */
resource_info_file_exists(const char * resource,const char * file)76974e76cbaSMaciej Wieczor-Retman bool resource_info_file_exists(const char *resource, const char *file)
77074e76cbaSMaciej Wieczor-Retman {
77174e76cbaSMaciej Wieczor-Retman 	char res_path[PATH_MAX];
77274e76cbaSMaciej Wieczor-Retman 	struct stat statbuf;
77374e76cbaSMaciej Wieczor-Retman 
77474e76cbaSMaciej Wieczor-Retman 	if (!file || !resource)
77574e76cbaSMaciej Wieczor-Retman 		return false;
77674e76cbaSMaciej Wieczor-Retman 
77774e76cbaSMaciej Wieczor-Retman 	snprintf(res_path, sizeof(res_path), "%s/%s/%s", INFO_PATH, resource,
77874e76cbaSMaciej Wieczor-Retman 		 file);
77974e76cbaSMaciej Wieczor-Retman 
78074e76cbaSMaciej Wieczor-Retman 	if (stat(res_path, &statbuf))
78174e76cbaSMaciej Wieczor-Retman 		return false;
78274e76cbaSMaciej Wieczor-Retman 
78374e76cbaSMaciej Wieczor-Retman 	return true;
78474e76cbaSMaciej Wieczor-Retman }
78574e76cbaSMaciej Wieczor-Retman 
test_resource_feature_check(const struct resctrl_test * test)786c603ff5bSIlpo Järvinen bool test_resource_feature_check(const struct resctrl_test *test)
787c603ff5bSIlpo Järvinen {
78800616416SMaciej Wieczor-Retman 	return resctrl_resource_exists(test->resource);
789c603ff5bSIlpo Järvinen }
790c603ff5bSIlpo Järvinen 
filter_dmesg(void)791ecdbb911SFenghua Yu int filter_dmesg(void)
792ecdbb911SFenghua Yu {
793ecdbb911SFenghua Yu 	char line[1024];
794ecdbb911SFenghua Yu 	FILE *fp;
795ecdbb911SFenghua Yu 	int pipefds[2];
796ecdbb911SFenghua Yu 	pid_t pid;
797ecdbb911SFenghua Yu 	int ret;
798ecdbb911SFenghua Yu 
799ecdbb911SFenghua Yu 	ret = pipe(pipefds);
800ecdbb911SFenghua Yu 	if (ret) {
801cc8ff7f5SIlpo Järvinen 		ksft_perror("pipe");
802ecdbb911SFenghua Yu 		return ret;
803ecdbb911SFenghua Yu 	}
804a080b6e7SShaopeng Tan 	fflush(stdout);
805ecdbb911SFenghua Yu 	pid = fork();
806ecdbb911SFenghua Yu 	if (pid == 0) {
807ecdbb911SFenghua Yu 		close(pipefds[0]);
808ecdbb911SFenghua Yu 		dup2(pipefds[1], STDOUT_FILENO);
809ecdbb911SFenghua Yu 		execlp("dmesg", "dmesg", NULL);
810cc8ff7f5SIlpo Järvinen 		ksft_perror("Executing dmesg");
811ecdbb911SFenghua Yu 		exit(1);
812ecdbb911SFenghua Yu 	}
813ecdbb911SFenghua Yu 	close(pipefds[1]);
814ecdbb911SFenghua Yu 	fp = fdopen(pipefds[0], "r");
815ecdbb911SFenghua Yu 	if (!fp) {
816cc8ff7f5SIlpo Järvinen 		ksft_perror("fdopen(pipe)");
817ecdbb911SFenghua Yu 		kill(pid, SIGTERM);
818ecdbb911SFenghua Yu 
819ecdbb911SFenghua Yu 		return -1;
820ecdbb911SFenghua Yu 	}
821ecdbb911SFenghua Yu 
822ecdbb911SFenghua Yu 	while (fgets(line, 1024, fp)) {
823ecdbb911SFenghua Yu 		if (strstr(line, "intel_rdt:"))
824ca2f4214SFenghua Yu 			ksft_print_msg("dmesg: %s", line);
825ecdbb911SFenghua Yu 		if (strstr(line, "resctrl:"))
826ca2f4214SFenghua Yu 			ksft_print_msg("dmesg: %s", line);
827ecdbb911SFenghua Yu 	}
828ecdbb911SFenghua Yu 	fclose(fp);
829ecdbb911SFenghua Yu 	waitpid(pid, NULL, 0);
830ecdbb911SFenghua Yu 
831ecdbb911SFenghua Yu 	return 0;
832ecdbb911SFenghua Yu }
833ecdbb911SFenghua Yu 
get_bw_report_type(const char * bw_report)834fa1116d0SIlpo Järvinen const char *get_bw_report_type(const char *bw_report)
835591a6e85SSai Praneeth Prakhya {
836591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "reads") == 0)
837fa1116d0SIlpo Järvinen 		return bw_report;
838591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "writes") == 0)
839fa1116d0SIlpo Järvinen 		return bw_report;
840591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "nt-writes") == 0) {
841fa1116d0SIlpo Järvinen 		return "writes";
842591a6e85SSai Praneeth Prakhya 	}
843591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "total") == 0)
844fa1116d0SIlpo Järvinen 		return bw_report;
845591a6e85SSai Praneeth Prakhya 
8462704b2d1SIlpo Järvinen 	fprintf(stderr, "Requested iMC bandwidth report type unavailable\n");
847591a6e85SSai Praneeth Prakhya 
848fa1116d0SIlpo Järvinen 	return NULL;
849591a6e85SSai Praneeth Prakhya }
850591a6e85SSai Praneeth Prakhya 
perf_event_open(struct perf_event_attr * hw_event,pid_t pid,int cpu,int group_fd,unsigned long flags)851591a6e85SSai Praneeth Prakhya int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
852591a6e85SSai Praneeth Prakhya 		    int group_fd, unsigned long flags)
853591a6e85SSai Praneeth Prakhya {
854591a6e85SSai Praneeth Prakhya 	int ret;
855591a6e85SSai Praneeth Prakhya 
856591a6e85SSai Praneeth Prakhya 	ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
857591a6e85SSai Praneeth Prakhya 		      group_fd, flags);
858591a6e85SSai Praneeth Prakhya 	return ret;
859591a6e85SSai Praneeth Prakhya }
86078941183SFenghua Yu 
count_bits(unsigned long n)86178941183SFenghua Yu unsigned int count_bits(unsigned long n)
86278941183SFenghua Yu {
86378941183SFenghua Yu 	unsigned int count = 0;
86478941183SFenghua Yu 
86578941183SFenghua Yu 	while (n) {
86678941183SFenghua Yu 		count += n & 1;
86778941183SFenghua Yu 		n >>= 1;
86878941183SFenghua Yu 	}
86978941183SFenghua Yu 
87078941183SFenghua Yu 	return count;
87178941183SFenghua Yu }
872