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 intel_uncore_unit_type_names_t uncore_unit_names[] = {
39 { INTEL_UNCORE_UNIT_IIO,
40 PERFMON_STRINGS ("PCIe0", "PCIe1", "MCP", "PCIe2", "PCIe3", "CBDMA/DMI") }
43 static perfmon_event_t intel_uncore_events[] = {
44 #define _(unit, event, umask, ch_mask, fc_mask, n, suffix, desc) \
45 [INTEL_UNCORE_E_##unit##_##n##_##suffix] = { \
47 (event) | (umask) << 8 | (u64) (ch_mask) << 36 | (u64) (fc_mask) << 48, \
48 .name = #n "." #suffix, \
49 .description = desc, \
50 .type_from_instance = 1, \
51 .instance_type = INTEL_UNCORE_UNIT_##unit, \
55 foreach_intel_uncore_event
60 intel_uncore_instance_name_cmp (void *v1, void *v2)
62 perfmon_instance_t *i1 = v1;
63 perfmon_instance_t *i2 = v2;
64 return strcmp (i1->name, i2->name);
68 format_instance_name (intel_uncore_unit_type_t u, char *unit_fmt, u8 socket_id,
73 /* uncore ubox may have specific names */
74 for (u8 i = 0; i < ARRAY_LEN (uncore_unit_names); i++)
76 intel_uncore_unit_type_names_t *n = &uncore_unit_names[i];
78 if (n->unit_type == u)
82 fmt = format (0, "%s (%s)%c", unit_fmt, (n->unit_names[ubox]), 0);
83 s = format (0, (char *) fmt, socket_id, ubox);
90 return format (0, unit_fmt, socket_id, ubox);
94 intel_uncore_add_unit (perfmon_source_t *src, intel_uncore_unit_type_t u,
95 char *name, char *type_str, char *fmt,
96 int *socket_by_cpu_id)
98 static char *base_path = "/sys/bus/event_source/devices/uncore";
100 clib_bitmap_t *cpumask = 0;
101 perfmon_instance_t *in;
102 perfmon_instance_type_t *it;
107 vec_validate (src->instances_by_type, u);
108 it = vec_elt_at_index (src->instances_by_type, u);
113 s = format (s, "%s_%s_%u/type%c", base_path, name, i, 0);
114 if ((err = clib_sysfs_read ((char *) s, "%u", &perf_type)))
116 vec_reset_length (s);
118 s = format (s, "%s_%s_%u/cpumask%c", base_path, name, i, 0);
119 if ((err = clib_sysfs_read ((char *) s, "%U", unformat_bitmap_list,
122 vec_reset_length (s);
124 clib_bitmap_foreach (j, cpumask)
126 vec_add2 (it->instances, in, 1);
127 in->type = perf_type;
131 (char *) format_instance_name (u, fmt, socket_by_cpu_id[j], i);
132 vec_terminate_c_string (in->name);
133 log_debug ("found %s %s", type_str, in->name);
137 clib_error_free (err);
138 clib_bitmap_free (cpumask);
142 static clib_error_t *
143 intel_uncore_init (vlib_main_t *vm, perfmon_source_t *src)
145 clib_error_t *err = 0;
146 clib_bitmap_t *node_bitmap = 0, *cpumask = 0;
147 int *numa_by_cpu_id = 0;
151 if ((err = clib_sysfs_read ("/sys/devices/system/node/online", "%U",
152 unformat_bitmap_list, &node_bitmap)))
154 clib_error_free (err);
155 return clib_error_return (0, "failed to discover numa topology");
158 clib_bitmap_foreach (i, node_bitmap)
160 s = format (s, "/sys/devices/system/node/node%u/cpulist%c", i, 0);
161 if ((err = clib_sysfs_read ((char *) s, "%U", unformat_bitmap_list,
164 clib_error_free (err);
165 err = clib_error_return (0, "failed to discover numa topology");
171 clib_error_free (err);
172 err = clib_error_return (
173 0, "while discovering numa topology: cpumask unexpectedly NULL");
177 clib_bitmap_foreach (j, cpumask)
179 vec_validate_init_empty (numa_by_cpu_id, j, -1);
180 numa_by_cpu_id[j] = i;
182 clib_bitmap_free (cpumask);
183 vec_reset_length (s);
186 #define _(t, n, name, fmt) \
187 intel_uncore_add_unit (src, INTEL_UNCORE_UNIT_##t, n, name, fmt, \
189 foreach_intel_uncore_unit_type;
192 for (i = 0, j = 0; i < vec_len (src->instances_by_type); i++)
194 perfmon_instance_type_t *it;
196 it = vec_elt_at_index (src->instances_by_type, i);
197 vec_sort_with_function (it->instances, intel_uncore_instance_name_cmp);
198 j += vec_len (it->instances);
203 vec_free (src->instances_by_type);
204 return clib_error_return (0, "no uncore units found");
210 vec_free (node_bitmap);
211 vec_free (numa_by_cpu_id);
215 format_function_t format_intel_core_config;
217 PERFMON_REGISTER_SOURCE (intel_uncore) = {
218 .name = "intel-uncore",
219 .description = "intel uncore events",
220 .events = intel_uncore_events,
221 .n_events = INTEL_UNCORE_N_EVENTS,
222 .init_fn = intel_uncore_init,
223 .format_config = format_intel_core_config,
224 .bundle_support = intel_bundle_supported,