blob: d940921d6bf39b1f9232eaf21db6ac0d457482e6 [file] [log] [blame]
Damjan Mariond5045e62022-04-06 21:16:37 +02001/* 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
15typedef 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
26typedef 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
36typedef struct
37{
38 u8 *name;
39 u32 start;
40} clib_perfmon_capture_group_t;
41
42typedef 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
55typedef 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
61typedef struct
62{
63 clib_perfmon_bundle_reg_t *bundle_regs;
64} clib_perfmon_main_t;
65
66extern clib_perfmon_main_t clib_perfmon_main;
67
68static_always_inline void
69clib_perfmon_ioctl (int fd, u32 req)
70{
71#ifdef __x86_64__
Guillaume Solignac6da77402022-04-13 12:03:48 +020072 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 Mariond5045e62022-04-06 21:16:37 +020076#else
77 ioctl (fd, req, PERF_IOC_FLAG_GROUP);
78#endif
79}
80
81clib_error_t *clib_perfmon_init_by_bundle_name (clib_perfmon_ctx_t *ctx,
82 char *fmt, ...);
83void clib_perfmon_free (clib_perfmon_ctx_t *ctx);
84void clib_perfmon_warmup (clib_perfmon_ctx_t *ctx);
85void clib_perfmon_clear (clib_perfmon_ctx_t *ctx);
86u64 *clib_perfmon_capture (clib_perfmon_ctx_t *ctx, u32 n_ops, char *fmt, ...);
87void clib_perfmon_capture_group (clib_perfmon_ctx_t *ctx, char *fmt, ...);
88format_function_t format_perfmon_bundle;
89
90static_always_inline void
91clib_perfmon_reset (clib_perfmon_ctx_t *ctx)
92{
93 clib_perfmon_ioctl (ctx->group_fd, PERF_EVENT_IOC_RESET);
94}
95static_always_inline void
96clib_perfmon_enable (clib_perfmon_ctx_t *ctx)
97{
98 clib_perfmon_ioctl (ctx->group_fd, PERF_EVENT_IOC_ENABLE);
99}
100static_always_inline void
101clib_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