139111695SAlexei Starovoitov /* This program is free software; you can redistribute it and/or 239111695SAlexei Starovoitov * modify it under the terms of version 2 of the GNU General Public 339111695SAlexei Starovoitov * License as published by the Free Software Foundation. 439111695SAlexei Starovoitov */ 539111695SAlexei Starovoitov #include <stdio.h> 639111695SAlexei Starovoitov #include <unistd.h> 739111695SAlexei Starovoitov #include <stdlib.h> 839111695SAlexei Starovoitov #include <stdbool.h> 939111695SAlexei Starovoitov #include <string.h> 1039111695SAlexei Starovoitov #include <fcntl.h> 1139111695SAlexei Starovoitov #include <poll.h> 1239111695SAlexei Starovoitov #include <linux/perf_event.h> 1339111695SAlexei Starovoitov #include <linux/bpf.h> 1439111695SAlexei Starovoitov #include <errno.h> 1539111695SAlexei Starovoitov #include <assert.h> 1639111695SAlexei Starovoitov #include <sys/syscall.h> 1739111695SAlexei Starovoitov #include <sys/ioctl.h> 1839111695SAlexei Starovoitov #include <sys/mman.h> 1939111695SAlexei Starovoitov #include <time.h> 2039111695SAlexei Starovoitov #include <signal.h> 2139111695SAlexei Starovoitov #include "libbpf.h" 2239111695SAlexei Starovoitov #include "bpf_load.h" 23205c8adaSJoe Stringer #include "perf-sys.h" 24*28dbf861SYonghong Song #include "trace_helpers.h" 2539111695SAlexei Starovoitov 2639111695SAlexei Starovoitov static int pmu_fd; 2739111695SAlexei Starovoitov 2839111695SAlexei Starovoitov static __u64 time_get_ns(void) 2939111695SAlexei Starovoitov { 3039111695SAlexei Starovoitov struct timespec ts; 3139111695SAlexei Starovoitov 3239111695SAlexei Starovoitov clock_gettime(CLOCK_MONOTONIC, &ts); 3339111695SAlexei Starovoitov return ts.tv_sec * 1000000000ull + ts.tv_nsec; 3439111695SAlexei Starovoitov } 3539111695SAlexei Starovoitov 3639111695SAlexei Starovoitov static __u64 start_time; 3739111695SAlexei Starovoitov 3839111695SAlexei Starovoitov #define MAX_CNT 100000ll 3939111695SAlexei Starovoitov 40*28dbf861SYonghong Song static int print_bpf_output(void *data, int size) 4139111695SAlexei Starovoitov { 4239111695SAlexei Starovoitov static __u64 cnt; 4339111695SAlexei Starovoitov struct { 4439111695SAlexei Starovoitov __u64 pid; 4539111695SAlexei Starovoitov __u64 cookie; 4639111695SAlexei Starovoitov } *e = data; 4739111695SAlexei Starovoitov 4839111695SAlexei Starovoitov if (e->cookie != 0x12345678) { 4939111695SAlexei Starovoitov printf("BUG pid %llx cookie %llx sized %d\n", 5039111695SAlexei Starovoitov e->pid, e->cookie, size); 51*28dbf861SYonghong Song return PERF_EVENT_ERROR; 5239111695SAlexei Starovoitov } 5339111695SAlexei Starovoitov 5439111695SAlexei Starovoitov cnt++; 5539111695SAlexei Starovoitov 5639111695SAlexei Starovoitov if (cnt == MAX_CNT) { 5739111695SAlexei Starovoitov printf("recv %lld events per sec\n", 5839111695SAlexei Starovoitov MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 59*28dbf861SYonghong Song return PERF_EVENT_DONE; 6039111695SAlexei Starovoitov } 61*28dbf861SYonghong Song 62*28dbf861SYonghong Song return PERF_EVENT_CONT; 6339111695SAlexei Starovoitov } 6439111695SAlexei Starovoitov 6539111695SAlexei Starovoitov static void test_bpf_perf_event(void) 6639111695SAlexei Starovoitov { 6739111695SAlexei Starovoitov struct perf_event_attr attr = { 6839111695SAlexei Starovoitov .sample_type = PERF_SAMPLE_RAW, 6939111695SAlexei Starovoitov .type = PERF_TYPE_SOFTWARE, 7039111695SAlexei Starovoitov .config = PERF_COUNT_SW_BPF_OUTPUT, 7139111695SAlexei Starovoitov }; 7239111695SAlexei Starovoitov int key = 0; 7339111695SAlexei Starovoitov 74205c8adaSJoe Stringer pmu_fd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); 7539111695SAlexei Starovoitov 7639111695SAlexei Starovoitov assert(pmu_fd >= 0); 77d40fc181SJoe Stringer assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0); 7839111695SAlexei Starovoitov ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0); 7939111695SAlexei Starovoitov } 8039111695SAlexei Starovoitov 8139111695SAlexei Starovoitov int main(int argc, char **argv) 8239111695SAlexei Starovoitov { 8339111695SAlexei Starovoitov char filename[256]; 8439111695SAlexei Starovoitov FILE *f; 85*28dbf861SYonghong Song int ret; 8639111695SAlexei Starovoitov 8739111695SAlexei Starovoitov snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 8839111695SAlexei Starovoitov 8939111695SAlexei Starovoitov if (load_bpf_file(filename)) { 9039111695SAlexei Starovoitov printf("%s", bpf_log_buf); 9139111695SAlexei Starovoitov return 1; 9239111695SAlexei Starovoitov } 9339111695SAlexei Starovoitov 9439111695SAlexei Starovoitov test_bpf_perf_event(); 9539111695SAlexei Starovoitov 9639111695SAlexei Starovoitov if (perf_event_mmap(pmu_fd) < 0) 9739111695SAlexei Starovoitov return 1; 9839111695SAlexei Starovoitov 9939111695SAlexei Starovoitov f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r"); 10039111695SAlexei Starovoitov (void) f; 10139111695SAlexei Starovoitov 10239111695SAlexei Starovoitov start_time = time_get_ns(); 103*28dbf861SYonghong Song ret = perf_event_poller(pmu_fd, print_bpf_output); 104*28dbf861SYonghong Song kill(0, SIGINT); 105*28dbf861SYonghong Song return ret; 10639111695SAlexei Starovoitov } 107