xref: /linux/tools/testing/selftests/resctrl/resctrlfs.c (revision d14d94da0e3f1d7e598f88204cf37ee41a06f900)
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 
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  */
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 
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  */
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 
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  *
459*d14d94daSIlpo Järvinen  * Creates a group @grp_name if it does not exist yet. If @grp_name is NULL,
460*d14d94daSIlpo Järvinen  * it is interpreted as the root group which always results in success.
461*d14d94daSIlpo Järvinen  *
46234813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
463591a6e85SSai Praneeth Prakhya  */
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 
470*d14d94daSIlpo 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 
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  * @resctrl_val:	Resctrl feature (Eg: mbm, mba.. etc)
526591a6e85SSai Praneeth Prakhya  *
527591a6e85SSai Praneeth Prakhya  * If a con_mon grp is requested, create it and write pid to it, otherwise
528591a6e85SSai Praneeth Prakhya  * write pid to root con_mon grp.
529591a6e85SSai Praneeth Prakhya  * If a mon grp is requested, create it and write pid to it, otherwise
530591a6e85SSai Praneeth Prakhya  * pid is not written, this means that pid is in con_mon grp and hence
531591a6e85SSai Praneeth Prakhya  * should consult con_mon grp's mon_data directory for results.
532591a6e85SSai Praneeth Prakhya  *
53334813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
534591a6e85SSai Praneeth Prakhya  */
535909592b5SIlpo Järvinen int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp,
536909592b5SIlpo Järvinen 			    const char *mongrp, const char *resctrl_val)
537591a6e85SSai Praneeth Prakhya {
538591a6e85SSai Praneeth Prakhya 	char controlgroup[128], monitorgroup[512], monitorgroup_p[256];
539591a6e85SSai Praneeth Prakhya 	char tasks[1024];
540591a6e85SSai Praneeth Prakhya 	int ret = 0;
541591a6e85SSai Praneeth Prakhya 
542*d14d94daSIlpo Järvinen 	if (ctrlgrp)
543591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s", RESCTRL_PATH, ctrlgrp);
544591a6e85SSai Praneeth Prakhya 	else
545591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s", RESCTRL_PATH);
546591a6e85SSai Praneeth Prakhya 
547591a6e85SSai Praneeth Prakhya 	/* Create control and monitoring group and write pid into it */
548591a6e85SSai Praneeth Prakhya 	ret = create_grp(ctrlgrp, controlgroup, RESCTRL_PATH);
549591a6e85SSai Praneeth Prakhya 	if (ret)
550591a6e85SSai Praneeth Prakhya 		goto out;
551591a6e85SSai Praneeth Prakhya 	sprintf(tasks, "%s/tasks", controlgroup);
552591a6e85SSai Praneeth Prakhya 	ret = write_pid_to_tasks(tasks, bm_pid);
553591a6e85SSai Praneeth Prakhya 	if (ret)
554591a6e85SSai Praneeth Prakhya 		goto out;
555591a6e85SSai Praneeth Prakhya 
5562f320911SFenghua Yu 	/* Create mon grp and write pid into it for "mbm" and "cmt" test */
5572f320911SFenghua Yu 	if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)) ||
55824286736SFenghua Yu 	    !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) {
559*d14d94daSIlpo Järvinen 		if (mongrp) {
560591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup_p, "%s/mon_groups", controlgroup);
561591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp);
562591a6e85SSai Praneeth Prakhya 			ret = create_grp(mongrp, monitorgroup, monitorgroup_p);
563591a6e85SSai Praneeth Prakhya 			if (ret)
564591a6e85SSai Praneeth Prakhya 				goto out;
565591a6e85SSai Praneeth Prakhya 
566591a6e85SSai Praneeth Prakhya 			sprintf(tasks, "%s/mon_groups/%s/tasks",
567591a6e85SSai Praneeth Prakhya 				controlgroup, mongrp);
568591a6e85SSai Praneeth Prakhya 			ret = write_pid_to_tasks(tasks, bm_pid);
569591a6e85SSai Praneeth Prakhya 			if (ret)
570591a6e85SSai Praneeth Prakhya 				goto out;
571591a6e85SSai Praneeth Prakhya 		}
572591a6e85SSai Praneeth Prakhya 	}
573591a6e85SSai Praneeth Prakhya 
574591a6e85SSai Praneeth Prakhya out:
575ca2f4214SFenghua Yu 	ksft_print_msg("Writing benchmark parameters to resctrl FS\n");
576591a6e85SSai Praneeth Prakhya 	if (ret)
577cc8ff7f5SIlpo Järvinen 		ksft_print_msg("Failed writing to resctrlfs\n");
578591a6e85SSai Praneeth Prakhya 
579591a6e85SSai Praneeth Prakhya 	return ret;
580591a6e85SSai Praneeth Prakhya }
581591a6e85SSai Praneeth Prakhya 
582591a6e85SSai Praneeth Prakhya /*
583591a6e85SSai Praneeth Prakhya  * write_schemata - Update schemata of a con_mon grp
584591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the con_mon grp
585591a6e85SSai Praneeth Prakhya  * @schemata:		Schemata that should be updated to
586591a6e85SSai Praneeth Prakhya  * @cpu_no:		CPU number that the benchmark PID is binded to
587ca160887SIlpo Järvinen  * @resource:		Resctrl resource (Eg: MB, L3, L2, etc.)
588591a6e85SSai Praneeth Prakhya  *
589ca160887SIlpo Järvinen  * Update schemata of a con_mon grp *only* if requested resctrl resource is
590591a6e85SSai Praneeth Prakhya  * allocation type
591591a6e85SSai Praneeth Prakhya  *
59234813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
593591a6e85SSai Praneeth Prakhya  */
594909592b5SIlpo Järvinen int write_schemata(const char *ctrlgrp, char *schemata, int cpu_no,
595909592b5SIlpo Järvinen 		   const char *resource)
596591a6e85SSai Praneeth Prakhya {
59720d96b25SMaciej Wieczor-Retman 	char controlgroup[1024], reason[128], schema[1024] = {};
5986874f6edSIlpo Järvinen 	int domain_id, fd, schema_len, ret = 0;
599591a6e85SSai Praneeth Prakhya 
600591a6e85SSai Praneeth Prakhya 	if (!schemata) {
601ca2f4214SFenghua Yu 		ksft_print_msg("Skipping empty schemata update\n");
602591a6e85SSai Praneeth Prakhya 
603591a6e85SSai Praneeth Prakhya 		return -1;
604591a6e85SSai Praneeth Prakhya 	}
605591a6e85SSai Praneeth Prakhya 
606345e8abeSIlpo Järvinen 	if (get_domain_id(resource, cpu_no, &domain_id) < 0) {
6076874f6edSIlpo Järvinen 		sprintf(reason, "Failed to get domain ID");
608591a6e85SSai Praneeth Prakhya 		ret = -1;
609591a6e85SSai Praneeth Prakhya 
610591a6e85SSai Praneeth Prakhya 		goto out;
611591a6e85SSai Praneeth Prakhya 	}
612591a6e85SSai Praneeth Prakhya 
613*d14d94daSIlpo Järvinen 	if (ctrlgrp)
614591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s/schemata", RESCTRL_PATH, ctrlgrp);
615591a6e85SSai Praneeth Prakhya 	else
616591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/schemata", RESCTRL_PATH);
617591a6e85SSai Praneeth Prakhya 
618ca160887SIlpo Järvinen 	schema_len = snprintf(schema, sizeof(schema), "%s:%d=%s\n",
6196874f6edSIlpo Järvinen 			      resource, domain_id, schemata);
62020d96b25SMaciej Wieczor-Retman 	if (schema_len < 0 || schema_len >= sizeof(schema)) {
62120d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
62220d96b25SMaciej Wieczor-Retman 			 "snprintf() failed with return value : %d", schema_len);
623591a6e85SSai Praneeth Prakhya 		ret = -1;
624591a6e85SSai Praneeth Prakhya 		goto out;
625591a6e85SSai Praneeth Prakhya 	}
626591a6e85SSai Praneeth Prakhya 
62720d96b25SMaciej Wieczor-Retman 	fd = open(controlgroup, O_WRONLY);
62820d96b25SMaciej Wieczor-Retman 	if (fd < 0) {
62920d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
63020d96b25SMaciej Wieczor-Retman 			 "open() failed : %s", strerror(errno));
631591a6e85SSai Praneeth Prakhya 		ret = -1;
632591a6e85SSai Praneeth Prakhya 
63320d96b25SMaciej Wieczor-Retman 		goto err_schema_not_empty;
634591a6e85SSai Praneeth Prakhya 	}
63520d96b25SMaciej Wieczor-Retman 	if (write(fd, schema, schema_len) < 0) {
63620d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
63720d96b25SMaciej Wieczor-Retman 			 "write() failed : %s", strerror(errno));
63820d96b25SMaciej Wieczor-Retman 		close(fd);
63920d96b25SMaciej Wieczor-Retman 		ret = -1;
640591a6e85SSai Praneeth Prakhya 
64120d96b25SMaciej Wieczor-Retman 		goto err_schema_not_empty;
64220d96b25SMaciej Wieczor-Retman 	}
64320d96b25SMaciej Wieczor-Retman 	close(fd);
64420d96b25SMaciej Wieczor-Retman 
64520d96b25SMaciej Wieczor-Retman err_schema_not_empty:
64620d96b25SMaciej Wieczor-Retman 	schema[schema_len - 1] = 0;
647591a6e85SSai Praneeth Prakhya out:
648ca2f4214SFenghua Yu 	ksft_print_msg("Write schema \"%s\" to resctrl FS%s%s\n",
649ca2f4214SFenghua Yu 		       schema, ret ? " # " : "",
650591a6e85SSai Praneeth Prakhya 		       ret ? reason : "");
651591a6e85SSai Praneeth Prakhya 
652591a6e85SSai Praneeth Prakhya 	return ret;
653591a6e85SSai Praneeth Prakhya }
654591a6e85SSai Praneeth Prakhya 
655ecdbb911SFenghua Yu bool check_resctrlfs_support(void)
656ecdbb911SFenghua Yu {
657ecdbb911SFenghua Yu 	FILE *inf = fopen("/proc/filesystems", "r");
658ecdbb911SFenghua Yu 	DIR *dp;
659ecdbb911SFenghua Yu 	char *res;
660ecdbb911SFenghua Yu 	bool ret = false;
661ecdbb911SFenghua Yu 
662ecdbb911SFenghua Yu 	if (!inf)
663ecdbb911SFenghua Yu 		return false;
664ecdbb911SFenghua Yu 
665ecdbb911SFenghua Yu 	res = fgrep(inf, "nodev\tresctrl\n");
666ecdbb911SFenghua Yu 
667ecdbb911SFenghua Yu 	if (res) {
668ecdbb911SFenghua Yu 		ret = true;
669ecdbb911SFenghua Yu 		free(res);
670ecdbb911SFenghua Yu 	}
671ecdbb911SFenghua Yu 
672ecdbb911SFenghua Yu 	fclose(inf);
673ecdbb911SFenghua Yu 
674e7507478SFenghua Yu 	ksft_print_msg("%s Check kernel supports resctrl filesystem\n",
675ca2f4214SFenghua Yu 		       ret ? "Pass:" : "Fail:");
676ecdbb911SFenghua Yu 
677a3611fbcSFenghua Yu 	if (!ret)
678a3611fbcSFenghua Yu 		return ret;
679a3611fbcSFenghua Yu 
680ecdbb911SFenghua Yu 	dp = opendir(RESCTRL_PATH);
681e7507478SFenghua Yu 	ksft_print_msg("%s Check resctrl mountpoint \"%s\" exists\n",
682ca2f4214SFenghua Yu 		       dp ? "Pass:" : "Fail:", RESCTRL_PATH);
683ecdbb911SFenghua Yu 	if (dp)
684ecdbb911SFenghua Yu 		closedir(dp);
685ecdbb911SFenghua Yu 
686ca2f4214SFenghua Yu 	ksft_print_msg("resctrl filesystem %s mounted\n",
687ecdbb911SFenghua Yu 		       find_resctrl_mount(NULL) ? "not" : "is");
688ecdbb911SFenghua Yu 
689ecdbb911SFenghua Yu 	return ret;
690ecdbb911SFenghua Yu }
691ecdbb911SFenghua Yu 
692591a6e85SSai Praneeth Prakhya char *fgrep(FILE *inf, const char *str)
693591a6e85SSai Praneeth Prakhya {
694591a6e85SSai Praneeth Prakhya 	char line[256];
695591a6e85SSai Praneeth Prakhya 	int slen = strlen(str);
696591a6e85SSai Praneeth Prakhya 
697591a6e85SSai Praneeth Prakhya 	while (!feof(inf)) {
698591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, inf))
699591a6e85SSai Praneeth Prakhya 			break;
700591a6e85SSai Praneeth Prakhya 		if (strncmp(line, str, slen))
701591a6e85SSai Praneeth Prakhya 			continue;
702591a6e85SSai Praneeth Prakhya 
703591a6e85SSai Praneeth Prakhya 		return strdup(line);
704591a6e85SSai Praneeth Prakhya 	}
705591a6e85SSai Praneeth Prakhya 
706591a6e85SSai Praneeth Prakhya 	return NULL;
707591a6e85SSai Praneeth Prakhya }
708591a6e85SSai Praneeth Prakhya 
709591a6e85SSai Praneeth Prakhya /*
71000616416SMaciej Wieczor-Retman  * resctrl_resource_exists - Check if a resource is supported.
71100616416SMaciej Wieczor-Retman  * @resource:	Resctrl resource (e.g., MB, L3, L2, L3_MON, etc.)
712591a6e85SSai Praneeth Prakhya  *
71300616416SMaciej Wieczor-Retman  * Return: True if the resource is supported, else false. False is
714d56e5da0SIlpo Järvinen  *         also returned if resctrl FS is not mounted.
715591a6e85SSai Praneeth Prakhya  */
71600616416SMaciej Wieczor-Retman bool resctrl_resource_exists(const char *resource)
717591a6e85SSai Praneeth Prakhya {
718d56e5da0SIlpo Järvinen 	char res_path[PATH_MAX];
719ee041568SFenghua Yu 	struct stat statbuf;
720caddc0fbSIlpo Järvinen 	int ret;
721591a6e85SSai Praneeth Prakhya 
722d56e5da0SIlpo Järvinen 	if (!resource)
723ee041568SFenghua Yu 		return false;
724ee041568SFenghua Yu 
725caddc0fbSIlpo Järvinen 	ret = find_resctrl_mount(NULL);
726caddc0fbSIlpo Järvinen 	if (ret)
727ee041568SFenghua Yu 		return false;
728ee041568SFenghua Yu 
729d56e5da0SIlpo Järvinen 	snprintf(res_path, sizeof(res_path), "%s/%s", INFO_PATH, resource);
730d56e5da0SIlpo Järvinen 
731d56e5da0SIlpo Järvinen 	if (stat(res_path, &statbuf))
732d56e5da0SIlpo Järvinen 		return false;
733d56e5da0SIlpo Järvinen 
734ee041568SFenghua Yu 	return true;
73500616416SMaciej Wieczor-Retman }
73600616416SMaciej Wieczor-Retman 
73700616416SMaciej Wieczor-Retman /*
73800616416SMaciej Wieczor-Retman  * resctrl_mon_feature_exists - Check if requested monitoring feature is valid.
73900616416SMaciej Wieczor-Retman  * @resource:	Resource that uses the mon_features file. Currently only L3_MON
74000616416SMaciej Wieczor-Retman  *		is valid.
74100616416SMaciej Wieczor-Retman  * @feature:	Required monitor feature (in mon_features file).
74200616416SMaciej Wieczor-Retman  *
74300616416SMaciej Wieczor-Retman  * Return: True if the feature is supported, else false.
74400616416SMaciej Wieczor-Retman  */
74500616416SMaciej Wieczor-Retman bool resctrl_mon_feature_exists(const char *resource, const char *feature)
74600616416SMaciej Wieczor-Retman {
74700616416SMaciej Wieczor-Retman 	char res_path[PATH_MAX];
74800616416SMaciej Wieczor-Retman 	char *res;
74900616416SMaciej Wieczor-Retman 	FILE *inf;
75000616416SMaciej Wieczor-Retman 
75100616416SMaciej Wieczor-Retman 	if (!feature || !resource)
75200616416SMaciej Wieczor-Retman 		return false;
753d56e5da0SIlpo Järvinen 
754d56e5da0SIlpo Järvinen 	snprintf(res_path, sizeof(res_path), "%s/%s/mon_features", INFO_PATH, resource);
755d56e5da0SIlpo Järvinen 	inf = fopen(res_path, "r");
756591a6e85SSai Praneeth Prakhya 	if (!inf)
757591a6e85SSai Praneeth Prakhya 		return false;
758591a6e85SSai Praneeth Prakhya 
759d56e5da0SIlpo Järvinen 	res = fgrep(inf, feature);
760591a6e85SSai Praneeth Prakhya 	free(res);
761591a6e85SSai Praneeth Prakhya 	fclose(inf);
762591a6e85SSai Praneeth Prakhya 
763d56e5da0SIlpo Järvinen 	return !!res;
764591a6e85SSai Praneeth Prakhya }
765591a6e85SSai Praneeth Prakhya 
76674e76cbaSMaciej Wieczor-Retman /*
76774e76cbaSMaciej Wieczor-Retman  * resource_info_file_exists - Check if a file is present inside
76874e76cbaSMaciej Wieczor-Retman  * /sys/fs/resctrl/info/@resource.
76974e76cbaSMaciej Wieczor-Retman  * @resource:	Required resource (Eg: MB, L3, L2, etc.)
77074e76cbaSMaciej Wieczor-Retman  * @file:	Required file.
77174e76cbaSMaciej Wieczor-Retman  *
77274e76cbaSMaciej Wieczor-Retman  * Return: True if the /sys/fs/resctrl/info/@resource/@file exists, else false.
77374e76cbaSMaciej Wieczor-Retman  */
77474e76cbaSMaciej Wieczor-Retman bool resource_info_file_exists(const char *resource, const char *file)
77574e76cbaSMaciej Wieczor-Retman {
77674e76cbaSMaciej Wieczor-Retman 	char res_path[PATH_MAX];
77774e76cbaSMaciej Wieczor-Retman 	struct stat statbuf;
77874e76cbaSMaciej Wieczor-Retman 
77974e76cbaSMaciej Wieczor-Retman 	if (!file || !resource)
78074e76cbaSMaciej Wieczor-Retman 		return false;
78174e76cbaSMaciej Wieczor-Retman 
78274e76cbaSMaciej Wieczor-Retman 	snprintf(res_path, sizeof(res_path), "%s/%s/%s", INFO_PATH, resource,
78374e76cbaSMaciej Wieczor-Retman 		 file);
78474e76cbaSMaciej Wieczor-Retman 
78574e76cbaSMaciej Wieczor-Retman 	if (stat(res_path, &statbuf))
78674e76cbaSMaciej Wieczor-Retman 		return false;
78774e76cbaSMaciej Wieczor-Retman 
78874e76cbaSMaciej Wieczor-Retman 	return true;
78974e76cbaSMaciej Wieczor-Retman }
79074e76cbaSMaciej Wieczor-Retman 
791c603ff5bSIlpo Järvinen bool test_resource_feature_check(const struct resctrl_test *test)
792c603ff5bSIlpo Järvinen {
79300616416SMaciej Wieczor-Retman 	return resctrl_resource_exists(test->resource);
794c603ff5bSIlpo Järvinen }
795c603ff5bSIlpo Järvinen 
796ecdbb911SFenghua Yu int filter_dmesg(void)
797ecdbb911SFenghua Yu {
798ecdbb911SFenghua Yu 	char line[1024];
799ecdbb911SFenghua Yu 	FILE *fp;
800ecdbb911SFenghua Yu 	int pipefds[2];
801ecdbb911SFenghua Yu 	pid_t pid;
802ecdbb911SFenghua Yu 	int ret;
803ecdbb911SFenghua Yu 
804ecdbb911SFenghua Yu 	ret = pipe(pipefds);
805ecdbb911SFenghua Yu 	if (ret) {
806cc8ff7f5SIlpo Järvinen 		ksft_perror("pipe");
807ecdbb911SFenghua Yu 		return ret;
808ecdbb911SFenghua Yu 	}
809a080b6e7SShaopeng Tan 	fflush(stdout);
810ecdbb911SFenghua Yu 	pid = fork();
811ecdbb911SFenghua Yu 	if (pid == 0) {
812ecdbb911SFenghua Yu 		close(pipefds[0]);
813ecdbb911SFenghua Yu 		dup2(pipefds[1], STDOUT_FILENO);
814ecdbb911SFenghua Yu 		execlp("dmesg", "dmesg", NULL);
815cc8ff7f5SIlpo Järvinen 		ksft_perror("Executing dmesg");
816ecdbb911SFenghua Yu 		exit(1);
817ecdbb911SFenghua Yu 	}
818ecdbb911SFenghua Yu 	close(pipefds[1]);
819ecdbb911SFenghua Yu 	fp = fdopen(pipefds[0], "r");
820ecdbb911SFenghua Yu 	if (!fp) {
821cc8ff7f5SIlpo Järvinen 		ksft_perror("fdopen(pipe)");
822ecdbb911SFenghua Yu 		kill(pid, SIGTERM);
823ecdbb911SFenghua Yu 
824ecdbb911SFenghua Yu 		return -1;
825ecdbb911SFenghua Yu 	}
826ecdbb911SFenghua Yu 
827ecdbb911SFenghua Yu 	while (fgets(line, 1024, fp)) {
828ecdbb911SFenghua Yu 		if (strstr(line, "intel_rdt:"))
829ca2f4214SFenghua Yu 			ksft_print_msg("dmesg: %s", line);
830ecdbb911SFenghua Yu 		if (strstr(line, "resctrl:"))
831ca2f4214SFenghua Yu 			ksft_print_msg("dmesg: %s", line);
832ecdbb911SFenghua Yu 	}
833ecdbb911SFenghua Yu 	fclose(fp);
834ecdbb911SFenghua Yu 	waitpid(pid, NULL, 0);
835ecdbb911SFenghua Yu 
836ecdbb911SFenghua Yu 	return 0;
837ecdbb911SFenghua Yu }
838ecdbb911SFenghua Yu 
839fa1116d0SIlpo Järvinen const char *get_bw_report_type(const char *bw_report)
840591a6e85SSai Praneeth Prakhya {
841591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "reads") == 0)
842fa1116d0SIlpo Järvinen 		return bw_report;
843591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "writes") == 0)
844fa1116d0SIlpo Järvinen 		return bw_report;
845591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "nt-writes") == 0) {
846fa1116d0SIlpo Järvinen 		return "writes";
847591a6e85SSai Praneeth Prakhya 	}
848591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "total") == 0)
849fa1116d0SIlpo Järvinen 		return bw_report;
850591a6e85SSai Praneeth Prakhya 
8512704b2d1SIlpo Järvinen 	fprintf(stderr, "Requested iMC bandwidth report type unavailable\n");
852591a6e85SSai Praneeth Prakhya 
853fa1116d0SIlpo Järvinen 	return NULL;
854591a6e85SSai Praneeth Prakhya }
855591a6e85SSai Praneeth Prakhya 
856591a6e85SSai Praneeth Prakhya int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
857591a6e85SSai Praneeth Prakhya 		    int group_fd, unsigned long flags)
858591a6e85SSai Praneeth Prakhya {
859591a6e85SSai Praneeth Prakhya 	int ret;
860591a6e85SSai Praneeth Prakhya 
861591a6e85SSai Praneeth Prakhya 	ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
862591a6e85SSai Praneeth Prakhya 		      group_fd, flags);
863591a6e85SSai Praneeth Prakhya 	return ret;
864591a6e85SSai Praneeth Prakhya }
86578941183SFenghua Yu 
86678941183SFenghua Yu unsigned int count_bits(unsigned long n)
86778941183SFenghua Yu {
86878941183SFenghua Yu 	unsigned int count = 0;
86978941183SFenghua Yu 
87078941183SFenghua Yu 	while (n) {
87178941183SFenghua Yu 		count += n & 1;
87278941183SFenghua Yu 		n >>= 1;
87378941183SFenghua Yu 	}
87478941183SFenghua Yu 
87578941183SFenghua Yu 	return count;
87678941183SFenghua Yu }
877