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