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