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 <perfmon/perfmon.h>
18 #include <perfmon/intel/core.h>
19 #include <perfmon/intel/dispatch_wrapper.h>
20 #include <linux/perf_event.h>
22 static perfmon_event_t events[] = {
23 #define _(event, umask, edge, any, inv, cmask, n, suffix, desc) \
24 [INTEL_CORE_E_##n##_##suffix] = { .type = PERF_TYPE_RAW, \
25 .config = PERF_INTEL_CODE ( \
26 event, umask, edge, any, inv, cmask), \
27 .name = #n "." #suffix, \
28 .description = desc, \
30 .exclude_kernel = 1 },
32 foreach_perf_intel_core_event foreach_perf_intel_peusdo_event
33 foreach_perf_intel_tremont_event
39 format_intel_core_config (u8 *s, va_list *args)
41 u64 config = va_arg (*args, u64);
44 s = format (s, "event=0x%02x, umask=0x%02x", config & 0xff,
45 (config >> 8) & 0xff);
47 if ((v = (config >> 18) & 1))
48 s = format (s, ", edge=%u", v);
50 if ((v = (config >> 19) & 1))
51 s = format (s, ", pc=%u", v);
53 if ((v = (config >> 21) & 1))
54 s = format (s, ", any=%u", v);
56 if ((v = (config >> 23) & 1))
57 s = format (s, ", inv=%u", v);
59 if ((v = (config >> 24) & 0xff))
60 s = format (s, ", cmask=0x%02x", v);
62 /* show the raw config, for convenience sake */
63 if (!((config >> 16) & 0xffff))
64 s = format (s, ", raw=r%x", config & 0xffff);
70 intel_core_init (vlib_main_t *vm, perfmon_source_t *src)
72 u32 eax, ebx, ecx, edx;
73 if (__get_cpuid (0, &eax, &ebx, &ecx, &edx) == 0)
74 return clib_error_return (0, "unknown CPU (missing cpuid)");
77 if (ebx != 0x756e6547 || ecx != 0x6c65746e || edx != 0x49656e69)
78 return clib_error_return (0, "not a IA-32 CPU");
83 intel_core_get_event_type (u32 event)
85 u64 config = events[event].config;
86 u8 eventcode = (config & 0xFF);
87 u8 umask = ((config >> 8) & 0xFF);
89 if (!eventcode) /* is fixed or pseudo */
91 if (umask >= 0x80) /* is pseudo */
92 return PERFMON_EVENT_TYPE_PSEUDO;
94 return PERFMON_EVENT_TYPE_FIXED;
97 return PERFMON_EVENT_TYPE_GENERAL;
101 is_enough_counters (perfmon_bundle_t *b)
103 u8 bl[PERFMON_EVENT_TYPE_MAX];
104 u8 cpu[PERFMON_EVENT_TYPE_MAX];
106 clib_memset (&bl, 0, sizeof (bl));
107 clib_memset (&cpu, 0, sizeof (cpu));
109 /* how many does this uarch support */
110 if (!clib_get_pmu_counter_count (&cpu[PERFMON_EVENT_TYPE_FIXED],
111 &cpu[PERFMON_EVENT_TYPE_GENERAL]))
114 /* how many does the bundle require */
115 for (u16 i = 0; i < b->n_events; i++)
117 /* if source allows us to identify events, otherwise assume general */
118 if (b->src->get_event_type)
119 bl[b->src->get_event_type (b->events[i])]++;
121 bl[PERFMON_EVENT_TYPE_GENERAL]++;
124 /* consciously ignoring pseudo events here */
125 return cpu[PERFMON_EVENT_TYPE_GENERAL] >= bl[PERFMON_EVENT_TYPE_GENERAL] &&
126 cpu[PERFMON_EVENT_TYPE_FIXED] >= bl[PERFMON_EVENT_TYPE_FIXED];
130 intel_bundle_supported (perfmon_bundle_t *b)
132 perfmon_cpu_supports_t *supports = b->cpu_supports;
134 if (!is_enough_counters (b))
137 if (!b->cpu_supports)
140 for (int i = 0; i < b->n_cpu_supports; ++i)
141 if (supports[i].cpu_supports ())
147 PERFMON_REGISTER_SOURCE (intel_core) = {
148 .name = "intel-core",
149 .description = "intel arch core events",
151 .n_events = ARRAY_LEN (events),
152 .init_fn = intel_core_init,
153 .get_event_type = intel_core_get_event_type,
154 .format_config = format_intel_core_config,
155 .bundle_support = intel_bundle_supported,
156 .config_dispatch_wrapper = intel_config_dispatch_wrapper,