diff options
Diffstat (limited to 'src/vppinfra/perfmon/perfmon.h')
-rw-r--r-- | src/vppinfra/perfmon/perfmon.h | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/src/vppinfra/perfmon/perfmon.h b/src/vppinfra/perfmon/perfmon.h new file mode 100644 index 00000000000..0d09dc6fb23 --- /dev/null +++ b/src/vppinfra/perfmon/perfmon.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2022 Cisco Systems, Inc. + */ + +#ifndef included_perfmon_perfmon_h +#define included_perfmon_perfmon_h + +#include <vppinfra/cpu.h> +#ifdef __linux__ +#include <sys/ioctl.h> +#include <linux/perf_event.h> +#endif + +#define CLIB_PERFMON_MAX_EVENTS 7 +typedef struct +{ + char *name; + char *desc; + u64 config[CLIB_PERFMON_MAX_EVENTS]; + u32 type; + u8 n_events; + format_function_t *format_fn; + char **column_headers; +} clib_perfmon_bundle_t; + +typedef struct +{ + u64 time_enabled; + u64 time_running; + u64 data[CLIB_PERFMON_MAX_EVENTS]; + u8 *desc; + u32 n_ops; + u32 group; +} clib_perfmon_capture_t; + +typedef struct +{ + u8 *name; + u32 start; +} clib_perfmon_capture_group_t; + +typedef struct +{ + int group_fd; + int *fds; + clib_perfmon_bundle_t *bundle; + u64 *data; + u8 debug : 1; + u32 n_captures; + clib_perfmon_capture_t *captures; + clib_perfmon_capture_group_t *capture_groups; + f64 ref_clock; +} clib_perfmon_ctx_t; + +typedef struct clib_perfmon_bundle_reg +{ + clib_perfmon_bundle_t *bundle; + struct clib_perfmon_bundle_reg *next; +} clib_perfmon_bundle_reg_t; + +typedef struct +{ + clib_perfmon_bundle_reg_t *bundle_regs; +} clib_perfmon_main_t; + +extern clib_perfmon_main_t clib_perfmon_main; + +static_always_inline void +clib_perfmon_ioctl (int fd, u32 req) +{ +#ifdef __x86_64__ + asm inline("syscall" + : + : "D"(fd), "S"(req), "a"(__NR_ioctl), "d"(PERF_IOC_FLAG_GROUP) + : "rcx", "r11" /* registers modified by kernel */); +#else + ioctl (fd, req, PERF_IOC_FLAG_GROUP); +#endif +} + +clib_error_t *clib_perfmon_init_by_bundle_name (clib_perfmon_ctx_t *ctx, + char *fmt, ...); +void clib_perfmon_free (clib_perfmon_ctx_t *ctx); +void clib_perfmon_warmup (clib_perfmon_ctx_t *ctx); +void clib_perfmon_clear (clib_perfmon_ctx_t *ctx); +u64 *clib_perfmon_capture (clib_perfmon_ctx_t *ctx, u32 n_ops, char *fmt, ...); +void clib_perfmon_capture_group (clib_perfmon_ctx_t *ctx, char *fmt, ...); +format_function_t format_perfmon_bundle; + +static_always_inline void +clib_perfmon_reset (clib_perfmon_ctx_t *ctx) +{ + clib_perfmon_ioctl (ctx->group_fd, PERF_EVENT_IOC_RESET); +} +static_always_inline void +clib_perfmon_enable (clib_perfmon_ctx_t *ctx) +{ + clib_perfmon_ioctl (ctx->group_fd, PERF_EVENT_IOC_ENABLE); +} +static_always_inline void +clib_perfmon_disable (clib_perfmon_ctx_t *ctx) +{ + clib_perfmon_ioctl (ctx->group_fd, PERF_EVENT_IOC_DISABLE); +} + +#define CLIB_PERFMON_BUNDLE(x) \ + static clib_perfmon_bundle_reg_t clib_perfmon_bundle_reg_##x; \ + static clib_perfmon_bundle_t clib_perfmon_bundle_##x; \ + static void __clib_constructor clib_perfmon_bundle_reg_fn_##x (void) \ + { \ + clib_perfmon_bundle_reg_##x.bundle = &clib_perfmon_bundle_##x; \ + clib_perfmon_bundle_reg_##x.next = clib_perfmon_main.bundle_regs; \ + clib_perfmon_main.bundle_regs = &clib_perfmon_bundle_reg_##x; \ + } \ + static clib_perfmon_bundle_t clib_perfmon_bundle_##x + +#endif |