1591a6e85SSai Praneeth Prakhya /* SPDX-License-Identifier: GPL-2.0 */
2591a6e85SSai Praneeth Prakhya #ifndef RESCTRL_H
3591a6e85SSai Praneeth Prakhya #define RESCTRL_H
4591a6e85SSai Praneeth Prakhya #include <stdio.h>
57f4d257eSSai Praneeth Prakhya #include <math.h>
6591a6e85SSai Praneeth Prakhya #include <errno.h>
7591a6e85SSai Praneeth Prakhya #include <sched.h>
8591a6e85SSai Praneeth Prakhya #include <stdlib.h>
9591a6e85SSai Praneeth Prakhya #include <unistd.h>
10591a6e85SSai Praneeth Prakhya #include <string.h>
11591a6e85SSai Praneeth Prakhya #include <signal.h>
12591a6e85SSai Praneeth Prakhya #include <dirent.h>
13591a6e85SSai Praneeth Prakhya #include <stdbool.h>
14a1cd99e7SMaciej Wieczor-Retman #include <ctype.h>
15591a6e85SSai Praneeth Prakhya #include <sys/stat.h>
16591a6e85SSai Praneeth Prakhya #include <sys/ioctl.h>
17591a6e85SSai Praneeth Prakhya #include <sys/mount.h>
18591a6e85SSai Praneeth Prakhya #include <sys/types.h>
19591a6e85SSai Praneeth Prakhya #include <sys/wait.h>
2078941183SFenghua Yu #include <sys/select.h>
2178941183SFenghua Yu #include <sys/time.h>
2278941183SFenghua Yu #include <sys/eventfd.h>
23591a6e85SSai Praneeth Prakhya #include <asm/unistd.h>
24591a6e85SSai Praneeth Prakhya #include <linux/perf_event.h>
25a1cd99e7SMaciej Wieczor-Retman #include <linux/compiler.h>
26ca2f4214SFenghua Yu #include "../kselftest.h"
27591a6e85SSai Praneeth Prakhya
287f4d257eSSai Praneeth Prakhya #define MB (1024 * 1024)
29591a6e85SSai Praneeth Prakhya #define RESCTRL_PATH "/sys/fs/resctrl"
30591a6e85SSai Praneeth Prakhya #define PHYS_ID_PATH "/sys/devices/system/cpu/cpu"
31e48c3230SFenghua Yu #define INFO_PATH "/sys/fs/resctrl/info"
32591a6e85SSai Praneeth Prakhya
33c603ff5bSIlpo Järvinen /*
34c603ff5bSIlpo Järvinen * CPU vendor IDs
35c603ff5bSIlpo Järvinen *
36c603ff5bSIlpo Järvinen * Define as bits because they're used for vendor_specific bitmask in
37c603ff5bSIlpo Järvinen * the struct resctrl_test.
38c603ff5bSIlpo Järvinen */
396220f69eSShaopeng Tan #define ARCH_INTEL 1
406220f69eSShaopeng Tan #define ARCH_AMD 2
416220f69eSShaopeng Tan
42fa10366cSIlpo Järvinen #define END_OF_TESTS 1
43fa10366cSIlpo Järvinen
44e33cb570SIlpo Järvinen #define BENCHMARK_ARGS 64
45e33cb570SIlpo Järvinen
46f77b9672SReinette Chatre #define MINIMUM_SPAN (250 * MB)
47b1a901e0SIlpo Järvinen
487f4d257eSSai Praneeth Prakhya /*
49501cfdbaSReinette Chatre * Memory bandwidth (in MiB) below which the bandwidth comparisons
50501cfdbaSReinette Chatre * between iMC and resctrl are considered unreliable. For example RAS
51501cfdbaSReinette Chatre * features or memory performance features that generate memory traffic
52501cfdbaSReinette Chatre * may drive accesses that are counted differently by performance counters
53501cfdbaSReinette Chatre * and MBM respectively, for instance generating "overhead" traffic which
54501cfdbaSReinette Chatre * is not counted against any specific RMID.
55501cfdbaSReinette Chatre */
56501cfdbaSReinette Chatre #define THROTTLE_THRESHOLD 750
57501cfdbaSReinette Chatre
58501cfdbaSReinette Chatre /*
59e958c21eSReinette Chatre * fill_buf_param: "fill_buf" benchmark parameters
60e958c21eSReinette Chatre * @buf_size: Size (in bytes) of buffer used in benchmark.
61e958c21eSReinette Chatre * "fill_buf" allocates and initializes buffer of
62e958c21eSReinette Chatre * @buf_size. User can change value via command line.
63e958c21eSReinette Chatre * @memflush: If false the buffer will not be flushed after
64e958c21eSReinette Chatre * allocation and initialization, otherwise the
65e958c21eSReinette Chatre * buffer will be flushed. User can change value via
66e958c21eSReinette Chatre * command line (via integers with 0 interpreted as
67e958c21eSReinette Chatre * false and anything else as true).
68e958c21eSReinette Chatre */
69e958c21eSReinette Chatre struct fill_buf_param {
70e958c21eSReinette Chatre size_t buf_size;
71e958c21eSReinette Chatre bool memflush;
72e958c21eSReinette Chatre };
73e958c21eSReinette Chatre
74e958c21eSReinette Chatre /*
7515f29882SIlpo Järvinen * user_params: User supplied parameters
7615f29882SIlpo Järvinen * @cpu: CPU number to which the benchmark will be bound to
7715f29882SIlpo Järvinen * @bits: Number of bits used for cache allocation size
7815f29882SIlpo Järvinen * @benchmark_cmd: Benchmark command to run during (some of the) tests
79e958c21eSReinette Chatre * @fill_buf: Pointer to user provided parameters for "fill_buf",
80e958c21eSReinette Chatre * NULL if user did not provide parameters and test
81e958c21eSReinette Chatre * specific defaults should be used.
8215f29882SIlpo Järvinen */
8315f29882SIlpo Järvinen struct user_params {
8415f29882SIlpo Järvinen int cpu;
8515f29882SIlpo Järvinen int bits;
8615f29882SIlpo Järvinen const char *benchmark_cmd[BENCHMARK_ARGS];
87e958c21eSReinette Chatre const struct fill_buf_param *fill_buf;
8815f29882SIlpo Järvinen };
8915f29882SIlpo Järvinen
9015f29882SIlpo Järvinen /*
91c603ff5bSIlpo Järvinen * resctrl_test: resctrl test definition
92c603ff5bSIlpo Järvinen * @name: Test name
935339792bSIlpo Järvinen * @group: Test group - a common name for tests that share some characteristic
945339792bSIlpo Järvinen * (e.g., L3 CAT test belongs to the CAT group). Can be NULL
95c603ff5bSIlpo Järvinen * @resource: Resource to test (e.g., MB, L3, L2, etc.)
96c603ff5bSIlpo Järvinen * @vendor_specific: Bitmask for vendor-specific tests (can be 0 for universal tests)
97c603ff5bSIlpo Järvinen * @disabled: Test is disabled
98c603ff5bSIlpo Järvinen * @feature_check: Callback to check required resctrl features
99c603ff5bSIlpo Järvinen * @run_test: Callback to run the test
1008780bc88SMaciej Wieczor-Retman * @cleanup: Callback to cleanup after the test
101c603ff5bSIlpo Järvinen */
102c603ff5bSIlpo Järvinen struct resctrl_test {
103c603ff5bSIlpo Järvinen const char *name;
1045339792bSIlpo Järvinen const char *group;
105c603ff5bSIlpo Järvinen const char *resource;
106c603ff5bSIlpo Järvinen unsigned int vendor_specific;
107c603ff5bSIlpo Järvinen bool disabled;
108c603ff5bSIlpo Järvinen bool (*feature_check)(const struct resctrl_test *test);
109c603ff5bSIlpo Järvinen int (*run_test)(const struct resctrl_test *test,
110c603ff5bSIlpo Järvinen const struct user_params *uparams);
1118780bc88SMaciej Wieczor-Retman void (*cleanup)(void);
112c603ff5bSIlpo Järvinen };
113c603ff5bSIlpo Järvinen
114c603ff5bSIlpo Järvinen /*
1157f4d257eSSai Praneeth Prakhya * resctrl_val_param: resctrl test parameters
1167f4d257eSSai Praneeth Prakhya * @ctrlgrp: Name of the control monitor group (con_mon grp)
1177f4d257eSSai Praneeth Prakhya * @mongrp: Name of the monitor group (mon grp)
1187f4d257eSSai Praneeth Prakhya * @filename: Name of file to which the o/p should be written
119aef5efa6SIlpo Järvinen * @init: Callback function to initialize test environment
120aef5efa6SIlpo Järvinen * @setup: Callback function to setup per test run environment
1210e251816SIlpo Järvinen * @measure: Callback that performs the measurement (a single test)
122e958c21eSReinette Chatre * @fill_buf: Parameters for default "fill_buf" benchmark.
123e958c21eSReinette Chatre * Initialized with user provided parameters, possibly
124e958c21eSReinette Chatre * adapted to be relevant to the test. If user does
125e958c21eSReinette Chatre * not provide parameters for "fill_buf" nor a
126e958c21eSReinette Chatre * replacement benchmark then initialized with defaults
127e958c21eSReinette Chatre * appropriate for test. NULL if user provided
128e958c21eSReinette Chatre * benchmark.
1297f4d257eSSai Praneeth Prakhya */
1307f4d257eSSai Praneeth Prakhya struct resctrl_val_param {
131d14d94daSIlpo Järvinen const char *ctrlgrp;
132d14d94daSIlpo Järvinen const char *mongrp;
1337f4d257eSSai Praneeth Prakhya char filename[64];
13478941183SFenghua Yu unsigned long mask;
13578941183SFenghua Yu int num_of_runs;
136aef5efa6SIlpo Järvinen int (*init)(const struct resctrl_val_param *param,
137aef5efa6SIlpo Järvinen int domain_id);
138ca160887SIlpo Järvinen int (*setup)(const struct resctrl_test *test,
139ca160887SIlpo Järvinen const struct user_params *uparams,
14015f29882SIlpo Järvinen struct resctrl_val_param *param);
1410e251816SIlpo Järvinen int (*measure)(const struct user_params *uparams,
1420e251816SIlpo Järvinen struct resctrl_val_param *param,
1430e251816SIlpo Järvinen pid_t bm_pid);
144e958c21eSReinette Chatre struct fill_buf_param *fill_buf;
1457f4d257eSSai Praneeth Prakhya };
1467f4d257eSSai Praneeth Prakhya
147433f437bSIlpo Järvinen struct perf_event_read {
148433f437bSIlpo Järvinen __u64 nr; /* The number of events */
149433f437bSIlpo Järvinen struct {
150433f437bSIlpo Järvinen __u64 value; /* The value of the event */
151433f437bSIlpo Järvinen } values[2];
152433f437bSIlpo Järvinen };
153433f437bSIlpo Järvinen
15490a009dbSIlpo Järvinen /*
15590a009dbSIlpo Järvinen * Memory location that consumes values compiler must not optimize away.
15690a009dbSIlpo Järvinen * Volatile ensures writes to this location cannot be optimized away by
15790a009dbSIlpo Järvinen * compiler.
15890a009dbSIlpo Järvinen */
15990a009dbSIlpo Järvinen extern volatile int *value_sink;
16090a009dbSIlpo Järvinen
161a1cd99e7SMaciej Wieczor-Retman extern int snc_unreliable;
162a1cd99e7SMaciej Wieczor-Retman
163896016d2SFenghua Yu extern char llc_occup_path[1024];
16478941183SFenghua Yu
165a1cd99e7SMaciej Wieczor-Retman int snc_nodes_per_l3_cache(void);
1666220f69eSShaopeng Tan int get_vendor(void);
167ecdbb911SFenghua Yu bool check_resctrlfs_support(void);
168ecdbb911SFenghua Yu int filter_dmesg(void);
169345e8abeSIlpo Järvinen int get_domain_id(const char *resource, int cpu_no, int *domain_id);
1706383851aSIlpo Järvinen int mount_resctrlfs(void);
1717f4d257eSSai Praneeth Prakhya int umount_resctrlfs(void);
17200616416SMaciej Wieczor-Retman bool resctrl_resource_exists(const char *resource);
17300616416SMaciej Wieczor-Retman bool resctrl_mon_feature_exists(const char *resource, const char *feature);
17474e76cbaSMaciej Wieczor-Retman bool resource_info_file_exists(const char *resource, const char *file);
175c603ff5bSIlpo Järvinen bool test_resource_feature_check(const struct resctrl_test *test);
176591a6e85SSai Praneeth Prakhya char *fgrep(FILE *inf, const char *str);
1776c8cb747SIlpo Järvinen int taskset_benchmark(pid_t bm_pid, int cpu_no, cpu_set_t *old_affinity);
1786c8cb747SIlpo Järvinen int taskset_restore(pid_t bm_pid, cpu_set_t *old_affinity);
179909592b5SIlpo Järvinen int write_schemata(const char *ctrlgrp, char *schemata, int cpu_no,
180909592b5SIlpo Järvinen const char *resource);
1810d66ddb2SIlpo Järvinen int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, const char *mongrp);
182591a6e85SSai Praneeth Prakhya int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
183591a6e85SSai Praneeth Prakhya int group_fd, unsigned long flags);
184e958c21eSReinette Chatre unsigned char *alloc_buffer(size_t buf_size, bool memflush);
185205de6ddSIlpo Järvinen void mem_flush(unsigned char *buf, size_t buf_size);
186205de6ddSIlpo Järvinen void fill_cache_read(unsigned char *buf, size_t buf_size, bool once);
187f77b9672SReinette Chatre ssize_t get_fill_buf_size(int cpu_no, const char *cache_type);
18876f8f009SReinette Chatre int initialize_read_mem_bw_imc(void);
18976f8f009SReinette Chatre int measure_read_mem_bw(const struct user_params *uparams,
19076f8f009SReinette Chatre struct resctrl_val_param *param, pid_t bm_pid);
191aef5efa6SIlpo Järvinen void initialize_mem_bw_resctrl(const struct resctrl_val_param *param,
192aef5efa6SIlpo Järvinen int domain_id);
193ca160887SIlpo Järvinen int resctrl_val(const struct resctrl_test *test,
194ca160887SIlpo Järvinen const struct user_params *uparams,
19515f29882SIlpo Järvinen struct resctrl_val_param *param);
196b6dfac94SIlpo Järvinen unsigned long create_bit_mask(unsigned int start, unsigned int len);
197205de6ddSIlpo Järvinen unsigned int count_contiguous_bits(unsigned long val, unsigned int *start);
1984b357e2aSIlpo Järvinen int get_full_cbm(const char *cache_type, unsigned long *mask);
199b6dfac94SIlpo Järvinen int get_mask_no_shareable(const char *cache_type, unsigned long *mask);
20060c2a692SIlpo Järvinen int get_cache_size(int cpu_no, const char *cache_type, unsigned long *cache_size);
201e331ac14SMaciej Wieczor-Retman int resource_info_unsigned_get(const char *resource, const char *filename, unsigned int *val);
20278941183SFenghua Yu void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
203e6487230SMaciej Wieczor-Retman int signal_handler_register(const struct resctrl_test *test);
20473c55fa5SShaopeng Tan void signal_handler_unregister(void);
20578941183SFenghua Yu unsigned int count_bits(unsigned long n);
206*d6d35d0bSMaciej Wieczor-Retman int snc_kernel_support(void);
207433f437bSIlpo Järvinen
208433f437bSIlpo Järvinen void perf_event_attr_initialize(struct perf_event_attr *pea, __u64 config);
209433f437bSIlpo Järvinen void perf_event_initialize_read_format(struct perf_event_read *pe_read);
210433f437bSIlpo Järvinen int perf_open(struct perf_event_attr *pea, pid_t pid, int cpu_no);
2112892731eSIlpo Järvinen int perf_event_reset_enable(int pe_fd);
212433f437bSIlpo Järvinen int perf_event_measure(int pe_fd, struct perf_event_read *pe_read,
2138245a70eSIlpo Järvinen const char *filename, pid_t bm_pid);
2148245a70eSIlpo Järvinen int measure_llc_resctrl(const char *filename, pid_t bm_pid);
21533403bc7SIlpo Järvinen void show_cache_info(int no_of_bits, __u64 avg_llc_val, size_t cache_span, bool lines);
216591a6e85SSai Praneeth Prakhya
21719e94a23SIlpo Järvinen /*
21819e94a23SIlpo Järvinen * cache_portion_size - Calculate the size of a cache portion
21919e94a23SIlpo Järvinen * @cache_size: Total cache size in bytes
22019e94a23SIlpo Järvinen * @portion_mask: Cache portion mask
22119e94a23SIlpo Järvinen * @full_cache_mask: Full Cache Bit Mask (CBM) for the cache
22219e94a23SIlpo Järvinen *
22319e94a23SIlpo Järvinen * Return: The size of the cache portion in bytes.
22419e94a23SIlpo Järvinen */
cache_portion_size(unsigned long cache_size,unsigned long portion_mask,unsigned long full_cache_mask)22519e94a23SIlpo Järvinen static inline unsigned long cache_portion_size(unsigned long cache_size,
22619e94a23SIlpo Järvinen unsigned long portion_mask,
22719e94a23SIlpo Järvinen unsigned long full_cache_mask)
22819e94a23SIlpo Järvinen {
22919e94a23SIlpo Järvinen unsigned int bits = count_bits(full_cache_mask);
23019e94a23SIlpo Järvinen
23119e94a23SIlpo Järvinen /*
23219e94a23SIlpo Järvinen * With no bits the full CBM, assume cache cannot be split into
23319e94a23SIlpo Järvinen * smaller portions. To avoid divide by zero, return cache_size.
23419e94a23SIlpo Järvinen */
23519e94a23SIlpo Järvinen if (!bits)
23619e94a23SIlpo Järvinen return cache_size;
23719e94a23SIlpo Järvinen
23819e94a23SIlpo Järvinen return cache_size * count_bits(portion_mask) / bits;
23919e94a23SIlpo Järvinen }
24019e94a23SIlpo Järvinen
241c603ff5bSIlpo Järvinen extern struct resctrl_test mbm_test;
242c603ff5bSIlpo Järvinen extern struct resctrl_test mba_test;
243c603ff5bSIlpo Järvinen extern struct resctrl_test cmt_test;
244c603ff5bSIlpo Järvinen extern struct resctrl_test l3_cat_test;
245ae638551SMaciej Wieczor-Retman extern struct resctrl_test l3_noncont_cat_test;
246ae638551SMaciej Wieczor-Retman extern struct resctrl_test l2_noncont_cat_test;
247c603ff5bSIlpo Järvinen
248591a6e85SSai Praneeth Prakhya #endif /* RESCTRL_H */
249