Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: Apache-2.0 |
| 2 | * Copyright(c) 2022 Cisco Systems, Inc. |
| 3 | */ |
| 4 | |
| 5 | #ifndef included_perfmon_perfmon_h |
| 6 | #define included_perfmon_perfmon_h |
| 7 | |
| 8 | #include <vppinfra/cpu.h> |
| 9 | #ifdef __linux__ |
| 10 | #include <sys/ioctl.h> |
| 11 | #include <linux/perf_event.h> |
| 12 | #endif |
| 13 | |
| 14 | #define CLIB_PERFMON_MAX_EVENTS 7 |
| 15 | typedef struct |
| 16 | { |
| 17 | char *name; |
| 18 | char *desc; |
| 19 | u64 config[CLIB_PERFMON_MAX_EVENTS]; |
| 20 | u32 type; |
| 21 | u8 n_events; |
| 22 | format_function_t *format_fn; |
| 23 | char **column_headers; |
| 24 | } clib_perfmon_bundle_t; |
| 25 | |
| 26 | typedef struct |
| 27 | { |
| 28 | u64 time_enabled; |
| 29 | u64 time_running; |
| 30 | u64 data[CLIB_PERFMON_MAX_EVENTS]; |
| 31 | u8 *desc; |
| 32 | u32 n_ops; |
| 33 | u32 group; |
| 34 | } clib_perfmon_capture_t; |
| 35 | |
| 36 | typedef struct |
| 37 | { |
| 38 | u8 *name; |
| 39 | u32 start; |
| 40 | } clib_perfmon_capture_group_t; |
| 41 | |
| 42 | typedef struct |
| 43 | { |
| 44 | int group_fd; |
| 45 | int *fds; |
| 46 | clib_perfmon_bundle_t *bundle; |
| 47 | u64 *data; |
| 48 | u8 debug : 1; |
| 49 | u32 n_captures; |
| 50 | clib_perfmon_capture_t *captures; |
| 51 | clib_perfmon_capture_group_t *capture_groups; |
| 52 | f64 ref_clock; |
| 53 | } clib_perfmon_ctx_t; |
| 54 | |
| 55 | typedef struct clib_perfmon_bundle_reg |
| 56 | { |
| 57 | clib_perfmon_bundle_t *bundle; |
| 58 | struct clib_perfmon_bundle_reg *next; |
| 59 | } clib_perfmon_bundle_reg_t; |
| 60 | |
| 61 | typedef struct |
| 62 | { |
| 63 | clib_perfmon_bundle_reg_t *bundle_regs; |
| 64 | } clib_perfmon_main_t; |
| 65 | |
| 66 | extern clib_perfmon_main_t clib_perfmon_main; |
| 67 | |
| 68 | static_always_inline void |
| 69 | clib_perfmon_ioctl (int fd, u32 req) |
| 70 | { |
| 71 | #ifdef __x86_64__ |
Guillaume Solignac | 6da7740 | 2022-04-13 12:03:48 +0200 | [diff] [blame] | 72 | asm volatile("syscall" |
| 73 | : |
| 74 | : "D"(fd), "S"(req), "a"(__NR_ioctl), "d"(PERF_IOC_FLAG_GROUP) |
| 75 | : "rcx", "r11" /* registers modified by kernel */); |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 76 | #else |
| 77 | ioctl (fd, req, PERF_IOC_FLAG_GROUP); |
| 78 | #endif |
| 79 | } |
| 80 | |
| 81 | clib_error_t *clib_perfmon_init_by_bundle_name (clib_perfmon_ctx_t *ctx, |
| 82 | char *fmt, ...); |
| 83 | void clib_perfmon_free (clib_perfmon_ctx_t *ctx); |
| 84 | void clib_perfmon_warmup (clib_perfmon_ctx_t *ctx); |
| 85 | void clib_perfmon_clear (clib_perfmon_ctx_t *ctx); |
| 86 | u64 *clib_perfmon_capture (clib_perfmon_ctx_t *ctx, u32 n_ops, char *fmt, ...); |
| 87 | void clib_perfmon_capture_group (clib_perfmon_ctx_t *ctx, char *fmt, ...); |
| 88 | format_function_t format_perfmon_bundle; |
| 89 | |
| 90 | static_always_inline void |
| 91 | clib_perfmon_reset (clib_perfmon_ctx_t *ctx) |
| 92 | { |
| 93 | clib_perfmon_ioctl (ctx->group_fd, PERF_EVENT_IOC_RESET); |
| 94 | } |
| 95 | static_always_inline void |
| 96 | clib_perfmon_enable (clib_perfmon_ctx_t *ctx) |
| 97 | { |
| 98 | clib_perfmon_ioctl (ctx->group_fd, PERF_EVENT_IOC_ENABLE); |
| 99 | } |
| 100 | static_always_inline void |
| 101 | clib_perfmon_disable (clib_perfmon_ctx_t *ctx) |
| 102 | { |
| 103 | clib_perfmon_ioctl (ctx->group_fd, PERF_EVENT_IOC_DISABLE); |
| 104 | } |
| 105 | |
| 106 | #define CLIB_PERFMON_BUNDLE(x) \ |
| 107 | static clib_perfmon_bundle_reg_t clib_perfmon_bundle_reg_##x; \ |
| 108 | static clib_perfmon_bundle_t clib_perfmon_bundle_##x; \ |
| 109 | static void __clib_constructor clib_perfmon_bundle_reg_fn_##x (void) \ |
| 110 | { \ |
| 111 | clib_perfmon_bundle_reg_##x.bundle = &clib_perfmon_bundle_##x; \ |
| 112 | clib_perfmon_bundle_reg_##x.next = clib_perfmon_main.bundle_regs; \ |
| 113 | clib_perfmon_main.bundle_regs = &clib_perfmon_bundle_reg_##x; \ |
| 114 | } \ |
| 115 | static clib_perfmon_bundle_t clib_perfmon_bundle_##x |
| 116 | |
| 117 | #endif |