xref: /linux/tools/testing/selftests/resctrl/resctrlfs.c (revision e331ac141f1df6d151d24e60ff16e93ec075509e)
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 /*
253*e331ac14SMaciej Wieczor-Retman  * resource_info_unsigned_get - Read an unsigned value from
254*e331ac14SMaciej Wieczor-Retman  * /sys/fs/resctrl/info/@resource/@filename
255*e331ac14SMaciej Wieczor-Retman  * @resource:	Resource name that matches directory name in
256*e331ac14SMaciej Wieczor-Retman  *		/sys/fs/resctrl/info
257*e331ac14SMaciej Wieczor-Retman  * @filename:	File in /sys/fs/resctrl/info/@resource
258*e331ac14SMaciej Wieczor-Retman  * @val:	Contains read value on success.
259*e331ac14SMaciej Wieczor-Retman  *
260*e331ac14SMaciej Wieczor-Retman  * Return: = 0 on success, < 0 on failure. On success the read
261*e331ac14SMaciej Wieczor-Retman  * value is saved into @val.
262*e331ac14SMaciej Wieczor-Retman  */
263*e331ac14SMaciej Wieczor-Retman int resource_info_unsigned_get(const char *resource, const char *filename,
264*e331ac14SMaciej Wieczor-Retman 			       unsigned int *val)
265*e331ac14SMaciej Wieczor-Retman {
266*e331ac14SMaciej Wieczor-Retman 	char file_path[PATH_MAX];
267*e331ac14SMaciej Wieczor-Retman 	FILE *fp;
268*e331ac14SMaciej Wieczor-Retman 
269*e331ac14SMaciej Wieczor-Retman 	snprintf(file_path, sizeof(file_path), "%s/%s/%s", INFO_PATH, resource,
270*e331ac14SMaciej Wieczor-Retman 		 filename);
271*e331ac14SMaciej Wieczor-Retman 
272*e331ac14SMaciej Wieczor-Retman 	fp = fopen(file_path, "r");
273*e331ac14SMaciej Wieczor-Retman 	if (!fp) {
274*e331ac14SMaciej Wieczor-Retman 		ksft_print_msg("Error opening %s: %m\n", file_path);
275*e331ac14SMaciej Wieczor-Retman 		return -1;
276*e331ac14SMaciej Wieczor-Retman 	}
277*e331ac14SMaciej Wieczor-Retman 
278*e331ac14SMaciej Wieczor-Retman 	if (fscanf(fp, "%u", val) <= 0) {
279*e331ac14SMaciej Wieczor-Retman 		ksft_print_msg("Could not get contents of %s: %m\n", file_path);
280*e331ac14SMaciej Wieczor-Retman 		fclose(fp);
281*e331ac14SMaciej Wieczor-Retman 		return -1;
282*e331ac14SMaciej Wieczor-Retman 	}
283*e331ac14SMaciej Wieczor-Retman 
284*e331ac14SMaciej Wieczor-Retman 	fclose(fp);
285*e331ac14SMaciej Wieczor-Retman 	return 0;
286*e331ac14SMaciej Wieczor-Retman }
287*e331ac14SMaciej Wieczor-Retman 
288*e331ac14SMaciej 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  *
45934813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
460591a6e85SSai Praneeth Prakhya  */
461591a6e85SSai Praneeth Prakhya static int create_grp(const char *grp_name, char *grp, const char *parent_grp)
462591a6e85SSai Praneeth Prakhya {
463591a6e85SSai Praneeth Prakhya 	int found_grp = 0;
464591a6e85SSai Praneeth Prakhya 	struct dirent *ep;
465591a6e85SSai Praneeth Prakhya 	DIR *dp;
466591a6e85SSai Praneeth Prakhya 
46778941183SFenghua Yu 	/*
46878941183SFenghua Yu 	 * At this point, we are guaranteed to have resctrl FS mounted and if
46978941183SFenghua Yu 	 * length of grp_name == 0, it means, user wants to use root con_mon
47078941183SFenghua Yu 	 * grp, so do nothing
47178941183SFenghua Yu 	 */
47278941183SFenghua Yu 	if (strlen(grp_name) == 0)
47378941183SFenghua Yu 		return 0;
47478941183SFenghua Yu 
475591a6e85SSai Praneeth Prakhya 	/* Check if requested grp exists or not */
476591a6e85SSai Praneeth Prakhya 	dp = opendir(parent_grp);
477591a6e85SSai Praneeth Prakhya 	if (dp) {
478591a6e85SSai Praneeth Prakhya 		while ((ep = readdir(dp)) != NULL) {
479591a6e85SSai Praneeth Prakhya 			if (strcmp(ep->d_name, grp_name) == 0)
480591a6e85SSai Praneeth Prakhya 				found_grp = 1;
481591a6e85SSai Praneeth Prakhya 		}
482591a6e85SSai Praneeth Prakhya 		closedir(dp);
483591a6e85SSai Praneeth Prakhya 	} else {
484cc8ff7f5SIlpo Järvinen 		ksft_perror("Unable to open resctrl for group");
485591a6e85SSai Praneeth Prakhya 
486591a6e85SSai Praneeth Prakhya 		return -1;
487591a6e85SSai Praneeth Prakhya 	}
488591a6e85SSai Praneeth Prakhya 
489591a6e85SSai Praneeth Prakhya 	/* Requested grp doesn't exist, hence create it */
490591a6e85SSai Praneeth Prakhya 	if (found_grp == 0) {
491591a6e85SSai Praneeth Prakhya 		if (mkdir(grp, 0) == -1) {
492cc8ff7f5SIlpo Järvinen 			ksft_perror("Unable to create group");
493591a6e85SSai Praneeth Prakhya 
494591a6e85SSai Praneeth Prakhya 			return -1;
495591a6e85SSai Praneeth Prakhya 		}
496591a6e85SSai Praneeth Prakhya 	}
497591a6e85SSai Praneeth Prakhya 
498591a6e85SSai Praneeth Prakhya 	return 0;
499591a6e85SSai Praneeth Prakhya }
500591a6e85SSai Praneeth Prakhya 
501591a6e85SSai Praneeth Prakhya static int write_pid_to_tasks(char *tasks, pid_t pid)
502591a6e85SSai Praneeth Prakhya {
503591a6e85SSai Praneeth Prakhya 	FILE *fp;
504591a6e85SSai Praneeth Prakhya 
505591a6e85SSai Praneeth Prakhya 	fp = fopen(tasks, "w");
506591a6e85SSai Praneeth Prakhya 	if (!fp) {
507cc8ff7f5SIlpo Järvinen 		ksft_perror("Failed to open tasks file");
508591a6e85SSai Praneeth Prakhya 
509591a6e85SSai Praneeth Prakhya 		return -1;
510591a6e85SSai Praneeth Prakhya 	}
511591a6e85SSai Praneeth Prakhya 	if (fprintf(fp, "%d\n", pid) < 0) {
512cc8ff7f5SIlpo Järvinen 		ksft_print_msg("Failed to write pid to tasks file\n");
513591a6e85SSai Praneeth Prakhya 		fclose(fp);
514591a6e85SSai Praneeth Prakhya 
515591a6e85SSai Praneeth Prakhya 		return -1;
516591a6e85SSai Praneeth Prakhya 	}
517591a6e85SSai Praneeth Prakhya 	fclose(fp);
518591a6e85SSai Praneeth Prakhya 
519591a6e85SSai Praneeth Prakhya 	return 0;
520591a6e85SSai Praneeth Prakhya }
521591a6e85SSai Praneeth Prakhya 
522591a6e85SSai Praneeth Prakhya /*
523591a6e85SSai Praneeth Prakhya  * write_bm_pid_to_resctrl - Write a PID (i.e. benchmark) to resctrl FS
524591a6e85SSai Praneeth Prakhya  * @bm_pid:		PID that should be written
525591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the control monitor group (con_mon grp)
526591a6e85SSai Praneeth Prakhya  * @mongrp:		Name of the monitor group (mon grp)
527591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Resctrl feature (Eg: mbm, mba.. etc)
528591a6e85SSai Praneeth Prakhya  *
529591a6e85SSai Praneeth Prakhya  * If a con_mon grp is requested, create it and write pid to it, otherwise
530591a6e85SSai Praneeth Prakhya  * write pid to root con_mon grp.
531591a6e85SSai Praneeth Prakhya  * If a mon grp is requested, create it and write pid to it, otherwise
532591a6e85SSai Praneeth Prakhya  * pid is not written, this means that pid is in con_mon grp and hence
533591a6e85SSai Praneeth Prakhya  * should consult con_mon grp's mon_data directory for results.
534591a6e85SSai Praneeth Prakhya  *
53534813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
536591a6e85SSai Praneeth Prakhya  */
537591a6e85SSai Praneeth Prakhya int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
538591a6e85SSai Praneeth Prakhya 			    char *resctrl_val)
539591a6e85SSai Praneeth Prakhya {
540591a6e85SSai Praneeth Prakhya 	char controlgroup[128], monitorgroup[512], monitorgroup_p[256];
541591a6e85SSai Praneeth Prakhya 	char tasks[1024];
542591a6e85SSai Praneeth Prakhya 	int ret = 0;
543591a6e85SSai Praneeth Prakhya 
544591a6e85SSai Praneeth Prakhya 	if (strlen(ctrlgrp))
545591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s", RESCTRL_PATH, ctrlgrp);
546591a6e85SSai Praneeth Prakhya 	else
547591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s", RESCTRL_PATH);
548591a6e85SSai Praneeth Prakhya 
549591a6e85SSai Praneeth Prakhya 	/* Create control and monitoring group and write pid into it */
550591a6e85SSai Praneeth Prakhya 	ret = create_grp(ctrlgrp, controlgroup, RESCTRL_PATH);
551591a6e85SSai Praneeth Prakhya 	if (ret)
552591a6e85SSai Praneeth Prakhya 		goto out;
553591a6e85SSai Praneeth Prakhya 	sprintf(tasks, "%s/tasks", controlgroup);
554591a6e85SSai Praneeth Prakhya 	ret = write_pid_to_tasks(tasks, bm_pid);
555591a6e85SSai Praneeth Prakhya 	if (ret)
556591a6e85SSai Praneeth Prakhya 		goto out;
557591a6e85SSai Praneeth Prakhya 
5582f320911SFenghua Yu 	/* Create mon grp and write pid into it for "mbm" and "cmt" test */
5592f320911SFenghua Yu 	if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)) ||
56024286736SFenghua Yu 	    !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) {
56178941183SFenghua Yu 		if (strlen(mongrp)) {
562591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup_p, "%s/mon_groups", controlgroup);
563591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp);
564591a6e85SSai Praneeth Prakhya 			ret = create_grp(mongrp, monitorgroup, monitorgroup_p);
565591a6e85SSai Praneeth Prakhya 			if (ret)
566591a6e85SSai Praneeth Prakhya 				goto out;
567591a6e85SSai Praneeth Prakhya 
568591a6e85SSai Praneeth Prakhya 			sprintf(tasks, "%s/mon_groups/%s/tasks",
569591a6e85SSai Praneeth Prakhya 				controlgroup, mongrp);
570591a6e85SSai Praneeth Prakhya 			ret = write_pid_to_tasks(tasks, bm_pid);
571591a6e85SSai Praneeth Prakhya 			if (ret)
572591a6e85SSai Praneeth Prakhya 				goto out;
573591a6e85SSai Praneeth Prakhya 		}
574591a6e85SSai Praneeth Prakhya 	}
575591a6e85SSai Praneeth Prakhya 
576591a6e85SSai Praneeth Prakhya out:
577ca2f4214SFenghua Yu 	ksft_print_msg("Writing benchmark parameters to resctrl FS\n");
578591a6e85SSai Praneeth Prakhya 	if (ret)
579cc8ff7f5SIlpo Järvinen 		ksft_print_msg("Failed writing to resctrlfs\n");
580591a6e85SSai Praneeth Prakhya 
581591a6e85SSai Praneeth Prakhya 	return ret;
582591a6e85SSai Praneeth Prakhya }
583591a6e85SSai Praneeth Prakhya 
584591a6e85SSai Praneeth Prakhya /*
585591a6e85SSai Praneeth Prakhya  * write_schemata - Update schemata of a con_mon grp
586591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the con_mon grp
587591a6e85SSai Praneeth Prakhya  * @schemata:		Schemata that should be updated to
588591a6e85SSai Praneeth Prakhya  * @cpu_no:		CPU number that the benchmark PID is binded to
589ca160887SIlpo Järvinen  * @resource:		Resctrl resource (Eg: MB, L3, L2, etc.)
590591a6e85SSai Praneeth Prakhya  *
591ca160887SIlpo Järvinen  * Update schemata of a con_mon grp *only* if requested resctrl resource is
592591a6e85SSai Praneeth Prakhya  * allocation type
593591a6e85SSai Praneeth Prakhya  *
59434813938SIlpo Järvinen  * Return: 0 on success, < 0 on error.
595591a6e85SSai Praneeth Prakhya  */
596ca160887SIlpo Järvinen int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, const char *resource)
597591a6e85SSai Praneeth Prakhya {
59820d96b25SMaciej Wieczor-Retman 	char controlgroup[1024], reason[128], schema[1024] = {};
5996874f6edSIlpo Järvinen 	int domain_id, fd, schema_len, ret = 0;
600591a6e85SSai Praneeth Prakhya 
601591a6e85SSai Praneeth Prakhya 	if (!schemata) {
602ca2f4214SFenghua Yu 		ksft_print_msg("Skipping empty schemata update\n");
603591a6e85SSai Praneeth Prakhya 
604591a6e85SSai Praneeth Prakhya 		return -1;
605591a6e85SSai Praneeth Prakhya 	}
606591a6e85SSai Praneeth Prakhya 
607345e8abeSIlpo Järvinen 	if (get_domain_id(resource, cpu_no, &domain_id) < 0) {
6086874f6edSIlpo Järvinen 		sprintf(reason, "Failed to get domain ID");
609591a6e85SSai Praneeth Prakhya 		ret = -1;
610591a6e85SSai Praneeth Prakhya 
611591a6e85SSai Praneeth Prakhya 		goto out;
612591a6e85SSai Praneeth Prakhya 	}
613591a6e85SSai Praneeth Prakhya 
614591a6e85SSai Praneeth Prakhya 	if (strlen(ctrlgrp) != 0)
615591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s/schemata", RESCTRL_PATH, ctrlgrp);
616591a6e85SSai Praneeth Prakhya 	else
617591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/schemata", RESCTRL_PATH);
618591a6e85SSai Praneeth Prakhya 
619ca160887SIlpo Järvinen 	schema_len = snprintf(schema, sizeof(schema), "%s:%d=%s\n",
6206874f6edSIlpo Järvinen 			      resource, domain_id, schemata);
62120d96b25SMaciej Wieczor-Retman 	if (schema_len < 0 || schema_len >= sizeof(schema)) {
62220d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
62320d96b25SMaciej Wieczor-Retman 			 "snprintf() failed with return value : %d", schema_len);
624591a6e85SSai Praneeth Prakhya 		ret = -1;
625591a6e85SSai Praneeth Prakhya 		goto out;
626591a6e85SSai Praneeth Prakhya 	}
627591a6e85SSai Praneeth Prakhya 
62820d96b25SMaciej Wieczor-Retman 	fd = open(controlgroup, O_WRONLY);
62920d96b25SMaciej Wieczor-Retman 	if (fd < 0) {
63020d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
63120d96b25SMaciej Wieczor-Retman 			 "open() failed : %s", strerror(errno));
632591a6e85SSai Praneeth Prakhya 		ret = -1;
633591a6e85SSai Praneeth Prakhya 
63420d96b25SMaciej Wieczor-Retman 		goto err_schema_not_empty;
635591a6e85SSai Praneeth Prakhya 	}
63620d96b25SMaciej Wieczor-Retman 	if (write(fd, schema, schema_len) < 0) {
63720d96b25SMaciej Wieczor-Retman 		snprintf(reason, sizeof(reason),
63820d96b25SMaciej Wieczor-Retman 			 "write() failed : %s", strerror(errno));
63920d96b25SMaciej Wieczor-Retman 		close(fd);
64020d96b25SMaciej Wieczor-Retman 		ret = -1;
641591a6e85SSai Praneeth Prakhya 
64220d96b25SMaciej Wieczor-Retman 		goto err_schema_not_empty;
64320d96b25SMaciej Wieczor-Retman 	}
64420d96b25SMaciej Wieczor-Retman 	close(fd);
64520d96b25SMaciej Wieczor-Retman 
64620d96b25SMaciej Wieczor-Retman err_schema_not_empty:
64720d96b25SMaciej Wieczor-Retman 	schema[schema_len - 1] = 0;
648591a6e85SSai Praneeth Prakhya out:
649ca2f4214SFenghua Yu 	ksft_print_msg("Write schema \"%s\" to resctrl FS%s%s\n",
650ca2f4214SFenghua Yu 		       schema, ret ? " # " : "",
651591a6e85SSai Praneeth Prakhya 		       ret ? reason : "");
652591a6e85SSai Praneeth Prakhya 
653591a6e85SSai Praneeth Prakhya 	return ret;
654591a6e85SSai Praneeth Prakhya }
655591a6e85SSai Praneeth Prakhya 
656ecdbb911SFenghua Yu bool check_resctrlfs_support(void)
657ecdbb911SFenghua Yu {
658ecdbb911SFenghua Yu 	FILE *inf = fopen("/proc/filesystems", "r");
659ecdbb911SFenghua Yu 	DIR *dp;
660ecdbb911SFenghua Yu 	char *res;
661ecdbb911SFenghua Yu 	bool ret = false;
662ecdbb911SFenghua Yu 
663ecdbb911SFenghua Yu 	if (!inf)
664ecdbb911SFenghua Yu 		return false;
665ecdbb911SFenghua Yu 
666ecdbb911SFenghua Yu 	res = fgrep(inf, "nodev\tresctrl\n");
667ecdbb911SFenghua Yu 
668ecdbb911SFenghua Yu 	if (res) {
669ecdbb911SFenghua Yu 		ret = true;
670ecdbb911SFenghua Yu 		free(res);
671ecdbb911SFenghua Yu 	}
672ecdbb911SFenghua Yu 
673ecdbb911SFenghua Yu 	fclose(inf);
674ecdbb911SFenghua Yu 
675e7507478SFenghua Yu 	ksft_print_msg("%s Check kernel supports resctrl filesystem\n",
676ca2f4214SFenghua Yu 		       ret ? "Pass:" : "Fail:");
677ecdbb911SFenghua Yu 
678a3611fbcSFenghua Yu 	if (!ret)
679a3611fbcSFenghua Yu 		return ret;
680a3611fbcSFenghua Yu 
681ecdbb911SFenghua Yu 	dp = opendir(RESCTRL_PATH);
682e7507478SFenghua Yu 	ksft_print_msg("%s Check resctrl mountpoint \"%s\" exists\n",
683ca2f4214SFenghua Yu 		       dp ? "Pass:" : "Fail:", RESCTRL_PATH);
684ecdbb911SFenghua Yu 	if (dp)
685ecdbb911SFenghua Yu 		closedir(dp);
686ecdbb911SFenghua Yu 
687ca2f4214SFenghua Yu 	ksft_print_msg("resctrl filesystem %s mounted\n",
688ecdbb911SFenghua Yu 		       find_resctrl_mount(NULL) ? "not" : "is");
689ecdbb911SFenghua Yu 
690ecdbb911SFenghua Yu 	return ret;
691ecdbb911SFenghua Yu }
692ecdbb911SFenghua Yu 
693591a6e85SSai Praneeth Prakhya char *fgrep(FILE *inf, const char *str)
694591a6e85SSai Praneeth Prakhya {
695591a6e85SSai Praneeth Prakhya 	char line[256];
696591a6e85SSai Praneeth Prakhya 	int slen = strlen(str);
697591a6e85SSai Praneeth Prakhya 
698591a6e85SSai Praneeth Prakhya 	while (!feof(inf)) {
699591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, inf))
700591a6e85SSai Praneeth Prakhya 			break;
701591a6e85SSai Praneeth Prakhya 		if (strncmp(line, str, slen))
702591a6e85SSai Praneeth Prakhya 			continue;
703591a6e85SSai Praneeth Prakhya 
704591a6e85SSai Praneeth Prakhya 		return strdup(line);
705591a6e85SSai Praneeth Prakhya 	}
706591a6e85SSai Praneeth Prakhya 
707591a6e85SSai Praneeth Prakhya 	return NULL;
708591a6e85SSai Praneeth Prakhya }
709591a6e85SSai Praneeth Prakhya 
710591a6e85SSai Praneeth Prakhya /*
711591a6e85SSai Praneeth Prakhya  * validate_resctrl_feature_request - Check if requested feature is valid.
712d56e5da0SIlpo Järvinen  * @resource:	Required resource (e.g., MB, L3, L2, L3_MON, etc.)
713d56e5da0SIlpo Järvinen  * @feature:	Required monitor feature (in mon_features file). Can only be
714d56e5da0SIlpo Järvinen  *		set for L3_MON. Must be NULL for all other resources.
715591a6e85SSai Praneeth Prakhya  *
716d56e5da0SIlpo Järvinen  * Return: True if the resource/feature is supported, else false. False is
717d56e5da0SIlpo Järvinen  *         also returned if resctrl FS is not mounted.
718591a6e85SSai Praneeth Prakhya  */
719d56e5da0SIlpo Järvinen bool validate_resctrl_feature_request(const char *resource, const char *feature)
720591a6e85SSai Praneeth Prakhya {
721d56e5da0SIlpo Järvinen 	char res_path[PATH_MAX];
722ee041568SFenghua Yu 	struct stat statbuf;
723591a6e85SSai Praneeth Prakhya 	char *res;
724ee041568SFenghua Yu 	FILE *inf;
725caddc0fbSIlpo Järvinen 	int ret;
726591a6e85SSai Praneeth Prakhya 
727d56e5da0SIlpo Järvinen 	if (!resource)
728ee041568SFenghua Yu 		return false;
729ee041568SFenghua Yu 
730caddc0fbSIlpo Järvinen 	ret = find_resctrl_mount(NULL);
731caddc0fbSIlpo Järvinen 	if (ret)
732ee041568SFenghua Yu 		return false;
733ee041568SFenghua Yu 
734d56e5da0SIlpo Järvinen 	snprintf(res_path, sizeof(res_path), "%s/%s", INFO_PATH, resource);
735d56e5da0SIlpo Järvinen 
736d56e5da0SIlpo Järvinen 	if (stat(res_path, &statbuf))
737d56e5da0SIlpo Järvinen 		return false;
738d56e5da0SIlpo Järvinen 
739d56e5da0SIlpo Järvinen 	if (!feature)
740ee041568SFenghua Yu 		return true;
741d56e5da0SIlpo Järvinen 
742d56e5da0SIlpo Järvinen 	snprintf(res_path, sizeof(res_path), "%s/%s/mon_features", INFO_PATH, resource);
743d56e5da0SIlpo Järvinen 	inf = fopen(res_path, "r");
744591a6e85SSai Praneeth Prakhya 	if (!inf)
745591a6e85SSai Praneeth Prakhya 		return false;
746591a6e85SSai Praneeth Prakhya 
747d56e5da0SIlpo Järvinen 	res = fgrep(inf, feature);
748591a6e85SSai Praneeth Prakhya 	free(res);
749591a6e85SSai Praneeth Prakhya 	fclose(inf);
750591a6e85SSai Praneeth Prakhya 
751d56e5da0SIlpo Järvinen 	return !!res;
752591a6e85SSai Praneeth Prakhya }
753591a6e85SSai Praneeth Prakhya 
754c603ff5bSIlpo Järvinen bool test_resource_feature_check(const struct resctrl_test *test)
755c603ff5bSIlpo Järvinen {
756c603ff5bSIlpo Järvinen 	return validate_resctrl_feature_request(test->resource, NULL);
757c603ff5bSIlpo Järvinen }
758c603ff5bSIlpo Järvinen 
759ecdbb911SFenghua Yu int filter_dmesg(void)
760ecdbb911SFenghua Yu {
761ecdbb911SFenghua Yu 	char line[1024];
762ecdbb911SFenghua Yu 	FILE *fp;
763ecdbb911SFenghua Yu 	int pipefds[2];
764ecdbb911SFenghua Yu 	pid_t pid;
765ecdbb911SFenghua Yu 	int ret;
766ecdbb911SFenghua Yu 
767ecdbb911SFenghua Yu 	ret = pipe(pipefds);
768ecdbb911SFenghua Yu 	if (ret) {
769cc8ff7f5SIlpo Järvinen 		ksft_perror("pipe");
770ecdbb911SFenghua Yu 		return ret;
771ecdbb911SFenghua Yu 	}
772a080b6e7SShaopeng Tan 	fflush(stdout);
773ecdbb911SFenghua Yu 	pid = fork();
774ecdbb911SFenghua Yu 	if (pid == 0) {
775ecdbb911SFenghua Yu 		close(pipefds[0]);
776ecdbb911SFenghua Yu 		dup2(pipefds[1], STDOUT_FILENO);
777ecdbb911SFenghua Yu 		execlp("dmesg", "dmesg", NULL);
778cc8ff7f5SIlpo Järvinen 		ksft_perror("Executing dmesg");
779ecdbb911SFenghua Yu 		exit(1);
780ecdbb911SFenghua Yu 	}
781ecdbb911SFenghua Yu 	close(pipefds[1]);
782ecdbb911SFenghua Yu 	fp = fdopen(pipefds[0], "r");
783ecdbb911SFenghua Yu 	if (!fp) {
784cc8ff7f5SIlpo Järvinen 		ksft_perror("fdopen(pipe)");
785ecdbb911SFenghua Yu 		kill(pid, SIGTERM);
786ecdbb911SFenghua Yu 
787ecdbb911SFenghua Yu 		return -1;
788ecdbb911SFenghua Yu 	}
789ecdbb911SFenghua Yu 
790ecdbb911SFenghua Yu 	while (fgets(line, 1024, fp)) {
791ecdbb911SFenghua Yu 		if (strstr(line, "intel_rdt:"))
792ca2f4214SFenghua Yu 			ksft_print_msg("dmesg: %s", line);
793ecdbb911SFenghua Yu 		if (strstr(line, "resctrl:"))
794ca2f4214SFenghua Yu 			ksft_print_msg("dmesg: %s", line);
795ecdbb911SFenghua Yu 	}
796ecdbb911SFenghua Yu 	fclose(fp);
797ecdbb911SFenghua Yu 	waitpid(pid, NULL, 0);
798ecdbb911SFenghua Yu 
799ecdbb911SFenghua Yu 	return 0;
800ecdbb911SFenghua Yu }
801ecdbb911SFenghua Yu 
802591a6e85SSai Praneeth Prakhya int validate_bw_report_request(char *bw_report)
803591a6e85SSai Praneeth Prakhya {
804591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "reads") == 0)
805591a6e85SSai Praneeth Prakhya 		return 0;
806591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "writes") == 0)
807591a6e85SSai Praneeth Prakhya 		return 0;
808591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "nt-writes") == 0) {
809591a6e85SSai Praneeth Prakhya 		strcpy(bw_report, "writes");
810591a6e85SSai Praneeth Prakhya 		return 0;
811591a6e85SSai Praneeth Prakhya 	}
812591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "total") == 0)
813591a6e85SSai Praneeth Prakhya 		return 0;
814591a6e85SSai Praneeth Prakhya 
815591a6e85SSai Praneeth Prakhya 	fprintf(stderr, "Requested iMC B/W report type unavailable\n");
816591a6e85SSai Praneeth Prakhya 
817591a6e85SSai Praneeth Prakhya 	return -1;
818591a6e85SSai Praneeth Prakhya }
819591a6e85SSai Praneeth Prakhya 
820591a6e85SSai Praneeth Prakhya int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
821591a6e85SSai Praneeth Prakhya 		    int group_fd, unsigned long flags)
822591a6e85SSai Praneeth Prakhya {
823591a6e85SSai Praneeth Prakhya 	int ret;
824591a6e85SSai Praneeth Prakhya 
825591a6e85SSai Praneeth Prakhya 	ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
826591a6e85SSai Praneeth Prakhya 		      group_fd, flags);
827591a6e85SSai Praneeth Prakhya 	return ret;
828591a6e85SSai Praneeth Prakhya }
82978941183SFenghua Yu 
83078941183SFenghua Yu unsigned int count_bits(unsigned long n)
83178941183SFenghua Yu {
83278941183SFenghua Yu 	unsigned int count = 0;
83378941183SFenghua Yu 
83478941183SFenghua Yu 	while (n) {
83578941183SFenghua Yu 		count += n & 1;
83678941183SFenghua Yu 		n >>= 1;
83778941183SFenghua Yu 	}
83878941183SFenghua Yu 
83978941183SFenghua Yu 	return count;
84078941183SFenghua Yu }
841