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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/vnet.h>
17 #include <vppinfra/linux/sysfs.h>
18 #include <perfmon/perfmon.h>
19 #include <perfmon/intel/core.h>
20 #include <perfmon/intel/uncore.h>
22 VLIB_REGISTER_LOG_CLASS (if_intel_uncore_log, static) = {
23 .class_name = "perfmon",
24 .subclass_name = "intel-uncore",
27 #define log_debug(fmt, ...) \
28 vlib_log_debug (if_intel_uncore_log.class, fmt, __VA_ARGS__)
29 #define log_warn(fmt, ...) \
30 vlib_log_warn (if_intel_uncore_log.class, fmt, __VA_ARGS__)
31 #define log_err(fmt, ...) \
32 vlib_log_err (if_intel_uncore_log.class, fmt, __VA_ARGS__)
34 #define PERF_INTEL_CODE(event, umask, edge, any, inv, cmask) \
35 ((event) | (umask) << 8 | (edge) << 18 | (any) << 21 | (inv) << 23 | \
38 static perfmon_event_t intel_uncore_events[] = {
39 #define _(unit, event, umask, n, suffix, desc) \
40 [INTEL_UNCORE_E_##unit##_##n##_##suffix] = { \
41 .config = (event) | (umask) << 8, \
42 .name = #n "." #suffix, \
43 .description = desc, \
44 .type_from_instance = 1, \
45 .instance_type = INTEL_UNCORE_UNIT_##unit, \
48 foreach_intel_uncore_event
53 intel_uncore_instance_name_cmp (void *v1, void *v2)
55 perfmon_instance_t *i1 = v1;
56 perfmon_instance_t *i2 = v2;
57 return strcmp (i1->name, i2->name);
61 intel_uncore_add_unit (perfmon_source_t *src, intel_uncore_unit_type_t u,
62 char *name, char *type_str, char *fmt,
63 int *socket_by_cpu_id)
65 static char *base_path = "/sys/bus/event_source/devices/uncore";
67 clib_bitmap_t *cpumask = 0;
68 perfmon_instance_t *in;
69 perfmon_instance_type_t *it;
74 vec_validate (src->instances_by_type, u);
75 it = vec_elt_at_index (src->instances_by_type, u);
80 s = format (s, "%s_%s_%u/type%c", base_path, name, i, 0);
81 if ((err = clib_sysfs_read ((char *) s, "%u", &perf_type)))
85 s = format (s, "%s_%s_%u/cpumask%c", base_path, name, i, 0);
86 if ((err = clib_sysfs_read ((char *) s, "%U", unformat_bitmap_list,
91 clib_bitmap_foreach (j, cpumask)
93 vec_add2 (it->instances, in, 1);
97 in->name = (char *) format (0, fmt, socket_by_cpu_id[j], i);
98 vec_terminate_c_string (in->name);
99 log_debug ("found %s %s", type_str, in->name);
103 clib_error_free (err);
104 clib_bitmap_free (cpumask);
108 static clib_error_t *
109 intel_uncore_init (vlib_main_t *vm, perfmon_source_t *src)
111 clib_error_t *err = 0;
112 clib_bitmap_t *node_bitmap = 0, *cpumask = 0;
113 int *numa_by_cpu_id = 0;
117 if ((err = clib_sysfs_read ("/sys/devices/system/node/has_cpu", "%U",
118 unformat_bitmap_list, &node_bitmap)))
120 clib_error_free (err);
121 return clib_error_return (0, "failed to discover numa topology");
124 clib_bitmap_foreach (i, node_bitmap)
126 s = format (s, "/sys/devices/system/node/node%u/cpulist%c", i, 0);
127 if ((err = clib_sysfs_read ((char *) s, "%U", unformat_bitmap_list,
130 clib_error_free (err);
131 err = clib_error_return (0, "failed to discover numa topology");
135 clib_bitmap_foreach (j, cpumask)
137 vec_validate_init_empty (numa_by_cpu_id, j, -1);
138 numa_by_cpu_id[j] = i;
140 clib_bitmap_free (cpumask);
141 vec_reset_length (s);
144 #define _(t, n, name, fmt) \
145 intel_uncore_add_unit (src, INTEL_UNCORE_UNIT_##t, n, name, fmt, \
147 foreach_intel_uncore_unit_type;
150 for (i = 0, j = 0; i < vec_len (src->instances_by_type); i++)
152 perfmon_instance_type_t *it;
154 it = vec_elt_at_index (src->instances_by_type, i);
155 vec_sort_with_function (it->instances, intel_uncore_instance_name_cmp);
156 j += vec_len (it->instances);
161 vec_free (src->instances_by_type);
162 return clib_error_return (0, "no uncore units found");
168 vec_free (node_bitmap);
169 vec_free (numa_by_cpu_id);
173 format_function_t format_intel_core_config;
175 PERFMON_REGISTER_SOURCE (intel_uncore) = {
176 .name = "intel-uncore",
177 .description = "intel uncore events",
178 .events = intel_uncore_events,
179 .n_events = INTEL_UNCORE_N_EVENTS,
180 .init_fn = intel_uncore_init,
181 .format_config = format_intel_core_config,