xref: /linux/tools/testing/selftests/powerpc/pmu/sampling_tests/misc.c (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
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 
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 POWER11:
63 	case POWER10:
64 		ev_mask_thd_cmp = 0x3ffff;
65 		ev_shift_thd_cmp = 0;
66 		ev_mask_rsq = 1;
67 		ev_shift_rsq = 9;
68 		ev_mask_comb = 3;
69 		ev_shift_comb = 10;
70 		ev_mask_cache = 3;
71 		ev_shift_cache = 20;
72 		ev_mask_sm = 0x3;
73 		ev_shift_sm = 22;
74 		ev_mask_l2l3 = 0x1f;
75 		ev_shift_l2l3 = 40;
76 		ev_mask_mmcr3_src = 0x7fff;
77 		ev_shift_mmcr3_src = 45;
78 		break;
79 	case POWER9:
80 		ev_mask_comb = 3;
81 		ev_shift_comb = 10;
82 		ev_mask_cache = 0xf;
83 		ev_shift_cache = 20;
84 		ev_mask_thd_cmp = 0x3ff;
85 		ev_shift_thd_cmp = 40;
86 		ev_mask_sm = 0x3;
87 		ev_shift_sm = 50;
88 		break;
89 	default:
90 		FAIL_IF_EXIT(1);
91 	}
92 }
93 
94 /* Return the extended regs mask value */
95 u64 perf_get_platform_reg_mask(void)
96 {
97 	if (have_hwcap2(PPC_FEATURE2_ARCH_3_1))
98 		return PERF_POWER10_MASK;
99 	if (have_hwcap2(PPC_FEATURE2_ARCH_3_00))
100 		return PERF_POWER9_MASK;
101 
102 	return -1;
103 }
104 
105 int check_extended_regs_support(void)
106 {
107 	int fd;
108 	struct event event;
109 
110 	event_init(&event, 0x1001e);
111 
112 	event.attr.type = 4;
113 	event.attr.sample_period = 1;
114 	event.attr.disabled = 1;
115 	event.attr.sample_type = PERF_SAMPLE_REGS_INTR;
116 	event.attr.sample_regs_intr = platform_extended_mask;
117 
118 	fd = event_open(&event);
119 	if (fd != -1)
120 		return 0;
121 
122 	return -1;
123 }
124 
125 int platform_check_for_tests(void)
126 {
127 	pvr = PVR_VER(mfspr(SPRN_PVR));
128 
129 	/*
130 	 * Check for supported platforms
131 	 * for sampling test
132 	 */
133 	switch (pvr) {
134 	case POWER11:
135 	case POWER10:
136 	case POWER9:
137 		break;
138 	default:
139 		goto out;
140 	}
141 
142 	/*
143 	 * Check PMU driver registered by looking for
144 	 * PPC_FEATURE2_EBB bit in AT_HWCAP2
145 	 */
146 	if (!have_hwcap2(PPC_FEATURE2_EBB) || !have_hwcap2(PPC_FEATURE2_ARCH_3_00))
147 		goto out;
148 
149 	return 0;
150 
151 out:
152 	printf("%s: Tests unsupported for this platform\n", __func__);
153 	return -1;
154 }
155 
156 int check_pvr_for_sampling_tests(void)
157 {
158 	SKIP_IF(platform_check_for_tests());
159 
160 	platform_extended_mask = perf_get_platform_reg_mask();
161 	/* check if platform supports extended regs */
162 	if (check_extended_regs_support())
163 		goto out;
164 
165 	init_ev_encodes();
166 	return 0;
167 
168 out:
169 	printf("%s: Sampling tests un-supported\n", __func__);
170 	return -1;
171 }
172 
173 /*
174  * Allocate mmap buffer of "mmap_pages" number of
175  * pages.
176  */
177 void *event_sample_buf_mmap(int fd, int mmap_pages)
178 {
179 	size_t page_size = sysconf(_SC_PAGESIZE);
180 	size_t mmap_size;
181 	void *buff;
182 
183 	if (mmap_pages <= 0)
184 		return NULL;
185 
186 	if (fd <= 0)
187 		return NULL;
188 
189 	mmap_size =  page_size * (1 + mmap_pages);
190 	buff = mmap(NULL, mmap_size,
191 		PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
192 
193 	if (buff == MAP_FAILED) {
194 		perror("mmap() failed.");
195 		return NULL;
196 	}
197 	return buff;
198 }
199 
200 /*
201  * Post process the mmap buffer.
202  * - If sample_count != NULL then return count of total
203  *   number of samples present in the mmap buffer.
204  * - If sample_count == NULL then return the address
205  *   of first sample from the mmap buffer
206  */
207 void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count)
208 {
209 	size_t page_size = sysconf(_SC_PAGESIZE);
210 	struct perf_event_header *header = sample_buff + page_size;
211 	struct perf_event_mmap_page *metadata_page = sample_buff;
212 	unsigned long data_head, data_tail;
213 
214 	/*
215 	 * PERF_RECORD_SAMPLE:
216 	 * struct {
217 	 *     struct perf_event_header hdr;
218 	 *     u64 data[];
219 	 * };
220 	 */
221 
222 	data_head = metadata_page->data_head;
223 	/* sync memory before reading sample */
224 	mb();
225 	data_tail = metadata_page->data_tail;
226 
227 	/* Check for sample_count */
228 	if (sample_count)
229 		*sample_count = 0;
230 
231 	while (1) {
232 		/*
233 		 * Reads the mmap data buffer by moving
234 		 * the data_tail to know the last read data.
235 		 * data_head points to head in data buffer.
236 		 * refer "struct perf_event_mmap_page" in
237 		 * "include/uapi/linux/perf_event.h".
238 		 */
239 		if (data_head - data_tail < sizeof(header))
240 			return NULL;
241 
242 		data_tail += sizeof(header);
243 		if (header->type == PERF_RECORD_SAMPLE) {
244 			*size = (header->size - sizeof(header));
245 			if (!sample_count)
246 				return sample_buff + page_size + data_tail;
247 			data_tail += *size;
248 			*sample_count += 1;
249 		} else {
250 			*size = (header->size - sizeof(header));
251 			if ((metadata_page->data_tail + *size) > metadata_page->data_head)
252 				data_tail = metadata_page->data_head;
253 			else
254 				data_tail += *size;
255 		}
256 		header = (struct perf_event_header *)((void *)header + header->size);
257 	}
258 	return NULL;
259 }
260 
261 int collect_samples(void *sample_buff)
262 {
263 	u64 sample_count;
264 	size_t size = 0;
265 
266 	__event_read_samples(sample_buff, &size, &sample_count);
267 	return sample_count;
268 }
269 
270 static void *perf_read_first_sample(void *sample_buff, size_t *size)
271 {
272 	return __event_read_samples(sample_buff, size, NULL);
273 }
274 
275 u64 *get_intr_regs(struct event *event, void *sample_buff)
276 {
277 	u64 type = event->attr.sample_type;
278 	u64 *intr_regs;
279 	size_t size = 0;
280 
281 	if ((type ^ (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_BRANCH_STACK)) &&
282 			(type  ^ PERF_SAMPLE_REGS_INTR))
283 		return NULL;
284 
285 	intr_regs = (u64 *)perf_read_first_sample(sample_buff, &size);
286 	if (!intr_regs)
287 		return NULL;
288 
289 	if (type & PERF_SAMPLE_BRANCH_STACK) {
290 		/*
291 		 * PERF_RECORD_SAMPLE and PERF_SAMPLE_BRANCH_STACK:
292 		 * struct {
293 		 *     struct perf_event_header hdr;
294 		 *     u64 number_of_branches;
295 		 *     struct perf_branch_entry[number_of_branches];
296 		 *     u64 data[];
297 		 * };
298 		 * struct perf_branch_entry {
299 		 *     u64	from;
300 		 *     u64	to;
301 		 *     u64	misc;
302 		 * };
303 		 */
304 		intr_regs += ((*intr_regs) * 3) + 1;
305 	}
306 
307 	/*
308 	 * First entry in the sample buffer used to specify
309 	 * PERF_SAMPLE_REGS_ABI_64, skip perf regs abi to access
310 	 * interrupt registers.
311 	 */
312 	++intr_regs;
313 
314 	return intr_regs;
315 }
316 
317 static const int __perf_reg_mask(const char *register_name)
318 {
319 	if (!strcmp(register_name, "R0"))
320 		return 0;
321 	else if (!strcmp(register_name, "R1"))
322 		return 1;
323 	else if (!strcmp(register_name, "R2"))
324 		return 2;
325 	else if (!strcmp(register_name, "R3"))
326 		return 3;
327 	else if (!strcmp(register_name, "R4"))
328 		return 4;
329 	else if (!strcmp(register_name, "R5"))
330 		return 5;
331 	else if (!strcmp(register_name, "R6"))
332 		return 6;
333 	else if (!strcmp(register_name, "R7"))
334 		return 7;
335 	else if (!strcmp(register_name, "R8"))
336 		return 8;
337 	else if (!strcmp(register_name, "R9"))
338 		return 9;
339 	else if (!strcmp(register_name, "R10"))
340 		return 10;
341 	else if (!strcmp(register_name, "R11"))
342 		return 11;
343 	else if (!strcmp(register_name, "R12"))
344 		return 12;
345 	else if (!strcmp(register_name, "R13"))
346 		return 13;
347 	else if (!strcmp(register_name, "R14"))
348 		return 14;
349 	else if (!strcmp(register_name, "R15"))
350 		return 15;
351 	else if (!strcmp(register_name, "R16"))
352 		return 16;
353 	else if (!strcmp(register_name, "R17"))
354 		return 17;
355 	else if (!strcmp(register_name, "R18"))
356 		return 18;
357 	else if (!strcmp(register_name, "R19"))
358 		return 19;
359 	else if (!strcmp(register_name, "R20"))
360 		return 20;
361 	else if (!strcmp(register_name, "R21"))
362 		return 21;
363 	else if (!strcmp(register_name, "R22"))
364 		return 22;
365 	else if (!strcmp(register_name, "R23"))
366 		return 23;
367 	else if (!strcmp(register_name, "R24"))
368 		return 24;
369 	else if (!strcmp(register_name, "R25"))
370 		return 25;
371 	else if (!strcmp(register_name, "R26"))
372 		return 26;
373 	else if (!strcmp(register_name, "R27"))
374 		return 27;
375 	else if (!strcmp(register_name, "R28"))
376 		return 28;
377 	else if (!strcmp(register_name, "R29"))
378 		return 29;
379 	else if (!strcmp(register_name, "R30"))
380 		return 30;
381 	else if (!strcmp(register_name, "R31"))
382 		return 31;
383 	else if (!strcmp(register_name, "NIP"))
384 		return 32;
385 	else if (!strcmp(register_name, "MSR"))
386 		return 33;
387 	else if (!strcmp(register_name, "ORIG_R3"))
388 		return 34;
389 	else if (!strcmp(register_name, "CTR"))
390 		return 35;
391 	else if (!strcmp(register_name, "LINK"))
392 		return 36;
393 	else if (!strcmp(register_name, "XER"))
394 		return 37;
395 	else if (!strcmp(register_name, "CCR"))
396 		return 38;
397 	else if (!strcmp(register_name, "SOFTE"))
398 		return 39;
399 	else if (!strcmp(register_name, "TRAP"))
400 		return 40;
401 	else if (!strcmp(register_name, "DAR"))
402 		return 41;
403 	else if (!strcmp(register_name, "DSISR"))
404 		return 42;
405 	else if (!strcmp(register_name, "SIER"))
406 		return 43;
407 	else if (!strcmp(register_name, "MMCRA"))
408 		return 44;
409 	else if (!strcmp(register_name, "MMCR0"))
410 		return 45;
411 	else if (!strcmp(register_name, "MMCR1"))
412 		return 46;
413 	else if (!strcmp(register_name, "MMCR2"))
414 		return 47;
415 	else if (!strcmp(register_name, "MMCR3"))
416 		return 48;
417 	else if (!strcmp(register_name, "SIER2"))
418 		return 49;
419 	else if (!strcmp(register_name, "SIER3"))
420 		return 50;
421 	else if (!strcmp(register_name, "PMC1"))
422 		return 51;
423 	else if (!strcmp(register_name, "PMC2"))
424 		return 52;
425 	else if (!strcmp(register_name, "PMC3"))
426 		return 53;
427 	else if (!strcmp(register_name, "PMC4"))
428 		return 54;
429 	else if (!strcmp(register_name, "PMC5"))
430 		return 55;
431 	else if (!strcmp(register_name, "PMC6"))
432 		return 56;
433 	else if (!strcmp(register_name, "SDAR"))
434 		return 57;
435 	else if (!strcmp(register_name, "SIAR"))
436 		return 58;
437 	else
438 		return -1;
439 }
440 
441 u64 get_reg_value(u64 *intr_regs, char *register_name)
442 {
443 	int register_bit_position;
444 
445 	register_bit_position = __perf_reg_mask(register_name);
446 
447 	if (register_bit_position < 0 || (!((platform_extended_mask >>
448 			(register_bit_position - 1)) & 1)))
449 		return -1;
450 
451 	return *(intr_regs + register_bit_position);
452 }
453 
454 int get_thresh_cmp_val(struct event event)
455 {
456 	int exp = 0;
457 	u64 result = 0;
458 	u64 value;
459 
460 	if (!have_hwcap2(PPC_FEATURE2_ARCH_3_1))
461 		return EV_CODE_EXTRACT(event.attr.config, thd_cmp);
462 
463 	value = EV_CODE_EXTRACT(event.attr.config1, thd_cmp);
464 
465 	if (!value)
466 		return value;
467 
468 	/*
469 	 * Incase of P10, thresh_cmp value is not part of raw event code
470 	 * and provided via attr.config1 parameter. To program threshold in MMCRA,
471 	 * take a 18 bit number N and shift right 2 places and increment
472 	 * the exponent E by 1 until the upper 10 bits of N are zero.
473 	 * Write E to the threshold exponent and write the lower 8 bits of N
474 	 * to the threshold mantissa.
475 	 * The max threshold that can be written is 261120.
476 	 */
477 	if (value > 261120)
478 		value = 261120;
479 	while ((64 - __builtin_clzl(value)) > 8) {
480 		exp++;
481 		value >>= 2;
482 	}
483 
484 	/*
485 	 * Note that it is invalid to write a mantissa with the
486 	 * upper 2 bits of mantissa being zero, unless the
487 	 * exponent is also zero.
488 	 */
489 	if (!(value & 0xC0) && exp)
490 		result = -1;
491 	else
492 		result = (exp << 8) | value;
493 	return result;
494 }
495 
496 /*
497  * Utility function to check for generic compat PMU
498  * by comparing base_platform value from auxv and real
499  * PVR value.
500  * auxv_base_platform() func gives information of "base platform"
501  * corresponding to PVR value. Incase, if the distro doesn't
502  * support platform PVR (missing cputable support), base platform
503  * in auxv will have a default value other than the real PVR's.
504  * In this case, ISAv3 PMU (generic compat PMU) will be registered
505  * in the system. auxv_generic_compat_pmu() makes use of the base
506  * platform value from auxv to do this check.
507  */
508 static bool auxv_generic_compat_pmu(void)
509 {
510 	int base_pvr = 0;
511 
512 	if (!strcmp(auxv_base_platform(), "power9"))
513 		base_pvr = POWER9;
514 	else if (!strcmp(auxv_base_platform(), "power10"))
515 		base_pvr = POWER10;
516 	else if (!strcmp(auxv_base_platform(), "power11"))
517 		base_pvr = POWER11;
518 
519 	return (!base_pvr);
520 }
521 
522 /*
523  * Check for generic compat PMU.
524  * First check for presence of pmu_name from
525  * "/sys/bus/event_source/devices/cpu/caps".
526  * If doesn't exist, fallback to using value
527  * auxv.
528  */
529 bool check_for_generic_compat_pmu(void)
530 {
531 	char pmu_name[256];
532 
533 	memset(pmu_name, 0, sizeof(pmu_name));
534 	if (read_sysfs_file("bus/event_source/devices/cpu/caps/pmu_name",
535 		pmu_name, sizeof(pmu_name)) < 0)
536 		return auxv_generic_compat_pmu();
537 
538 	if (!strcmp(pmu_name, "ISAv3"))
539 		return true;
540 	else
541 		return false;
542 }
543 
544 /*
545  * Check if system is booted in compat mode.
546  */
547 bool check_for_compat_mode(void)
548 {
549 	char *platform = auxv_platform();
550 	char *base_platform = auxv_base_platform();
551 
552 	return strcmp(platform, base_platform);
553 }
554