Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf jevents: Remove jevents.c

Remove files and build rules.

Remove test for comparing with jevents.py as there is no longer a binary
to compare with.

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: John Garry <john.garry@huawei.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ananth Narayan <ananth.narayan@amd.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Andrew Kilroy <andrew.kilroy@arm.com>
Cc: Caleb Biggers <caleb.biggers@intel.com>
Cc: Felix Fietkau <nbd@nbd.name>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Kshipra Bopardikar <kshipra.bopardikar@intel.com>
Cc: Like Xu <likexu@tencent.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nick Forrington <nick.forrington@arm.com>
Cc: Paul Clarke <pc@us.ibm.com>
Cc: Perry Taylor <perry.taylor@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Qi Liu <liuqi115@huawei.com>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Sandipan Das <sandipan.das@amd.com>
Cc: Santosh Shukla <santosh.shukla@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Will Deacon <will@kernel.org>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Link: https://lore.kernel.org/r/20220629182505.406269-5-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
5a059790 00facc76

+2 -2019
+2 -19
tools/perf/Makefile.perf
··· 651 651 652 652 PERF_IN := $(OUTPUT)perf-in.o 653 653 654 - JEVENTS := $(OUTPUT)pmu-events/jevents 655 - JEVENTS_IN := $(OUTPUT)pmu-events/jevents-in.o 656 - 657 654 PMU_EVENTS_IN := $(OUTPUT)pmu-events/pmu-events-in.o 658 655 export NO_JEVENTS 659 - 660 - export JEVENTS 661 656 662 657 build := -f $(srctree)/tools/build/Makefile.build dir=. obj 663 658 664 659 $(PERF_IN): prepare FORCE 665 660 $(Q)$(MAKE) $(build)=perf 666 661 667 - $(JEVENTS_IN): FORCE 668 - $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=jevents 669 - 670 - $(JEVENTS): $(JEVENTS_IN) 671 - $(QUIET_LINK)$(HOSTCC) $(JEVENTS_IN) -o $@ 672 - 673 - JEVENTS_PY := pmu-events/jevents.py 674 - JEVENTS_PY_TEST := pmu-events/jevents-test.sh 675 - .PHONY: jevents-py-test 676 - jevents-py-test: $(JEVENTS) 677 - $(Q)$(call echo-cmd,gen)$(JEVENTS_PY_TEST) $(JEVENTS) $(JEVENTS_PY) pmu-events/arch 678 - 679 - $(PMU_EVENTS_IN): $(JEVENTS) FORCE 662 + $(PMU_EVENTS_IN): FORCE 680 663 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=pmu-events 681 664 682 665 $(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) ··· 1079 1096 $(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive $(OUTPUT)perf-iostat $(LANG_BINDINGS) 1080 1097 $(Q)find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 1081 1098 $(Q)$(RM) $(OUTPUT).config-detected 1082 - $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents $(OUTPUT)$(LIBJVMTI).so 1099 + $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)$(LIBJVMTI).so 1083 1100 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \ 1084 1101 $(OUTPUT)util/intel-pt-decoder/inat-tables.c \ 1085 1102 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
-4
tools/perf/pmu-events/Build
··· 1 - hostprogs := jevents 2 - 3 - jevents-y += json.o jsmn.o jevents.o 4 - HOSTCFLAGS_jevents.o = -I$(srctree)/tools/include 5 1 pmu-events-y += pmu-events.o 6 2 JDIR = pmu-events/arch/$(SRCARCH) 7 3 JSON = $(shell [ -d $(JDIR) ] && \
-33
tools/perf/pmu-events/jevents-test.sh
··· 1 - #!/bin/sh 2 - # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 3 - # Validate that the legacy jevents and jevents.py produce identical output. 4 - set -e 5 - 6 - JEVENTS="$1" 7 - JEVENTS_PY="$2" 8 - ARCH_PATH="$3" 9 - JEVENTS_C_GENERATED=$(mktemp /tmp/jevents_c.XXXXX.c) 10 - JEVENTS_PY_GENERATED=$(mktemp /tmp/jevents_py.XXXXX.c) 11 - 12 - cleanup() { 13 - rm "$JEVENTS_C_GENERATED" "$JEVENTS_PY_GENERATED" 14 - trap - exit term int 15 - } 16 - trap cleanup exit term int 17 - 18 - for path in "$ARCH_PATH"/* 19 - do 20 - arch=$(basename $path) 21 - if [ "$arch" = "test" ] 22 - then 23 - continue 24 - fi 25 - echo "Checking architecture: $arch" 26 - echo "Generating using jevents.c" 27 - "$JEVENTS" "$arch" "$ARCH_PATH" "$JEVENTS_C_GENERATED" 28 - echo "Generating using jevents.py" 29 - "$JEVENTS_PY" "$arch" "$ARCH_PATH" "$JEVENTS_PY_GENERATED" 30 - echo "Diffing" 31 - diff -u "$JEVENTS_C_GENERATED" "$JEVENTS_PY_GENERATED" 32 - done 33 - cleanup
-1342
tools/perf/pmu-events/jevents.c
··· 1 - #define _XOPEN_SOURCE 500 /* needed for nftw() */ 2 - #define _GNU_SOURCE /* needed for asprintf() */ 3 - 4 - /* Parse event JSON files */ 5 - 6 - /* 7 - * Copyright (c) 2014, Intel Corporation 8 - * All rights reserved. 9 - * 10 - * Redistribution and use in source and binary forms, with or without 11 - * modification, are permitted provided that the following conditions are met: 12 - * 13 - * 1. Redistributions of source code must retain the above copyright notice, 14 - * this list of conditions and the following disclaimer. 15 - * 16 - * 2. Redistributions in binary form must reproduce the above copyright 17 - * notice, this list of conditions and the following disclaimer in the 18 - * documentation and/or other materials provided with the distribution. 19 - * 20 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25 - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 - * OF THE POSSIBILITY OF SUCH DAMAGE. 32 - */ 33 - 34 - #include <stdio.h> 35 - #include <stdlib.h> 36 - #include <errno.h> 37 - #include <string.h> 38 - #include <ctype.h> 39 - #include <unistd.h> 40 - #include <stdarg.h> 41 - #include <libgen.h> 42 - #include <limits.h> 43 - #include <dirent.h> 44 - #include <sys/time.h> /* getrlimit */ 45 - #include <sys/resource.h> /* getrlimit */ 46 - #include <ftw.h> 47 - #include <sys/stat.h> 48 - #include <linux/compiler.h> 49 - #include <linux/list.h> 50 - #include "jsmn.h" 51 - #include "json.h" 52 - #include "pmu-events.h" 53 - 54 - int verbose; 55 - char *prog; 56 - 57 - struct json_event { 58 - char *name; 59 - char *compat; 60 - char *event; 61 - char *desc; 62 - char *long_desc; 63 - char *pmu; 64 - char *unit; 65 - char *perpkg; 66 - char *aggr_mode; 67 - char *metric_expr; 68 - char *metric_name; 69 - char *metric_group; 70 - char *deprecated; 71 - char *metric_constraint; 72 - }; 73 - 74 - static enum aggr_mode_class convert(const char *aggr_mode) 75 - { 76 - if (!strcmp(aggr_mode, "PerCore")) 77 - return PerCore; 78 - else if (!strcmp(aggr_mode, "PerChip")) 79 - return PerChip; 80 - 81 - pr_err("%s: Wrong AggregationMode value '%s'\n", prog, aggr_mode); 82 - return -1; 83 - } 84 - 85 - static LIST_HEAD(sys_event_tables); 86 - 87 - struct sys_event_table { 88 - struct list_head list; 89 - char *soc_id; 90 - }; 91 - 92 - static void free_sys_event_tables(void) 93 - { 94 - struct sys_event_table *et, *next; 95 - 96 - list_for_each_entry_safe(et, next, &sys_event_tables, list) { 97 - free(et->soc_id); 98 - free(et); 99 - } 100 - } 101 - 102 - int eprintf(int level, int var, const char *fmt, ...) 103 - { 104 - 105 - int ret; 106 - va_list args; 107 - 108 - if (var < level) 109 - return 0; 110 - 111 - va_start(args, fmt); 112 - 113 - ret = vfprintf(stderr, fmt, args); 114 - 115 - va_end(args); 116 - 117 - return ret; 118 - } 119 - 120 - static void addfield(char *map, char **dst, const char *sep, 121 - const char *a, jsmntok_t *bt) 122 - { 123 - unsigned int len = strlen(a) + 1 + strlen(sep); 124 - int olen = *dst ? strlen(*dst) : 0; 125 - int blen = bt ? json_len(bt) : 0; 126 - char *out; 127 - 128 - out = realloc(*dst, len + olen + blen); 129 - if (!out) { 130 - /* Don't add field in this case */ 131 - return; 132 - } 133 - *dst = out; 134 - 135 - if (!olen) 136 - *(*dst) = 0; 137 - else 138 - strcat(*dst, sep); 139 - strcat(*dst, a); 140 - if (bt) 141 - strncat(*dst, map + bt->start, blen); 142 - } 143 - 144 - static void fixname(char *s) 145 - { 146 - for (; *s; s++) 147 - *s = tolower(*s); 148 - } 149 - 150 - static void fixdesc(char *s) 151 - { 152 - char *e = s + strlen(s); 153 - 154 - /* Remove trailing dots that look ugly in perf list */ 155 - --e; 156 - while (e >= s && isspace(*e)) 157 - --e; 158 - if (*e == '.') 159 - *e = 0; 160 - } 161 - 162 - /* Add escapes for '\' so they are proper C strings. */ 163 - static char *fixregex(char *s) 164 - { 165 - int len = 0; 166 - int esc_count = 0; 167 - char *fixed = NULL; 168 - char *p, *q; 169 - 170 - /* Count the number of '\' in string */ 171 - for (p = s; *p; p++) { 172 - ++len; 173 - if (*p == '\\') 174 - ++esc_count; 175 - } 176 - 177 - if (esc_count == 0) 178 - return s; 179 - 180 - /* allocate space for a new string */ 181 - fixed = (char *) malloc(len + esc_count + 1); 182 - if (!fixed) 183 - return NULL; 184 - 185 - /* copy over the characters */ 186 - q = fixed; 187 - for (p = s; *p; p++) { 188 - if (*p == '\\') { 189 - *q = '\\'; 190 - ++q; 191 - } 192 - *q = *p; 193 - ++q; 194 - } 195 - *q = '\0'; 196 - return fixed; 197 - } 198 - 199 - static struct msrmap { 200 - const char *num; 201 - const char *pname; 202 - } msrmap[] = { 203 - { "0x3F6", "ldlat=" }, 204 - { "0x1A6", "offcore_rsp=" }, 205 - { "0x1A7", "offcore_rsp=" }, 206 - { "0x3F7", "frontend=" }, 207 - { NULL, NULL } 208 - }; 209 - 210 - static void cut_comma(char *map, jsmntok_t *newval) 211 - { 212 - int i; 213 - 214 - /* Cut off everything after comma */ 215 - for (i = newval->start; i < newval->end; i++) { 216 - if (map[i] == ',') 217 - newval->end = i; 218 - } 219 - } 220 - 221 - static struct msrmap *lookup_msr(char *map, jsmntok_t *val) 222 - { 223 - jsmntok_t newval = *val; 224 - static bool warned; 225 - int i; 226 - 227 - cut_comma(map, &newval); 228 - for (i = 0; msrmap[i].num; i++) 229 - if (json_streq(map, &newval, msrmap[i].num)) 230 - return &msrmap[i]; 231 - if (!warned) { 232 - warned = true; 233 - pr_err("%s: Unknown MSR in event file %.*s\n", prog, 234 - json_len(val), map + val->start); 235 - } 236 - return NULL; 237 - } 238 - 239 - static struct map { 240 - const char *json; 241 - const char *perf; 242 - } unit_to_pmu[] = { 243 - { "CBO", "uncore_cbox" }, 244 - { "QPI LL", "uncore_qpi" }, 245 - { "SBO", "uncore_sbox" }, 246 - { "iMPH-U", "uncore_arb" }, 247 - { "CPU-M-CF", "cpum_cf" }, 248 - { "CPU-M-SF", "cpum_sf" }, 249 - { "UPI LL", "uncore_upi" }, 250 - { "hisi_sicl,cpa", "hisi_sicl,cpa"}, 251 - { "hisi_sccl,ddrc", "hisi_sccl,ddrc" }, 252 - { "hisi_sccl,hha", "hisi_sccl,hha" }, 253 - { "hisi_sccl,l3c", "hisi_sccl,l3c" }, 254 - /* it's not realistic to keep adding these, we need something more scalable ... */ 255 - { "imx8_ddr", "imx8_ddr" }, 256 - { "L3PMC", "amd_l3" }, 257 - { "DFPMC", "amd_df" }, 258 - { "cpu_core", "cpu_core" }, 259 - { "cpu_atom", "cpu_atom" }, 260 - {} 261 - }; 262 - 263 - static const char *field_to_perf(struct map *table, char *map, jsmntok_t *val) 264 - { 265 - int i; 266 - 267 - for (i = 0; table[i].json; i++) { 268 - if (json_streq(map, val, table[i].json)) 269 - return table[i].perf; 270 - } 271 - return NULL; 272 - } 273 - 274 - #define EXPECT(e, t, m) do { if (!(e)) { \ 275 - jsmntok_t *loc = (t); \ 276 - if (!(t)->start && (t) > tokens) \ 277 - loc = (t) - 1; \ 278 - pr_err("%s:%d: " m ", got %s\n", fn, \ 279 - json_line(map, loc), \ 280 - json_name(t)); \ 281 - err = -EIO; \ 282 - goto out_free; \ 283 - } } while (0) 284 - 285 - static char *topic; 286 - 287 - static char *get_topic(void) 288 - { 289 - char *tp; 290 - int i; 291 - 292 - /* tp is free'd in process_one_file() */ 293 - i = asprintf(&tp, "%s", topic); 294 - if (i < 0) { 295 - pr_info("%s: asprintf() error %s\n", prog); 296 - return NULL; 297 - } 298 - 299 - for (i = 0; i < (int) strlen(tp); i++) { 300 - char c = tp[i]; 301 - 302 - if (c == '-') 303 - tp[i] = ' '; 304 - else if (c == '.') { 305 - tp[i] = '\0'; 306 - break; 307 - } 308 - } 309 - 310 - return tp; 311 - } 312 - 313 - static int add_topic(char *bname) 314 - { 315 - free(topic); 316 - topic = strdup(bname); 317 - if (!topic) { 318 - pr_info("%s: strdup() error %s for file %s\n", prog, 319 - strerror(errno), bname); 320 - return -ENOMEM; 321 - } 322 - return 0; 323 - } 324 - 325 - struct perf_entry_data { 326 - FILE *outfp; 327 - char *topic; 328 - }; 329 - 330 - static int close_table; 331 - 332 - static void print_events_table_prefix(FILE *fp, const char *tblname) 333 - { 334 - fprintf(fp, "static const struct pmu_event %s[] = {\n", tblname); 335 - close_table = 1; 336 - } 337 - 338 - static int print_events_table_entry(void *data, struct json_event *je) 339 - { 340 - struct perf_entry_data *pd = data; 341 - FILE *outfp = pd->outfp; 342 - char *topic_local = pd->topic; 343 - 344 - /* 345 - * TODO: Remove formatting chars after debugging to reduce 346 - * string lengths. 347 - */ 348 - fprintf(outfp, "{\n"); 349 - 350 - if (je->name) 351 - fprintf(outfp, "\t.name = \"%s\",\n", je->name); 352 - if (je->event) 353 - fprintf(outfp, "\t.event = \"%s\",\n", je->event); 354 - fprintf(outfp, "\t.desc = \"%s\",\n", je->desc); 355 - if (je->compat) 356 - fprintf(outfp, "\t.compat = \"%s\",\n", je->compat); 357 - fprintf(outfp, "\t.topic = \"%s\",\n", topic_local); 358 - if (je->long_desc && je->long_desc[0]) 359 - fprintf(outfp, "\t.long_desc = \"%s\",\n", je->long_desc); 360 - if (je->pmu) 361 - fprintf(outfp, "\t.pmu = \"%s\",\n", je->pmu); 362 - if (je->unit) 363 - fprintf(outfp, "\t.unit = \"%s\",\n", je->unit); 364 - if (je->perpkg) 365 - fprintf(outfp, "\t.perpkg = \"%s\",\n", je->perpkg); 366 - if (je->aggr_mode) 367 - fprintf(outfp, "\t.aggr_mode = \"%d\",\n", convert(je->aggr_mode)); 368 - if (je->metric_expr) 369 - fprintf(outfp, "\t.metric_expr = \"%s\",\n", je->metric_expr); 370 - if (je->metric_name) 371 - fprintf(outfp, "\t.metric_name = \"%s\",\n", je->metric_name); 372 - if (je->metric_group) 373 - fprintf(outfp, "\t.metric_group = \"%s\",\n", je->metric_group); 374 - if (je->deprecated) 375 - fprintf(outfp, "\t.deprecated = \"%s\",\n", je->deprecated); 376 - if (je->metric_constraint) 377 - fprintf(outfp, "\t.metric_constraint = \"%s\",\n", je->metric_constraint); 378 - fprintf(outfp, "},\n"); 379 - 380 - return 0; 381 - } 382 - 383 - struct event_struct { 384 - struct list_head list; 385 - char *name; 386 - char *event; 387 - char *compat; 388 - char *desc; 389 - char *long_desc; 390 - char *pmu; 391 - char *unit; 392 - char *perpkg; 393 - char *aggr_mode; 394 - char *metric_expr; 395 - char *metric_name; 396 - char *metric_group; 397 - char *deprecated; 398 - char *metric_constraint; 399 - }; 400 - 401 - #define ADD_EVENT_FIELD(field) do { if (je->field) { \ 402 - es->field = strdup(je->field); \ 403 - if (!es->field) \ 404 - goto out_free; \ 405 - } } while (0) 406 - 407 - #define FREE_EVENT_FIELD(field) free(es->field) 408 - 409 - #define TRY_FIXUP_FIELD(field) do { if (es->field && !je->field) {\ 410 - je->field = strdup(es->field); \ 411 - if (!je->field) \ 412 - return -ENOMEM; \ 413 - } } while (0) 414 - 415 - #define FOR_ALL_EVENT_STRUCT_FIELDS(op) do { \ 416 - op(name); \ 417 - op(event); \ 418 - op(desc); \ 419 - op(long_desc); \ 420 - op(pmu); \ 421 - op(unit); \ 422 - op(perpkg); \ 423 - op(aggr_mode); \ 424 - op(metric_expr); \ 425 - op(metric_name); \ 426 - op(metric_group); \ 427 - op(deprecated); \ 428 - } while (0) 429 - 430 - static LIST_HEAD(arch_std_events); 431 - 432 - static void free_arch_std_events(void) 433 - { 434 - struct event_struct *es, *next; 435 - 436 - list_for_each_entry_safe(es, next, &arch_std_events, list) { 437 - FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD); 438 - list_del_init(&es->list); 439 - free(es); 440 - } 441 - } 442 - 443 - static int save_arch_std_events(void *data __maybe_unused, struct json_event *je) 444 - { 445 - struct event_struct *es; 446 - 447 - es = malloc(sizeof(*es)); 448 - if (!es) 449 - return -ENOMEM; 450 - memset(es, 0, sizeof(*es)); 451 - FOR_ALL_EVENT_STRUCT_FIELDS(ADD_EVENT_FIELD); 452 - list_add_tail(&es->list, &arch_std_events); 453 - return 0; 454 - out_free: 455 - FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD); 456 - free(es); 457 - return -ENOMEM; 458 - } 459 - 460 - static void print_events_table_suffix(FILE *outfp) 461 - { 462 - fprintf(outfp, "{\n"); 463 - 464 - fprintf(outfp, "\t.name = 0,\n"); 465 - fprintf(outfp, "\t.event = 0,\n"); 466 - fprintf(outfp, "\t.desc = 0,\n"); 467 - 468 - fprintf(outfp, "},\n"); 469 - fprintf(outfp, "};\n"); 470 - close_table = 0; 471 - } 472 - 473 - static struct fixed { 474 - const char *name; 475 - const char *event; 476 - } fixed[] = { 477 - { "inst_retired.any", "event=0xc0,period=2000003" }, 478 - { "inst_retired.any_p", "event=0xc0,period=2000003" }, 479 - { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03,period=2000003" }, 480 - { "cpu_clk_unhalted.thread", "event=0x3c,period=2000003" }, 481 - { "cpu_clk_unhalted.core", "event=0x3c,period=2000003" }, 482 - { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1,period=2000003" }, 483 - { NULL, NULL}, 484 - }; 485 - 486 - /* 487 - * Handle different fixed counter encodings between JSON and perf. 488 - */ 489 - static char *real_event(const char *name, char *event) 490 - { 491 - int i; 492 - 493 - if (!name) 494 - return NULL; 495 - 496 - for (i = 0; fixed[i].name; i++) 497 - if (!strcasecmp(name, fixed[i].name)) 498 - return (char *)fixed[i].event; 499 - return event; 500 - } 501 - 502 - static int 503 - try_fixup(const char *fn, char *arch_std, struct json_event *je, char **event) 504 - { 505 - /* try to find matching event from arch standard values */ 506 - struct event_struct *es; 507 - 508 - list_for_each_entry(es, &arch_std_events, list) { 509 - if (!strcmp(arch_std, es->name)) { 510 - FOR_ALL_EVENT_STRUCT_FIELDS(TRY_FIXUP_FIELD); 511 - *event = je->event; 512 - return 0; 513 - } 514 - } 515 - 516 - pr_err("%s: could not find matching %s for %s\n", 517 - prog, arch_std, fn); 518 - return -1; 519 - } 520 - 521 - /* Call func with each event in the json file */ 522 - static int json_events(const char *fn, 523 - int (*func)(void *data, struct json_event *je), 524 - void *data) 525 - { 526 - int err; 527 - size_t size; 528 - jsmntok_t *tokens, *tok; 529 - int i, j, len; 530 - char *map; 531 - char buf[128]; 532 - 533 - if (!fn) 534 - return -ENOENT; 535 - 536 - tokens = parse_json(fn, &map, &size, &len); 537 - if (!tokens) 538 - return -EIO; 539 - EXPECT(tokens->type == JSMN_ARRAY, tokens, "expected top level array"); 540 - tok = tokens + 1; 541 - for (i = 0; i < tokens->size; i++) { 542 - char *event = NULL; 543 - char *extra_desc = NULL; 544 - char *filter = NULL; 545 - struct json_event je = {}; 546 - char *arch_std = NULL; 547 - unsigned long long eventcode = 0; 548 - unsigned long long configcode = 0; 549 - struct msrmap *msr = NULL; 550 - jsmntok_t *msrval = NULL; 551 - jsmntok_t *precise = NULL; 552 - jsmntok_t *obj = tok++; 553 - bool configcode_present = false; 554 - char *umask = NULL; 555 - char *cmask = NULL; 556 - char *inv = NULL; 557 - char *any = NULL; 558 - char *edge = NULL; 559 - char *period = NULL; 560 - char *fc_mask = NULL; 561 - char *ch_mask = NULL; 562 - 563 - EXPECT(obj->type == JSMN_OBJECT, obj, "expected object"); 564 - for (j = 0; j < obj->size; j += 2) { 565 - jsmntok_t *field, *val; 566 - int nz; 567 - char *s; 568 - 569 - field = tok + j; 570 - EXPECT(field->type == JSMN_STRING, tok + j, 571 - "Expected field name"); 572 - val = tok + j + 1; 573 - EXPECT(val->type == JSMN_STRING, tok + j + 1, 574 - "Expected string value"); 575 - 576 - nz = !json_streq(map, val, "0"); 577 - /* match_field */ 578 - if (json_streq(map, field, "UMask") && nz) { 579 - addfield(map, &umask, "", "umask=", val); 580 - } else if (json_streq(map, field, "CounterMask") && nz) { 581 - addfield(map, &cmask, "", "cmask=", val); 582 - } else if (json_streq(map, field, "Invert") && nz) { 583 - addfield(map, &inv, "", "inv=", val); 584 - } else if (json_streq(map, field, "AnyThread") && nz) { 585 - addfield(map, &any, "", "any=", val); 586 - } else if (json_streq(map, field, "EdgeDetect") && nz) { 587 - addfield(map, &edge, "", "edge=", val); 588 - } else if (json_streq(map, field, "SampleAfterValue") && nz) { 589 - addfield(map, &period, "", "period=", val); 590 - } else if (json_streq(map, field, "FCMask") && nz) { 591 - addfield(map, &fc_mask, "", "fc_mask=", val); 592 - } else if (json_streq(map, field, "PortMask") && nz) { 593 - addfield(map, &ch_mask, "", "ch_mask=", val); 594 - } else if (json_streq(map, field, "EventCode")) { 595 - char *code = NULL; 596 - addfield(map, &code, "", "", val); 597 - eventcode |= strtoul(code, NULL, 0); 598 - free(code); 599 - } else if (json_streq(map, field, "ConfigCode")) { 600 - char *code = NULL; 601 - addfield(map, &code, "", "", val); 602 - configcode |= strtoul(code, NULL, 0); 603 - free(code); 604 - configcode_present = true; 605 - } else if (json_streq(map, field, "ExtSel")) { 606 - char *code = NULL; 607 - addfield(map, &code, "", "", val); 608 - eventcode |= strtoul(code, NULL, 0) << 8; 609 - free(code); 610 - } else if (json_streq(map, field, "EventName")) { 611 - addfield(map, &je.name, "", "", val); 612 - } else if (json_streq(map, field, "Compat")) { 613 - addfield(map, &je.compat, "", "", val); 614 - } else if (json_streq(map, field, "BriefDescription")) { 615 - addfield(map, &je.desc, "", "", val); 616 - fixdesc(je.desc); 617 - } else if (json_streq(map, field, 618 - "PublicDescription")) { 619 - addfield(map, &je.long_desc, "", "", val); 620 - fixdesc(je.long_desc); 621 - } else if (json_streq(map, field, "PEBS") && nz) { 622 - precise = val; 623 - } else if (json_streq(map, field, "MSRIndex") && nz) { 624 - msr = lookup_msr(map, val); 625 - } else if (json_streq(map, field, "MSRValue")) { 626 - msrval = val; 627 - } else if (json_streq(map, field, "Errata") && 628 - !json_streq(map, val, "null")) { 629 - addfield(map, &extra_desc, ". ", 630 - " Spec update: ", val); 631 - } else if (json_streq(map, field, "Data_LA") && nz) { 632 - addfield(map, &extra_desc, ". ", 633 - " Supports address when precise", 634 - NULL); 635 - } else if (json_streq(map, field, "Unit")) { 636 - const char *ppmu; 637 - 638 - ppmu = field_to_perf(unit_to_pmu, map, val); 639 - if (ppmu) { 640 - je.pmu = strdup(ppmu); 641 - } else { 642 - if (!je.pmu) 643 - je.pmu = strdup("uncore_"); 644 - addfield(map, &je.pmu, "", "", val); 645 - for (s = je.pmu; *s; s++) 646 - *s = tolower(*s); 647 - } 648 - } else if (json_streq(map, field, "Filter")) { 649 - addfield(map, &filter, "", "", val); 650 - } else if (json_streq(map, field, "ScaleUnit")) { 651 - addfield(map, &je.unit, "", "", val); 652 - } else if (json_streq(map, field, "PerPkg")) { 653 - addfield(map, &je.perpkg, "", "", val); 654 - } else if (json_streq(map, field, "AggregationMode")) { 655 - addfield(map, &je.aggr_mode, "", "", val); 656 - } else if (json_streq(map, field, "Deprecated")) { 657 - addfield(map, &je.deprecated, "", "", val); 658 - } else if (json_streq(map, field, "MetricName")) { 659 - addfield(map, &je.metric_name, "", "", val); 660 - } else if (json_streq(map, field, "MetricGroup")) { 661 - addfield(map, &je.metric_group, "", "", val); 662 - } else if (json_streq(map, field, "MetricConstraint")) { 663 - addfield(map, &je.metric_constraint, "", "", val); 664 - } else if (json_streq(map, field, "MetricExpr")) { 665 - addfield(map, &je.metric_expr, "", "", val); 666 - } else if (json_streq(map, field, "ArchStdEvent")) { 667 - addfield(map, &arch_std, "", "", val); 668 - for (s = arch_std; *s; s++) 669 - *s = tolower(*s); 670 - } 671 - /* ignore unknown fields */ 672 - } 673 - if (precise && je.desc && !strstr(je.desc, "(Precise Event)")) { 674 - if (json_streq(map, precise, "2")) 675 - addfield(map, &extra_desc, " ", 676 - "(Must be precise)", NULL); 677 - else 678 - addfield(map, &extra_desc, " ", 679 - "(Precise event)", NULL); 680 - } 681 - if (configcode_present) 682 - snprintf(buf, sizeof buf, "config=%#llx", configcode); 683 - else 684 - snprintf(buf, sizeof buf, "event=%#llx", eventcode); 685 - addfield(map, &event, ",", buf, NULL); 686 - if (any) 687 - addfield(map, &event, ",", any, NULL); 688 - if (ch_mask) 689 - addfield(map, &event, ",", ch_mask, NULL); 690 - if (cmask) 691 - addfield(map, &event, ",", cmask, NULL); 692 - if (edge) 693 - addfield(map, &event, ",", edge, NULL); 694 - if (fc_mask) 695 - addfield(map, &event, ",", fc_mask, NULL); 696 - if (inv) 697 - addfield(map, &event, ",", inv, NULL); 698 - if (period) 699 - addfield(map, &event, ",", period, NULL); 700 - if (umask) 701 - addfield(map, &event, ",", umask, NULL); 702 - 703 - if (je.desc && extra_desc) 704 - addfield(map, &je.desc, " ", extra_desc, NULL); 705 - if (je.long_desc && extra_desc) 706 - addfield(map, &je.long_desc, " ", extra_desc, NULL); 707 - if (je.pmu) { 708 - addfield(map, &je.desc, ". ", "Unit: ", NULL); 709 - addfield(map, &je.desc, "", je.pmu, NULL); 710 - addfield(map, &je.desc, "", " ", NULL); 711 - } 712 - if (filter) 713 - addfield(map, &event, ",", filter, NULL); 714 - if (msr != NULL) 715 - addfield(map, &event, ",", msr->pname, msrval); 716 - if (je.name) 717 - fixname(je.name); 718 - 719 - if (arch_std) { 720 - /* 721 - * An arch standard event is referenced, so try to 722 - * fixup any unassigned values. 723 - */ 724 - err = try_fixup(fn, arch_std, &je, &event); 725 - if (err) 726 - goto free_strings; 727 - } 728 - je.event = real_event(je.name, event); 729 - err = func(data, &je); 730 - free_strings: 731 - free(umask); 732 - free(cmask); 733 - free(inv); 734 - free(any); 735 - free(edge); 736 - free(period); 737 - free(fc_mask); 738 - free(ch_mask); 739 - free(event); 740 - free(je.desc); 741 - free(je.name); 742 - free(je.compat); 743 - free(je.long_desc); 744 - free(extra_desc); 745 - free(je.pmu); 746 - free(filter); 747 - free(je.perpkg); 748 - free(je.aggr_mode); 749 - free(je.deprecated); 750 - free(je.unit); 751 - free(je.metric_expr); 752 - free(je.metric_name); 753 - free(je.metric_group); 754 - free(je.metric_constraint); 755 - free(arch_std); 756 - 757 - if (err) 758 - break; 759 - tok += j; 760 - } 761 - EXPECT(tok - tokens == len, tok, "unexpected objects at end"); 762 - err = 0; 763 - out_free: 764 - free_json(map, size, tokens); 765 - return err; 766 - } 767 - 768 - static char *file_name_to_table_name(char *fname) 769 - { 770 - unsigned int i; 771 - int n; 772 - int c; 773 - char *tblname; 774 - 775 - /* 776 - * Ensure tablename starts with alphabetic character. 777 - * Derive rest of table name from basename of the JSON file, 778 - * replacing hyphens and stripping out .json suffix. 779 - */ 780 - n = asprintf(&tblname, "pme_%s", fname); 781 - if (n < 0) { 782 - pr_info("%s: asprintf() error %s for file %s\n", prog, 783 - strerror(errno), fname); 784 - return NULL; 785 - } 786 - 787 - for (i = 0; i < strlen(tblname); i++) { 788 - c = tblname[i]; 789 - 790 - if (c == '-' || c == '/') 791 - tblname[i] = '_'; 792 - else if (c == '.') { 793 - tblname[i] = '\0'; 794 - break; 795 - } else if (!isalnum(c) && c != '_') { 796 - pr_err("%s: Invalid character '%c' in file name %s\n", 797 - prog, c, basename(fname)); 798 - free(tblname); 799 - tblname = NULL; 800 - break; 801 - } 802 - } 803 - 804 - return tblname; 805 - } 806 - 807 - static bool is_sys_dir(char *fname) 808 - { 809 - size_t len = strlen(fname), len2 = strlen("/sys"); 810 - 811 - if (len2 > len) 812 - return false; 813 - return !strcmp(fname+len-len2, "/sys"); 814 - } 815 - 816 - static void print_mapping_table_prefix(FILE *outfp) 817 - { 818 - fprintf(outfp, "const struct pmu_events_map pmu_events_map[] = {\n"); 819 - } 820 - 821 - static void print_mapping_table_suffix(FILE *outfp) 822 - { 823 - /* 824 - * Print the terminating, NULL entry. 825 - */ 826 - fprintf(outfp, "{\n"); 827 - fprintf(outfp, "\t.cpuid = 0,\n"); 828 - fprintf(outfp, "\t.version = 0,\n"); 829 - fprintf(outfp, "\t.type = 0,\n"); 830 - fprintf(outfp, "\t.table = 0,\n"); 831 - fprintf(outfp, "},\n"); 832 - 833 - /* and finally, the closing curly bracket for the struct */ 834 - fprintf(outfp, "};\n"); 835 - } 836 - 837 - static void print_mapping_test_table(FILE *outfp) 838 - { 839 - /* 840 - * Print the terminating, NULL entry. 841 - */ 842 - fprintf(outfp, "{\n"); 843 - fprintf(outfp, "\t.cpuid = \"testcpu\",\n"); 844 - fprintf(outfp, "\t.version = \"v1\",\n"); 845 - fprintf(outfp, "\t.type = \"core\",\n"); 846 - fprintf(outfp, "\t.table = pme_test_soc_cpu,\n"); 847 - fprintf(outfp, "},\n"); 848 - } 849 - 850 - static void print_system_event_mapping_table_prefix(FILE *outfp) 851 - { 852 - fprintf(outfp, "\nconst struct pmu_sys_events pmu_sys_event_tables[] = {"); 853 - } 854 - 855 - static void print_system_event_mapping_table_suffix(FILE *outfp) 856 - { 857 - fprintf(outfp, "\n\t{\n\t\t.table = 0\n\t},"); 858 - fprintf(outfp, "\n};\n"); 859 - } 860 - 861 - static int process_system_event_tables(FILE *outfp) 862 - { 863 - struct sys_event_table *sys_event_table; 864 - 865 - print_system_event_mapping_table_prefix(outfp); 866 - 867 - list_for_each_entry(sys_event_table, &sys_event_tables, list) { 868 - fprintf(outfp, "\n\t{\n\t\t.table = %s,\n\t\t.name = \"%s\",\n\t},", 869 - sys_event_table->soc_id, 870 - sys_event_table->soc_id); 871 - } 872 - 873 - print_system_event_mapping_table_suffix(outfp); 874 - 875 - return 0; 876 - } 877 - 878 - static int process_mapfile(FILE *outfp, char *fpath) 879 - { 880 - int n = 16384; 881 - FILE *mapfp; 882 - char *save = NULL; 883 - char *line, *p; 884 - int line_num; 885 - char *tblname; 886 - int ret = 0; 887 - 888 - pr_info("%s: Processing mapfile %s\n", prog, fpath); 889 - 890 - line = malloc(n); 891 - if (!line) 892 - return -1; 893 - 894 - mapfp = fopen(fpath, "r"); 895 - if (!mapfp) { 896 - pr_info("%s: Error %s opening %s\n", prog, strerror(errno), 897 - fpath); 898 - free(line); 899 - return -1; 900 - } 901 - 902 - print_mapping_table_prefix(outfp); 903 - 904 - /* Skip first line (header) */ 905 - p = fgets(line, n, mapfp); 906 - if (!p) 907 - goto out; 908 - 909 - line_num = 1; 910 - while (1) { 911 - char *cpuid, *version, *type, *fname; 912 - 913 - line_num++; 914 - p = fgets(line, n, mapfp); 915 - if (!p) 916 - break; 917 - 918 - if (line[0] == '#' || line[0] == '\n') 919 - continue; 920 - 921 - if (line[strlen(line)-1] != '\n') { 922 - /* TODO Deal with lines longer than 16K */ 923 - pr_info("%s: Mapfile %s: line %d too long, aborting\n", 924 - prog, fpath, line_num); 925 - ret = -1; 926 - goto out; 927 - } 928 - line[strlen(line)-1] = '\0'; 929 - 930 - cpuid = fixregex(strtok_r(p, ",", &save)); 931 - version = strtok_r(NULL, ",", &save); 932 - fname = strtok_r(NULL, ",", &save); 933 - type = strtok_r(NULL, ",", &save); 934 - 935 - tblname = file_name_to_table_name(fname); 936 - fprintf(outfp, "{\n"); 937 - fprintf(outfp, "\t.cpuid = \"%s\",\n", cpuid); 938 - fprintf(outfp, "\t.version = \"%s\",\n", version); 939 - fprintf(outfp, "\t.type = \"%s\",\n", type); 940 - 941 - /* 942 - * CHECK: We can't use the type (eg "core") field in the 943 - * table name. For us to do that, we need to somehow tweak 944 - * the other caller of file_name_to_table(), process_json() 945 - * to determine the type. process_json() file has no way 946 - * of knowing these are "core" events unless file name has 947 - * core in it. If filename has core in it, we can safely 948 - * ignore the type field here also. 949 - */ 950 - fprintf(outfp, "\t.table = %s\n", tblname); 951 - fprintf(outfp, "},\n"); 952 - } 953 - 954 - out: 955 - print_mapping_test_table(outfp); 956 - print_mapping_table_suffix(outfp); 957 - fclose(mapfp); 958 - free(line); 959 - return ret; 960 - } 961 - 962 - /* 963 - * If we fail to locate/process JSON and map files, create a NULL mapping 964 - * table. This would at least allow perf to build even if we can't find/use 965 - * the aliases. 966 - */ 967 - static void create_empty_mapping(const char *output_file) 968 - { 969 - FILE *outfp; 970 - 971 - pr_info("%s: Creating empty pmu_events_map[] table\n", prog); 972 - 973 - /* Truncate file to clear any partial writes to it */ 974 - outfp = fopen(output_file, "w"); 975 - if (!outfp) { 976 - perror("fopen()"); 977 - _Exit(1); 978 - } 979 - 980 - fprintf(outfp, "#include \"pmu-events/pmu-events.h\"\n"); 981 - print_mapping_table_prefix(outfp); 982 - print_mapping_table_suffix(outfp); 983 - print_system_event_mapping_table_prefix(outfp); 984 - print_system_event_mapping_table_suffix(outfp); 985 - fclose(outfp); 986 - } 987 - 988 - static int get_maxfds(void) 989 - { 990 - struct rlimit rlim; 991 - 992 - if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) 993 - return min(rlim.rlim_max / 2, (rlim_t)512); 994 - 995 - return 512; 996 - } 997 - 998 - /* 999 - * nftw() doesn't let us pass an argument to the processing function, 1000 - * so use a global variables. 1001 - */ 1002 - static FILE *eventsfp; 1003 - static char *mapfile; 1004 - 1005 - static int is_leaf_dir(const char *fpath) 1006 - { 1007 - DIR *d; 1008 - struct dirent *dir; 1009 - int res = 1; 1010 - 1011 - d = opendir(fpath); 1012 - if (!d) 1013 - return 0; 1014 - 1015 - while ((dir = readdir(d)) != NULL) { 1016 - if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) 1017 - continue; 1018 - 1019 - if (dir->d_type == DT_DIR) { 1020 - res = 0; 1021 - break; 1022 - } else if (dir->d_type == DT_UNKNOWN) { 1023 - char path[PATH_MAX]; 1024 - struct stat st; 1025 - 1026 - sprintf(path, "%s/%s", fpath, dir->d_name); 1027 - if (stat(path, &st)) 1028 - break; 1029 - 1030 - if (S_ISDIR(st.st_mode)) { 1031 - res = 0; 1032 - break; 1033 - } 1034 - } 1035 - } 1036 - 1037 - closedir(d); 1038 - 1039 - return res; 1040 - } 1041 - 1042 - static int is_json_file(const char *name) 1043 - { 1044 - const char *suffix; 1045 - 1046 - if (strlen(name) < 5) 1047 - return 0; 1048 - 1049 - suffix = name + strlen(name) - 5; 1050 - 1051 - if (strncmp(suffix, ".json", 5) == 0) 1052 - return 1; 1053 - return 0; 1054 - } 1055 - 1056 - static int preprocess_arch_std_files(const char *fpath, const struct stat *sb, 1057 - int typeflag, struct FTW *ftwbuf) 1058 - { 1059 - int level = ftwbuf->level; 1060 - int is_file = typeflag == FTW_F; 1061 - 1062 - if (level == 1 && is_file && is_json_file(fpath)) 1063 - return json_events(fpath, save_arch_std_events, (void *)sb); 1064 - 1065 - return 0; 1066 - } 1067 - 1068 - static int process_one_file(const char *fpath, const struct stat *sb, 1069 - int typeflag, struct FTW *ftwbuf) 1070 - { 1071 - char *tblname, *bname; 1072 - int is_dir = typeflag == FTW_D; 1073 - int is_file = typeflag == FTW_F; 1074 - int level = ftwbuf->level; 1075 - int err = 0; 1076 - 1077 - if (level >= 2 && is_dir) { 1078 - int count = 0; 1079 - /* 1080 - * For level 2 directory, bname will include parent name, 1081 - * like vendor/platform. So search back from platform dir 1082 - * to find this. 1083 - * Something similar for level 3 directory, but we're a PMU 1084 - * category folder, like vendor/platform/cpu. 1085 - */ 1086 - bname = (char *) fpath + ftwbuf->base - 2; 1087 - for (;;) { 1088 - if (*bname == '/') 1089 - count++; 1090 - if (count == level - 1) 1091 - break; 1092 - bname--; 1093 - } 1094 - bname++; 1095 - } else 1096 - bname = (char *) fpath + ftwbuf->base; 1097 - 1098 - pr_debug("%s %d %7jd %-20s %s\n", 1099 - is_file ? "f" : is_dir ? "d" : "x", 1100 - level, sb->st_size, bname, fpath); 1101 - 1102 - /* base dir or too deep */ 1103 - if (level == 0 || level > 4) 1104 - return 0; 1105 - 1106 - 1107 - /* model directory, reset topic */ 1108 - if ((level == 1 && is_dir && is_leaf_dir(fpath)) || 1109 - (level >= 2 && is_dir && is_leaf_dir(fpath))) { 1110 - if (close_table) 1111 - print_events_table_suffix(eventsfp); 1112 - 1113 - /* 1114 - * Drop file name suffix. Replace hyphens with underscores. 1115 - * Fail if file name contains any alphanum characters besides 1116 - * underscores. 1117 - */ 1118 - tblname = file_name_to_table_name(bname); 1119 - if (!tblname) { 1120 - pr_info("%s: Error determining table name for %s\n", prog, 1121 - bname); 1122 - return -1; 1123 - } 1124 - 1125 - if (is_sys_dir(bname)) { 1126 - struct sys_event_table *sys_event_table; 1127 - 1128 - sys_event_table = malloc(sizeof(*sys_event_table)); 1129 - if (!sys_event_table) 1130 - return -1; 1131 - 1132 - sys_event_table->soc_id = strdup(tblname); 1133 - if (!sys_event_table->soc_id) { 1134 - free(sys_event_table); 1135 - return -1; 1136 - } 1137 - list_add_tail(&sys_event_table->list, 1138 - &sys_event_tables); 1139 - } 1140 - 1141 - print_events_table_prefix(eventsfp, tblname); 1142 - return 0; 1143 - } 1144 - 1145 - /* 1146 - * Save the mapfile name for now. We will process mapfile 1147 - * after processing all JSON files (so we can write out the 1148 - * mapping table after all PMU events tables). 1149 - * 1150 - */ 1151 - if (level == 1 && is_file) { 1152 - if (!strcmp(bname, "mapfile.csv")) { 1153 - mapfile = strdup(fpath); 1154 - return 0; 1155 - } 1156 - if (is_json_file(bname)) 1157 - pr_debug("%s: ArchStd json is preprocessed %s\n", prog, fpath); 1158 - else 1159 - pr_info("%s: Ignoring file %s\n", prog, fpath); 1160 - return 0; 1161 - } 1162 - 1163 - /* 1164 - * If the file name does not have a .json extension, 1165 - * ignore it. It could be a readme.txt for instance. 1166 - */ 1167 - if (is_file) { 1168 - if (!is_json_file(bname)) { 1169 - pr_info("%s: Ignoring file without .json suffix %s\n", prog, 1170 - fpath); 1171 - return 0; 1172 - } 1173 - } 1174 - 1175 - if (level > 1 && add_topic(bname)) 1176 - return -ENOMEM; 1177 - 1178 - /* 1179 - * Assume all other files are JSON files. 1180 - * 1181 - * If mapfile refers to 'power7_core.json', we create a table 1182 - * named 'power7_core'. Any inconsistencies between the mapfile 1183 - * and directory tree could result in build failure due to table 1184 - * names not being found. 1185 - * 1186 - * At least for now, be strict with processing JSON file names. 1187 - * i.e. if JSON file name cannot be mapped to C-style table name, 1188 - * fail. 1189 - */ 1190 - if (is_file) { 1191 - struct perf_entry_data data = { 1192 - .topic = get_topic(), 1193 - .outfp = eventsfp, 1194 - }; 1195 - 1196 - err = json_events(fpath, print_events_table_entry, &data); 1197 - 1198 - free(data.topic); 1199 - } 1200 - 1201 - return err; 1202 - } 1203 - 1204 - #ifndef PATH_MAX 1205 - #define PATH_MAX 4096 1206 - #endif 1207 - 1208 - /* 1209 - * Starting in directory 'start_dirname', find the "mapfile.csv" and 1210 - * the set of JSON files for the architecture 'arch'. 1211 - * 1212 - * From each JSON file, create a C-style "PMU events table" from the 1213 - * JSON file (see struct pmu_event). 1214 - * 1215 - * From the mapfile, create a mapping between the CPU revisions and 1216 - * PMU event tables (see struct pmu_events_map). 1217 - * 1218 - * Write out the PMU events tables and the mapping table to pmu-event.c. 1219 - */ 1220 - int main(int argc, char *argv[]) 1221 - { 1222 - int rc, ret = 0, empty_map = 0; 1223 - int maxfds; 1224 - char ldirname[PATH_MAX]; 1225 - const char *arch; 1226 - const char *output_file; 1227 - const char *start_dirname; 1228 - const char *err_string_ext = ""; 1229 - struct stat stbuf; 1230 - 1231 - prog = basename(argv[0]); 1232 - if (argc < 4) { 1233 - pr_err("Usage: %s <arch> <starting_dir> <output_file>\n", prog); 1234 - return 1; 1235 - } 1236 - 1237 - arch = argv[1]; 1238 - start_dirname = argv[2]; 1239 - output_file = argv[3]; 1240 - 1241 - if (argc > 4) 1242 - verbose = atoi(argv[4]); 1243 - 1244 - eventsfp = fopen(output_file, "w"); 1245 - if (!eventsfp) { 1246 - pr_err("%s Unable to create required file %s (%s)\n", 1247 - prog, output_file, strerror(errno)); 1248 - return 2; 1249 - } 1250 - 1251 - sprintf(ldirname, "%s/%s", start_dirname, arch); 1252 - 1253 - /* If architecture does not have any event lists, bail out */ 1254 - if (stat(ldirname, &stbuf) < 0) { 1255 - pr_info("%s: Arch %s has no PMU event lists\n", prog, arch); 1256 - empty_map = 1; 1257 - goto err_close_eventsfp; 1258 - } 1259 - 1260 - /* Include pmu-events.h first */ 1261 - fprintf(eventsfp, "#include \"pmu-events/pmu-events.h\"\n"); 1262 - 1263 - /* 1264 - * The mapfile allows multiple CPUids to point to the same JSON file, 1265 - * so, not sure if there is a need for symlinks within the pmu-events 1266 - * directory. 1267 - * 1268 - * For now, treat symlinks of JSON files as regular files and create 1269 - * separate tables for each symlink (presumably, each symlink refers 1270 - * to specific version of the CPU). 1271 - */ 1272 - 1273 - maxfds = get_maxfds(); 1274 - rc = nftw(ldirname, preprocess_arch_std_files, maxfds, 0); 1275 - if (rc) 1276 - goto err_processing_std_arch_event_dir; 1277 - 1278 - rc = nftw(ldirname, process_one_file, maxfds, 0); 1279 - if (rc) 1280 - goto err_processing_dir; 1281 - 1282 - sprintf(ldirname, "%s/test", start_dirname); 1283 - 1284 - rc = nftw(ldirname, preprocess_arch_std_files, maxfds, 0); 1285 - if (rc) 1286 - goto err_processing_std_arch_event_dir; 1287 - 1288 - rc = nftw(ldirname, process_one_file, maxfds, 0); 1289 - if (rc) 1290 - goto err_processing_dir; 1291 - 1292 - if (close_table) 1293 - print_events_table_suffix(eventsfp); 1294 - 1295 - if (!mapfile) { 1296 - pr_info("%s: No CPU->JSON mapping?\n", prog); 1297 - empty_map = 1; 1298 - goto err_close_eventsfp; 1299 - } 1300 - 1301 - rc = process_mapfile(eventsfp, mapfile); 1302 - if (rc) { 1303 - pr_info("%s: Error processing mapfile %s\n", prog, mapfile); 1304 - /* Make build fail */ 1305 - ret = 1; 1306 - goto err_close_eventsfp; 1307 - } 1308 - 1309 - rc = process_system_event_tables(eventsfp); 1310 - fclose(eventsfp); 1311 - if (rc) { 1312 - ret = 1; 1313 - goto err_out; 1314 - } 1315 - 1316 - free_arch_std_events(); 1317 - free_sys_event_tables(); 1318 - free(mapfile); 1319 - return 0; 1320 - 1321 - err_processing_std_arch_event_dir: 1322 - err_string_ext = " for std arch event"; 1323 - err_processing_dir: 1324 - if (verbose) { 1325 - pr_info("%s: Error walking file tree %s%s\n", prog, ldirname, 1326 - err_string_ext); 1327 - empty_map = 1; 1328 - } else if (rc < 0) { 1329 - ret = 1; 1330 - } else { 1331 - empty_map = 1; 1332 - } 1333 - err_close_eventsfp: 1334 - fclose(eventsfp); 1335 - if (empty_map) 1336 - create_empty_mapping(output_file); 1337 - err_out: 1338 - free_arch_std_events(); 1339 - free_sys_event_tables(); 1340 - free(mapfile); 1341 - return ret; 1342 - }
-352
tools/perf/pmu-events/jsmn.c
··· 1 - /* 2 - * Copyright (c) 2010 Serge A. Zaitsev 3 - * 4 - * Permission is hereby granted, free of charge, to any person obtaining a copy 5 - * of this software and associated documentation files (the "Software"), to deal 6 - * in the Software without restriction, including without limitation the rights 7 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 - * copies of the Software, and to permit persons to whom the Software is 9 - * furnished to do so, subject to the following conditions: 10 - * 11 - * The above copyright notice and this permission notice shall be included in 12 - * all copies or substantial portions of the Software. 13 - * 14 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 - * THE SOFTWARE. 21 - * 22 - * Slightly modified by AK to not assume 0 terminated input. 23 - */ 24 - 25 - #include <stdlib.h> 26 - #include "jsmn.h" 27 - #define JSMN_STRICT 28 - 29 - /* 30 - * Allocates a fresh unused token from the token pool. 31 - */ 32 - static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 33 - jsmntok_t *tokens, size_t num_tokens) 34 - { 35 - jsmntok_t *tok; 36 - 37 - if ((unsigned)parser->toknext >= num_tokens) 38 - return NULL; 39 - tok = &tokens[parser->toknext++]; 40 - tok->start = tok->end = -1; 41 - tok->size = 0; 42 - return tok; 43 - } 44 - 45 - /* 46 - * Fills token type and boundaries. 47 - */ 48 - static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 49 - int start, int end) 50 - { 51 - token->type = type; 52 - token->start = start; 53 - token->end = end; 54 - token->size = 0; 55 - } 56 - 57 - /* 58 - * Fills next available token with JSON primitive. 59 - */ 60 - static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, 61 - size_t len, 62 - jsmntok_t *tokens, size_t num_tokens) 63 - { 64 - jsmntok_t *token; 65 - int start; 66 - 67 - start = parser->pos; 68 - 69 - for (; parser->pos < len; parser->pos++) { 70 - switch (js[parser->pos]) { 71 - #ifndef JSMN_STRICT 72 - /* 73 - * In strict mode primitive must be followed by "," 74 - * or "}" or "]" 75 - */ 76 - case ':': 77 - #endif 78 - case '\t': 79 - case '\r': 80 - case '\n': 81 - case ' ': 82 - case ',': 83 - case ']': 84 - case '}': 85 - goto found; 86 - default: 87 - break; 88 - } 89 - if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 90 - parser->pos = start; 91 - return JSMN_ERROR_INVAL; 92 - } 93 - } 94 - #ifdef JSMN_STRICT 95 - /* 96 - * In strict mode primitive must be followed by a 97 - * comma/object/array. 98 - */ 99 - parser->pos = start; 100 - return JSMN_ERROR_PART; 101 - #endif 102 - 103 - found: 104 - token = jsmn_alloc_token(parser, tokens, num_tokens); 105 - if (token == NULL) { 106 - parser->pos = start; 107 - return JSMN_ERROR_NOMEM; 108 - } 109 - jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 110 - parser->pos--; /* parent sees closing brackets */ 111 - return JSMN_SUCCESS; 112 - } 113 - 114 - /* 115 - * Fills next token with JSON string. 116 - */ 117 - static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, 118 - size_t len, 119 - jsmntok_t *tokens, size_t num_tokens) 120 - { 121 - jsmntok_t *token; 122 - int start = parser->pos; 123 - 124 - /* Skip starting quote */ 125 - parser->pos++; 126 - 127 - for (; parser->pos < len; parser->pos++) { 128 - char c = js[parser->pos]; 129 - 130 - /* Quote: end of string */ 131 - if (c == '\"') { 132 - token = jsmn_alloc_token(parser, tokens, num_tokens); 133 - if (token == NULL) { 134 - parser->pos = start; 135 - return JSMN_ERROR_NOMEM; 136 - } 137 - jsmn_fill_token(token, JSMN_STRING, start+1, 138 - parser->pos); 139 - return JSMN_SUCCESS; 140 - } 141 - 142 - /* Backslash: Quoted symbol expected */ 143 - if (c == '\\') { 144 - parser->pos++; 145 - switch (js[parser->pos]) { 146 - /* Allowed escaped symbols */ 147 - case '\"': 148 - case '/': 149 - case '\\': 150 - case 'b': 151 - case 'f': 152 - case 'r': 153 - case 'n': 154 - case 't': 155 - break; 156 - /* Allows escaped symbol \uXXXX */ 157 - case 'u': 158 - /* TODO */ 159 - break; 160 - /* Unexpected symbol */ 161 - default: 162 - parser->pos = start; 163 - return JSMN_ERROR_INVAL; 164 - } 165 - } 166 - } 167 - parser->pos = start; 168 - return JSMN_ERROR_PART; 169 - } 170 - 171 - /* 172 - * Parse JSON string and fill tokens. 173 - */ 174 - jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 175 - jsmntok_t *tokens, unsigned int num_tokens) 176 - { 177 - jsmnerr_t r; 178 - int i; 179 - jsmntok_t *token; 180 - #ifdef JSMN_STRICT 181 - /* 182 - * Keeps track of whether a new object/list/primitive is expected. New items are only 183 - * allowed after an opening brace, comma or colon. A closing brace after a comma is not 184 - * valid JSON. 185 - */ 186 - int expecting_item = 1; 187 - #endif 188 - 189 - for (; parser->pos < len; parser->pos++) { 190 - char c; 191 - jsmntype_t type; 192 - 193 - c = js[parser->pos]; 194 - switch (c) { 195 - case '{': 196 - case '[': 197 - #ifdef JSMN_STRICT 198 - if (!expecting_item) 199 - return JSMN_ERROR_INVAL; 200 - #endif 201 - token = jsmn_alloc_token(parser, tokens, num_tokens); 202 - if (token == NULL) 203 - return JSMN_ERROR_NOMEM; 204 - if (parser->toksuper != -1) 205 - tokens[parser->toksuper].size++; 206 - token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 207 - token->start = parser->pos; 208 - parser->toksuper = parser->toknext - 1; 209 - break; 210 - case '}': 211 - case ']': 212 - #ifdef JSMN_STRICT 213 - if (expecting_item) 214 - return JSMN_ERROR_INVAL; 215 - #endif 216 - type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 217 - for (i = parser->toknext - 1; i >= 0; i--) { 218 - token = &tokens[i]; 219 - if (token->start != -1 && token->end == -1) { 220 - if (token->type != type) 221 - return JSMN_ERROR_INVAL; 222 - parser->toksuper = -1; 223 - token->end = parser->pos + 1; 224 - break; 225 - } 226 - } 227 - /* Error if unmatched closing bracket */ 228 - if (i == -1) 229 - return JSMN_ERROR_INVAL; 230 - for (; i >= 0; i--) { 231 - token = &tokens[i]; 232 - if (token->start != -1 && token->end == -1) { 233 - parser->toksuper = i; 234 - break; 235 - } 236 - } 237 - break; 238 - case '\"': 239 - #ifdef JSMN_STRICT 240 - if (!expecting_item) 241 - return JSMN_ERROR_INVAL; 242 - expecting_item = 0; 243 - #endif 244 - r = jsmn_parse_string(parser, js, len, tokens, 245 - num_tokens); 246 - if (r < 0) 247 - return r; 248 - if (parser->toksuper != -1) 249 - tokens[parser->toksuper].size++; 250 - break; 251 - case '\t': 252 - case '\r': 253 - case '\n': 254 - case ' ': 255 - break; 256 - #ifdef JSMN_STRICT 257 - case ':': 258 - case ',': 259 - if (expecting_item) 260 - return JSMN_ERROR_INVAL; 261 - expecting_item = 1; 262 - break; 263 - /* 264 - * In strict mode primitives are: 265 - * numbers and booleans. 266 - */ 267 - case '-': 268 - case '0': 269 - case '1': 270 - case '2': 271 - case '3': 272 - case '4': 273 - case '5': 274 - case '6': 275 - case '7': 276 - case '8': 277 - case '9': 278 - case 't': 279 - case 'f': 280 - case 'n': 281 - #else 282 - case ':': 283 - case ',': 284 - break; 285 - /* 286 - * In non-strict mode every unquoted value 287 - * is a primitive. 288 - */ 289 - /*FALL THROUGH */ 290 - default: 291 - #endif 292 - 293 - #ifdef JSMN_STRICT 294 - if (!expecting_item) 295 - return JSMN_ERROR_INVAL; 296 - expecting_item = 0; 297 - #endif 298 - r = jsmn_parse_primitive(parser, js, len, tokens, 299 - num_tokens); 300 - if (r < 0) 301 - return r; 302 - if (parser->toksuper != -1) 303 - tokens[parser->toksuper].size++; 304 - break; 305 - 306 - #ifdef JSMN_STRICT 307 - /* Unexpected char in strict mode */ 308 - default: 309 - return JSMN_ERROR_INVAL; 310 - #endif 311 - } 312 - } 313 - 314 - for (i = parser->toknext - 1; i >= 0; i--) { 315 - /* Unmatched opened object or array */ 316 - if (tokens[i].start != -1 && tokens[i].end == -1) 317 - return JSMN_ERROR_PART; 318 - } 319 - 320 - #ifdef JSMN_STRICT 321 - return expecting_item ? JSMN_ERROR_INVAL : JSMN_SUCCESS; 322 - #else 323 - return JSMN_SUCCESS; 324 - #endif 325 - } 326 - 327 - /* 328 - * Creates a new parser based over a given buffer with an array of tokens 329 - * available. 330 - */ 331 - void jsmn_init(jsmn_parser *parser) 332 - { 333 - parser->pos = 0; 334 - parser->toknext = 0; 335 - parser->toksuper = -1; 336 - } 337 - 338 - const char *jsmn_strerror(jsmnerr_t err) 339 - { 340 - switch (err) { 341 - case JSMN_ERROR_NOMEM: 342 - return "No enough tokens"; 343 - case JSMN_ERROR_INVAL: 344 - return "Invalid character inside JSON string"; 345 - case JSMN_ERROR_PART: 346 - return "The string is not a full JSON packet, more bytes expected"; 347 - case JSMN_SUCCESS: 348 - return "Success"; 349 - default: 350 - return "Unknown json error"; 351 - } 352 - }
-68
tools/perf/pmu-events/jsmn.h
··· 1 - /* SPDX-License-Identifier: MIT */ 2 - #ifndef __JSMN_H_ 3 - #define __JSMN_H_ 4 - 5 - /* 6 - * JSON type identifier. Basic types are: 7 - * o Object 8 - * o Array 9 - * o String 10 - * o Other primitive: number, boolean (true/false) or null 11 - */ 12 - typedef enum { 13 - JSMN_PRIMITIVE = 0, 14 - JSMN_OBJECT = 1, 15 - JSMN_ARRAY = 2, 16 - JSMN_STRING = 3 17 - } jsmntype_t; 18 - 19 - typedef enum { 20 - /* Not enough tokens were provided */ 21 - JSMN_ERROR_NOMEM = -1, 22 - /* Invalid character inside JSON string */ 23 - JSMN_ERROR_INVAL = -2, 24 - /* The string is not a full JSON packet, more bytes expected */ 25 - JSMN_ERROR_PART = -3, 26 - /* Everything was fine */ 27 - JSMN_SUCCESS = 0 28 - } jsmnerr_t; 29 - 30 - /* 31 - * JSON token description. 32 - * @param type type (object, array, string etc.) 33 - * @param start start position in JSON data string 34 - * @param end end position in JSON data string 35 - */ 36 - typedef struct { 37 - jsmntype_t type; 38 - int start; 39 - int end; 40 - int size; 41 - } jsmntok_t; 42 - 43 - /* 44 - * JSON parser. Contains an array of token blocks available. Also stores 45 - * the string being parsed now and current position in that string 46 - */ 47 - typedef struct { 48 - unsigned int pos; /* offset in the JSON string */ 49 - int toknext; /* next token to allocate */ 50 - int toksuper; /* superior token node, e.g parent object or array */ 51 - } jsmn_parser; 52 - 53 - /* 54 - * Create JSON parser over an array of tokens 55 - */ 56 - void jsmn_init(jsmn_parser *parser); 57 - 58 - /* 59 - * Run JSON parser. It parses a JSON data string into and array of tokens, 60 - * each describing a single JSON object. 61 - */ 62 - jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, 63 - size_t len, 64 - jsmntok_t *tokens, unsigned int num_tokens); 65 - 66 - const char *jsmn_strerror(jsmnerr_t err); 67 - 68 - #endif /* __JSMN_H_ */
-162
tools/perf/pmu-events/json.c
··· 1 - /* Parse JSON files using the JSMN parser. */ 2 - 3 - /* 4 - * Copyright (c) 2014, Intel Corporation 5 - * All rights reserved. 6 - * 7 - * Redistribution and use in source and binary forms, with or without 8 - * modification, are permitted provided that the following conditions are met: 9 - * 10 - * 1. Redistributions of source code must retain the above copyright notice, 11 - * this list of conditions and the following disclaimer. 12 - * 13 - * 2. Redistributions in binary form must reproduce the above copyright 14 - * notice, this list of conditions and the following disclaimer in the 15 - * documentation and/or other materials provided with the distribution. 16 - * 17 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 - * OF THE POSSIBILITY OF SUCH DAMAGE. 29 - */ 30 - 31 - #include <stdlib.h> 32 - #include <string.h> 33 - #include <sys/mman.h> 34 - #include <sys/stat.h> 35 - #include <fcntl.h> 36 - #include <stdio.h> 37 - #include <errno.h> 38 - #include <unistd.h> 39 - #include "jsmn.h" 40 - #include "json.h" 41 - #include <linux/kernel.h> 42 - 43 - 44 - static char *mapfile(const char *fn, size_t *size) 45 - { 46 - unsigned ps = sysconf(_SC_PAGESIZE); 47 - struct stat st; 48 - char *map = NULL; 49 - int err; 50 - int fd = open(fn, O_RDONLY); 51 - 52 - if (fd < 0 && verbose > 0 && fn) { 53 - pr_err("Error opening events file '%s': %s\n", fn, 54 - strerror(errno)); 55 - } 56 - 57 - if (fd < 0) 58 - return NULL; 59 - err = fstat(fd, &st); 60 - if (err < 0) 61 - goto out; 62 - *size = st.st_size; 63 - map = mmap(NULL, 64 - (st.st_size + ps - 1) & ~(ps - 1), 65 - PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 66 - if (map == MAP_FAILED) 67 - map = NULL; 68 - out: 69 - close(fd); 70 - return map; 71 - } 72 - 73 - static void unmapfile(char *map, size_t size) 74 - { 75 - unsigned ps = sysconf(_SC_PAGESIZE); 76 - munmap(map, roundup(size, ps)); 77 - } 78 - 79 - /* 80 - * Parse json file using jsmn. Return array of tokens, 81 - * and mapped file. Caller needs to free array. 82 - */ 83 - jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len) 84 - { 85 - jsmn_parser parser; 86 - jsmntok_t *tokens; 87 - jsmnerr_t res; 88 - unsigned sz; 89 - 90 - *map = mapfile(fn, size); 91 - if (!*map) 92 - return NULL; 93 - /* Heuristic */ 94 - sz = *size * 16; 95 - tokens = malloc(sz); 96 - if (!tokens) 97 - goto error; 98 - jsmn_init(&parser); 99 - res = jsmn_parse(&parser, *map, *size, tokens, 100 - sz / sizeof(jsmntok_t)); 101 - if (res != JSMN_SUCCESS) { 102 - pr_err("%s: json error %s\n", fn, jsmn_strerror(res)); 103 - goto error_free; 104 - } 105 - if (len) 106 - *len = parser.toknext; 107 - return tokens; 108 - error_free: 109 - free(tokens); 110 - error: 111 - unmapfile(*map, *size); 112 - return NULL; 113 - } 114 - 115 - void free_json(char *map, size_t size, jsmntok_t *tokens) 116 - { 117 - free(tokens); 118 - unmapfile(map, size); 119 - } 120 - 121 - static int countchar(char *map, char c, int end) 122 - { 123 - int i; 124 - int count = 0; 125 - for (i = 0; i < end; i++) 126 - if (map[i] == c) 127 - count++; 128 - return count; 129 - } 130 - 131 - /* Return line number of a jsmn token */ 132 - int json_line(char *map, jsmntok_t *t) 133 - { 134 - return countchar(map, '\n', t->start) + 1; 135 - } 136 - 137 - static const char * const jsmn_types[] = { 138 - [JSMN_PRIMITIVE] = "primitive", 139 - [JSMN_ARRAY] = "array", 140 - [JSMN_OBJECT] = "object", 141 - [JSMN_STRING] = "string" 142 - }; 143 - 144 - #define LOOKUP(a, i) ((i) < (sizeof(a)/sizeof(*(a))) ? ((a)[i]) : "?") 145 - 146 - /* Return type name of a jsmn token */ 147 - const char *json_name(jsmntok_t *t) 148 - { 149 - return LOOKUP(jsmn_types, t->type); 150 - } 151 - 152 - int json_len(jsmntok_t *t) 153 - { 154 - return t->end - t->start; 155 - } 156 - 157 - /* Is string t equal to s? */ 158 - int json_streq(char *map, jsmntok_t *t, const char *s) 159 - { 160 - unsigned len = json_len(t); 161 - return len == strlen(s) && !strncasecmp(map + t->start, s, len); 162 - }
-39
tools/perf/pmu-events/json.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef JSON_H 3 - #define JSON_H 1 4 - 5 - #include "jsmn.h" 6 - 7 - jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len); 8 - void free_json(char *map, size_t size, jsmntok_t *tokens); 9 - int json_line(char *map, jsmntok_t *t); 10 - const char *json_name(jsmntok_t *t); 11 - int json_streq(char *map, jsmntok_t *t, const char *s); 12 - int json_len(jsmntok_t *t); 13 - 14 - extern int verbose; 15 - 16 - #include <stdbool.h> 17 - 18 - extern int eprintf(int level, int var, const char *fmt, ...); 19 - #define pr_fmt(fmt) fmt 20 - 21 - #define pr_err(fmt, ...) \ 22 - eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__) 23 - 24 - #define pr_info(fmt, ...) \ 25 - eprintf(1, verbose, pr_fmt(fmt), ##__VA_ARGS__) 26 - 27 - #define pr_debug(fmt, ...) \ 28 - eprintf(2, verbose, pr_fmt(fmt), ##__VA_ARGS__) 29 - 30 - #ifndef roundup 31 - #define roundup(x, y) ( \ 32 - { \ 33 - const typeof(y) __y = y; \ 34 - (((x) + (__y - 1)) / __y) * __y; \ 35 - } \ 36 - ) 37 - #endif 38 - 39 - #endif