summaryrefslogtreecommitdiffstats
path: root/src/vppinfra/perfmon/perfmon.h
blob: d940921d6bf39b1f9232eaf21db6ac0d457482e6 (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
/* 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 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
}

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