18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2013, Michael Ellerman, IBM Corp. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#define _GNU_SOURCE 78c2ecf20Sopenharmony_ci#include <unistd.h> 88c2ecf20Sopenharmony_ci#include <sys/syscall.h> 98c2ecf20Sopenharmony_ci#include <string.h> 108c2ecf20Sopenharmony_ci#include <stdio.h> 118c2ecf20Sopenharmony_ci#include <sys/ioctl.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "event.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciint perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, 178c2ecf20Sopenharmony_ci int group_fd, unsigned long flags) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci return syscall(__NR_perf_event_open, attr, pid, cpu, 208c2ecf20Sopenharmony_ci group_fd, flags); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_civoid event_init_opts(struct event *e, u64 config, int type, char *name) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci memset(e, 0, sizeof(*e)); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci e->name = name; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci e->attr.type = type; 308c2ecf20Sopenharmony_ci e->attr.config = config; 318c2ecf20Sopenharmony_ci e->attr.size = sizeof(e->attr); 328c2ecf20Sopenharmony_ci /* This has to match the structure layout in the header */ 338c2ecf20Sopenharmony_ci e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \ 348c2ecf20Sopenharmony_ci PERF_FORMAT_TOTAL_TIME_RUNNING; 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_civoid event_init_named(struct event *e, u64 config, char *name) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci event_init_opts(e, config, PERF_TYPE_RAW, name); 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_civoid event_init(struct event *e, u64 config) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci event_init_opts(e, config, PERF_TYPE_RAW, "event"); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define PERF_CURRENT_PID 0 488c2ecf20Sopenharmony_ci#define PERF_NO_PID -1 498c2ecf20Sopenharmony_ci#define PERF_NO_CPU -1 508c2ecf20Sopenharmony_ci#define PERF_NO_GROUP -1 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciint event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0); 558c2ecf20Sopenharmony_ci if (e->fd == -1) { 568c2ecf20Sopenharmony_ci perror("perf_event_open"); 578c2ecf20Sopenharmony_ci return -1; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return 0; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ciint event_open_with_group(struct event *e, int group_fd) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ciint event_open_with_pid(struct event *e, pid_t pid) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci return event_open_with_options(e, pid, PERF_NO_CPU, PERF_NO_GROUP); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciint event_open_with_cpu(struct event *e, int cpu) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci return event_open_with_options(e, PERF_NO_PID, cpu, PERF_NO_GROUP); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciint event_open(struct event *e) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_civoid event_close(struct event *e) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci close(e->fd); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ciint event_enable(struct event *e) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci return ioctl(e->fd, PERF_EVENT_IOC_ENABLE); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ciint event_disable(struct event *e) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci return ioctl(e->fd, PERF_EVENT_IOC_DISABLE); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ciint event_reset(struct event *e) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci return ioctl(e->fd, PERF_EVENT_IOC_RESET); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciint event_read(struct event *e) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci int rc; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci rc = read(e->fd, &e->result, sizeof(e->result)); 1088c2ecf20Sopenharmony_ci if (rc != sizeof(e->result)) { 1098c2ecf20Sopenharmony_ci fprintf(stderr, "read error on event %p!\n", e); 1108c2ecf20Sopenharmony_ci return -1; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci return 0; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_civoid event_report_justified(struct event *e, int name_width, int result_width) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci printf("%*s: result %*llu ", name_width, e->name, result_width, 1198c2ecf20Sopenharmony_ci e->result.value); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (e->result.running == e->result.enabled) 1228c2ecf20Sopenharmony_ci printf("running/enabled %llu\n", e->result.running); 1238c2ecf20Sopenharmony_ci else 1248c2ecf20Sopenharmony_ci printf("running %llu enabled %llu\n", e->result.running, 1258c2ecf20Sopenharmony_ci e->result.enabled); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_civoid event_report(struct event *e) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci event_report_justified(e, 0, 0); 1318c2ecf20Sopenharmony_ci} 132