xref: /linux/tools/testing/selftests/powerpc/pmu/event.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1f50a7f3dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2cb96143dSMichael Ellerman /*
3cb96143dSMichael Ellerman  * Copyright 2013, Michael Ellerman, IBM Corp.
4cb96143dSMichael Ellerman  */
5cb96143dSMichael Ellerman 
6cb96143dSMichael Ellerman #define _GNU_SOURCE
7cb96143dSMichael Ellerman #include <unistd.h>
8cb96143dSMichael Ellerman #include <sys/syscall.h>
9cb96143dSMichael Ellerman #include <string.h>
10cb96143dSMichael Ellerman #include <stdio.h>
11*54d4ba7fSMadhavan Srinivasan #include <stdbool.h>
12cb96143dSMichael Ellerman #include <sys/ioctl.h>
13cb96143dSMichael Ellerman 
14cb96143dSMichael Ellerman #include "event.h"
15cb96143dSMichael Ellerman 
16cb96143dSMichael Ellerman 
perf_event_open(struct perf_event_attr * attr,pid_t pid,int cpu,int group_fd,unsigned long flags)17cb96143dSMichael Ellerman int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
18cb96143dSMichael Ellerman 		int group_fd, unsigned long flags)
19cb96143dSMichael Ellerman {
20cb96143dSMichael Ellerman 	return syscall(__NR_perf_event_open, attr, pid, cpu,
21cb96143dSMichael Ellerman 			   group_fd, flags);
22cb96143dSMichael Ellerman }
23cb96143dSMichael Ellerman 
__event_init_opts(struct event * e,u64 config,int type,char * name,bool sampling)24*54d4ba7fSMadhavan Srinivasan static void  __event_init_opts(struct event *e, u64 config,
25*54d4ba7fSMadhavan Srinivasan 			       int type, char *name, bool sampling)
26cb96143dSMichael Ellerman {
27cb96143dSMichael Ellerman 	memset(e, 0, sizeof(*e));
28cb96143dSMichael Ellerman 
29cb96143dSMichael Ellerman 	e->name = name;
30cb96143dSMichael Ellerman 
31cb96143dSMichael Ellerman 	e->attr.type = type;
32cb96143dSMichael Ellerman 	e->attr.config = config;
33cb96143dSMichael Ellerman 	e->attr.size = sizeof(e->attr);
34cb96143dSMichael Ellerman 	/* This has to match the structure layout in the header */
35cb96143dSMichael Ellerman 	e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \
36cb96143dSMichael Ellerman 				  PERF_FORMAT_TOTAL_TIME_RUNNING;
37*54d4ba7fSMadhavan Srinivasan 	if (sampling) {
38*54d4ba7fSMadhavan Srinivasan 		e->attr.sample_period = 1000;
39*54d4ba7fSMadhavan Srinivasan 		e->attr.sample_type = PERF_SAMPLE_REGS_INTR;
40*54d4ba7fSMadhavan Srinivasan 		e->attr.disabled = 1;
41*54d4ba7fSMadhavan Srinivasan 	}
42*54d4ba7fSMadhavan Srinivasan }
43*54d4ba7fSMadhavan Srinivasan 
event_init_opts(struct event * e,u64 config,int type,char * name)44*54d4ba7fSMadhavan Srinivasan void event_init_opts(struct event *e, u64 config, int type, char *name)
45*54d4ba7fSMadhavan Srinivasan {
46*54d4ba7fSMadhavan Srinivasan 	__event_init_opts(e, config, type, name, false);
47cb96143dSMichael Ellerman }
48cb96143dSMichael Ellerman 
event_init_named(struct event * e,u64 config,char * name)49cb96143dSMichael Ellerman void event_init_named(struct event *e, u64 config, char *name)
50cb96143dSMichael Ellerman {
51cb96143dSMichael Ellerman 	event_init_opts(e, config, PERF_TYPE_RAW, name);
52cb96143dSMichael Ellerman }
53cb96143dSMichael Ellerman 
event_init(struct event * e,u64 config)543752e453SMichael Ellerman void event_init(struct event *e, u64 config)
553752e453SMichael Ellerman {
563752e453SMichael Ellerman 	event_init_opts(e, config, PERF_TYPE_RAW, "event");
573752e453SMichael Ellerman }
583752e453SMichael Ellerman 
event_init_sampling(struct event * e,u64 config)59*54d4ba7fSMadhavan Srinivasan void event_init_sampling(struct event *e, u64 config)
60*54d4ba7fSMadhavan Srinivasan {
61*54d4ba7fSMadhavan Srinivasan 	__event_init_opts(e, config, PERF_TYPE_RAW, "event", true);
62*54d4ba7fSMadhavan Srinivasan }
63*54d4ba7fSMadhavan Srinivasan 
64cb96143dSMichael Ellerman #define PERF_CURRENT_PID	0
653752e453SMichael Ellerman #define PERF_NO_PID		-1
66cb96143dSMichael Ellerman #define PERF_NO_CPU		-1
67cb96143dSMichael Ellerman #define PERF_NO_GROUP		-1
68cb96143dSMichael Ellerman 
event_open_with_options(struct event * e,pid_t pid,int cpu,int group_fd)69cb96143dSMichael Ellerman int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd)
70cb96143dSMichael Ellerman {
71cb96143dSMichael Ellerman 	e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0);
72cb96143dSMichael Ellerman 	if (e->fd == -1) {
73cb96143dSMichael Ellerman 		perror("perf_event_open");
74cb96143dSMichael Ellerman 		return -1;
75cb96143dSMichael Ellerman 	}
76cb96143dSMichael Ellerman 
77cb96143dSMichael Ellerman 	return 0;
78cb96143dSMichael Ellerman }
79cb96143dSMichael Ellerman 
event_open_with_group(struct event * e,int group_fd)80cb96143dSMichael Ellerman int event_open_with_group(struct event *e, int group_fd)
81cb96143dSMichael Ellerman {
82cb96143dSMichael Ellerman 	return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd);
83cb96143dSMichael Ellerman }
84cb96143dSMichael Ellerman 
event_open_with_pid(struct event * e,pid_t pid)853752e453SMichael Ellerman int event_open_with_pid(struct event *e, pid_t pid)
863752e453SMichael Ellerman {
873752e453SMichael Ellerman 	return event_open_with_options(e, pid, PERF_NO_CPU, PERF_NO_GROUP);
883752e453SMichael Ellerman }
893752e453SMichael Ellerman 
event_open_with_cpu(struct event * e,int cpu)903752e453SMichael Ellerman int event_open_with_cpu(struct event *e, int cpu)
913752e453SMichael Ellerman {
923752e453SMichael Ellerman 	return event_open_with_options(e, PERF_NO_PID, cpu, PERF_NO_GROUP);
933752e453SMichael Ellerman }
943752e453SMichael Ellerman 
event_open(struct event * e)95cb96143dSMichael Ellerman int event_open(struct event *e)
96cb96143dSMichael Ellerman {
97cb96143dSMichael Ellerman 	return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP);
98cb96143dSMichael Ellerman }
99cb96143dSMichael Ellerman 
event_close(struct event * e)100cb96143dSMichael Ellerman void event_close(struct event *e)
101cb96143dSMichael Ellerman {
102cb96143dSMichael Ellerman 	close(e->fd);
103cb96143dSMichael Ellerman }
104cb96143dSMichael Ellerman 
event_enable(struct event * e)1053752e453SMichael Ellerman int event_enable(struct event *e)
1063752e453SMichael Ellerman {
1073752e453SMichael Ellerman 	return ioctl(e->fd, PERF_EVENT_IOC_ENABLE);
1083752e453SMichael Ellerman }
1093752e453SMichael Ellerman 
event_disable(struct event * e)1103752e453SMichael Ellerman int event_disable(struct event *e)
1113752e453SMichael Ellerman {
1123752e453SMichael Ellerman 	return ioctl(e->fd, PERF_EVENT_IOC_DISABLE);
1133752e453SMichael Ellerman }
1143752e453SMichael Ellerman 
event_reset(struct event * e)115cb96143dSMichael Ellerman int event_reset(struct event *e)
116cb96143dSMichael Ellerman {
117cb96143dSMichael Ellerman 	return ioctl(e->fd, PERF_EVENT_IOC_RESET);
118cb96143dSMichael Ellerman }
119cb96143dSMichael Ellerman 
event_read(struct event * e)120cb96143dSMichael Ellerman int event_read(struct event *e)
121cb96143dSMichael Ellerman {
122cb96143dSMichael Ellerman 	int rc;
123cb96143dSMichael Ellerman 
124cb96143dSMichael Ellerman 	rc = read(e->fd, &e->result, sizeof(e->result));
125cb96143dSMichael Ellerman 	if (rc != sizeof(e->result)) {
126cb96143dSMichael Ellerman 		fprintf(stderr, "read error on event %p!\n", e);
127cb96143dSMichael Ellerman 		return -1;
128cb96143dSMichael Ellerman 	}
129cb96143dSMichael Ellerman 
130cb96143dSMichael Ellerman 	return 0;
131cb96143dSMichael Ellerman }
132cb96143dSMichael Ellerman 
event_report_justified(struct event * e,int name_width,int result_width)133cb96143dSMichael Ellerman void event_report_justified(struct event *e, int name_width, int result_width)
134cb96143dSMichael Ellerman {
135cb96143dSMichael Ellerman 	printf("%*s: result %*llu ", name_width, e->name, result_width,
136cb96143dSMichael Ellerman 	       e->result.value);
137cb96143dSMichael Ellerman 
138cb96143dSMichael Ellerman 	if (e->result.running == e->result.enabled)
139cb96143dSMichael Ellerman 		printf("running/enabled %llu\n", e->result.running);
140cb96143dSMichael Ellerman 	else
141cb96143dSMichael Ellerman 		printf("running %llu enabled %llu\n", e->result.running,
142cb96143dSMichael Ellerman 			e->result.enabled);
143cb96143dSMichael Ellerman }
144cb96143dSMichael Ellerman 
event_report(struct event * e)145cb96143dSMichael Ellerman void event_report(struct event *e)
146cb96143dSMichael Ellerman {
147cb96143dSMichael Ellerman 	event_report_justified(e, 0, 0);
148cb96143dSMichael Ellerman }
149