Line data Source code
1 : /* 2 : * Copyright (c) 2020 Cisco and/or its affiliates. 3 : * Licensed under the Apache License, Version 2.0 (the "License"); 4 : * you may not use this file except in compliance with the License. 5 : * You may obtain a copy of the License at: 6 : * 7 : * http://www.apache.org/licenses/LICENSE-2.0 8 : * 9 : * Unless required by applicable law or agreed to in writing, software 10 : * distributed under the License is distributed on an "AS IS" BASIS, 11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : * See the License for the specific language governing permissions and 13 : * limitations under the License. 14 : */ 15 : 16 : #ifndef __perfmon_perfmon_h 17 : #define __perfmon_perfmon_h 18 : 19 : #include <linux/perf_event.h> 20 : #include <vppinfra/clib.h> 21 : #include <vppinfra/format.h> 22 : #include <vppinfra/error.h> 23 : #include <vppinfra/cpu.h> 24 : #include <vlib/vlib.h> 25 : 26 : #if defined(__x86_64__) 27 : #define PERF_MAX_EVENTS 12 /* 4 fixed and 8 programable on ICX */ 28 : #elif defined(__aarch64__) 29 : #define PERF_MAX_EVENTS 7 /* 6 events + 1 CPU cycle counter */ 30 : #endif 31 : 32 : typedef enum 33 : { 34 : PERFMON_EVENT_TYPE_GENERAL, 35 : PERFMON_EVENT_TYPE_FIXED, 36 : PERFMON_EVENT_TYPE_PSEUDO, 37 : PERFMON_EVENT_TYPE_MAX, 38 : } perfmon_event_type_t; 39 : 40 : typedef enum 41 : { 42 : PERFMON_BUNDLE_TYPE_UNKNOWN, 43 : PERFMON_BUNDLE_TYPE_NODE, 44 : PERFMON_BUNDLE_TYPE_THREAD, 45 : PERFMON_BUNDLE_TYPE_SYSTEM, 46 : PERFMON_BUNDLE_TYPE_MAX, 47 : PERFMON_BUNDLE_TYPE_NODE_OR_THREAD, 48 : } perfmon_bundle_type_t; 49 : 50 : #define foreach_perfmon_bundle_type \ 51 : _ (PERFMON_BUNDLE_TYPE_UNKNOWN, "not supported") \ 52 : _ (PERFMON_BUNDLE_TYPE_NODE, "node") \ 53 : _ (PERFMON_BUNDLE_TYPE_THREAD, "thread") \ 54 : _ (PERFMON_BUNDLE_TYPE_SYSTEM, "system") 55 : 56 : typedef enum 57 : { 58 : #define _(e, str) e##_FLAG = 1 << e, 59 : foreach_perfmon_bundle_type 60 : #undef _ 61 : 62 : } perfmon_bundle_type_flag_t; 63 : 64 : typedef struct 65 : { 66 : u32 type_from_instance : 1; 67 : u32 exclude_kernel : 1; 68 : u32 config1 : 2; 69 : u32 implemented : 1; 70 : union 71 : { 72 : u32 type; 73 : u32 instance_type; 74 : }; 75 : u64 config; 76 : char *name; 77 : char *description; 78 : } perfmon_event_t; 79 : 80 : typedef struct 81 : { 82 : u32 type; 83 : int cpu; 84 : pid_t pid; 85 : char *name; 86 : } perfmon_instance_t; 87 : 88 : typedef struct 89 : { 90 : char *name; 91 : perfmon_instance_t *instances; 92 : } perfmon_instance_type_t; 93 : 94 : struct perfmon_source; 95 : typedef struct perfmon_bundle perfmon_bundle_t; 96 : 97 : typedef clib_error_t *(perfmon_source_init_fn_t) (vlib_main_t *vm, 98 : struct perfmon_source *); 99 : typedef perfmon_event_type_t (perfmon_source_get_event_type) (u32 event); 100 : typedef u8 (perfmon_source_bundle_support_t) (perfmon_bundle_t *); 101 : typedef clib_error_t *(perfmon_source_config_dispatch_wrapper_t) ( 102 : perfmon_bundle_t *b, vlib_node_function_t **dispatch_wrapper); 103 : 104 : typedef struct perfmon_source 105 : { 106 : char *name; 107 : char *description; 108 : struct perfmon_source *next; 109 : perfmon_event_t *events; 110 : u32 n_events; 111 : perfmon_instance_type_t *instances_by_type; 112 : format_function_t *format_config; 113 : perfmon_source_get_event_type *get_event_type; 114 : perfmon_source_init_fn_t *init_fn; 115 : perfmon_source_bundle_support_t *bundle_support; 116 : perfmon_source_config_dispatch_wrapper_t *config_dispatch_wrapper; 117 : } perfmon_source_t; 118 : 119 : typedef clib_error_t *(perfmon_bundle_init_fn_t) (vlib_main_t *vm, 120 : struct perfmon_bundle *); 121 : 122 : typedef struct 123 : { 124 : clib_cpu_supports_func_t cpu_supports; 125 : perfmon_bundle_type_t bundle_type; 126 : } perfmon_cpu_supports_t; 127 : 128 : typedef struct perfmon_bundle 129 : { 130 : char *name; 131 : char *description; 132 : char *source; 133 : char *footer; 134 : 135 : union 136 : { 137 : perfmon_bundle_type_flag_t type_flags; 138 : perfmon_bundle_type_t type; 139 : }; 140 : perfmon_bundle_type_t active_type; 141 : 142 : u32 events[PERF_MAX_EVENTS]; 143 : u32 n_events; 144 : u32 n_columns; 145 : 146 : uword *event_disabled; 147 : uword *column_disabled; 148 : u8 *column_events; 149 : 150 : u16 preserve_samples; 151 : 152 : perfmon_cpu_supports_t *cpu_supports; 153 : u32 n_cpu_supports; 154 : 155 : perfmon_bundle_init_fn_t *init_fn; 156 : 157 : char **column_headers; 158 : format_function_t *format_fn; 159 : 160 : /* do not set manually */ 161 : perfmon_source_t *src; 162 : struct perfmon_bundle *next; 163 : } perfmon_bundle_t; 164 : 165 : typedef struct 166 : { 167 : u64 nr; 168 : u64 time_enabled; 169 : u64 time_running; 170 : u64 value[PERF_MAX_EVENTS]; 171 : } perfmon_reading_t; 172 : 173 : typedef struct 174 : { 175 : CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); 176 : u64 n_calls; 177 : u64 n_packets; 178 : union 179 : { 180 : struct 181 : { 182 : u64 value[PERF_MAX_EVENTS]; 183 : } t[2]; 184 : u64 value[PERF_MAX_EVENTS * 2]; 185 : }; 186 : } perfmon_node_stats_t; 187 : 188 : typedef struct 189 : { 190 : u8 n_events; 191 : u16 n_nodes; 192 : perfmon_node_stats_t *node_stats; 193 : perfmon_bundle_t *bundle; 194 : u32 indexes[PERF_MAX_EVENTS]; 195 : u16 preserve_samples; 196 : struct perf_event_mmap_page *mmap_pages[PERF_MAX_EVENTS]; 197 : } perfmon_thread_runtime_t; 198 : 199 : typedef struct 200 : { 201 : perfmon_thread_runtime_t *thread_runtimes; 202 : perfmon_bundle_t *bundles; 203 : uword *bundle_by_name; 204 : perfmon_source_t *sources; 205 : uword *source_by_name; 206 : perfmon_bundle_t *active_bundle; 207 : int is_running; 208 : f64 sample_time; 209 : int *group_fds; 210 : int *fds_to_close; 211 : perfmon_instance_type_t *default_instance_type; 212 : perfmon_instance_type_t *active_instance_type; 213 : } perfmon_main_t; 214 : 215 : extern perfmon_main_t perfmon_main; 216 : 217 : #define PERFMON_BUNDLE_TYPE_TO_FLAGS(type) \ 218 : ({ \ 219 : uword rtype = 0; \ 220 : if (type == PERFMON_BUNDLE_TYPE_NODE_OR_THREAD) \ 221 : rtype = \ 222 : 1 << PERFMON_BUNDLE_TYPE_THREAD | 1 << PERFMON_BUNDLE_TYPE_NODE; \ 223 : else \ 224 : rtype = 1 << type; \ 225 : rtype; \ 226 : }) 227 : 228 : always_inline uword 229 10350 : perfmon_cpu_update_bundle_type (perfmon_bundle_t *b) 230 : { 231 10350 : perfmon_cpu_supports_t *supports = b->cpu_supports; 232 10350 : uword type = 0; 233 : 234 : /* either supports or b->type should be set, but not both */ 235 10350 : ASSERT (!!supports ^ !!b->type); 236 : 237 : /* if nothing specific for this bundle, go with the defaults */ 238 10350 : if (!supports) 239 4600 : type = PERFMON_BUNDLE_TYPE_TO_FLAGS (b->type); 240 : else 241 : { 242 : /* more than one type may be supported by a given bundle */ 243 11500 : for (int i = 0; i < b->n_cpu_supports; ++i) 244 5750 : if (supports[i].cpu_supports ()) 245 0 : type |= PERFMON_BUNDLE_TYPE_TO_FLAGS (supports[i].bundle_type); 246 : } 247 : 248 10350 : return type; 249 : } 250 : #undef PERFMON_BUNDLE_TYPE_TO_FLAGS 251 : 252 : #define PERFMON_REGISTER_SOURCE(x) \ 253 : perfmon_source_t __perfmon_source_##x; \ 254 : static void __clib_constructor __perfmon_source_registration_##x (void) \ 255 : { \ 256 : perfmon_main_t *pm = &perfmon_main; \ 257 : __perfmon_source_##x.next = pm->sources; \ 258 : pm->sources = &__perfmon_source_##x; \ 259 : } \ 260 : perfmon_source_t __perfmon_source_##x 261 : 262 : #define PERFMON_REGISTER_BUNDLE(x) \ 263 : perfmon_bundle_t __perfmon_bundle_##x; \ 264 : static void __clib_constructor __perfmon_bundle_registration_##x (void) \ 265 : { \ 266 : perfmon_main_t *pm = &perfmon_main; \ 267 : __perfmon_bundle_##x.next = pm->bundles; \ 268 : __perfmon_bundle_##x.type_flags = \ 269 : perfmon_cpu_update_bundle_type (&__perfmon_bundle_##x); \ 270 : pm->bundles = &__perfmon_bundle_##x; \ 271 : } \ 272 : perfmon_bundle_t __perfmon_bundle_##x 273 : 274 : void perfmon_reset (vlib_main_t *vm); 275 : clib_error_t *perfmon_start (vlib_main_t *vm, perfmon_bundle_t *); 276 : clib_error_t *perfmon_stop (vlib_main_t *vm); 277 : 278 : #define PERFMON_STRINGS(...) \ 279 : (char *[]) { __VA_ARGS__, 0 } 280 : 281 : #define PERFMON_COLUMN_EVENTS(...) \ 282 : (u8[]) { __VA_ARGS__ } 283 : 284 : #endif