^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #define _XOPEN_SOURCE 500 /* needed for nftw() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #define _GNU_SOURCE /* needed for asprintf() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /* Parse event JSON files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2014, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * modification, are permitted provided that the following conditions are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 1. Redistributions of source code must retain the above copyright notice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * 2. Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * notice, this list of conditions and the following disclaimer in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * documentation and/or other materials provided with the distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <libgen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <dirent.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <sys/time.h> /* getrlimit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <sys/resource.h> /* getrlimit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <ftw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include "jsmn.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include "json.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include "pmu-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int verbose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) char *prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct json_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) char *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) char *long_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) char *pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) char *unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) char *perpkg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) char *aggr_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) char *metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) char *metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) char *metric_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) char *deprecated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) char *metric_constraint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) enum aggr_mode_class convert(const char *aggr_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (!strcmp(aggr_mode, "PerCore"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return PerCore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) else if (!strcmp(aggr_mode, "PerChip"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return PerChip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) pr_err("%s: Wrong AggregationMode value '%s'\n", prog, aggr_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) typedef int (*func)(void *data, struct json_event *je);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int eprintf(int level, int var, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (var < level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret = vfprintf(stderr, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void addfield(char *map, char **dst, const char *sep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) const char *a, jsmntok_t *bt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int len = strlen(a) + 1 + strlen(sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int olen = *dst ? strlen(*dst) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int blen = bt ? json_len(bt) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) char *out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) out = realloc(*dst, len + olen + blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Don't add field in this case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *dst = out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!olen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *(*dst) = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) strcat(*dst, sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) strcat(*dst, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (bt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) strncat(*dst, map + bt->start, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static void fixname(char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) for (; *s; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *s = tolower(*s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void fixdesc(char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) char *e = s + strlen(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* Remove trailing dots that look ugly in perf list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) --e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) while (e >= s && isspace(*e))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) --e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (*e == '.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) *e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* Add escapes for '\' so they are proper C strings. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static char *fixregex(char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int esc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) char *fixed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) char *p, *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Count the number of '\' in string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) for (p = s; *p; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ++len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (*p == '\\')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ++esc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (esc_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* allocate space for a new string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) fixed = (char *) malloc(len + esc_count + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (!fixed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* copy over the characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) q = fixed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) for (p = s; *p; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (*p == '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *q = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ++q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *q = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ++q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) *q = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return fixed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static struct msrmap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) const char *num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) const char *pname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) } msrmap[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { "0x3F6", "ldlat=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { "0x1A6", "offcore_rsp=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { "0x1A7", "offcore_rsp=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { "0x3F7", "frontend=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) { NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static struct field {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) const char *field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) const char *kernel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) } fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { "UMask", "umask=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) { "CounterMask", "cmask=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { "Invert", "inv=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) { "AnyThread", "any=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { "EdgeDetect", "edge=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { "SampleAfterValue", "period=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { "FCMask", "fc_mask=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) { "PortMask", "ch_mask=" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void cut_comma(char *map, jsmntok_t *newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* Cut off everything after comma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) for (i = newval->start; i < newval->end; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (map[i] == ',')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) newval->end = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static int match_field(char *map, jsmntok_t *field, int nz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) char **event, jsmntok_t *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct field *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) jsmntok_t newval = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) for (f = fields; f->field; f++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (json_streq(map, field, f->field) && nz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) cut_comma(map, &newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) addfield(map, event, ",", f->kernel, &newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static struct msrmap *lookup_msr(char *map, jsmntok_t *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) jsmntok_t newval = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static bool warned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) cut_comma(map, &newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) for (i = 0; msrmap[i].num; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (json_streq(map, &newval, msrmap[i].num))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return &msrmap[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!warned) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) warned = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pr_err("%s: Unknown MSR in event file %.*s\n", prog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) json_len(val), map + val->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static struct map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) const char *json;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) const char *perf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) } unit_to_pmu[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) { "CBO", "uncore_cbox" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { "QPI LL", "uncore_qpi" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { "SBO", "uncore_sbox" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { "iMPH-U", "uncore_arb" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) { "CPU-M-CF", "cpum_cf" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { "CPU-M-SF", "cpum_sf" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) { "UPI LL", "uncore_upi" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) { "hisi_sccl,ddrc", "hisi_sccl,ddrc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) { "hisi_sccl,hha", "hisi_sccl,hha" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) { "hisi_sccl,l3c", "hisi_sccl,l3c" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) { "L3PMC", "amd_l3" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) { "DFPMC", "amd_df" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static const char *field_to_perf(struct map *table, char *map, jsmntok_t *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) for (i = 0; table[i].json; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (json_streq(map, val, table[i].json))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return table[i].perf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #define EXPECT(e, t, m) do { if (!(e)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) jsmntok_t *loc = (t); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (!(t)->start && (t) > tokens) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) loc = (t) - 1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) pr_err("%s:%d: " m ", got %s\n", fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) json_line(map, loc), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) json_name(t)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) err = -EIO; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) goto out_free; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) } } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static char *topic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static char *get_topic(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) char *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* tp is free'd in process_one_file() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) i = asprintf(&tp, "%s", topic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (i < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) pr_info("%s: asprintf() error %s\n", prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) for (i = 0; i < (int) strlen(tp); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) char c = tp[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (c == '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) tp[i] = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) else if (c == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) tp[i] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static int add_topic(char *bname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) free(topic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) topic = strdup(bname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (!topic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) pr_info("%s: strdup() error %s for file %s\n", prog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) strerror(errno), bname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct perf_entry_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) FILE *outfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) char *topic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) static int close_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static void print_events_table_prefix(FILE *fp, const char *tblname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) fprintf(fp, "struct pmu_event %s[] = {\n", tblname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) close_table = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static int print_events_table_entry(void *data, struct json_event *je)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct perf_entry_data *pd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) FILE *outfp = pd->outfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) char *topic = pd->topic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * TODO: Remove formatting chars after debugging to reduce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * string lengths.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) fprintf(outfp, "{\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (je->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) fprintf(outfp, "\t.name = \"%s\",\n", je->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (je->event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) fprintf(outfp, "\t.event = \"%s\",\n", je->event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) fprintf(outfp, "\t.desc = \"%s\",\n", je->desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) fprintf(outfp, "\t.topic = \"%s\",\n", topic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (je->long_desc && je->long_desc[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) fprintf(outfp, "\t.long_desc = \"%s\",\n", je->long_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (je->pmu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) fprintf(outfp, "\t.pmu = \"%s\",\n", je->pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (je->unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) fprintf(outfp, "\t.unit = \"%s\",\n", je->unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (je->perpkg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) fprintf(outfp, "\t.perpkg = \"%s\",\n", je->perpkg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (je->aggr_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) fprintf(outfp, "\t.aggr_mode = \"%d\",\n", convert(je->aggr_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (je->metric_expr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) fprintf(outfp, "\t.metric_expr = \"%s\",\n", je->metric_expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (je->metric_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) fprintf(outfp, "\t.metric_name = \"%s\",\n", je->metric_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (je->metric_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) fprintf(outfp, "\t.metric_group = \"%s\",\n", je->metric_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (je->deprecated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) fprintf(outfp, "\t.deprecated = \"%s\",\n", je->deprecated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (je->metric_constraint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) fprintf(outfp, "\t.metric_constraint = \"%s\",\n", je->metric_constraint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) fprintf(outfp, "},\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct event_struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) char *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) char *long_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) char *pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) char *unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) char *perpkg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) char *aggr_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) char *metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) char *metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) char *metric_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) char *deprecated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) char *metric_constraint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) #define ADD_EVENT_FIELD(field) do { if (je->field) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) es->field = strdup(je->field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (!es->field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) goto out_free; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) } } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #define FREE_EVENT_FIELD(field) free(es->field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) #define TRY_FIXUP_FIELD(field) do { if (es->field && !je->field) {\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) je->field = strdup(es->field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (!je->field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return -ENOMEM; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) #define FOR_ALL_EVENT_STRUCT_FIELDS(op) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) op(name); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) op(event); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) op(desc); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) op(long_desc); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) op(pmu); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) op(unit); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) op(perpkg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) op(aggr_mode); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) op(metric_expr); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) op(metric_name); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) op(metric_group); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) op(deprecated); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static LIST_HEAD(arch_std_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static void free_arch_std_events(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct event_struct *es, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) list_for_each_entry_safe(es, next, &arch_std_events, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) list_del_init(&es->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) free(es);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static int save_arch_std_events(void *data, struct json_event *je)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct event_struct *es;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) es = malloc(sizeof(*es));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (!es)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) memset(es, 0, sizeof(*es));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) FOR_ALL_EVENT_STRUCT_FIELDS(ADD_EVENT_FIELD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) list_add_tail(&es->list, &arch_std_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) free(es);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static void print_events_table_suffix(FILE *outfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) fprintf(outfp, "{\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) fprintf(outfp, "\t.name = 0,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) fprintf(outfp, "\t.event = 0,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) fprintf(outfp, "\t.desc = 0,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) fprintf(outfp, "},\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) fprintf(outfp, "};\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) close_table = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static struct fixed {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) const char *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) } fixed[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) { "inst_retired.any", "event=0xc0,period=2000003" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) { "inst_retired.any_p", "event=0xc0,period=2000003" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03,period=2000003" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) { "cpu_clk_unhalted.thread", "event=0x3c,period=2000003" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) { "cpu_clk_unhalted.core", "event=0x3c,period=2000003" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1,period=2000003" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) { NULL, NULL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * Handle different fixed counter encodings between JSON and perf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static char *real_event(const char *name, char *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) for (i = 0; fixed[i].name; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (!strcasecmp(name, fixed[i].name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return (char *)fixed[i].event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) try_fixup(const char *fn, char *arch_std, struct json_event *je, char **event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* try to find matching event from arch standard values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) struct event_struct *es;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) list_for_each_entry(es, &arch_std_events, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (!strcmp(arch_std, es->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) FOR_ALL_EVENT_STRUCT_FIELDS(TRY_FIXUP_FIELD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) *event = je->event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) pr_err("%s: could not find matching %s for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) prog, arch_std, fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /* Call func with each event in the json file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static int json_events(const char *fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) int (*func)(void *data, struct json_event *je),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) jsmntok_t *tokens, *tok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int i, j, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) char *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) char buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) tokens = parse_json(fn, &map, &size, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (!tokens)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) EXPECT(tokens->type == JSMN_ARRAY, tokens, "expected top level array");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) tok = tokens + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) for (i = 0; i < tokens->size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) char *event = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) char *extra_desc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) char *filter = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) struct json_event je = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) char *arch_std = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) unsigned long long eventcode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct msrmap *msr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) jsmntok_t *msrval = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) jsmntok_t *precise = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) jsmntok_t *obj = tok++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) EXPECT(obj->type == JSMN_OBJECT, obj, "expected object");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) for (j = 0; j < obj->size; j += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) jsmntok_t *field, *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int nz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) field = tok + j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) EXPECT(field->type == JSMN_STRING, tok + j,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) "Expected field name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) val = tok + j + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) EXPECT(val->type == JSMN_STRING, tok + j + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) "Expected string value");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) nz = !json_streq(map, val, "0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (match_field(map, field, nz, &event, val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /* ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) } else if (json_streq(map, field, "EventCode")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) char *code = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) addfield(map, &code, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) eventcode |= strtoul(code, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) free(code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) } else if (json_streq(map, field, "ExtSel")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) char *code = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) addfield(map, &code, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) eventcode |= strtoul(code, NULL, 0) << 21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) free(code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) } else if (json_streq(map, field, "EventName")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) addfield(map, &je.name, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) } else if (json_streq(map, field, "BriefDescription")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) addfield(map, &je.desc, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) fixdesc(je.desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) } else if (json_streq(map, field,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) "PublicDescription")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) addfield(map, &je.long_desc, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) fixdesc(je.long_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) } else if (json_streq(map, field, "PEBS") && nz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) precise = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) } else if (json_streq(map, field, "MSRIndex") && nz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) msr = lookup_msr(map, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) } else if (json_streq(map, field, "MSRValue")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) msrval = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) } else if (json_streq(map, field, "Errata") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) !json_streq(map, val, "null")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) addfield(map, &extra_desc, ". ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) " Spec update: ", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) } else if (json_streq(map, field, "Data_LA") && nz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) addfield(map, &extra_desc, ". ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) " Supports address when precise",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) } else if (json_streq(map, field, "Unit")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) const char *ppmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ppmu = field_to_perf(unit_to_pmu, map, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (ppmu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) je.pmu = strdup(ppmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (!je.pmu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) je.pmu = strdup("uncore_");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) addfield(map, &je.pmu, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) for (s = je.pmu; *s; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) *s = tolower(*s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) addfield(map, &je.desc, ". ", "Unit: ", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) addfield(map, &je.desc, "", je.pmu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) addfield(map, &je.desc, "", " ", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) } else if (json_streq(map, field, "Filter")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) addfield(map, &filter, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) } else if (json_streq(map, field, "ScaleUnit")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) addfield(map, &je.unit, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) } else if (json_streq(map, field, "PerPkg")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) addfield(map, &je.perpkg, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) } else if (json_streq(map, field, "AggregationMode")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) addfield(map, &je.aggr_mode, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) } else if (json_streq(map, field, "Deprecated")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) addfield(map, &je.deprecated, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) } else if (json_streq(map, field, "MetricName")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) addfield(map, &je.metric_name, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) } else if (json_streq(map, field, "MetricGroup")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) addfield(map, &je.metric_group, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) } else if (json_streq(map, field, "MetricConstraint")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) addfield(map, &je.metric_constraint, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) } else if (json_streq(map, field, "MetricExpr")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) addfield(map, &je.metric_expr, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) for (s = je.metric_expr; *s; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) *s = tolower(*s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) } else if (json_streq(map, field, "ArchStdEvent")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) addfield(map, &arch_std, "", "", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) for (s = arch_std; *s; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) *s = tolower(*s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* ignore unknown fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (precise && je.desc && !strstr(je.desc, "(Precise Event)")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (json_streq(map, precise, "2"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) addfield(map, &extra_desc, " ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) "(Must be precise)", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) addfield(map, &extra_desc, " ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) "(Precise event)", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) snprintf(buf, sizeof buf, "event=%#llx", eventcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) addfield(map, &event, ",", buf, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (je.desc && extra_desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) addfield(map, &je.desc, " ", extra_desc, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (je.long_desc && extra_desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) addfield(map, &je.long_desc, " ", extra_desc, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) addfield(map, &event, ",", filter, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (msr != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) addfield(map, &event, ",", msr->pname, msrval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (je.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) fixname(je.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (arch_std) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * An arch standard event is referenced, so try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * fixup any unassigned values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) err = try_fixup(fn, arch_std, &je, &event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) goto free_strings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) je.event = real_event(je.name, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) err = func(data, &je);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) free_strings:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) free(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) free(je.desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) free(je.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) free(je.long_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) free(extra_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) free(je.pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) free(filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) free(je.perpkg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) free(je.aggr_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) free(je.deprecated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) free(je.unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) free(je.metric_expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) free(je.metric_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) free(je.metric_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) free(je.metric_constraint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) free(arch_std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) tok += j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) EXPECT(tok - tokens == len, tok, "unexpected objects at end");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) free_json(map, size, tokens);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static char *file_name_to_table_name(char *fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) char *tblname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * Ensure tablename starts with alphabetic character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * Derive rest of table name from basename of the JSON file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * replacing hyphens and stripping out .json suffix.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) n = asprintf(&tblname, "pme_%s", fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (n < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) pr_info("%s: asprintf() error %s for file %s\n", prog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) strerror(errno), fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) for (i = 0; i < strlen(tblname); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) c = tblname[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (c == '-' || c == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) tblname[i] = '_';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) else if (c == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) tblname[i] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) } else if (!isalnum(c) && c != '_') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) pr_err("%s: Invalid character '%c' in file name %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) prog, c, basename(fname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) free(tblname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) tblname = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return tblname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static void print_mapping_table_prefix(FILE *outfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) fprintf(outfp, "struct pmu_events_map pmu_events_map[] = {\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) static void print_mapping_table_suffix(FILE *outfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * Print the terminating, NULL entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) fprintf(outfp, "{\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) fprintf(outfp, "\t.cpuid = 0,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) fprintf(outfp, "\t.version = 0,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) fprintf(outfp, "\t.type = 0,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) fprintf(outfp, "\t.table = 0,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) fprintf(outfp, "},\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /* and finally, the closing curly bracket for the struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) fprintf(outfp, "};\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static void print_mapping_test_table(FILE *outfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * Print the terminating, NULL entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) fprintf(outfp, "{\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) fprintf(outfp, "\t.cpuid = \"testcpu\",\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) fprintf(outfp, "\t.version = \"v1\",\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) fprintf(outfp, "\t.type = \"core\",\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) fprintf(outfp, "\t.table = pme_test_cpu,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) fprintf(outfp, "},\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static int process_mapfile(FILE *outfp, char *fpath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) int n = 16384;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) FILE *mapfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) char *save = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) char *line, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) int line_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) char *tblname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) pr_info("%s: Processing mapfile %s\n", prog, fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) line = malloc(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (!line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) mapfp = fopen(fpath, "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (!mapfp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) pr_info("%s: Error %s opening %s\n", prog, strerror(errno),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) free(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) print_mapping_table_prefix(outfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) /* Skip first line (header) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) p = fgets(line, n, mapfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) line_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) char *cpuid, *version, *type, *fname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) line_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) p = fgets(line, n, mapfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (line[0] == '#' || line[0] == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (line[strlen(line)-1] != '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /* TODO Deal with lines longer than 16K */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) pr_info("%s: Mapfile %s: line %d too long, aborting\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) prog, fpath, line_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) line[strlen(line)-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) cpuid = fixregex(strtok_r(p, ",", &save));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) version = strtok_r(NULL, ",", &save);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) fname = strtok_r(NULL, ",", &save);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) type = strtok_r(NULL, ",", &save);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) tblname = file_name_to_table_name(fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) fprintf(outfp, "{\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) fprintf(outfp, "\t.cpuid = \"%s\",\n", cpuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) fprintf(outfp, "\t.version = \"%s\",\n", version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) fprintf(outfp, "\t.type = \"%s\",\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * CHECK: We can't use the type (eg "core") field in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * table name. For us to do that, we need to somehow tweak
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * the other caller of file_name_to_table(), process_json()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * to determine the type. process_json() file has no way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * of knowing these are "core" events unless file name has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * core in it. If filename has core in it, we can safely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * ignore the type field here also.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) fprintf(outfp, "\t.table = %s\n", tblname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) fprintf(outfp, "},\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) print_mapping_test_table(outfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) print_mapping_table_suffix(outfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) fclose(mapfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) free(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * If we fail to locate/process JSON and map files, create a NULL mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * table. This would at least allow perf to build even if we can't find/use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * the aliases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static void create_empty_mapping(const char *output_file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) FILE *outfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) pr_info("%s: Creating empty pmu_events_map[] table\n", prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* Truncate file to clear any partial writes to it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) outfp = fopen(output_file, "w");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (!outfp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) perror("fopen()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) _Exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) fprintf(outfp, "#include \"pmu-events/pmu-events.h\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) print_mapping_table_prefix(outfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) print_mapping_table_suffix(outfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) fclose(outfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static int get_maxfds(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct rlimit rlim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return min(rlim.rlim_max / 2, (rlim_t)512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * nftw() doesn't let us pass an argument to the processing function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * so use a global variables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static FILE *eventsfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) static char *mapfile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static int is_leaf_dir(const char *fpath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) DIR *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) struct dirent *dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) int res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) d = opendir(fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (!d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) while ((dir = readdir(d)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (dir->d_type == DT_DIR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) } else if (dir->d_type == DT_UNKNOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) char path[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) struct stat st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) sprintf(path, "%s/%s", fpath, dir->d_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (stat(path, &st))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (S_ISDIR(st.st_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) closedir(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) static int is_json_file(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) const char *suffix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (strlen(name) < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) suffix = name + strlen(name) - 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (strncmp(suffix, ".json", 5) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) static int preprocess_arch_std_files(const char *fpath, const struct stat *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) int typeflag, struct FTW *ftwbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) int level = ftwbuf->level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) int is_file = typeflag == FTW_F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (level == 1 && is_file && is_json_file(fpath))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return json_events(fpath, save_arch_std_events, (void *)sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) static int process_one_file(const char *fpath, const struct stat *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) int typeflag, struct FTW *ftwbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) char *tblname, *bname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) int is_dir = typeflag == FTW_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) int is_file = typeflag == FTW_F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) int level = ftwbuf->level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (level == 2 && is_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) * For level 2 directory, bname will include parent name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) * like vendor/platform. So search back from platform dir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * to find this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) bname = (char *) fpath + ftwbuf->base - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (*bname == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) bname--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) bname++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) bname = (char *) fpath + ftwbuf->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) pr_debug("%s %d %7jd %-20s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) is_file ? "f" : is_dir ? "d" : "x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) level, sb->st_size, bname, fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /* base dir or too deep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (level == 0 || level > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* model directory, reset topic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if ((level == 1 && is_dir && is_leaf_dir(fpath)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) (level == 2 && is_dir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (close_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) print_events_table_suffix(eventsfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * Drop file name suffix. Replace hyphens with underscores.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * Fail if file name contains any alphanum characters besides
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * underscores.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) tblname = file_name_to_table_name(bname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (!tblname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) pr_info("%s: Error determining table name for %s\n", prog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) bname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) print_events_table_prefix(eventsfp, tblname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * Save the mapfile name for now. We will process mapfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * after processing all JSON files (so we can write out the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * mapping table after all PMU events tables).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (level == 1 && is_file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (!strcmp(bname, "mapfile.csv")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) mapfile = strdup(fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) pr_info("%s: Ignoring file %s\n", prog, fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * If the file name does not have a .json extension,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * ignore it. It could be a readme.txt for instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (is_file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (!is_json_file(bname)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) pr_info("%s: Ignoring file without .json suffix %s\n", prog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (level > 1 && add_topic(bname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * Assume all other files are JSON files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * If mapfile refers to 'power7_core.json', we create a table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) * named 'power7_core'. Any inconsistencies between the mapfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * and directory tree could result in build failure due to table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * names not being found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * Atleast for now, be strict with processing JSON file names.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * i.e. if JSON file name cannot be mapped to C-style table name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (is_file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) struct perf_entry_data data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) .topic = get_topic(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) .outfp = eventsfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) err = json_events(fpath, print_events_table_entry, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) free(data.topic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) #ifndef PATH_MAX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) #define PATH_MAX 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) * Starting in directory 'start_dirname', find the "mapfile.csv" and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) * the set of JSON files for the architecture 'arch'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * From each JSON file, create a C-style "PMU events table" from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) * JSON file (see struct pmu_event).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) * From the mapfile, create a mapping between the CPU revisions and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * PMU event tables (see struct pmu_events_map).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * Write out the PMU events tables and the mapping table to pmu-event.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) int main(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) int rc, ret = 0, empty_map = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) int maxfds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) char ldirname[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) const char *arch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) const char *output_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) const char *start_dirname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) char *err_string_ext = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) struct stat stbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) prog = basename(argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (argc < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) pr_err("Usage: %s <arch> <starting_dir> <output_file>\n", prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) arch = argv[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) start_dirname = argv[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) output_file = argv[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (argc > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) verbose = atoi(argv[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) eventsfp = fopen(output_file, "w");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (!eventsfp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) pr_err("%s Unable to create required file %s (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) prog, output_file, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) sprintf(ldirname, "%s/%s", start_dirname, arch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) /* If architecture does not have any event lists, bail out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (stat(ldirname, &stbuf) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) pr_info("%s: Arch %s has no PMU event lists\n", prog, arch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) empty_map = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) goto err_close_eventsfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) /* Include pmu-events.h first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) fprintf(eventsfp, "#include \"pmu-events/pmu-events.h\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * The mapfile allows multiple CPUids to point to the same JSON file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) * so, not sure if there is a need for symlinks within the pmu-events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * For now, treat symlinks of JSON files as regular files and create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * separate tables for each symlink (presumably, each symlink refers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) * to specific version of the CPU).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) maxfds = get_maxfds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) rc = nftw(ldirname, preprocess_arch_std_files, maxfds, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) goto err_processing_std_arch_event_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) rc = nftw(ldirname, process_one_file, maxfds, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) goto err_processing_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) sprintf(ldirname, "%s/test", start_dirname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) rc = nftw(ldirname, process_one_file, maxfds, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) goto err_processing_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (close_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) print_events_table_suffix(eventsfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (!mapfile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) pr_info("%s: No CPU->JSON mapping?\n", prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) empty_map = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) goto err_close_eventsfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) rc = process_mapfile(eventsfp, mapfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) fclose(eventsfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) pr_info("%s: Error processing mapfile %s\n", prog, mapfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) /* Make build fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) free_arch_std_events();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) free(mapfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) err_processing_std_arch_event_dir:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) err_string_ext = " for std arch event";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) err_processing_dir:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (verbose) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) pr_info("%s: Error walking file tree %s%s\n", prog, ldirname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) err_string_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) empty_map = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) } else if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) empty_map = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) err_close_eventsfp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) fclose(eventsfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (empty_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) create_empty_mapping(output_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) free_arch_std_events();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) free(mapfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }