1*cb96143dSMichael Ellerman /* 2*cb96143dSMichael Ellerman * Copyright 2013, Michael Ellerman, IBM Corp. 3*cb96143dSMichael Ellerman * Licensed under GPLv2. 4*cb96143dSMichael Ellerman */ 5*cb96143dSMichael Ellerman 6*cb96143dSMichael Ellerman #define _GNU_SOURCE 7*cb96143dSMichael Ellerman #include <unistd.h> 8*cb96143dSMichael Ellerman #include <sys/syscall.h> 9*cb96143dSMichael Ellerman #include <string.h> 10*cb96143dSMichael Ellerman #include <stdio.h> 11*cb96143dSMichael Ellerman #include <sys/ioctl.h> 12*cb96143dSMichael Ellerman 13*cb96143dSMichael Ellerman #include "event.h" 14*cb96143dSMichael Ellerman 15*cb96143dSMichael Ellerman 16*cb96143dSMichael Ellerman int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, 17*cb96143dSMichael Ellerman int group_fd, unsigned long flags) 18*cb96143dSMichael Ellerman { 19*cb96143dSMichael Ellerman return syscall(__NR_perf_event_open, attr, pid, cpu, 20*cb96143dSMichael Ellerman group_fd, flags); 21*cb96143dSMichael Ellerman } 22*cb96143dSMichael Ellerman 23*cb96143dSMichael Ellerman void event_init_opts(struct event *e, u64 config, int type, char *name) 24*cb96143dSMichael Ellerman { 25*cb96143dSMichael Ellerman memset(e, 0, sizeof(*e)); 26*cb96143dSMichael Ellerman 27*cb96143dSMichael Ellerman e->name = name; 28*cb96143dSMichael Ellerman 29*cb96143dSMichael Ellerman e->attr.type = type; 30*cb96143dSMichael Ellerman e->attr.config = config; 31*cb96143dSMichael Ellerman e->attr.size = sizeof(e->attr); 32*cb96143dSMichael Ellerman /* This has to match the structure layout in the header */ 33*cb96143dSMichael Ellerman e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \ 34*cb96143dSMichael Ellerman PERF_FORMAT_TOTAL_TIME_RUNNING; 35*cb96143dSMichael Ellerman } 36*cb96143dSMichael Ellerman 37*cb96143dSMichael Ellerman void event_init_named(struct event *e, u64 config, char *name) 38*cb96143dSMichael Ellerman { 39*cb96143dSMichael Ellerman event_init_opts(e, config, PERF_TYPE_RAW, name); 40*cb96143dSMichael Ellerman } 41*cb96143dSMichael Ellerman 42*cb96143dSMichael Ellerman #define PERF_CURRENT_PID 0 43*cb96143dSMichael Ellerman #define PERF_NO_CPU -1 44*cb96143dSMichael Ellerman #define PERF_NO_GROUP -1 45*cb96143dSMichael Ellerman 46*cb96143dSMichael Ellerman int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd) 47*cb96143dSMichael Ellerman { 48*cb96143dSMichael Ellerman e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0); 49*cb96143dSMichael Ellerman if (e->fd == -1) { 50*cb96143dSMichael Ellerman perror("perf_event_open"); 51*cb96143dSMichael Ellerman return -1; 52*cb96143dSMichael Ellerman } 53*cb96143dSMichael Ellerman 54*cb96143dSMichael Ellerman return 0; 55*cb96143dSMichael Ellerman } 56*cb96143dSMichael Ellerman 57*cb96143dSMichael Ellerman int event_open_with_group(struct event *e, int group_fd) 58*cb96143dSMichael Ellerman { 59*cb96143dSMichael Ellerman return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd); 60*cb96143dSMichael Ellerman } 61*cb96143dSMichael Ellerman 62*cb96143dSMichael Ellerman int event_open(struct event *e) 63*cb96143dSMichael Ellerman { 64*cb96143dSMichael Ellerman return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP); 65*cb96143dSMichael Ellerman } 66*cb96143dSMichael Ellerman 67*cb96143dSMichael Ellerman void event_close(struct event *e) 68*cb96143dSMichael Ellerman { 69*cb96143dSMichael Ellerman close(e->fd); 70*cb96143dSMichael Ellerman } 71*cb96143dSMichael Ellerman 72*cb96143dSMichael Ellerman int event_reset(struct event *e) 73*cb96143dSMichael Ellerman { 74*cb96143dSMichael Ellerman return ioctl(e->fd, PERF_EVENT_IOC_RESET); 75*cb96143dSMichael Ellerman } 76*cb96143dSMichael Ellerman 77*cb96143dSMichael Ellerman int event_read(struct event *e) 78*cb96143dSMichael Ellerman { 79*cb96143dSMichael Ellerman int rc; 80*cb96143dSMichael Ellerman 81*cb96143dSMichael Ellerman rc = read(e->fd, &e->result, sizeof(e->result)); 82*cb96143dSMichael Ellerman if (rc != sizeof(e->result)) { 83*cb96143dSMichael Ellerman fprintf(stderr, "read error on event %p!\n", e); 84*cb96143dSMichael Ellerman return -1; 85*cb96143dSMichael Ellerman } 86*cb96143dSMichael Ellerman 87*cb96143dSMichael Ellerman return 0; 88*cb96143dSMichael Ellerman } 89*cb96143dSMichael Ellerman 90*cb96143dSMichael Ellerman void event_report_justified(struct event *e, int name_width, int result_width) 91*cb96143dSMichael Ellerman { 92*cb96143dSMichael Ellerman printf("%*s: result %*llu ", name_width, e->name, result_width, 93*cb96143dSMichael Ellerman e->result.value); 94*cb96143dSMichael Ellerman 95*cb96143dSMichael Ellerman if (e->result.running == e->result.enabled) 96*cb96143dSMichael Ellerman printf("running/enabled %llu\n", e->result.running); 97*cb96143dSMichael Ellerman else 98*cb96143dSMichael Ellerman printf("running %llu enabled %llu\n", e->result.running, 99*cb96143dSMichael Ellerman e->result.enabled); 100*cb96143dSMichael Ellerman } 101*cb96143dSMichael Ellerman 102*cb96143dSMichael Ellerman void event_report(struct event *e) 103*cb96143dSMichael Ellerman { 104*cb96143dSMichael Ellerman event_report_justified(e, 0, 0); 105*cb96143dSMichael Ellerman } 106