1 /* SPDX-License-Identifier: Apache-2.0
2 * Copyright(c) 2021 Cisco Systems, Inc.
5 #include <vppinfra/format.h>
6 #include <vppinfra/vector/test/test.h>
7 #include <vppinfra/error.h>
12 test_march_supported (clib_march_variant_type_t type)
15 if (CLIB_MARCH_VARIANT_TYPE_##s == type) \
16 return clib_cpu_march_priority_##s ();
23 test_funct (test_main_t *tm)
25 for (int i = 0; i < CLIB_MARCH_TYPE_N_VARIANTS; i++)
27 test_registration_t *r = tm->registrations[i];
29 if (r == 0 || test_march_supported (i) < 0)
32 fformat (stdout, "\nMultiarch Variant: %U\n", format_march_variant, i);
34 "-------------------------------------------------------\n");
38 if (tm->filter && strstr (r->name, (char *) tm->filter) == 0)
41 fformat (stdout, "%-50s %s\n", r->name, err ? "FAIL" : "PASS");
44 clib_error_report (err);
45 fformat (stdout, "\n");
52 fformat (stdout, "\n");
56 #define TEST_PERF_MAX_EVENTS 7
59 u64 config[TEST_PERF_MAX_EVENTS];
61 format_function_t *format_fn;
62 } test_perf_event_bundle_t;
65 format_test_perf_bundle_default (u8 *s, va_list *args)
67 test_perf_event_bundle_t __clib_unused *b =
68 va_arg (*args, test_perf_event_bundle_t *);
69 test_perf_t *tp = va_arg (*args, test_perf_t *);
70 u64 *data = va_arg (*args, u64 *);
73 s = format (s, "%5.2f", (f64) data[1] / data[0]);
75 s = format (s, "%5s", "IPC");
78 s = format (s, "%8.2f", (f64) data[0] / tp->n_ops);
80 s = format (s, "%8s", "Clks/Op");
83 s = format (s, "%8.2f", (f64) data[1] / tp->n_ops);
85 s = format (s, "%8s", "Inst/Op");
88 s = format (s, "%9.2f", (f64) data[2] / tp->n_ops);
90 s = format (s, "%9s", "Brnch/Op");
93 s = format (s, "%10.2f", (f64) data[3] / tp->n_ops);
95 s = format (s, "%10s", "BrMiss/Op");
99 test_perf_event_bundle_t perf_bundles[] = { {
100 .config[0] = PERF_COUNT_HW_CPU_CYCLES,
101 .config[1] = PERF_COUNT_HW_INSTRUCTIONS,
102 .config[2] = PERF_COUNT_HW_BRANCH_INSTRUCTIONS,
103 .config[3] = PERF_COUNT_HW_BRANCH_MISSES,
105 .format_fn = format_test_perf_bundle_default,
110 test_perf (test_main_t *tm)
112 clib_error_t *err = 0;
113 test_perf_event_bundle_t *b = perf_bundles;
114 int group_fd = -1, fds[TEST_PERF_MAX_EVENTS];
115 u64 count[TEST_PERF_MAX_EVENTS + 3] = {};
116 struct perf_event_attr pe = {
117 .size = sizeof (struct perf_event_attr),
118 .type = PERF_TYPE_HARDWARE,
124 .read_format = (PERF_FORMAT_GROUP | PERF_FORMAT_TOTAL_TIME_ENABLED |
125 PERF_FORMAT_TOTAL_TIME_RUNNING),
128 for (int i = 0; i < TEST_PERF_MAX_EVENTS; i++)
131 for (int i = 0; i < b->n_events; i++)
133 pe.config = b->config[i];
134 int fd = syscall (__NR_perf_event_open, &pe, /* pid */ 0, /* cpu */ -1,
135 /* group_fd */ group_fd, /* flags */ 0);
138 err = clib_error_return_unix (0, "perf_event_open");
151 for (int i = 0; i < CLIB_MARCH_TYPE_N_VARIANTS; i++)
153 test_registration_t *r = tm->registrations[i];
155 if (r == 0 || test_march_supported (i) < 0)
158 fformat (stdout, "\nMultiarch Variant: %U\n", format_march_variant, i);
160 "-------------------------------------------------------\n");
165 test_perf_t *pt = r->perf_tests;
166 if (tm->filter && strstr (r->name, (char *) tm->filter) == 0)
168 fformat (stdout, "%-22s%-12s%U\n", r->name, "OpType",
169 b->format_fn, b, pt, 0UL);
172 u32 read_size = (b->n_events + 3) * sizeof (u64);
173 for (int i = 0; i < tm->repeat; i++)
175 test_perf_event_reset (group_fd);
176 pt->fn (group_fd, pt);
177 if ((read (group_fd, &count, read_size) != read_size))
179 err = clib_error_return_unix (0, "read");
182 if (count[1] != count[2])
184 "perf counters were not running all the time."
186 "\nConsider turning NMI watchdog off ('sysctl -w "
187 "kernel.nmi_watchdog=0')."
190 fformat (stdout, " %-20s%-12s%U\n", pt->name,
191 pt->op_name ? pt->op_name : "", b->format_fn, b,
203 for (int i = 0; i < TEST_PERF_MAX_EVENTS; i++)
211 main (int argc, char *argv[])
213 test_main_t *tm = &test_main;
214 unformat_input_t _i = {}, *i = &_i;
215 clib_mem_init (0, 64ULL << 20);
222 unformat_init_command_line (i, argv);
224 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
226 if (unformat (i, "perf"))
228 else if (unformat (i, "filter %s", &tm->filter))
230 else if (unformat (i, "repeat %d", &tm->repeat))
234 clib_warning ("unknown input '%U'", format_unformat_error, i);
240 err = test_perf (tm);
242 err = test_funct (tm);
246 clib_error_report (err);
247 fformat (stderr, "\n");
254 test_mem_alloc (uword size)
257 size = round_pow2 (size, CLIB_CACHE_LINE_BYTES);
258 rv = clib_mem_alloc_aligned (size, CLIB_CACHE_LINE_BYTES);
259 clib_memset_u8 (rv, 0, size);
264 test_mem_alloc_and_fill_inc_u8 (uword size, u8 start, u8 mask)
267 mask = mask ? mask : 0xff;
268 size = round_pow2 (size, CLIB_CACHE_LINE_BYTES);
269 rv = clib_mem_alloc_aligned (size, CLIB_CACHE_LINE_BYTES);
270 for (uword i = 0; i < size; i++)
271 rv[i] = ((u8) i + start) & mask;
276 test_mem_alloc_and_splat (uword elt_size, uword n_elts, void *elt)
279 uword data_size = elt_size * n_elts;
280 uword alloc_size = round_pow2 (data_size, CLIB_CACHE_LINE_BYTES);
281 e = rv = clib_mem_alloc_aligned (alloc_size, CLIB_CACHE_LINE_BYTES);
282 while (e - rv < data_size)
284 clib_memcpy_fast (e, elt, elt_size);
288 if (data_size < alloc_size)
289 clib_memset_u8 (e, 0, alloc_size - data_size);
294 test_mem_free (void *p)