1c315669eSAthira Rajeev // SPDX-License-Identifier: GPL-2.0-only
2c315669eSAthira Rajeev /*
3c315669eSAthira Rajeev  * Copyright 2022, Athira Rajeev, IBM Corp.
46523dce8SMadhavan Srinivasan  * Copyright 2022, Madhavan Srinivasan, IBM Corp.
55f6c3061SKajol Jain  * Copyright 2022, Kajol Jain, IBM Corp.
6c315669eSAthira Rajeev  */
7c315669eSAthira Rajeev 
8c315669eSAthira Rajeev #include <unistd.h>
9c315669eSAthira Rajeev #include <sys/syscall.h>
10c315669eSAthira Rajeev #include <string.h>
11c315669eSAthira Rajeev #include <stdio.h>
12c315669eSAthira Rajeev #include <sys/ioctl.h>
13c315669eSAthira Rajeev #include <sys/mman.h>
14c315669eSAthira Rajeev #include <stdlib.h>
15c315669eSAthira Rajeev #include <ctype.h>
16c315669eSAthira Rajeev 
17c315669eSAthira Rajeev #include "misc.h"
18c315669eSAthira Rajeev 
19c315669eSAthira Rajeev #define PAGE_SIZE               sysconf(_SC_PAGESIZE)
20c315669eSAthira Rajeev 
216523dce8SMadhavan Srinivasan /* Storage for platform version */
226523dce8SMadhavan Srinivasan int pvr;
236523dce8SMadhavan Srinivasan u64 platform_extended_mask;
246523dce8SMadhavan Srinivasan 
256523dce8SMadhavan Srinivasan /* Mask and Shift for Event code fields */
266523dce8SMadhavan Srinivasan int ev_mask_pmcxsel, ev_shift_pmcxsel;		//pmcxsel field
276523dce8SMadhavan Srinivasan int ev_mask_marked, ev_shift_marked;		//marked filed
286523dce8SMadhavan Srinivasan int ev_mask_comb, ev_shift_comb;		//combine field
296523dce8SMadhavan Srinivasan int ev_mask_unit, ev_shift_unit;		//unit field
306523dce8SMadhavan Srinivasan int ev_mask_pmc, ev_shift_pmc;			//pmc field
316523dce8SMadhavan Srinivasan int ev_mask_cache, ev_shift_cache;		//Cache sel field
326523dce8SMadhavan Srinivasan int ev_mask_sample, ev_shift_sample;		//Random sampling field
336523dce8SMadhavan Srinivasan int ev_mask_thd_sel, ev_shift_thd_sel;		//thresh_sel field
346523dce8SMadhavan Srinivasan int ev_mask_thd_start, ev_shift_thd_start;	//thresh_start field
356523dce8SMadhavan Srinivasan int ev_mask_thd_stop, ev_shift_thd_stop;	//thresh_stop field
366523dce8SMadhavan Srinivasan int ev_mask_thd_cmp, ev_shift_thd_cmp;		//thresh cmp field
376523dce8SMadhavan Srinivasan int ev_mask_sm, ev_shift_sm;			//SDAR mode field
386523dce8SMadhavan Srinivasan int ev_mask_rsq, ev_shift_rsq;			//radix scope qual field
396523dce8SMadhavan Srinivasan int ev_mask_l2l3, ev_shift_l2l3;		//l2l3 sel field
406523dce8SMadhavan Srinivasan int ev_mask_mmcr3_src, ev_shift_mmcr3_src;	//mmcr3 field
416523dce8SMadhavan Srinivasan 
init_ev_encodes(void)426523dce8SMadhavan Srinivasan static void init_ev_encodes(void)
436523dce8SMadhavan Srinivasan {
446523dce8SMadhavan Srinivasan 	ev_mask_pmcxsel = 0xff;
456523dce8SMadhavan Srinivasan 	ev_shift_pmcxsel = 0;
466523dce8SMadhavan Srinivasan 	ev_mask_marked = 1;
476523dce8SMadhavan Srinivasan 	ev_shift_marked = 8;
486523dce8SMadhavan Srinivasan 	ev_mask_unit = 0xf;
496523dce8SMadhavan Srinivasan 	ev_shift_unit = 12;
506523dce8SMadhavan Srinivasan 	ev_mask_pmc = 0xf;
516523dce8SMadhavan Srinivasan 	ev_shift_pmc = 16;
526523dce8SMadhavan Srinivasan 	ev_mask_sample	= 0x1f;
536523dce8SMadhavan Srinivasan 	ev_shift_sample = 24;
546523dce8SMadhavan Srinivasan 	ev_mask_thd_sel = 0x7;
556523dce8SMadhavan Srinivasan 	ev_shift_thd_sel = 29;
566523dce8SMadhavan Srinivasan 	ev_mask_thd_start = 0xf;
576523dce8SMadhavan Srinivasan 	ev_shift_thd_start = 36;
586523dce8SMadhavan Srinivasan 	ev_mask_thd_stop = 0xf;
596523dce8SMadhavan Srinivasan 	ev_shift_thd_stop = 32;
606523dce8SMadhavan Srinivasan 
616523dce8SMadhavan Srinivasan 	switch (pvr) {
626523dce8SMadhavan Srinivasan 	case POWER10:
6342e0576eSKajol Jain 		ev_mask_thd_cmp = 0x3ffff;
6442e0576eSKajol Jain 		ev_shift_thd_cmp = 0;
656523dce8SMadhavan Srinivasan 		ev_mask_rsq = 1;
666523dce8SMadhavan Srinivasan 		ev_shift_rsq = 9;
676523dce8SMadhavan Srinivasan 		ev_mask_comb = 3;
686523dce8SMadhavan Srinivasan 		ev_shift_comb = 10;
696523dce8SMadhavan Srinivasan 		ev_mask_cache = 3;
706523dce8SMadhavan Srinivasan 		ev_shift_cache = 20;
716523dce8SMadhavan Srinivasan 		ev_mask_sm = 0x3;
726523dce8SMadhavan Srinivasan 		ev_shift_sm = 22;
736523dce8SMadhavan Srinivasan 		ev_mask_l2l3 = 0x1f;
746523dce8SMadhavan Srinivasan 		ev_shift_l2l3 = 40;
756523dce8SMadhavan Srinivasan 		ev_mask_mmcr3_src = 0x7fff;
766523dce8SMadhavan Srinivasan 		ev_shift_mmcr3_src = 45;
776523dce8SMadhavan Srinivasan 		break;
786523dce8SMadhavan Srinivasan 	case POWER9:
796523dce8SMadhavan Srinivasan 		ev_mask_comb = 3;
806523dce8SMadhavan Srinivasan 		ev_shift_comb = 10;
816523dce8SMadhavan Srinivasan 		ev_mask_cache = 0xf;
826523dce8SMadhavan Srinivasan 		ev_shift_cache = 20;
836523dce8SMadhavan Srinivasan 		ev_mask_thd_cmp = 0x3ff;
846523dce8SMadhavan Srinivasan 		ev_shift_thd_cmp = 40;
856523dce8SMadhavan Srinivasan 		ev_mask_sm = 0x3;
866523dce8SMadhavan Srinivasan 		ev_shift_sm = 50;
876523dce8SMadhavan Srinivasan 		break;
886523dce8SMadhavan Srinivasan 	default:
896523dce8SMadhavan Srinivasan 		FAIL_IF_EXIT(1);
906523dce8SMadhavan Srinivasan 	}
916523dce8SMadhavan Srinivasan }
926523dce8SMadhavan Srinivasan 
936523dce8SMadhavan Srinivasan /* Return the extended regs mask value */
perf_get_platform_reg_mask(void)946523dce8SMadhavan Srinivasan static u64 perf_get_platform_reg_mask(void)
956523dce8SMadhavan Srinivasan {
966523dce8SMadhavan Srinivasan 	if (have_hwcap2(PPC_FEATURE2_ARCH_3_1))
976523dce8SMadhavan Srinivasan 		return PERF_POWER10_MASK;
986523dce8SMadhavan Srinivasan 	if (have_hwcap2(PPC_FEATURE2_ARCH_3_00))
996523dce8SMadhavan Srinivasan 		return PERF_POWER9_MASK;
1006523dce8SMadhavan Srinivasan 
1016523dce8SMadhavan Srinivasan 	return -1;
1026523dce8SMadhavan Srinivasan }
1036523dce8SMadhavan Srinivasan 
check_extended_regs_support(void)1046523dce8SMadhavan Srinivasan int check_extended_regs_support(void)
1056523dce8SMadhavan Srinivasan {
1066523dce8SMadhavan Srinivasan 	int fd;
1076523dce8SMadhavan Srinivasan 	struct event event;
1086523dce8SMadhavan Srinivasan 
1096523dce8SMadhavan Srinivasan 	event_init(&event, 0x1001e);
1106523dce8SMadhavan Srinivasan 
1116523dce8SMadhavan Srinivasan 	event.attr.type = 4;
1126523dce8SMadhavan Srinivasan 	event.attr.sample_period = 1;
1136523dce8SMadhavan Srinivasan 	event.attr.disabled = 1;
1146523dce8SMadhavan Srinivasan 	event.attr.sample_type = PERF_SAMPLE_REGS_INTR;
1156523dce8SMadhavan Srinivasan 	event.attr.sample_regs_intr = platform_extended_mask;
1166523dce8SMadhavan Srinivasan 
1176523dce8SMadhavan Srinivasan 	fd = event_open(&event);
1186523dce8SMadhavan Srinivasan 	if (fd != -1)
1196523dce8SMadhavan Srinivasan 		return 0;
1206523dce8SMadhavan Srinivasan 
1216523dce8SMadhavan Srinivasan 	return -1;
1226523dce8SMadhavan Srinivasan }
1236523dce8SMadhavan Srinivasan 
platform_check_for_tests(void)124*9cfd110aSAthira Rajeev int platform_check_for_tests(void)
1256523dce8SMadhavan Srinivasan {
1266523dce8SMadhavan Srinivasan 	pvr = PVR_VER(mfspr(SPRN_PVR));
1276523dce8SMadhavan Srinivasan 
1286523dce8SMadhavan Srinivasan 	/*
1296523dce8SMadhavan Srinivasan 	 * Check for supported platforms
1306523dce8SMadhavan Srinivasan 	 * for sampling test
1316523dce8SMadhavan Srinivasan 	 */
1326523dce8SMadhavan Srinivasan 	if ((pvr != POWER10) && (pvr != POWER9))
1336523dce8SMadhavan Srinivasan 		goto out;
1346523dce8SMadhavan Srinivasan 
1356523dce8SMadhavan Srinivasan 	/*
1366523dce8SMadhavan Srinivasan 	 * Check PMU driver registered by looking for
1376523dce8SMadhavan Srinivasan 	 * PPC_FEATURE2_EBB bit in AT_HWCAP2
1386523dce8SMadhavan Srinivasan 	 */
139*9cfd110aSAthira Rajeev 	if (!have_hwcap2(PPC_FEATURE2_EBB) || !have_hwcap2(PPC_FEATURE2_ARCH_3_00))
1406523dce8SMadhavan Srinivasan 		goto out;
1416523dce8SMadhavan Srinivasan 
142*9cfd110aSAthira Rajeev 	return 0;
143*9cfd110aSAthira Rajeev 
144*9cfd110aSAthira Rajeev out:
145*9cfd110aSAthira Rajeev 	printf("%s: Tests unsupported for this platform\n", __func__);
146*9cfd110aSAthira Rajeev 	return -1;
147*9cfd110aSAthira Rajeev }
148*9cfd110aSAthira Rajeev 
check_pvr_for_sampling_tests(void)149*9cfd110aSAthira Rajeev int check_pvr_for_sampling_tests(void)
150*9cfd110aSAthira Rajeev {
151*9cfd110aSAthira Rajeev 	SKIP_IF(platform_check_for_tests());
152*9cfd110aSAthira Rajeev 
153*9cfd110aSAthira Rajeev 	platform_extended_mask = perf_get_platform_reg_mask();
1546523dce8SMadhavan Srinivasan 	/* check if platform supports extended regs */
1556523dce8SMadhavan Srinivasan 	if (check_extended_regs_support())
1566523dce8SMadhavan Srinivasan 		goto out;
1576523dce8SMadhavan Srinivasan 
1586523dce8SMadhavan Srinivasan 	init_ev_encodes();
1596523dce8SMadhavan Srinivasan 	return 0;
160*9cfd110aSAthira Rajeev 
1616523dce8SMadhavan Srinivasan out:
1626523dce8SMadhavan Srinivasan 	printf("%s: Sampling tests un-supported\n", __func__);
1636523dce8SMadhavan Srinivasan 	return -1;
1646523dce8SMadhavan Srinivasan }
165*9cfd110aSAthira Rajeev 
166c315669eSAthira Rajeev /*
167c315669eSAthira Rajeev  * Allocate mmap buffer of "mmap_pages" number of
168c315669eSAthira Rajeev  * pages.
169c315669eSAthira Rajeev  */
event_sample_buf_mmap(int fd,int mmap_pages)170c315669eSAthira Rajeev void *event_sample_buf_mmap(int fd, int mmap_pages)
171c315669eSAthira Rajeev {
172c315669eSAthira Rajeev 	size_t page_size = sysconf(_SC_PAGESIZE);
173c315669eSAthira Rajeev 	size_t mmap_size;
174c315669eSAthira Rajeev 	void *buff;
175c315669eSAthira Rajeev 
176c315669eSAthira Rajeev 	if (mmap_pages <= 0)
177c315669eSAthira Rajeev 		return NULL;
178c315669eSAthira Rajeev 
179c315669eSAthira Rajeev 	if (fd <= 0)
180c315669eSAthira Rajeev 		return NULL;
181c315669eSAthira Rajeev 
182c315669eSAthira Rajeev 	mmap_size =  page_size * (1 + mmap_pages);
183c315669eSAthira Rajeev 	buff = mmap(NULL, mmap_size,
184c315669eSAthira Rajeev 		PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
185c315669eSAthira Rajeev 
186c315669eSAthira Rajeev 	if (buff == MAP_FAILED) {
187c315669eSAthira Rajeev 		perror("mmap() failed.");
188c315669eSAthira Rajeev 		return NULL;
189c315669eSAthira Rajeev 	}
190c315669eSAthira Rajeev 	return buff;
191c315669eSAthira Rajeev }
192c315669eSAthira Rajeev 
193c315669eSAthira Rajeev /*
194c315669eSAthira Rajeev  * Post process the mmap buffer.
195c315669eSAthira Rajeev  * - If sample_count != NULL then return count of total
196c315669eSAthira Rajeev  *   number of samples present in the mmap buffer.
197c315669eSAthira Rajeev  * - If sample_count == NULL then return the address
198c315669eSAthira Rajeev  *   of first sample from the mmap buffer
199c315669eSAthira Rajeev  */
__event_read_samples(void * sample_buff,size_t * size,u64 * sample_count)200c315669eSAthira Rajeev void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count)
201c315669eSAthira Rajeev {
202c315669eSAthira Rajeev 	size_t page_size = sysconf(_SC_PAGESIZE);
203c315669eSAthira Rajeev 	struct perf_event_header *header = sample_buff + page_size;
204c315669eSAthira Rajeev 	struct perf_event_mmap_page *metadata_page = sample_buff;
205c315669eSAthira Rajeev 	unsigned long data_head, data_tail;
206c315669eSAthira Rajeev 
207c315669eSAthira Rajeev 	/*
208c315669eSAthira Rajeev 	 * PERF_RECORD_SAMPLE:
209c315669eSAthira Rajeev 	 * struct {
210c315669eSAthira Rajeev 	 *     struct perf_event_header hdr;
211c315669eSAthira Rajeev 	 *     u64 data[];
212c315669eSAthira Rajeev 	 * };
213c315669eSAthira Rajeev 	 */
214c315669eSAthira Rajeev 
215c315669eSAthira Rajeev 	data_head = metadata_page->data_head;
216c315669eSAthira Rajeev 	/* sync memory before reading sample */
217c315669eSAthira Rajeev 	mb();
218c315669eSAthira Rajeev 	data_tail = metadata_page->data_tail;
219c315669eSAthira Rajeev 
220c315669eSAthira Rajeev 	/* Check for sample_count */
221c315669eSAthira Rajeev 	if (sample_count)
222c315669eSAthira Rajeev 		*sample_count = 0;
223c315669eSAthira Rajeev 
224c315669eSAthira Rajeev 	while (1) {
225c315669eSAthira Rajeev 		/*
226c315669eSAthira Rajeev 		 * Reads the mmap data buffer by moving
227c315669eSAthira Rajeev 		 * the data_tail to know the last read data.
228c315669eSAthira Rajeev 		 * data_head points to head in data buffer.
229c315669eSAthira Rajeev 		 * refer "struct perf_event_mmap_page" in
230c315669eSAthira Rajeev 		 * "include/uapi/linux/perf_event.h".
231c315669eSAthira Rajeev 		 */
232c315669eSAthira Rajeev 		if (data_head - data_tail < sizeof(header))
233c315669eSAthira Rajeev 			return NULL;
234c315669eSAthira Rajeev 
235c315669eSAthira Rajeev 		data_tail += sizeof(header);
236c315669eSAthira Rajeev 		if (header->type == PERF_RECORD_SAMPLE) {
237c315669eSAthira Rajeev 			*size = (header->size - sizeof(header));
238c315669eSAthira Rajeev 			if (!sample_count)
239c315669eSAthira Rajeev 				return sample_buff + page_size + data_tail;
240c315669eSAthira Rajeev 			data_tail += *size;
241c315669eSAthira Rajeev 			*sample_count += 1;
242c315669eSAthira Rajeev 		} else {
243c315669eSAthira Rajeev 			*size = (header->size - sizeof(header));
244c315669eSAthira Rajeev 			if ((metadata_page->data_tail + *size) > metadata_page->data_head)
245c315669eSAthira Rajeev 				data_tail = metadata_page->data_head;
246c315669eSAthira Rajeev 			else
247c315669eSAthira Rajeev 				data_tail += *size;
248c315669eSAthira Rajeev 		}
249c315669eSAthira Rajeev 		header = (struct perf_event_header *)((void *)header + header->size);
250c315669eSAthira Rajeev 	}
251c315669eSAthira Rajeev 	return NULL;
252c315669eSAthira Rajeev }
2535f6c3061SKajol Jain 
collect_samples(void * sample_buff)2545f6c3061SKajol Jain int collect_samples(void *sample_buff)
2555f6c3061SKajol Jain {
2565f6c3061SKajol Jain 	u64 sample_count;
2575f6c3061SKajol Jain 	size_t size = 0;
2585f6c3061SKajol Jain 
2595f6c3061SKajol Jain 	__event_read_samples(sample_buff, &size, &sample_count);
2605f6c3061SKajol Jain 	return sample_count;
2615f6c3061SKajol Jain }
2625f6c3061SKajol Jain 
perf_read_first_sample(void * sample_buff,size_t * size)2635f6c3061SKajol Jain static void *perf_read_first_sample(void *sample_buff, size_t *size)
2645f6c3061SKajol Jain {
2655f6c3061SKajol Jain 	return __event_read_samples(sample_buff, size, NULL);
2665f6c3061SKajol Jain }
2675f6c3061SKajol Jain 
get_intr_regs(struct event * event,void * sample_buff)2685f6c3061SKajol Jain u64 *get_intr_regs(struct event *event, void *sample_buff)
2695f6c3061SKajol Jain {
2705f6c3061SKajol Jain 	u64 type = event->attr.sample_type;
2715f6c3061SKajol Jain 	u64 *intr_regs;
2725f6c3061SKajol Jain 	size_t size = 0;
2735f6c3061SKajol Jain 
27461d89900SKajol Jain 	if ((type ^ (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_BRANCH_STACK)) &&
27561d89900SKajol Jain 			(type  ^ PERF_SAMPLE_REGS_INTR))
2765f6c3061SKajol Jain 		return NULL;
2775f6c3061SKajol Jain 
2785f6c3061SKajol Jain 	intr_regs = (u64 *)perf_read_first_sample(sample_buff, &size);
2795f6c3061SKajol Jain 	if (!intr_regs)
2805f6c3061SKajol Jain 		return NULL;
2815f6c3061SKajol Jain 
28261d89900SKajol Jain 	if (type & PERF_SAMPLE_BRANCH_STACK) {
28361d89900SKajol Jain 		/*
28461d89900SKajol Jain 		 * PERF_RECORD_SAMPLE and PERF_SAMPLE_BRANCH_STACK:
28561d89900SKajol Jain 		 * struct {
28661d89900SKajol Jain 		 *     struct perf_event_header hdr;
28761d89900SKajol Jain 		 *     u64 number_of_branches;
28861d89900SKajol Jain 		 *     struct perf_branch_entry[number_of_branches];
28961d89900SKajol Jain 		 *     u64 data[];
29061d89900SKajol Jain 		 * };
29161d89900SKajol Jain 		 * struct perf_branch_entry {
29261d89900SKajol Jain 		 *     u64	from;
29361d89900SKajol Jain 		 *     u64	to;
29461d89900SKajol Jain 		 *     u64	misc;
29561d89900SKajol Jain 		 * };
29661d89900SKajol Jain 		 */
29761d89900SKajol Jain 		intr_regs += ((*intr_regs) * 3) + 1;
29861d89900SKajol Jain 	}
29961d89900SKajol Jain 
3005f6c3061SKajol Jain 	/*
3015f6c3061SKajol Jain 	 * First entry in the sample buffer used to specify
3025f6c3061SKajol Jain 	 * PERF_SAMPLE_REGS_ABI_64, skip perf regs abi to access
3035f6c3061SKajol Jain 	 * interrupt registers.
3045f6c3061SKajol Jain 	 */
3055f6c3061SKajol Jain 	++intr_regs;
3065f6c3061SKajol Jain 
3075f6c3061SKajol Jain 	return intr_regs;
3085f6c3061SKajol Jain }
3095f6c3061SKajol Jain 
__perf_reg_mask(const char * register_name)310a84ca704SHaowen Bai static const int __perf_reg_mask(const char *register_name)
3115f6c3061SKajol Jain {
3125f6c3061SKajol Jain 	if (!strcmp(register_name, "R0"))
3135f6c3061SKajol Jain 		return 0;
3145f6c3061SKajol Jain 	else if (!strcmp(register_name, "R1"))
3155f6c3061SKajol Jain 		return 1;
3165f6c3061SKajol Jain 	else if (!strcmp(register_name, "R2"))
3175f6c3061SKajol Jain 		return 2;
3185f6c3061SKajol Jain 	else if (!strcmp(register_name, "R3"))
3195f6c3061SKajol Jain 		return 3;
3205f6c3061SKajol Jain 	else if (!strcmp(register_name, "R4"))
3215f6c3061SKajol Jain 		return 4;
3225f6c3061SKajol Jain 	else if (!strcmp(register_name, "R5"))
3235f6c3061SKajol Jain 		return 5;
3245f6c3061SKajol Jain 	else if (!strcmp(register_name, "R6"))
3255f6c3061SKajol Jain 		return 6;
3265f6c3061SKajol Jain 	else if (!strcmp(register_name, "R7"))
3275f6c3061SKajol Jain 		return 7;
3285f6c3061SKajol Jain 	else if (!strcmp(register_name, "R8"))
3295f6c3061SKajol Jain 		return 8;
3305f6c3061SKajol Jain 	else if (!strcmp(register_name, "R9"))
3315f6c3061SKajol Jain 		return 9;
3325f6c3061SKajol Jain 	else if (!strcmp(register_name, "R10"))
3335f6c3061SKajol Jain 		return 10;
3345f6c3061SKajol Jain 	else if (!strcmp(register_name, "R11"))
3355f6c3061SKajol Jain 		return 11;
3365f6c3061SKajol Jain 	else if (!strcmp(register_name, "R12"))
3375f6c3061SKajol Jain 		return 12;
3385f6c3061SKajol Jain 	else if (!strcmp(register_name, "R13"))
3395f6c3061SKajol Jain 		return 13;
3405f6c3061SKajol Jain 	else if (!strcmp(register_name, "R14"))
3415f6c3061SKajol Jain 		return 14;
3425f6c3061SKajol Jain 	else if (!strcmp(register_name, "R15"))
3435f6c3061SKajol Jain 		return 15;
3445f6c3061SKajol Jain 	else if (!strcmp(register_name, "R16"))
3455f6c3061SKajol Jain 		return 16;
3465f6c3061SKajol Jain 	else if (!strcmp(register_name, "R17"))
3475f6c3061SKajol Jain 		return 17;
3485f6c3061SKajol Jain 	else if (!strcmp(register_name, "R18"))
3495f6c3061SKajol Jain 		return 18;
3505f6c3061SKajol Jain 	else if (!strcmp(register_name, "R19"))
3515f6c3061SKajol Jain 		return 19;
3525f6c3061SKajol Jain 	else if (!strcmp(register_name, "R20"))
3535f6c3061SKajol Jain 		return 20;
3545f6c3061SKajol Jain 	else if (!strcmp(register_name, "R21"))
3555f6c3061SKajol Jain 		return 21;
3565f6c3061SKajol Jain 	else if (!strcmp(register_name, "R22"))
3575f6c3061SKajol Jain 		return 22;
3585f6c3061SKajol Jain 	else if (!strcmp(register_name, "R23"))
3595f6c3061SKajol Jain 		return 23;
3605f6c3061SKajol Jain 	else if (!strcmp(register_name, "R24"))
3615f6c3061SKajol Jain 		return 24;
3625f6c3061SKajol Jain 	else if (!strcmp(register_name, "R25"))
3635f6c3061SKajol Jain 		return 25;
3645f6c3061SKajol Jain 	else if (!strcmp(register_name, "R26"))
3655f6c3061SKajol Jain 		return 26;
3665f6c3061SKajol Jain 	else if (!strcmp(register_name, "R27"))
3675f6c3061SKajol Jain 		return 27;
3685f6c3061SKajol Jain 	else if (!strcmp(register_name, "R28"))
3695f6c3061SKajol Jain 		return 28;
3705f6c3061SKajol Jain 	else if (!strcmp(register_name, "R29"))
3715f6c3061SKajol Jain 		return 29;
3725f6c3061SKajol Jain 	else if (!strcmp(register_name, "R30"))
3735f6c3061SKajol Jain 		return 30;
3745f6c3061SKajol Jain 	else if (!strcmp(register_name, "R31"))
3755f6c3061SKajol Jain 		return 31;
3765f6c3061SKajol Jain 	else if (!strcmp(register_name, "NIP"))
3775f6c3061SKajol Jain 		return 32;
3785f6c3061SKajol Jain 	else if (!strcmp(register_name, "MSR"))
3795f6c3061SKajol Jain 		return 33;
3805f6c3061SKajol Jain 	else if (!strcmp(register_name, "ORIG_R3"))
3815f6c3061SKajol Jain 		return 34;
3825f6c3061SKajol Jain 	else if (!strcmp(register_name, "CTR"))
3835f6c3061SKajol Jain 		return 35;
3845f6c3061SKajol Jain 	else if (!strcmp(register_name, "LINK"))
3855f6c3061SKajol Jain 		return 36;
3865f6c3061SKajol Jain 	else if (!strcmp(register_name, "XER"))
3875f6c3061SKajol Jain 		return 37;
3885f6c3061SKajol Jain 	else if (!strcmp(register_name, "CCR"))
3895f6c3061SKajol Jain 		return 38;
3905f6c3061SKajol Jain 	else if (!strcmp(register_name, "SOFTE"))
3915f6c3061SKajol Jain 		return 39;
3925f6c3061SKajol Jain 	else if (!strcmp(register_name, "TRAP"))
3935f6c3061SKajol Jain 		return 40;
3945f6c3061SKajol Jain 	else if (!strcmp(register_name, "DAR"))
3955f6c3061SKajol Jain 		return 41;
3965f6c3061SKajol Jain 	else if (!strcmp(register_name, "DSISR"))
3975f6c3061SKajol Jain 		return 42;
3985f6c3061SKajol Jain 	else if (!strcmp(register_name, "SIER"))
3995f6c3061SKajol Jain 		return 43;
4005f6c3061SKajol Jain 	else if (!strcmp(register_name, "MMCRA"))
4015f6c3061SKajol Jain 		return 44;
4025f6c3061SKajol Jain 	else if (!strcmp(register_name, "MMCR0"))
4035f6c3061SKajol Jain 		return 45;
4045f6c3061SKajol Jain 	else if (!strcmp(register_name, "MMCR1"))
4055f6c3061SKajol Jain 		return 46;
4065f6c3061SKajol Jain 	else if (!strcmp(register_name, "MMCR2"))
4075f6c3061SKajol Jain 		return 47;
4085f6c3061SKajol Jain 	else if (!strcmp(register_name, "MMCR3"))
4095f6c3061SKajol Jain 		return 48;
4105f6c3061SKajol Jain 	else if (!strcmp(register_name, "SIER2"))
4115f6c3061SKajol Jain 		return 49;
4125f6c3061SKajol Jain 	else if (!strcmp(register_name, "SIER3"))
4135f6c3061SKajol Jain 		return 50;
4145f6c3061SKajol Jain 	else if (!strcmp(register_name, "PMC1"))
4155f6c3061SKajol Jain 		return 51;
4165f6c3061SKajol Jain 	else if (!strcmp(register_name, "PMC2"))
4175f6c3061SKajol Jain 		return 52;
4185f6c3061SKajol Jain 	else if (!strcmp(register_name, "PMC3"))
4195f6c3061SKajol Jain 		return 53;
4205f6c3061SKajol Jain 	else if (!strcmp(register_name, "PMC4"))
4215f6c3061SKajol Jain 		return 54;
4225f6c3061SKajol Jain 	else if (!strcmp(register_name, "PMC5"))
4235f6c3061SKajol Jain 		return 55;
4245f6c3061SKajol Jain 	else if (!strcmp(register_name, "PMC6"))
4255f6c3061SKajol Jain 		return 56;
4265f6c3061SKajol Jain 	else if (!strcmp(register_name, "SDAR"))
4275f6c3061SKajol Jain 		return 57;
4285f6c3061SKajol Jain 	else if (!strcmp(register_name, "SIAR"))
4295f6c3061SKajol Jain 		return 58;
4305f6c3061SKajol Jain 	else
4315f6c3061SKajol Jain 		return -1;
4325f6c3061SKajol Jain }
4335f6c3061SKajol Jain 
get_reg_value(u64 * intr_regs,char * register_name)4345f6c3061SKajol Jain u64 get_reg_value(u64 *intr_regs, char *register_name)
4355f6c3061SKajol Jain {
4365f6c3061SKajol Jain 	int register_bit_position;
4375f6c3061SKajol Jain 
4385f6c3061SKajol Jain 	register_bit_position = __perf_reg_mask(register_name);
4395f6c3061SKajol Jain 
4405f6c3061SKajol Jain 	if (register_bit_position < 0 || (!((platform_extended_mask >>
4415f6c3061SKajol Jain 			(register_bit_position - 1)) & 1)))
4425f6c3061SKajol Jain 		return -1;
4435f6c3061SKajol Jain 
4445f6c3061SKajol Jain 	return *(intr_regs + register_bit_position);
4455f6c3061SKajol Jain }
44642e0576eSKajol Jain 
get_thresh_cmp_val(struct event event)44742e0576eSKajol Jain int get_thresh_cmp_val(struct event event)
44842e0576eSKajol Jain {
44942e0576eSKajol Jain 	int exp = 0;
45042e0576eSKajol Jain 	u64 result = 0;
45142e0576eSKajol Jain 	u64 value;
45242e0576eSKajol Jain 
45342e0576eSKajol Jain 	if (!have_hwcap2(PPC_FEATURE2_ARCH_3_1))
45442e0576eSKajol Jain 		return EV_CODE_EXTRACT(event.attr.config, thd_cmp);
45542e0576eSKajol Jain 
45642e0576eSKajol Jain 	value = EV_CODE_EXTRACT(event.attr.config1, thd_cmp);
45742e0576eSKajol Jain 
45842e0576eSKajol Jain 	if (!value)
45942e0576eSKajol Jain 		return value;
46042e0576eSKajol Jain 
46142e0576eSKajol Jain 	/*
46242e0576eSKajol Jain 	 * Incase of P10, thresh_cmp value is not part of raw event code
46342e0576eSKajol Jain 	 * and provided via attr.config1 parameter. To program threshold in MMCRA,
46442e0576eSKajol Jain 	 * take a 18 bit number N and shift right 2 places and increment
46542e0576eSKajol Jain 	 * the exponent E by 1 until the upper 10 bits of N are zero.
46642e0576eSKajol Jain 	 * Write E to the threshold exponent and write the lower 8 bits of N
46742e0576eSKajol Jain 	 * to the threshold mantissa.
46842e0576eSKajol Jain 	 * The max threshold that can be written is 261120.
46942e0576eSKajol Jain 	 */
47042e0576eSKajol Jain 	if (value > 261120)
47142e0576eSKajol Jain 		value = 261120;
47242e0576eSKajol Jain 	while ((64 - __builtin_clzl(value)) > 8) {
47342e0576eSKajol Jain 		exp++;
47442e0576eSKajol Jain 		value >>= 2;
47542e0576eSKajol Jain 	}
47642e0576eSKajol Jain 
47742e0576eSKajol Jain 	/*
47842e0576eSKajol Jain 	 * Note that it is invalid to write a mantissa with the
47942e0576eSKajol Jain 	 * upper 2 bits of mantissa being zero, unless the
48042e0576eSKajol Jain 	 * exponent is also zero.
48142e0576eSKajol Jain 	 */
48242e0576eSKajol Jain 	if (!(value & 0xC0) && exp)
48342e0576eSKajol Jain 		result = -1;
48442e0576eSKajol Jain 	else
48542e0576eSKajol Jain 		result = (exp << 8) | value;
48642e0576eSKajol Jain 	return result;
48742e0576eSKajol Jain }
488a069b5f9SAthira Rajeev 
489a069b5f9SAthira Rajeev /*
490a069b5f9SAthira Rajeev  * Utility function to check for generic compat PMU
491a069b5f9SAthira Rajeev  * by comparing base_platform value from auxv and real
492a069b5f9SAthira Rajeev  * PVR value.
493a069b5f9SAthira Rajeev  */
auxv_generic_compat_pmu(void)494a069b5f9SAthira Rajeev static bool auxv_generic_compat_pmu(void)
495a069b5f9SAthira Rajeev {
496a069b5f9SAthira Rajeev 	int base_pvr = 0;
497a069b5f9SAthira Rajeev 
498a069b5f9SAthira Rajeev 	if (!strcmp(auxv_base_platform(), "power9"))
499a069b5f9SAthira Rajeev 		base_pvr = POWER9;
500a069b5f9SAthira Rajeev 	else if (!strcmp(auxv_base_platform(), "power10"))
501a069b5f9SAthira Rajeev 		base_pvr = POWER10;
502a069b5f9SAthira Rajeev 
503a069b5f9SAthira Rajeev 	return (!base_pvr);
504a069b5f9SAthira Rajeev }
505a069b5f9SAthira Rajeev 
506a069b5f9SAthira Rajeev /*
507a069b5f9SAthira Rajeev  * Check for generic compat PMU.
508a069b5f9SAthira Rajeev  * First check for presence of pmu_name from
509a069b5f9SAthira Rajeev  * "/sys/bus/event_source/devices/cpu/caps".
510a069b5f9SAthira Rajeev  * If doesn't exist, fallback to using value
511a069b5f9SAthira Rajeev  * auxv.
512a069b5f9SAthira Rajeev  */
check_for_generic_compat_pmu(void)513a069b5f9SAthira Rajeev bool check_for_generic_compat_pmu(void)
514a069b5f9SAthira Rajeev {
515a069b5f9SAthira Rajeev 	char pmu_name[256];
516a069b5f9SAthira Rajeev 
517a069b5f9SAthira Rajeev 	memset(pmu_name, 0, sizeof(pmu_name));
518a069b5f9SAthira Rajeev 	if (read_sysfs_file("bus/event_source/devices/cpu/caps/pmu_name",
519a069b5f9SAthira Rajeev 		pmu_name, sizeof(pmu_name)) < 0)
520a069b5f9SAthira Rajeev 		return auxv_generic_compat_pmu();
521a069b5f9SAthira Rajeev 
522a069b5f9SAthira Rajeev 	if (!strcmp(pmu_name, "ISAv3"))
523a069b5f9SAthira Rajeev 		return true;
524a069b5f9SAthira Rajeev 	else
525a069b5f9SAthira Rajeev 		return false;
526a069b5f9SAthira Rajeev }
527a069b5f9SAthira Rajeev 
528a069b5f9SAthira Rajeev /*
529a069b5f9SAthira Rajeev  * Check if system is booted in compat mode.
530a069b5f9SAthira Rajeev  */
check_for_compat_mode(void)531a069b5f9SAthira Rajeev bool check_for_compat_mode(void)
532a069b5f9SAthira Rajeev {
533a069b5f9SAthira Rajeev 	char *platform = auxv_platform();
534a069b5f9SAthira Rajeev 	char *base_platform = auxv_base_platform();
535a069b5f9SAthira Rajeev 
536a069b5f9SAthira Rajeev 	return strcmp(platform, base_platform);
537a069b5f9SAthira Rajeev }
538