1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2022, Athira Rajeev, IBM Corp.
4  * Copyright 2022, Madhavan Srinivasan, IBM Corp.
5  * Copyright 2022, Kajol Jain, IBM Corp.
6  */
7 
8 #include <unistd.h>
9 #include <sys/syscall.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include <sys/ioctl.h>
13 #include <sys/mman.h>
14 #include <stdlib.h>
15 #include <ctype.h>
16 
17 #include "misc.h"
18 
19 #define PAGE_SIZE               sysconf(_SC_PAGESIZE)
20 
21 /* Storage for platform version */
22 int pvr;
23 u64 platform_extended_mask;
24 
25 /* Mask and Shift for Event code fields */
26 int ev_mask_pmcxsel, ev_shift_pmcxsel;		//pmcxsel field
27 int ev_mask_marked, ev_shift_marked;		//marked filed
28 int ev_mask_comb, ev_shift_comb;		//combine field
29 int ev_mask_unit, ev_shift_unit;		//unit field
30 int ev_mask_pmc, ev_shift_pmc;			//pmc field
31 int ev_mask_cache, ev_shift_cache;		//Cache sel field
32 int ev_mask_sample, ev_shift_sample;		//Random sampling field
33 int ev_mask_thd_sel, ev_shift_thd_sel;		//thresh_sel field
34 int ev_mask_thd_start, ev_shift_thd_start;	//thresh_start field
35 int ev_mask_thd_stop, ev_shift_thd_stop;	//thresh_stop field
36 int ev_mask_thd_cmp, ev_shift_thd_cmp;		//thresh cmp field
37 int ev_mask_sm, ev_shift_sm;			//SDAR mode field
38 int ev_mask_rsq, ev_shift_rsq;			//radix scope qual field
39 int ev_mask_l2l3, ev_shift_l2l3;		//l2l3 sel field
40 int ev_mask_mmcr3_src, ev_shift_mmcr3_src;	//mmcr3 field
41 
init_ev_encodes(void)42 static void init_ev_encodes(void)
43 {
44 	ev_mask_pmcxsel = 0xff;
45 	ev_shift_pmcxsel = 0;
46 	ev_mask_marked = 1;
47 	ev_shift_marked = 8;
48 	ev_mask_unit = 0xf;
49 	ev_shift_unit = 12;
50 	ev_mask_pmc = 0xf;
51 	ev_shift_pmc = 16;
52 	ev_mask_sample	= 0x1f;
53 	ev_shift_sample = 24;
54 	ev_mask_thd_sel = 0x7;
55 	ev_shift_thd_sel = 29;
56 	ev_mask_thd_start = 0xf;
57 	ev_shift_thd_start = 36;
58 	ev_mask_thd_stop = 0xf;
59 	ev_shift_thd_stop = 32;
60 
61 	switch (pvr) {
62 	case POWER10:
63 		ev_mask_rsq = 1;
64 		ev_shift_rsq = 9;
65 		ev_mask_comb = 3;
66 		ev_shift_comb = 10;
67 		ev_mask_cache = 3;
68 		ev_shift_cache = 20;
69 		ev_mask_sm = 0x3;
70 		ev_shift_sm = 22;
71 		ev_mask_l2l3 = 0x1f;
72 		ev_shift_l2l3 = 40;
73 		ev_mask_mmcr3_src = 0x7fff;
74 		ev_shift_mmcr3_src = 45;
75 		break;
76 	case POWER9:
77 		ev_mask_comb = 3;
78 		ev_shift_comb = 10;
79 		ev_mask_cache = 0xf;
80 		ev_shift_cache = 20;
81 		ev_mask_thd_cmp = 0x3ff;
82 		ev_shift_thd_cmp = 40;
83 		ev_mask_sm = 0x3;
84 		ev_shift_sm = 50;
85 		break;
86 	default:
87 		FAIL_IF_EXIT(1);
88 	}
89 }
90 
91 /* Return the extended regs mask value */
perf_get_platform_reg_mask(void)92 static u64 perf_get_platform_reg_mask(void)
93 {
94 	if (have_hwcap2(PPC_FEATURE2_ARCH_3_1))
95 		return PERF_POWER10_MASK;
96 	if (have_hwcap2(PPC_FEATURE2_ARCH_3_00))
97 		return PERF_POWER9_MASK;
98 
99 	return -1;
100 }
101 
check_extended_regs_support(void)102 int check_extended_regs_support(void)
103 {
104 	int fd;
105 	struct event event;
106 
107 	event_init(&event, 0x1001e);
108 
109 	event.attr.type = 4;
110 	event.attr.sample_period = 1;
111 	event.attr.disabled = 1;
112 	event.attr.sample_type = PERF_SAMPLE_REGS_INTR;
113 	event.attr.sample_regs_intr = platform_extended_mask;
114 
115 	fd = event_open(&event);
116 	if (fd != -1)
117 		return 0;
118 
119 	return -1;
120 }
121 
check_pvr_for_sampling_tests(void)122 int check_pvr_for_sampling_tests(void)
123 {
124 	pvr = PVR_VER(mfspr(SPRN_PVR));
125 
126 	platform_extended_mask = perf_get_platform_reg_mask();
127 
128 	/*
129 	 * Check for supported platforms
130 	 * for sampling test
131 	 */
132 	if ((pvr != POWER10) && (pvr != POWER9))
133 		goto out;
134 
135 	/*
136 	 * Check PMU driver registered by looking for
137 	 * PPC_FEATURE2_EBB bit in AT_HWCAP2
138 	 */
139 	if (!have_hwcap2(PPC_FEATURE2_EBB))
140 		goto out;
141 
142 	/* check if platform supports extended regs */
143 	if (check_extended_regs_support())
144 		goto out;
145 
146 	init_ev_encodes();
147 	return 0;
148 out:
149 	printf("%s: Sampling tests un-supported\n", __func__);
150 	return -1;
151 }
152 /*
153  * Allocate mmap buffer of "mmap_pages" number of
154  * pages.
155  */
event_sample_buf_mmap(int fd,int mmap_pages)156 void *event_sample_buf_mmap(int fd, int mmap_pages)
157 {
158 	size_t page_size = sysconf(_SC_PAGESIZE);
159 	size_t mmap_size;
160 	void *buff;
161 
162 	if (mmap_pages <= 0)
163 		return NULL;
164 
165 	if (fd <= 0)
166 		return NULL;
167 
168 	mmap_size =  page_size * (1 + mmap_pages);
169 	buff = mmap(NULL, mmap_size,
170 		PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
171 
172 	if (buff == MAP_FAILED) {
173 		perror("mmap() failed.");
174 		return NULL;
175 	}
176 	return buff;
177 }
178 
179 /*
180  * Post process the mmap buffer.
181  * - If sample_count != NULL then return count of total
182  *   number of samples present in the mmap buffer.
183  * - If sample_count == NULL then return the address
184  *   of first sample from the mmap buffer
185  */
__event_read_samples(void * sample_buff,size_t * size,u64 * sample_count)186 void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count)
187 {
188 	size_t page_size = sysconf(_SC_PAGESIZE);
189 	struct perf_event_header *header = sample_buff + page_size;
190 	struct perf_event_mmap_page *metadata_page = sample_buff;
191 	unsigned long data_head, data_tail;
192 
193 	/*
194 	 * PERF_RECORD_SAMPLE:
195 	 * struct {
196 	 *     struct perf_event_header hdr;
197 	 *     u64 data[];
198 	 * };
199 	 */
200 
201 	data_head = metadata_page->data_head;
202 	/* sync memory before reading sample */
203 	mb();
204 	data_tail = metadata_page->data_tail;
205 
206 	/* Check for sample_count */
207 	if (sample_count)
208 		*sample_count = 0;
209 
210 	while (1) {
211 		/*
212 		 * Reads the mmap data buffer by moving
213 		 * the data_tail to know the last read data.
214 		 * data_head points to head in data buffer.
215 		 * refer "struct perf_event_mmap_page" in
216 		 * "include/uapi/linux/perf_event.h".
217 		 */
218 		if (data_head - data_tail < sizeof(header))
219 			return NULL;
220 
221 		data_tail += sizeof(header);
222 		if (header->type == PERF_RECORD_SAMPLE) {
223 			*size = (header->size - sizeof(header));
224 			if (!sample_count)
225 				return sample_buff + page_size + data_tail;
226 			data_tail += *size;
227 			*sample_count += 1;
228 		} else {
229 			*size = (header->size - sizeof(header));
230 			if ((metadata_page->data_tail + *size) > metadata_page->data_head)
231 				data_tail = metadata_page->data_head;
232 			else
233 				data_tail += *size;
234 		}
235 		header = (struct perf_event_header *)((void *)header + header->size);
236 	}
237 	return NULL;
238 }
239 
collect_samples(void * sample_buff)240 int collect_samples(void *sample_buff)
241 {
242 	u64 sample_count;
243 	size_t size = 0;
244 
245 	__event_read_samples(sample_buff, &size, &sample_count);
246 	return sample_count;
247 }
248 
perf_read_first_sample(void * sample_buff,size_t * size)249 static void *perf_read_first_sample(void *sample_buff, size_t *size)
250 {
251 	return __event_read_samples(sample_buff, size, NULL);
252 }
253 
get_intr_regs(struct event * event,void * sample_buff)254 u64 *get_intr_regs(struct event *event, void *sample_buff)
255 {
256 	u64 type = event->attr.sample_type;
257 	u64 *intr_regs;
258 	size_t size = 0;
259 
260 	if ((type ^ PERF_SAMPLE_REGS_INTR))
261 		return NULL;
262 
263 	intr_regs = (u64 *)perf_read_first_sample(sample_buff, &size);
264 	if (!intr_regs)
265 		return NULL;
266 
267 	/*
268 	 * First entry in the sample buffer used to specify
269 	 * PERF_SAMPLE_REGS_ABI_64, skip perf regs abi to access
270 	 * interrupt registers.
271 	 */
272 	++intr_regs;
273 
274 	return intr_regs;
275 }
276 
__perf_reg_mask(const char * register_name)277 static const int __perf_reg_mask(const char *register_name)
278 {
279 	if (!strcmp(register_name, "R0"))
280 		return 0;
281 	else if (!strcmp(register_name, "R1"))
282 		return 1;
283 	else if (!strcmp(register_name, "R2"))
284 		return 2;
285 	else if (!strcmp(register_name, "R3"))
286 		return 3;
287 	else if (!strcmp(register_name, "R4"))
288 		return 4;
289 	else if (!strcmp(register_name, "R5"))
290 		return 5;
291 	else if (!strcmp(register_name, "R6"))
292 		return 6;
293 	else if (!strcmp(register_name, "R7"))
294 		return 7;
295 	else if (!strcmp(register_name, "R8"))
296 		return 8;
297 	else if (!strcmp(register_name, "R9"))
298 		return 9;
299 	else if (!strcmp(register_name, "R10"))
300 		return 10;
301 	else if (!strcmp(register_name, "R11"))
302 		return 11;
303 	else if (!strcmp(register_name, "R12"))
304 		return 12;
305 	else if (!strcmp(register_name, "R13"))
306 		return 13;
307 	else if (!strcmp(register_name, "R14"))
308 		return 14;
309 	else if (!strcmp(register_name, "R15"))
310 		return 15;
311 	else if (!strcmp(register_name, "R16"))
312 		return 16;
313 	else if (!strcmp(register_name, "R17"))
314 		return 17;
315 	else if (!strcmp(register_name, "R18"))
316 		return 18;
317 	else if (!strcmp(register_name, "R19"))
318 		return 19;
319 	else if (!strcmp(register_name, "R20"))
320 		return 20;
321 	else if (!strcmp(register_name, "R21"))
322 		return 21;
323 	else if (!strcmp(register_name, "R22"))
324 		return 22;
325 	else if (!strcmp(register_name, "R23"))
326 		return 23;
327 	else if (!strcmp(register_name, "R24"))
328 		return 24;
329 	else if (!strcmp(register_name, "R25"))
330 		return 25;
331 	else if (!strcmp(register_name, "R26"))
332 		return 26;
333 	else if (!strcmp(register_name, "R27"))
334 		return 27;
335 	else if (!strcmp(register_name, "R28"))
336 		return 28;
337 	else if (!strcmp(register_name, "R29"))
338 		return 29;
339 	else if (!strcmp(register_name, "R30"))
340 		return 30;
341 	else if (!strcmp(register_name, "R31"))
342 		return 31;
343 	else if (!strcmp(register_name, "NIP"))
344 		return 32;
345 	else if (!strcmp(register_name, "MSR"))
346 		return 33;
347 	else if (!strcmp(register_name, "ORIG_R3"))
348 		return 34;
349 	else if (!strcmp(register_name, "CTR"))
350 		return 35;
351 	else if (!strcmp(register_name, "LINK"))
352 		return 36;
353 	else if (!strcmp(register_name, "XER"))
354 		return 37;
355 	else if (!strcmp(register_name, "CCR"))
356 		return 38;
357 	else if (!strcmp(register_name, "SOFTE"))
358 		return 39;
359 	else if (!strcmp(register_name, "TRAP"))
360 		return 40;
361 	else if (!strcmp(register_name, "DAR"))
362 		return 41;
363 	else if (!strcmp(register_name, "DSISR"))
364 		return 42;
365 	else if (!strcmp(register_name, "SIER"))
366 		return 43;
367 	else if (!strcmp(register_name, "MMCRA"))
368 		return 44;
369 	else if (!strcmp(register_name, "MMCR0"))
370 		return 45;
371 	else if (!strcmp(register_name, "MMCR1"))
372 		return 46;
373 	else if (!strcmp(register_name, "MMCR2"))
374 		return 47;
375 	else if (!strcmp(register_name, "MMCR3"))
376 		return 48;
377 	else if (!strcmp(register_name, "SIER2"))
378 		return 49;
379 	else if (!strcmp(register_name, "SIER3"))
380 		return 50;
381 	else if (!strcmp(register_name, "PMC1"))
382 		return 51;
383 	else if (!strcmp(register_name, "PMC2"))
384 		return 52;
385 	else if (!strcmp(register_name, "PMC3"))
386 		return 53;
387 	else if (!strcmp(register_name, "PMC4"))
388 		return 54;
389 	else if (!strcmp(register_name, "PMC5"))
390 		return 55;
391 	else if (!strcmp(register_name, "PMC6"))
392 		return 56;
393 	else if (!strcmp(register_name, "SDAR"))
394 		return 57;
395 	else if (!strcmp(register_name, "SIAR"))
396 		return 58;
397 	else
398 		return -1;
399 }
400 
get_reg_value(u64 * intr_regs,char * register_name)401 u64 get_reg_value(u64 *intr_regs, char *register_name)
402 {
403 	int register_bit_position;
404 
405 	register_bit_position = __perf_reg_mask(register_name);
406 
407 	if (register_bit_position < 0 || (!((platform_extended_mask >>
408 			(register_bit_position - 1)) & 1)))
409 		return -1;
410 
411 	return *(intr_regs + register_bit_position);
412 }
413