projects/linux·blob uaccess-cleanups · refs

195 lines · 4.6 KiB

1// SPDX-License-Identifier: GPL-2.0
2
3#include <stdint.h>
4#include "resctrl.h"
5
6char llc_occup_path[1024];
7
8void perf_event_attr_initialize(struct perf_event_attr *pea, __u64 config)
9{
10 memset(pea, 0, sizeof(*pea));
11 pea->type = PERF_TYPE_HARDWARE;
12 pea->size = sizeof(*pea);
13 pea->exclude_kernel = 1;
14 pea->exclude_hv = 1;
15 pea->exclude_idle = 1;
16 pea->exclude_callchain_kernel = 1;
17 pea->inherit = 1;
18 pea->exclude_guest = 1;
19 pea->disabled = 1;
20 pea->config = config;
21}
22
23/* Start counters to log values */
24int perf_event_reset_enable(int pe_fd)
25{
26 int ret;
27
28 ret = ioctl(pe_fd, PERF_EVENT_IOC_RESET, 0);
29 if (ret < 0)
30 return ret;
31
32 ret = ioctl(pe_fd, PERF_EVENT_IOC_ENABLE, 0);
33 if (ret < 0)
34 return ret;
35
36 return 0;
37}
38
39int perf_open(struct perf_event_attr *pea, pid_t pid, int cpu_no)
40{
41 int pe_fd;
42
43 pe_fd = perf_event_open(pea, pid, cpu_no, -1, PERF_FLAG_FD_CLOEXEC);
44 if (pe_fd == -1) {
45 ksft_perror("Unable to set up performance monitoring");
46 return -1;
47 }
48
49 perf_event_reset_enable(pe_fd);
50
51 return pe_fd;
52}
53
54/*
55 * Get LLC Occupancy as reported by RESCTRL FS
56 * For CMT,
57 * 1. If con_mon grp and mon grp given, then read from mon grp in
58 * con_mon grp
59 * 2. If only con_mon grp given, then read from con_mon grp
60 * 3. If both not given, then read from root con_mon grp
61 * For CAT,
62 * 1. If con_mon grp given, then read from it
63 * 2. If con_mon grp not given, then read from root con_mon grp
64 *
65 * Return: =0 on success. <0 on failure.
66 */
67static int get_llc_occu_resctrl(unsigned long *llc_occupancy)
68{
69 FILE *fp;
70
71 fp = fopen(llc_occup_path, "r");
72 if (!fp) {
73 ksft_perror("Failed to open results file");
74
75 return -1;
76 }
77 if (fscanf(fp, "%lu", llc_occupancy) <= 0) {
78 ksft_perror("Could not get llc occupancy");
79 fclose(fp);
80
81 return -1;
82 }
83 fclose(fp);
84
85 return 0;
86}
87
88/*
89 * print_results_cache: the cache results are stored in a file
90 * @filename: file that stores the results
91 * @bm_pid: child pid that runs benchmark
92 * @llc_value: perf miss value /
93 * llc occupancy value reported by resctrl FS
94 *
95 * Return: 0 on success, < 0 on error.
96 */
97static int print_results_cache(const char *filename, pid_t bm_pid, __u64 llc_value)
98{
99 FILE *fp;
100
101 if (strcmp(filename, "stdio") == 0 || strcmp(filename, "stderr") == 0) {
102 printf("Pid: %d \t LLC_value: %llu\n", (int)bm_pid, llc_value);
103 } else {
104 fp = fopen(filename, "a");
105 if (!fp) {
106 ksft_perror("Cannot open results file");
107
108 return -1;
109 }
110 fprintf(fp, "Pid: %d \t llc_value: %llu\n", (int)bm_pid, llc_value);
111 fclose(fp);
112 }
113
114 return 0;
115}
116
117/*
118 * perf_event_measure - Measure perf events
119 * @filename: Filename for writing the results
120 * @bm_pid: PID that runs the benchmark
121 *
122 * Measures perf events (e.g., cache misses) and writes the results into
123 * @filename. @bm_pid is written to the results file along with the measured
124 * value.
125 *
126 * Return: =0 on success. <0 on failure.
127 */
128int perf_event_measure(int pe_fd, const char *filename, pid_t bm_pid)
129{
130 __u64 value;
131 int ret;
132
133 /* Stop counters after one span to get miss rate */
134 ret = ioctl(pe_fd, PERF_EVENT_IOC_DISABLE, 0);
135 if (ret < 0)
136 return ret;
137
138 ret = read(pe_fd, &value, sizeof(value));
139 if (ret == -1) {
140 ksft_perror("Could not get perf value");
141 return -1;
142 }
143
144 return print_results_cache(filename, bm_pid, value);
145}
146
147/*
148 * measure_llc_resctrl - Measure resctrl LLC value from resctrl
149 * @filename: Filename for writing the results
150 * @bm_pid: PID that runs the benchmark
151 *
152 * Measures LLC occupancy from resctrl and writes the results into @filename.
153 * @bm_pid is written to the results file along with the measured value.
154 *
155 * Return: =0 on success. <0 on failure.
156 */
157int measure_llc_resctrl(const char *filename, pid_t bm_pid)
158{
159 unsigned long llc_occu_resc = 0;
160 int ret;
161
162 ret = get_llc_occu_resctrl(&llc_occu_resc);
163 if (ret < 0)
164 return ret;
165
166 return print_results_cache(filename, bm_pid, llc_occu_resc);
167}
168
169/*
170 * Reduce L2 allocation to minimum when testing L3 cache allocation.
171 */
172int minimize_l2_occupancy(const struct resctrl_test *test,
173 const struct user_params *uparams,
174 const struct resctrl_val_param *param)
175{
176 if (!strcmp(test->resource, "L3") && resctrl_resource_exists("L2"))
177 return write_schemata(param->ctrlgrp, "0x1", uparams->cpu, "L2");
178
179 return 0;
180}
181
182/*
183 * show_cache_info - Show generic cache test information
184 * @no_of_bits: Number of bits
185 * @avg_llc_val: Average of LLC cache result data
186 * @cache_span: Cache span
187 * @lines: @cache_span in lines or bytes
188 */
189void show_cache_info(int no_of_bits, __u64 avg_llc_val, size_t cache_span, bool lines)
190{
191 ksft_print_msg("Number of bits: %d\n", no_of_bits);
192 ksft_print_msg("Average LLC val: %llu\n", avg_llc_val);
193 ksft_print_msg("Cache span (%s): %zu\n", lines ? "lines" : "bytes",
194 cache_span);
195}