aboutsummaryrefslogtreecommitdiffstats
path: root/src/vppinfra/perfmon/perfmon.h
blob: 5b904a632e31be300b283bc9f05e1bcf8d7a206f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* 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 __linux__
#ifdef __x86_64__
  asm volatile("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
#endif /* linux */
}

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;

#ifdef __linux__
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);
}
#elif __FreeBSD__
static_always_inline void
clib_perfmon_reset (clib_perfmon_ctx_t *ctx)
{
  /* TODO: Implement for FreeBSD */
}
static_always_inline void
clib_perfmon_enable (clib_perfmon_ctx_t *ctx)
{
  /* TODO: Implement for FreeBSD */
}
static_always_inline void
clib_perfmon_disable (clib_perfmon_ctx_t *ctx)
{
  /* TODO: Implement for FreeBSD */
}
#endif /* linux */

#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