153548f91SRobert Mustacchi /*
253548f91SRobert Mustacchi * This file and its contents are supplied under the terms of the
353548f91SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
453548f91SRobert Mustacchi * You may only use this file in accordance with the terms of version
553548f91SRobert Mustacchi * 1.0 of the CDDL.
653548f91SRobert Mustacchi *
753548f91SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
853548f91SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
953548f91SRobert Mustacchi * http://www.illumos.org/license/CDDL.
1053548f91SRobert Mustacchi */
1153548f91SRobert Mustacchi
1253548f91SRobert Mustacchi /*
131ad658abSJohn Levon * Copyright (c) 2019, Joyent, Inc.
1453548f91SRobert Mustacchi */
1553548f91SRobert Mustacchi
1653548f91SRobert Mustacchi /*
17*3db3a4acSRobert Mustacchi * This program transforms Intel perfmon and AMD PMC data files into C files and
18*3db3a4acSRobert Mustacchi * manual pages.
1953548f91SRobert Mustacchi */
2053548f91SRobert Mustacchi
2153548f91SRobert Mustacchi #include <stdio.h>
2253548f91SRobert Mustacchi #include <stdarg.h>
2353548f91SRobert Mustacchi #include <unistd.h>
2453548f91SRobert Mustacchi #include <err.h>
2553548f91SRobert Mustacchi #include <libgen.h>
2653548f91SRobert Mustacchi #include <libnvpair.h>
2753548f91SRobert Mustacchi #include <strings.h>
2853548f91SRobert Mustacchi #include <errno.h>
2953548f91SRobert Mustacchi #include <limits.h>
3053548f91SRobert Mustacchi #include <sys/mman.h>
3153548f91SRobert Mustacchi #include <sys/param.h>
3253548f91SRobert Mustacchi #include <assert.h>
3353548f91SRobert Mustacchi #include <ctype.h>
3453548f91SRobert Mustacchi #include <sys/types.h>
3553548f91SRobert Mustacchi #include <sys/stat.h>
3653548f91SRobert Mustacchi #include <fcntl.h>
37*3db3a4acSRobert Mustacchi #include <dirent.h>
3853548f91SRobert Mustacchi
3953548f91SRobert Mustacchi #include <json_nvlist.h>
4053548f91SRobert Mustacchi
4153548f91SRobert Mustacchi #define EXIT_USAGE 2
425fc40de0SRobert Mustacchi #define CPROC_MAX_STEPPINGS 16
4353548f91SRobert Mustacchi
44*3db3a4acSRobert Mustacchi typedef enum {
45*3db3a4acSRobert Mustacchi CPCGEN_MODE_UNKNOWN = 0,
46*3db3a4acSRobert Mustacchi CPCGEN_MODE_INTEL,
47*3db3a4acSRobert Mustacchi CPCGEN_MODE_AMD
48*3db3a4acSRobert Mustacchi } cpc_mode_t;
49*3db3a4acSRobert Mustacchi
5053548f91SRobert Mustacchi typedef struct cpc_proc {
5153548f91SRobert Mustacchi struct cpc_proc *cproc_next;
5253548f91SRobert Mustacchi uint_t cproc_family;
5353548f91SRobert Mustacchi uint_t cproc_model;
545fc40de0SRobert Mustacchi uint_t cproc_nsteps;
555fc40de0SRobert Mustacchi uint_t cproc_steppings[CPROC_MAX_STEPPINGS];
5653548f91SRobert Mustacchi } cpc_proc_t;
5753548f91SRobert Mustacchi
5853548f91SRobert Mustacchi typedef enum cpc_file_type {
5953548f91SRobert Mustacchi CPC_FILE_CORE = 1 << 0,
6053548f91SRobert Mustacchi CPC_FILE_OFF_CORE = 1 << 1,
6153548f91SRobert Mustacchi CPC_FILE_UNCORE = 1 << 2,
6253548f91SRobert Mustacchi CPC_FILE_FP_MATH = 1 << 3,
6353548f91SRobert Mustacchi CPC_FILE_UNCORE_EXP = 1 << 4
6453548f91SRobert Mustacchi } cpc_type_t;
6553548f91SRobert Mustacchi
6653548f91SRobert Mustacchi typedef struct cpc_map {
6753548f91SRobert Mustacchi struct cpc_map *cmap_next;
6853548f91SRobert Mustacchi cpc_type_t cmap_type;
6953548f91SRobert Mustacchi nvlist_t *cmap_data;
7053548f91SRobert Mustacchi char *cmap_path;
7153548f91SRobert Mustacchi const char *cmap_name;
7253548f91SRobert Mustacchi cpc_proc_t *cmap_procs;
7353548f91SRobert Mustacchi } cpc_map_t;
7453548f91SRobert Mustacchi
7553548f91SRobert Mustacchi typedef struct cpc_whitelist {
7653548f91SRobert Mustacchi const char *cwhite_short;
7753548f91SRobert Mustacchi const char *cwhite_human;
7853548f91SRobert Mustacchi uint_t cwhite_mask;
7953548f91SRobert Mustacchi } cpc_whitelist_t;
8053548f91SRobert Mustacchi
8153548f91SRobert Mustacchi /*
8253548f91SRobert Mustacchi * List of architectures that we support generating this data for. This is done
8353548f91SRobert Mustacchi * so that processors that illumos doesn't support or run on aren't generated
8453548f91SRobert Mustacchi * (generally the Xeon Phi).
8553548f91SRobert Mustacchi */
86*3db3a4acSRobert Mustacchi static cpc_whitelist_t cpcgen_intel_whitelist[] = {
8753548f91SRobert Mustacchi /* Nehalem */
8853548f91SRobert Mustacchi { "NHM-EP", "nhm_ep", CPC_FILE_CORE },
8953548f91SRobert Mustacchi { "NHM-EX", "nhm_ex", CPC_FILE_CORE },
9053548f91SRobert Mustacchi /* Westmere */
9153548f91SRobert Mustacchi { "WSM-EP-DP", "wsm_ep_dp", CPC_FILE_CORE },
9253548f91SRobert Mustacchi { "WSM-EP-SP", "wsm_ep_sp", CPC_FILE_CORE },
9353548f91SRobert Mustacchi { "WSM-EX", "wsm_ex", CPC_FILE_CORE },
9453548f91SRobert Mustacchi /* Sandy Bridge */
9553548f91SRobert Mustacchi { "SNB", "snb", CPC_FILE_CORE },
9653548f91SRobert Mustacchi { "JKT", "jkt", CPC_FILE_CORE },
9753548f91SRobert Mustacchi /* Ivy Bridge */
9853548f91SRobert Mustacchi { "IVB", "ivb", CPC_FILE_CORE },
9953548f91SRobert Mustacchi { "IVT", "ivt", CPC_FILE_CORE },
10053548f91SRobert Mustacchi /* Haswell */
10153548f91SRobert Mustacchi { "HSW", "hsw", CPC_FILE_CORE },
10253548f91SRobert Mustacchi { "HSX", "hsx", CPC_FILE_CORE },
10353548f91SRobert Mustacchi /* Broadwell */
10453548f91SRobert Mustacchi { "BDW", "bdw", CPC_FILE_CORE },
10553548f91SRobert Mustacchi { "BDW-DE", "bdw_de", CPC_FILE_CORE },
10653548f91SRobert Mustacchi { "BDX", "bdx", CPC_FILE_CORE },
10753548f91SRobert Mustacchi /* Skylake */
10853548f91SRobert Mustacchi { "SKL", "skl", CPC_FILE_CORE },
10953548f91SRobert Mustacchi { "SKX", "skx", CPC_FILE_CORE },
1105fc40de0SRobert Mustacchi /* Cascade Lake */
1115fc40de0SRobert Mustacchi { "CLX", "clx", CPC_FILE_CORE },
11253548f91SRobert Mustacchi /* Atom */
11353548f91SRobert Mustacchi { "BNL", "bnl", CPC_FILE_CORE },
11453548f91SRobert Mustacchi { "SLM", "slm", CPC_FILE_CORE },
11553548f91SRobert Mustacchi { "GLM", "glm", CPC_FILE_CORE },
11653548f91SRobert Mustacchi { "GLP", "glp", CPC_FILE_CORE },
11753548f91SRobert Mustacchi { NULL }
11853548f91SRobert Mustacchi };
11953548f91SRobert Mustacchi
12053548f91SRobert Mustacchi typedef struct cpc_papi {
12153548f91SRobert Mustacchi const char *cpapi_intc;
12253548f91SRobert Mustacchi const char *cpapi_papi;
12353548f91SRobert Mustacchi } cpc_papi_t;
12453548f91SRobert Mustacchi
12553548f91SRobert Mustacchi /*
12653548f91SRobert Mustacchi * This table maps events with an Intel specific name to the corresponding PAPI
1275fc40de0SRobert Mustacchi * name. There may be multiple Intel events which map to the same PAPI event.
12853548f91SRobert Mustacchi * This is usually because different processors have different names for an
12953548f91SRobert Mustacchi * event. We use the title as opposed to the event codes because those can
13053548f91SRobert Mustacchi * change somewhat arbitrarily between processor generations.
13153548f91SRobert Mustacchi */
132*3db3a4acSRobert Mustacchi static cpc_papi_t cpcgen_intel_papi_map[] = {
13353548f91SRobert Mustacchi { "CPU_CLK_UNHALTED.THREAD_P", "PAPI_tot_cyc" },
13453548f91SRobert Mustacchi { "INST_RETIRED.ANY_P", "PAPI_tot_ins" },
13553548f91SRobert Mustacchi { "BR_INST_RETIRED.ALL_BRANCHES", "PAPI_br_ins" },
13653548f91SRobert Mustacchi { "BR_MISP_RETIRED.ALL_BRANCHES", "PAPI_br_msp" },
13753548f91SRobert Mustacchi { "BR_INST_RETIRED.CONDITIONAL", "PAPI_br_cn" },
13853548f91SRobert Mustacchi { "CYCLE_ACTIVITY.CYCLES_L1D_MISS", "PAPI_l1_dcm" },
13953548f91SRobert Mustacchi { "L1I.HITS", "PAPI_l1_ich" },
14053548f91SRobert Mustacchi { "ICACHE.HIT", "PAPI_l1_ich" },
14153548f91SRobert Mustacchi { "L1I.MISS", "PAPI_L1_icm" },
14253548f91SRobert Mustacchi { "ICACHE.MISSES", "PAPI_l1_icm" },
14353548f91SRobert Mustacchi { "L1I.READS", "PAPI_l1_ica" },
14453548f91SRobert Mustacchi { "ICACHE.ACCESSES", "PAPI_l1_ica" },
14553548f91SRobert Mustacchi { "L1I.READS", "PAPI_l1_icr" },
14653548f91SRobert Mustacchi { "ICACHE.ACCESSES", "PAPI_l1_icr" },
14753548f91SRobert Mustacchi { "L2_RQSTS.CODE_RD_MISS", "PAPI_l2_icm" },
14853548f91SRobert Mustacchi { "L2_RQSTS.MISS", "PAPI_l2_tcm" },
14953548f91SRobert Mustacchi { "ITLB_MISSES.MISS_CAUSES_A_WALK", "PAPI_tlb_im" },
15053548f91SRobert Mustacchi { "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK", "PAPI_tlb_dm" },
15153548f91SRobert Mustacchi { "PAGE_WALKS.D_SIDE_WALKS", "PAPI_tlb_dm" },
15253548f91SRobert Mustacchi { "PAGE_WALKS.I_SIDE_WALKS", "PAPI_tlb_im" },
15353548f91SRobert Mustacchi { "PAGE_WALKS.WALKS", "PAPI_tlb_tl" },
15453548f91SRobert Mustacchi { "INST_QUEUE_WRITES", "PAPI_tot_iis" },
15553548f91SRobert Mustacchi { "MEM_INST_RETIRED.STORES" "PAPI_sr_ins" },
15653548f91SRobert Mustacchi { "MEM_INST_RETIRED.LOADS" "PAPI_ld_ins" },
15753548f91SRobert Mustacchi { NULL, NULL }
15853548f91SRobert Mustacchi };
15953548f91SRobert Mustacchi
16053548f91SRobert Mustacchi typedef struct cpcgen_ops {
161*3db3a4acSRobert Mustacchi void (*cgen_op_gather)(const char *, const char *);
162*3db3a4acSRobert Mustacchi void (*cgen_op_common)(int);
16353548f91SRobert Mustacchi char *(*cgen_op_name)(cpc_map_t *);
164*3db3a4acSRobert Mustacchi boolean_t (*cgen_op_skip)(nvlist_t *, const char *, uint_t);
16553548f91SRobert Mustacchi boolean_t (*cgen_op_file_before)(FILE *, cpc_map_t *);
16653548f91SRobert Mustacchi boolean_t (*cgen_op_file_after)(FILE *, cpc_map_t *);
16753548f91SRobert Mustacchi boolean_t (*cgen_op_event)(FILE *, nvlist_t *, const char *, uint32_t);
16853548f91SRobert Mustacchi } cpcgen_ops_t;
16953548f91SRobert Mustacchi
17053548f91SRobert Mustacchi static cpcgen_ops_t cpcgen_ops;
171*3db3a4acSRobert Mustacchi static const char *cpcgen_intel_mapfile = "/mapfile.csv";
17253548f91SRobert Mustacchi static const char *cpcgen_progname;
17353548f91SRobert Mustacchi static cpc_map_t *cpcgen_maps;
174*3db3a4acSRobert Mustacchi static cpc_mode_t cpcgen_mode = CPCGEN_MODE_UNKNOWN;
17553548f91SRobert Mustacchi
17653548f91SRobert Mustacchi /*
17753548f91SRobert Mustacchi * Constants used for generating data.
17853548f91SRobert Mustacchi */
17953548f91SRobert Mustacchi /* BEGIN CSTYLED */
180*3db3a4acSRobert Mustacchi static const char *cpcgen_cfile_intel_header = ""
18153548f91SRobert Mustacchi "/*\n"
18253548f91SRobert Mustacchi " * Copyright (c) 2018, Intel Corporation\n"
18353548f91SRobert Mustacchi " * Copyright (c) 2018, Joyent, Inc\n"
18453548f91SRobert Mustacchi " * All rights reserved.\n"
18553548f91SRobert Mustacchi " *\n"
18653548f91SRobert Mustacchi " * Redistribution and use in source and binary forms, with or without\n"
18753548f91SRobert Mustacchi " * modification, are permitted provided that the following conditions are met:\n"
18853548f91SRobert Mustacchi " * \n"
18953548f91SRobert Mustacchi " * 1. Redistributions of source code must retain the above copyright notice,\n"
19053548f91SRobert Mustacchi " * this list of conditions and the following disclaimer.\n"
19153548f91SRobert Mustacchi " * \n"
19253548f91SRobert Mustacchi " * 2. Redistributions in binary form must reproduce the above copyright \n"
19353548f91SRobert Mustacchi " * notice, this list of conditions and the following disclaimer in the\n"
19453548f91SRobert Mustacchi " * documentation and/or other materials provided with the distribution.\n"
19553548f91SRobert Mustacchi " * \n"
19653548f91SRobert Mustacchi " * 3. Neither the name of the Intel Corporation nor the names of its \n"
19753548f91SRobert Mustacchi " * contributors may be used to endorse or promote products derived from\n"
19853548f91SRobert Mustacchi " * this software without specific prior written permission.\n"
19953548f91SRobert Mustacchi " *\n"
20053548f91SRobert Mustacchi " * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n"
20153548f91SRobert Mustacchi " * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
20253548f91SRobert Mustacchi " * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
20353548f91SRobert Mustacchi " * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n"
20453548f91SRobert Mustacchi " * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n"
20553548f91SRobert Mustacchi " * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n"
20653548f91SRobert Mustacchi " * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n"
20753548f91SRobert Mustacchi " * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n"
20853548f91SRobert Mustacchi " * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n"
20953548f91SRobert Mustacchi " * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
21053548f91SRobert Mustacchi " * POSSIBILITY OF SUCH DAMAGE.\n"
21153548f91SRobert Mustacchi " *\n"
21253548f91SRobert Mustacchi " * This file was automatically generated by cpcgen from the data file\n"
21353548f91SRobert Mustacchi " * data/perfmon%s\n"
21453548f91SRobert Mustacchi " *\n"
21553548f91SRobert Mustacchi " * Do not modify this file. Your changes will be lost!\n"
21653548f91SRobert Mustacchi " */\n"
21753548f91SRobert Mustacchi "\n";
21853548f91SRobert Mustacchi /* END CSTYLED */
21953548f91SRobert Mustacchi
220*3db3a4acSRobert Mustacchi static const char *cpcgen_cfile_intel_table_start = ""
22153548f91SRobert Mustacchi "#include <core_pcbe_table.h>\n"
22253548f91SRobert Mustacchi "\n"
22353548f91SRobert Mustacchi "const struct events_table_t pcbe_core_events_%s[] = {\n";
22453548f91SRobert Mustacchi
225*3db3a4acSRobert Mustacchi static const char *cpcgen_cfile_intel_table_end = ""
22653548f91SRobert Mustacchi "\t{ NT_END, 0, 0, \"\" }\n"
22753548f91SRobert Mustacchi "};\n";
22853548f91SRobert Mustacchi
22953548f91SRobert Mustacchi /* BEGIN CSTYLED */
230*3db3a4acSRobert Mustacchi static const char *cpcgen_manual_intel_intel_header = ""
23153548f91SRobert Mustacchi ".\\\" Copyright (c) 2018, Intel Corporation \n"
23253548f91SRobert Mustacchi ".\\\" Copyright (c) 2018, Joyent, Inc.\n"
23353548f91SRobert Mustacchi ".\\\" All rights reserved.\n"
23453548f91SRobert Mustacchi ".\\\"\n"
23553548f91SRobert Mustacchi ".\\\" Redistribution and use in source and binary forms, with or without \n"
23653548f91SRobert Mustacchi ".\\\" modification, are permitted provided that the following conditions are met:\n"
23753548f91SRobert Mustacchi ".\\\"\n"
23853548f91SRobert Mustacchi ".\\\" 1. Redistributions of source code must retain the above copyright notice,\n"
23953548f91SRobert Mustacchi ".\\\" this list of conditions and the following disclaimer.\n"
24053548f91SRobert Mustacchi ".\\\"\n"
24153548f91SRobert Mustacchi ".\\\" 2. Redistributions in binary form must reproduce the above copyright\n"
24253548f91SRobert Mustacchi ".\\\" notice, this list of conditions and the following disclaimer in the\n"
24353548f91SRobert Mustacchi ".\\\" documentation and/or other materials provided with the distribution.\n"
24453548f91SRobert Mustacchi ".\\\"\n"
24553548f91SRobert Mustacchi ".\\\" 3. Neither the name of the Intel Corporation nor the names of its\n"
24653548f91SRobert Mustacchi ".\\\" contributors may be used to endorse or promote products derived from\n"
24753548f91SRobert Mustacchi ".\\\" this software without specific prior written permission.\n"
24853548f91SRobert Mustacchi ".\\\"\n"
24953548f91SRobert Mustacchi ".\\\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n"
25053548f91SRobert Mustacchi ".\\\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
25153548f91SRobert Mustacchi ".\\\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
25253548f91SRobert Mustacchi ".\\\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n"
25353548f91SRobert Mustacchi ".\\\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n"
25453548f91SRobert Mustacchi ".\\\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n"
25553548f91SRobert Mustacchi ".\\\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n"
25653548f91SRobert Mustacchi ".\\\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n"
25753548f91SRobert Mustacchi ".\\\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n"
25853548f91SRobert Mustacchi ".\\\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
25953548f91SRobert Mustacchi ".\\\" POSSIBILITY OF SUCH DAMAGE.\n"
26053548f91SRobert Mustacchi ".\\\"\n"
26153548f91SRobert Mustacchi ".\\\" This file was automatically generated by cpcgen from the data file\n"
26253548f91SRobert Mustacchi ".\\\" data/perfmon%s\n"
26353548f91SRobert Mustacchi ".\\\"\n"
26453548f91SRobert Mustacchi ".\\\" Do not modify this file. Your changes will be lost!\n"
26553548f91SRobert Mustacchi ".\\\"\n"
26653548f91SRobert Mustacchi ".\\\" We would like to thank Intel for providing the perfmon data for use in\n"
26753548f91SRobert Mustacchi ".\\\" our manual pages.\n"
26853548f91SRobert Mustacchi ".Dd June 18, 2018\n"
26953548f91SRobert Mustacchi ".Dt %s_EVENTS 3CPC\n"
27053548f91SRobert Mustacchi ".Os\n"
27153548f91SRobert Mustacchi ".Sh NAME\n"
27253548f91SRobert Mustacchi ".Nm %s_events\n"
27353548f91SRobert Mustacchi ".Nd processor model specific performance counter events\n"
27453548f91SRobert Mustacchi ".Sh DESCRIPTION\n"
27553548f91SRobert Mustacchi "This manual page describes events specific to the following Intel CPU\n"
27653548f91SRobert Mustacchi "models and is derived from Intel's perfmon data.\n"
27753548f91SRobert Mustacchi "For more information, please consult the Intel Software Developer's Manual "
27853548f91SRobert Mustacchi "or Intel's perfmon website.\n"
27953548f91SRobert Mustacchi ".Pp\n"
28053548f91SRobert Mustacchi "CPU models described by this document:\n"
28153548f91SRobert Mustacchi ".Bl -bullet\n";
28253548f91SRobert Mustacchi /* END CSTYLED */
28353548f91SRobert Mustacchi
284*3db3a4acSRobert Mustacchi static const char *cpcgen_manual_intel_data = ""
28553548f91SRobert Mustacchi ".El\n"
28653548f91SRobert Mustacchi ".Pp\n"
28753548f91SRobert Mustacchi "The following events are supported:\n"
28853548f91SRobert Mustacchi ".Bl -tag -width Sy\n";
28953548f91SRobert Mustacchi
290*3db3a4acSRobert Mustacchi static const char *cpcgen_manual_intel_trailer = ""
29153548f91SRobert Mustacchi ".El\n"
29253548f91SRobert Mustacchi ".Sh SEE ALSO\n"
29353548f91SRobert Mustacchi ".Xr cpc 3CPC\n"
29453548f91SRobert Mustacchi ".Pp\n"
29553548f91SRobert Mustacchi ".Lk https://download.01.org/perfmon/index/";
29653548f91SRobert Mustacchi
297*3db3a4acSRobert Mustacchi static const char *cpcgen_cfile_cddl_header = ""
298*3db3a4acSRobert Mustacchi "/*\n"
299*3db3a4acSRobert Mustacchi " * This file and its contents are supplied under the terms of the\n"
300*3db3a4acSRobert Mustacchi " * Common Development and Distribution License (\"CDDL\"), version 1.0.\n"
301*3db3a4acSRobert Mustacchi " * You may only use this file in accordance with the terms of version\n"
302*3db3a4acSRobert Mustacchi " * 1.0 of the CDDL.\n"
303*3db3a4acSRobert Mustacchi " *\n"
304*3db3a4acSRobert Mustacchi " * A full copy of the text of the CDDL should have accompanied this\n"
305*3db3a4acSRobert Mustacchi " * source. A copy of the CDDL is also available via the Internet at\n"
306*3db3a4acSRobert Mustacchi " * http://www.illumos.org/license/CDDL.\n"
307*3db3a4acSRobert Mustacchi " */\n"
308*3db3a4acSRobert Mustacchi "\n"
309*3db3a4acSRobert Mustacchi "/*\n"
310*3db3a4acSRobert Mustacchi " * Copyright 2019 Joyent, Inc\n"
311*3db3a4acSRobert Mustacchi " */\n"
312*3db3a4acSRobert Mustacchi "\n"
313*3db3a4acSRobert Mustacchi "/*\n"
314*3db3a4acSRobert Mustacchi " * This file was automatically generated by cpcgen.\n"
315*3db3a4acSRobert Mustacchi " */\n"
316*3db3a4acSRobert Mustacchi "\n"
317*3db3a4acSRobert Mustacchi "/*\n"
318*3db3a4acSRobert Mustacchi " * Do not modify this file. Your changes will be lost!\n"
319*3db3a4acSRobert Mustacchi " */\n"
320*3db3a4acSRobert Mustacchi "\n";
321*3db3a4acSRobert Mustacchi
322*3db3a4acSRobert Mustacchi static const char *cpcgen_manual_amd_header = ""
323*3db3a4acSRobert Mustacchi ".\\\" This file was automatically generated by cpcgen from the data file\n"
324*3db3a4acSRobert Mustacchi ".\\\" data/amdpmc/%s\n"
325*3db3a4acSRobert Mustacchi ".\\\"\n"
326*3db3a4acSRobert Mustacchi ".\\\" Do not modify this file. Your changes will be lost!\n"
327*3db3a4acSRobert Mustacchi ".\\\"\n"
328*3db3a4acSRobert Mustacchi ".\\\" We would like to thank AMD for providing the PMC data for use in\n"
329*3db3a4acSRobert Mustacchi ".\\\" our manual pages.\n"
330*3db3a4acSRobert Mustacchi ".Dd March 25, 2019\n"
331*3db3a4acSRobert Mustacchi ".Dt AMD_%s_EVENTS 3CPC\n"
332*3db3a4acSRobert Mustacchi ".Os\n"
333*3db3a4acSRobert Mustacchi ".Sh NAME\n"
334*3db3a4acSRobert Mustacchi ".Nm amd_%s_events\n"
335*3db3a4acSRobert Mustacchi ".Nd AMD family %s processor performance monitoring events\n"
336*3db3a4acSRobert Mustacchi ".Sh DESCRIPTION\n"
337*3db3a4acSRobert Mustacchi "This manual page describes events specfic to AMD family %s processors.\n"
338*3db3a4acSRobert Mustacchi "For more information, please consult the appropriate AMD BIOS and Kernel\n"
339*3db3a4acSRobert Mustacchi "Developer's guide or Open-Source Register Reference manual.\n"
340*3db3a4acSRobert Mustacchi ".Pp\n"
341*3db3a4acSRobert Mustacchi "Each of the events listed below includes the AMD mnemonic which matches\n"
342*3db3a4acSRobert Mustacchi "the name found in the AMD manual and a brief summary of the event.\n"
343*3db3a4acSRobert Mustacchi "If available, a more detailed description of the event follows and then\n"
344*3db3a4acSRobert Mustacchi "any additional unit values that modify the event.\n"
345*3db3a4acSRobert Mustacchi "Each unit can be combined to create a new event in the system by placing\n"
346*3db3a4acSRobert Mustacchi "the '.' character between the event name and the unit name.\n"
347*3db3a4acSRobert Mustacchi ".Pp\n"
348*3db3a4acSRobert Mustacchi "The following events are supported:\n"
349*3db3a4acSRobert Mustacchi ".Bl -tag -width Sy\n";
350*3db3a4acSRobert Mustacchi
351*3db3a4acSRobert Mustacchi static const char *cpcgen_manual_amd_trailer = ""
352*3db3a4acSRobert Mustacchi ".El\n"
353*3db3a4acSRobert Mustacchi ".Sh SEE ALSO\n"
354*3db3a4acSRobert Mustacchi ".Xr cpc 3CPC\n";
355*3db3a4acSRobert Mustacchi
356*3db3a4acSRobert Mustacchi static const char *cpcgen_cfile_amd_header = ""
357*3db3a4acSRobert Mustacchi "/*\n"
358*3db3a4acSRobert Mustacchi " * This file was automatically generated by cpcgen from the data file\n"
359*3db3a4acSRobert Mustacchi " * data/perfmon%s\n"
360*3db3a4acSRobert Mustacchi " *\n"
361*3db3a4acSRobert Mustacchi " * Do not modify this file. Your changes will be lost!\n"
362*3db3a4acSRobert Mustacchi " */\n"
363*3db3a4acSRobert Mustacchi "\n";
364*3db3a4acSRobert Mustacchi
365*3db3a4acSRobert Mustacchi static const char *cpcgen_cfile_amd_table_start = ""
366*3db3a4acSRobert Mustacchi "#include <opteron_pcbe_table.h>\n"
367*3db3a4acSRobert Mustacchi "#include <sys/null.h>\n"
368*3db3a4acSRobert Mustacchi "\n"
369*3db3a4acSRobert Mustacchi "const amd_event_t opteron_pcbe_%s_events[] = {\n";
370*3db3a4acSRobert Mustacchi
371*3db3a4acSRobert Mustacchi static const char *cpcgen_cfile_amd_table_end = ""
372*3db3a4acSRobert Mustacchi "\t{ NULL, 0, 0 }\n"
373*3db3a4acSRobert Mustacchi "};\n";
374*3db3a4acSRobert Mustacchi
37553548f91SRobert Mustacchi static cpc_map_t *
cpcgen_map_lookup(const char * path)37653548f91SRobert Mustacchi cpcgen_map_lookup(const char *path)
37753548f91SRobert Mustacchi {
37853548f91SRobert Mustacchi cpc_map_t *m;
37953548f91SRobert Mustacchi
38053548f91SRobert Mustacchi for (m = cpcgen_maps; m != NULL; m = m->cmap_next) {
38153548f91SRobert Mustacchi if (strcmp(path, m->cmap_path) == 0) {
38253548f91SRobert Mustacchi return (m);
38353548f91SRobert Mustacchi }
38453548f91SRobert Mustacchi }
38553548f91SRobert Mustacchi
38653548f91SRobert Mustacchi return (NULL);
38753548f91SRobert Mustacchi }
38853548f91SRobert Mustacchi
38953548f91SRobert Mustacchi /*
39053548f91SRobert Mustacchi * Parse a string of the form 'GenuineIntel-6-2E' and get out the family and
39153548f91SRobert Mustacchi * model.
39253548f91SRobert Mustacchi */
39353548f91SRobert Mustacchi static void
cpcgen_parse_model(char * fsr,uint_t * family,uint_t * model,uint_t * nstepp,uint_t * steppings)3945fc40de0SRobert Mustacchi cpcgen_parse_model(char *fsr, uint_t *family, uint_t *model, uint_t *nstepp,
3955fc40de0SRobert Mustacchi uint_t *steppings)
39653548f91SRobert Mustacchi {
39753548f91SRobert Mustacchi const char *bstr = "GenuineIntel";
3985fc40de0SRobert Mustacchi const char *brand, *fam, *mod, *step;
39953548f91SRobert Mustacchi char *last;
40053548f91SRobert Mustacchi long l;
4015fc40de0SRobert Mustacchi uint_t nstep = 0;
40253548f91SRobert Mustacchi
4035fc40de0SRobert Mustacchi /*
4045fc40de0SRobert Mustacchi * Tokeninze the string. There may be an optional stepping portion,
4055fc40de0SRobert Mustacchi * which has a range of steppings enclosed by '[' and ']' characters.
4065fc40de0SRobert Mustacchi * While the other parts are required, the stepping may be missing.
4075fc40de0SRobert Mustacchi */
40853548f91SRobert Mustacchi if ((brand = strtok_r(fsr, "-", &last)) == NULL ||
40953548f91SRobert Mustacchi (fam = strtok_r(NULL, "-", &last)) == NULL ||
41053548f91SRobert Mustacchi (mod = strtok_r(NULL, "-", &last)) == NULL) {
41153548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse processor id \"%s\"", fsr);
41253548f91SRobert Mustacchi }
4135fc40de0SRobert Mustacchi step = strtok_r(NULL, "-", &last);
41453548f91SRobert Mustacchi
41553548f91SRobert Mustacchi if (strcmp(bstr, brand) != 0) {
41653548f91SRobert Mustacchi errx(EXIT_FAILURE, "brand string \"%s\" did not match \"%s\"",
41753548f91SRobert Mustacchi brand, bstr);
41853548f91SRobert Mustacchi }
41953548f91SRobert Mustacchi
42053548f91SRobert Mustacchi errno = 0;
42153548f91SRobert Mustacchi l = strtol(fam, &last, 16);
4225fc40de0SRobert Mustacchi if (errno != 0 || l < 0 || l > UINT_MAX || *last != '\0') {
42353548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse family \"%s\"", fam);
42453548f91SRobert Mustacchi }
42553548f91SRobert Mustacchi *family = (uint_t)l;
42653548f91SRobert Mustacchi
42753548f91SRobert Mustacchi l = strtol(mod, &last, 16);
4285fc40de0SRobert Mustacchi if (errno != 0 || l < 0 || l > UINT_MAX || *last != '\0') {
42953548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse model \"%s\"", mod);
43053548f91SRobert Mustacchi }
43153548f91SRobert Mustacchi *model = (uint_t)l;
4325fc40de0SRobert Mustacchi
4335fc40de0SRobert Mustacchi if (step == NULL) {
4345fc40de0SRobert Mustacchi *nstepp = 0;
4355fc40de0SRobert Mustacchi return;
4365fc40de0SRobert Mustacchi }
4375fc40de0SRobert Mustacchi
4385fc40de0SRobert Mustacchi if (*step != '[' || ((last = strrchr(step, ']')) == NULL)) {
4395fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse stepping \"%s\": missing "
4405fc40de0SRobert Mustacchi "stepping range brackets", step);
4415fc40de0SRobert Mustacchi }
4425fc40de0SRobert Mustacchi step++;
4435fc40de0SRobert Mustacchi *last = '\0';
4445fc40de0SRobert Mustacchi while (*step != '\0') {
4455fc40de0SRobert Mustacchi if (!isxdigit(*step)) {
4465fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse stepping: invalid "
4475fc40de0SRobert Mustacchi "stepping identifier '0x%x'", *step);
4485fc40de0SRobert Mustacchi }
4495fc40de0SRobert Mustacchi
4505fc40de0SRobert Mustacchi if (nstep >= CPROC_MAX_STEPPINGS) {
4515fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse stepping: "
4525fc40de0SRobert Mustacchi "encountered too many steppings");
4535fc40de0SRobert Mustacchi }
4545fc40de0SRobert Mustacchi
4555fc40de0SRobert Mustacchi switch (*step) {
4565fc40de0SRobert Mustacchi case '0':
4575fc40de0SRobert Mustacchi steppings[nstep] = 0x0;
4585fc40de0SRobert Mustacchi break;
4595fc40de0SRobert Mustacchi case '1':
4605fc40de0SRobert Mustacchi steppings[nstep] = 0x1;
4615fc40de0SRobert Mustacchi break;
4625fc40de0SRobert Mustacchi case '2':
4635fc40de0SRobert Mustacchi steppings[nstep] = 0x2;
4645fc40de0SRobert Mustacchi break;
4655fc40de0SRobert Mustacchi case '3':
4665fc40de0SRobert Mustacchi steppings[nstep] = 0x3;
4675fc40de0SRobert Mustacchi break;
4685fc40de0SRobert Mustacchi case '4':
4695fc40de0SRobert Mustacchi steppings[nstep] = 0x4;
4705fc40de0SRobert Mustacchi break;
4715fc40de0SRobert Mustacchi case '5':
4725fc40de0SRobert Mustacchi steppings[nstep] = 0x5;
4735fc40de0SRobert Mustacchi break;
4745fc40de0SRobert Mustacchi case '6':
4755fc40de0SRobert Mustacchi steppings[nstep] = 0x6;
4765fc40de0SRobert Mustacchi break;
4775fc40de0SRobert Mustacchi case '7':
4785fc40de0SRobert Mustacchi steppings[nstep] = 0x7;
4795fc40de0SRobert Mustacchi break;
4805fc40de0SRobert Mustacchi case '8':
4815fc40de0SRobert Mustacchi steppings[nstep] = 0x8;
4825fc40de0SRobert Mustacchi break;
4835fc40de0SRobert Mustacchi case '9':
4845fc40de0SRobert Mustacchi steppings[nstep] = 0x9;
4855fc40de0SRobert Mustacchi break;
4865fc40de0SRobert Mustacchi case 'a':
4875fc40de0SRobert Mustacchi case 'A':
4885fc40de0SRobert Mustacchi steppings[nstep] = 0xa;
4895fc40de0SRobert Mustacchi break;
4905fc40de0SRobert Mustacchi case 'b':
4915fc40de0SRobert Mustacchi case 'B':
4925fc40de0SRobert Mustacchi steppings[nstep] = 0xb;
4935fc40de0SRobert Mustacchi break;
4945fc40de0SRobert Mustacchi case 'c':
4955fc40de0SRobert Mustacchi case 'C':
4965fc40de0SRobert Mustacchi steppings[nstep] = 0xc;
4975fc40de0SRobert Mustacchi break;
4985fc40de0SRobert Mustacchi case 'd':
4995fc40de0SRobert Mustacchi case 'D':
5005fc40de0SRobert Mustacchi steppings[nstep] = 0xd;
5015fc40de0SRobert Mustacchi break;
5025fc40de0SRobert Mustacchi case 'e':
5035fc40de0SRobert Mustacchi case 'E':
5045fc40de0SRobert Mustacchi steppings[nstep] = 0xe;
5055fc40de0SRobert Mustacchi break;
5065fc40de0SRobert Mustacchi case 'f':
5075fc40de0SRobert Mustacchi case 'F':
5085fc40de0SRobert Mustacchi steppings[nstep] = 0xf;
5095fc40de0SRobert Mustacchi break;
5105fc40de0SRobert Mustacchi default:
5115fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "encountered non-hex stepping "
5125fc40de0SRobert Mustacchi "character: '%c'", *step);
5135fc40de0SRobert Mustacchi }
5145fc40de0SRobert Mustacchi nstep++;
5155fc40de0SRobert Mustacchi step++;
5165fc40de0SRobert Mustacchi }
5175fc40de0SRobert Mustacchi
5185fc40de0SRobert Mustacchi *nstepp = nstep;
51953548f91SRobert Mustacchi }
52053548f91SRobert Mustacchi
52153548f91SRobert Mustacchi static nvlist_t *
cpcgen_read_datafile(const char * datadir,const char * file)52253548f91SRobert Mustacchi cpcgen_read_datafile(const char *datadir, const char *file)
52353548f91SRobert Mustacchi {
52453548f91SRobert Mustacchi int fd;
52553548f91SRobert Mustacchi char *path;
52653548f91SRobert Mustacchi struct stat st;
52753548f91SRobert Mustacchi void *map;
52853548f91SRobert Mustacchi nvlist_t *nvl;
52953548f91SRobert Mustacchi nvlist_parse_json_error_t jerr;
53053548f91SRobert Mustacchi
53153548f91SRobert Mustacchi if (asprintf(&path, "%s/%s", datadir, file) == -1) {
53253548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct path to data file %s",
53353548f91SRobert Mustacchi file);
53453548f91SRobert Mustacchi }
53553548f91SRobert Mustacchi
53653548f91SRobert Mustacchi if ((fd = open(path, O_RDONLY)) < 0) {
53753548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to open data file %s", path);
53853548f91SRobert Mustacchi }
53953548f91SRobert Mustacchi
54053548f91SRobert Mustacchi if (fstat(fd, &st) != 0) {
54153548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to stat %s", path);
54253548f91SRobert Mustacchi }
54353548f91SRobert Mustacchi
54453548f91SRobert Mustacchi if ((map = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
54553548f91SRobert Mustacchi fd, 0)) == MAP_FAILED) {
54653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to mmap %s", path);
54753548f91SRobert Mustacchi }
54853548f91SRobert Mustacchi
54953548f91SRobert Mustacchi if (nvlist_parse_json(map, st.st_size, &nvl, NVJSON_FORCE_INTEGER,
55053548f91SRobert Mustacchi &jerr) != 0) {
55153548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse file %s at pos %ld: %s",
55253548f91SRobert Mustacchi path, jerr.nje_pos, jerr.nje_message);
55353548f91SRobert Mustacchi }
55453548f91SRobert Mustacchi
55553548f91SRobert Mustacchi if (munmap(map, st.st_size) != 0) {
55653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to munmap %s", path);
55753548f91SRobert Mustacchi }
55853548f91SRobert Mustacchi
55953548f91SRobert Mustacchi if (close(fd) != 0) {
56053548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to close data file %s", path);
56153548f91SRobert Mustacchi }
56253548f91SRobert Mustacchi free(path);
56353548f91SRobert Mustacchi
56453548f91SRobert Mustacchi return (nvl);
56553548f91SRobert Mustacchi }
56653548f91SRobert Mustacchi
56753548f91SRobert Mustacchi /*
56853548f91SRobert Mustacchi * Check the whitelist to see if we should use this model.
56953548f91SRobert Mustacchi */
57053548f91SRobert Mustacchi static const char *
cpcgen_use_arch(const char * path,cpc_type_t type,const char * platform)57153548f91SRobert Mustacchi cpcgen_use_arch(const char *path, cpc_type_t type, const char *platform)
57253548f91SRobert Mustacchi {
57353548f91SRobert Mustacchi const char *slash;
57453548f91SRobert Mustacchi size_t len;
57553548f91SRobert Mustacchi uint_t i;
57653548f91SRobert Mustacchi
57753548f91SRobert Mustacchi if (*path != '/') {
57853548f91SRobert Mustacchi errx(EXIT_FAILURE, "invalid path in mapfile: \"%s\": missing "
57953548f91SRobert Mustacchi "leading '/'", path);
58053548f91SRobert Mustacchi }
58153548f91SRobert Mustacchi if ((slash = strchr(path + 1, '/')) == NULL) {
58253548f91SRobert Mustacchi errx(EXIT_FAILURE, "invalid path in mapfile: \"%s\": missing "
58353548f91SRobert Mustacchi "second '/'", path);
58453548f91SRobert Mustacchi }
58553548f91SRobert Mustacchi /* Account for the last '/' character. */
58653548f91SRobert Mustacchi len = slash - path - 1;
58753548f91SRobert Mustacchi assert(len > 0);
58853548f91SRobert Mustacchi
589*3db3a4acSRobert Mustacchi for (i = 0; cpcgen_intel_whitelist[i].cwhite_short != NULL; i++) {
59053548f91SRobert Mustacchi if (platform != NULL && strcasecmp(platform,
591*3db3a4acSRobert Mustacchi cpcgen_intel_whitelist[i].cwhite_short) != 0)
59253548f91SRobert Mustacchi continue;
593*3db3a4acSRobert Mustacchi if (strncmp(path + 1, cpcgen_intel_whitelist[i].cwhite_short,
59453548f91SRobert Mustacchi len) == 0 &&
595*3db3a4acSRobert Mustacchi (cpcgen_intel_whitelist[i].cwhite_mask & type) == type) {
596*3db3a4acSRobert Mustacchi return (cpcgen_intel_whitelist[i].cwhite_human);
59753548f91SRobert Mustacchi }
59853548f91SRobert Mustacchi }
59953548f91SRobert Mustacchi
60053548f91SRobert Mustacchi return (NULL);
60153548f91SRobert Mustacchi }
60253548f91SRobert Mustacchi
60353548f91SRobert Mustacchi /*
604*3db3a4acSRobert Mustacchi * Determine which CPU Vendor we're transmuting data from.
605*3db3a4acSRobert Mustacchi */
606*3db3a4acSRobert Mustacchi static void
cpcgen_determine_vendor(const char * datadir)607*3db3a4acSRobert Mustacchi cpcgen_determine_vendor(const char *datadir)
608*3db3a4acSRobert Mustacchi {
609*3db3a4acSRobert Mustacchi char *mappath;
610*3db3a4acSRobert Mustacchi struct stat st;
611*3db3a4acSRobert Mustacchi
612*3db3a4acSRobert Mustacchi if (asprintf(&mappath, "%s/%s", datadir, cpcgen_intel_mapfile) == -1) {
613*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to construct path to mapfile");
614*3db3a4acSRobert Mustacchi }
615*3db3a4acSRobert Mustacchi
616*3db3a4acSRobert Mustacchi if (stat(mappath, &st) == 0) {
617*3db3a4acSRobert Mustacchi cpcgen_mode = CPCGEN_MODE_INTEL;
618*3db3a4acSRobert Mustacchi } else {
619*3db3a4acSRobert Mustacchi if (errno != ENOENT) {
620*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "stat(2) of %s failed unexpectedly");
621*3db3a4acSRobert Mustacchi }
622*3db3a4acSRobert Mustacchi
623*3db3a4acSRobert Mustacchi cpcgen_mode = CPCGEN_MODE_AMD;
624*3db3a4acSRobert Mustacchi }
625*3db3a4acSRobert Mustacchi
626*3db3a4acSRobert Mustacchi free(mappath);
627*3db3a4acSRobert Mustacchi }
628*3db3a4acSRobert Mustacchi
629*3db3a4acSRobert Mustacchi /*
630*3db3a4acSRobert Mustacchi * Read in all the data files that exist for AMD.
631*3db3a4acSRobert Mustacchi *
632*3db3a4acSRobert Mustacchi * Our family names for AMD systems are based on the family and type so a given
633*3db3a4acSRobert Mustacchi * name will look like f17h_core.json.
634*3db3a4acSRobert Mustacchi */
635*3db3a4acSRobert Mustacchi static void
cpcgen_read_amd(const char * datadir,const char * platform)636*3db3a4acSRobert Mustacchi cpcgen_read_amd(const char *datadir, const char *platform)
637*3db3a4acSRobert Mustacchi {
638*3db3a4acSRobert Mustacchi DIR *dir;
639*3db3a4acSRobert Mustacchi struct dirent *d;
640*3db3a4acSRobert Mustacchi const char *suffix = ".json";
641*3db3a4acSRobert Mustacchi const size_t slen = strlen(suffix);
642*3db3a4acSRobert Mustacchi
643*3db3a4acSRobert Mustacchi if ((dir = opendir(datadir)) == NULL) {
644*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to open directory %s", datadir);
645*3db3a4acSRobert Mustacchi }
646*3db3a4acSRobert Mustacchi
647*3db3a4acSRobert Mustacchi while ((d = readdir(dir)) != NULL) {
648*3db3a4acSRobert Mustacchi char *name, *c;
649*3db3a4acSRobert Mustacchi cpc_map_t *map;
650*3db3a4acSRobert Mustacchi nvlist_t *parsed;
651*3db3a4acSRobert Mustacchi
652*3db3a4acSRobert Mustacchi if ((name = strdup(d->d_name)) == NULL) {
653*3db3a4acSRobert Mustacchi errx(EXIT_FAILURE, "ran out of memory duplicating "
654*3db3a4acSRobert Mustacchi "name %s", d->d_name);
655*3db3a4acSRobert Mustacchi }
656*3db3a4acSRobert Mustacchi c = strstr(name, suffix);
657*3db3a4acSRobert Mustacchi
658*3db3a4acSRobert Mustacchi if (c == NULL) {
659*3db3a4acSRobert Mustacchi free(name);
660*3db3a4acSRobert Mustacchi continue;
661*3db3a4acSRobert Mustacchi }
662*3db3a4acSRobert Mustacchi
663*3db3a4acSRobert Mustacchi if (*(c + slen) != '\0') {
664*3db3a4acSRobert Mustacchi free(name);
665*3db3a4acSRobert Mustacchi continue;
666*3db3a4acSRobert Mustacchi }
667*3db3a4acSRobert Mustacchi
668*3db3a4acSRobert Mustacchi *c = '\0';
669*3db3a4acSRobert Mustacchi c = strchr(name, '_');
670*3db3a4acSRobert Mustacchi if (c == NULL) {
671*3db3a4acSRobert Mustacchi free(name);
672*3db3a4acSRobert Mustacchi continue;
673*3db3a4acSRobert Mustacchi }
674*3db3a4acSRobert Mustacchi *c = '\0';
675*3db3a4acSRobert Mustacchi c++;
676*3db3a4acSRobert Mustacchi if (strcmp(c, "core") != 0) {
677*3db3a4acSRobert Mustacchi errx(EXIT_FAILURE, "unexpected AMD JSON file name: %s",
678*3db3a4acSRobert Mustacchi d->d_name);
679*3db3a4acSRobert Mustacchi }
680*3db3a4acSRobert Mustacchi
681*3db3a4acSRobert Mustacchi if (platform != NULL && strcmp(platform, name) != 0) {
682*3db3a4acSRobert Mustacchi free(name);
683*3db3a4acSRobert Mustacchi continue;
684*3db3a4acSRobert Mustacchi }
685*3db3a4acSRobert Mustacchi
686*3db3a4acSRobert Mustacchi if ((map = calloc(1, sizeof (cpc_map_t))) == NULL) {
687*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to allocate space for cpc "
688*3db3a4acSRobert Mustacchi "file");
689*3db3a4acSRobert Mustacchi }
690*3db3a4acSRobert Mustacchi
691*3db3a4acSRobert Mustacchi parsed = cpcgen_read_datafile(datadir, d->d_name);
692*3db3a4acSRobert Mustacchi if ((map->cmap_path = strdup(d->d_name)) == NULL) {
693*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to duplicate path string");
694*3db3a4acSRobert Mustacchi }
695*3db3a4acSRobert Mustacchi map->cmap_type = CPC_FILE_CORE;
696*3db3a4acSRobert Mustacchi map->cmap_data = parsed;
697*3db3a4acSRobert Mustacchi map->cmap_name = name;
698*3db3a4acSRobert Mustacchi map->cmap_procs = NULL;
699*3db3a4acSRobert Mustacchi
700*3db3a4acSRobert Mustacchi map->cmap_next = cpcgen_maps;
701*3db3a4acSRobert Mustacchi cpcgen_maps = map;
702*3db3a4acSRobert Mustacchi }
703*3db3a4acSRobert Mustacchi }
704*3db3a4acSRobert Mustacchi
705*3db3a4acSRobert Mustacchi /*
70653548f91SRobert Mustacchi * Read in the mapfile.csv that is used to map between processor families and
70753548f91SRobert Mustacchi * parse this. Each line has a comma separated value.
70853548f91SRobert Mustacchi */
70953548f91SRobert Mustacchi static void
cpcgen_read_intel(const char * datadir,const char * platform)710*3db3a4acSRobert Mustacchi cpcgen_read_intel(const char *datadir, const char *platform)
71153548f91SRobert Mustacchi {
71253548f91SRobert Mustacchi FILE *map;
71353548f91SRobert Mustacchi char *mappath, *last;
71453548f91SRobert Mustacchi char *data = NULL;
71553548f91SRobert Mustacchi size_t datalen = 0;
71653548f91SRobert Mustacchi uint_t lineno;
71753548f91SRobert Mustacchi
718*3db3a4acSRobert Mustacchi if (asprintf(&mappath, "%s/%s", datadir, cpcgen_intel_mapfile) == -1) {
71953548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct path to mapfile");
72053548f91SRobert Mustacchi }
72153548f91SRobert Mustacchi
72253548f91SRobert Mustacchi if ((map = fopen(mappath, "r")) == NULL) {
72353548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to open data mapfile %s", mappath);
72453548f91SRobert Mustacchi }
72553548f91SRobert Mustacchi
72653548f91SRobert Mustacchi lineno = 0;
72753548f91SRobert Mustacchi while (getline(&data, &datalen, map) != -1) {
72853548f91SRobert Mustacchi char *fstr, *path, *tstr;
72953548f91SRobert Mustacchi const char *name;
7305fc40de0SRobert Mustacchi uint_t family, model, nsteps;
7315fc40de0SRobert Mustacchi uint_t steppings[CPROC_MAX_STEPPINGS];
7325fc40de0SRobert Mustacchi
73353548f91SRobert Mustacchi cpc_type_t type;
73453548f91SRobert Mustacchi cpc_map_t *map;
73553548f91SRobert Mustacchi cpc_proc_t *proc;
73653548f91SRobert Mustacchi
73753548f91SRobert Mustacchi /*
73853548f91SRobert Mustacchi * The first line contains the header:
73953548f91SRobert Mustacchi * Family-model,Version,Filename,EventType
74053548f91SRobert Mustacchi */
74153548f91SRobert Mustacchi lineno++;
74253548f91SRobert Mustacchi if (lineno == 1) {
74353548f91SRobert Mustacchi continue;
74453548f91SRobert Mustacchi }
74553548f91SRobert Mustacchi
74653548f91SRobert Mustacchi if ((fstr = strtok_r(data, ",", &last)) == NULL ||
74753548f91SRobert Mustacchi strtok_r(NULL, ",", &last) == NULL ||
74853548f91SRobert Mustacchi (path = strtok_r(NULL, ",", &last)) == NULL ||
74953548f91SRobert Mustacchi (tstr = strtok_r(NULL, "\n", &last)) == NULL) {
75053548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse mapfile line "
75153548f91SRobert Mustacchi "%u in %s", lineno, mappath);
75253548f91SRobert Mustacchi }
75353548f91SRobert Mustacchi
7545fc40de0SRobert Mustacchi cpcgen_parse_model(fstr, &family, &model, &nsteps, steppings);
75553548f91SRobert Mustacchi
75653548f91SRobert Mustacchi if (strcmp(tstr, "core") == 0) {
75753548f91SRobert Mustacchi type = CPC_FILE_CORE;
75853548f91SRobert Mustacchi } else if (strcmp(tstr, "offcore") == 0) {
75953548f91SRobert Mustacchi type = CPC_FILE_OFF_CORE;
76053548f91SRobert Mustacchi } else if (strcmp(tstr, "uncore") == 0) {
76153548f91SRobert Mustacchi type = CPC_FILE_UNCORE;
76253548f91SRobert Mustacchi } else if (strcmp(tstr, "fp_arith_inst") == 0) {
76353548f91SRobert Mustacchi type = CPC_FILE_FP_MATH;
76453548f91SRobert Mustacchi } else if (strcmp(tstr, "uncore experimental") == 0) {
76553548f91SRobert Mustacchi type = CPC_FILE_UNCORE_EXP;
76653548f91SRobert Mustacchi } else {
76753548f91SRobert Mustacchi errx(EXIT_FAILURE, "unknown file type \"%s\" on line "
76853548f91SRobert Mustacchi "%u", tstr, lineno);
76953548f91SRobert Mustacchi }
77053548f91SRobert Mustacchi
77153548f91SRobert Mustacchi if ((name = cpcgen_use_arch(path, type, platform)) == NULL)
77253548f91SRobert Mustacchi continue;
77353548f91SRobert Mustacchi
77453548f91SRobert Mustacchi if ((map = cpcgen_map_lookup(path)) == NULL) {
77553548f91SRobert Mustacchi nvlist_t *parsed;
77653548f91SRobert Mustacchi
77753548f91SRobert Mustacchi parsed = cpcgen_read_datafile(datadir, path);
77853548f91SRobert Mustacchi
77953548f91SRobert Mustacchi if ((map = calloc(1, sizeof (cpc_map_t))) == NULL) {
78053548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to allocate space "
78153548f91SRobert Mustacchi "for cpc file");
78253548f91SRobert Mustacchi }
78353548f91SRobert Mustacchi
78453548f91SRobert Mustacchi if ((map->cmap_path = strdup(path)) == NULL) {
78553548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to duplicate path "
78653548f91SRobert Mustacchi "string");
78753548f91SRobert Mustacchi }
78853548f91SRobert Mustacchi
78953548f91SRobert Mustacchi map->cmap_type = type;
79053548f91SRobert Mustacchi map->cmap_data = parsed;
79153548f91SRobert Mustacchi map->cmap_name = name;
7925fc40de0SRobert Mustacchi map->cmap_procs = NULL;
793*3db3a4acSRobert Mustacchi
794*3db3a4acSRobert Mustacchi map->cmap_next = cpcgen_maps;
79553548f91SRobert Mustacchi cpcgen_maps = map;
79653548f91SRobert Mustacchi }
79753548f91SRobert Mustacchi
7985fc40de0SRobert Mustacchi if ((proc = calloc(1, sizeof (cpc_proc_t))) == NULL) {
79953548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to allocate memory for "
80053548f91SRobert Mustacchi "family and model tracking");
80153548f91SRobert Mustacchi }
80253548f91SRobert Mustacchi
80353548f91SRobert Mustacchi proc->cproc_family = family;
80453548f91SRobert Mustacchi proc->cproc_model = model;
8055fc40de0SRobert Mustacchi proc->cproc_nsteps = nsteps;
8065fc40de0SRobert Mustacchi if (nsteps > 0) {
8075fc40de0SRobert Mustacchi bcopy(steppings, proc->cproc_steppings,
8085fc40de0SRobert Mustacchi sizeof (steppings));
8095fc40de0SRobert Mustacchi }
81053548f91SRobert Mustacchi proc->cproc_next = map->cmap_procs;
81153548f91SRobert Mustacchi map->cmap_procs = proc;
81253548f91SRobert Mustacchi }
81353548f91SRobert Mustacchi
81453548f91SRobert Mustacchi if (errno != 0 || ferror(map)) {
81553548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to read %s", mappath);
81653548f91SRobert Mustacchi }
81753548f91SRobert Mustacchi
81853548f91SRobert Mustacchi if (fclose(map) == EOF) {
81953548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to close %s", mappath);
82053548f91SRobert Mustacchi }
82153548f91SRobert Mustacchi free(data);
82253548f91SRobert Mustacchi free(mappath);
82353548f91SRobert Mustacchi }
82453548f91SRobert Mustacchi
82553548f91SRobert Mustacchi static char *
cpcgen_manual_intel_name(cpc_map_t * map)826*3db3a4acSRobert Mustacchi cpcgen_manual_intel_name(cpc_map_t *map)
82753548f91SRobert Mustacchi {
82853548f91SRobert Mustacchi char *name;
82953548f91SRobert Mustacchi
83053548f91SRobert Mustacchi if (asprintf(&name, "%s_events.3cpc", map->cmap_name) == -1) {
83153548f91SRobert Mustacchi warn("failed to assemble manual page name for %s",
83253548f91SRobert Mustacchi map->cmap_path);
83353548f91SRobert Mustacchi return (NULL);
83453548f91SRobert Mustacchi }
83553548f91SRobert Mustacchi
83653548f91SRobert Mustacchi return (name);
83753548f91SRobert Mustacchi }
83853548f91SRobert Mustacchi
83953548f91SRobert Mustacchi static boolean_t
cpcgen_manual_intel_file_before(FILE * f,cpc_map_t * map)840*3db3a4acSRobert Mustacchi cpcgen_manual_intel_file_before(FILE *f, cpc_map_t *map)
84153548f91SRobert Mustacchi {
84253548f91SRobert Mustacchi size_t i;
84353548f91SRobert Mustacchi char *upper;
84453548f91SRobert Mustacchi cpc_proc_t *proc;
84553548f91SRobert Mustacchi
84653548f91SRobert Mustacchi if ((upper = strdup(map->cmap_name)) == NULL) {
84753548f91SRobert Mustacchi warn("failed to duplicate manual name for %s", map->cmap_name);
84853548f91SRobert Mustacchi return (B_FALSE);
84953548f91SRobert Mustacchi }
85053548f91SRobert Mustacchi
85153548f91SRobert Mustacchi for (i = 0; upper[i] != '\0'; i++) {
85253548f91SRobert Mustacchi upper[i] = toupper(upper[i]);
85353548f91SRobert Mustacchi }
85453548f91SRobert Mustacchi
855*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_manual_intel_intel_header, map->cmap_path, upper,
85653548f91SRobert Mustacchi map->cmap_name) == -1) {
85753548f91SRobert Mustacchi warn("failed to write out manual header for %s",
85853548f91SRobert Mustacchi map->cmap_name);
85953548f91SRobert Mustacchi free(upper);
86053548f91SRobert Mustacchi return (B_FALSE);
86153548f91SRobert Mustacchi }
862*3db3a4acSRobert Mustacchi free(upper);
86353548f91SRobert Mustacchi
86453548f91SRobert Mustacchi for (proc = map->cmap_procs; proc != NULL; proc = proc->cproc_next) {
8655fc40de0SRobert Mustacchi if (proc->cproc_nsteps > 0) {
8665fc40de0SRobert Mustacchi uint_t step;
8675fc40de0SRobert Mustacchi
8685fc40de0SRobert Mustacchi for (step = 0; step < proc->cproc_nsteps; step++) {
8695fc40de0SRobert Mustacchi if (fprintf(f, ".It\n.Sy Family 0x%x, Model "
8705fc40de0SRobert Mustacchi "0x%x, Stepping 0x%x\n",
8715fc40de0SRobert Mustacchi proc->cproc_family, proc->cproc_model,
8725fc40de0SRobert Mustacchi proc->cproc_steppings[step]) == -1) {
8735fc40de0SRobert Mustacchi warn("failed to write out model "
8745fc40de0SRobert Mustacchi "information for %s",
87553548f91SRobert Mustacchi map->cmap_name);
87653548f91SRobert Mustacchi return (B_FALSE);
87753548f91SRobert Mustacchi }
87853548f91SRobert Mustacchi }
8795fc40de0SRobert Mustacchi } else {
8805fc40de0SRobert Mustacchi if (fprintf(f, ".It\n.Sy Family 0x%x, Model 0x%x\n",
8815fc40de0SRobert Mustacchi proc->cproc_family, proc->cproc_model) == -1) {
8825fc40de0SRobert Mustacchi warn("failed to write out model information "
8835fc40de0SRobert Mustacchi "for %s", map->cmap_name);
8845fc40de0SRobert Mustacchi return (B_FALSE);
8855fc40de0SRobert Mustacchi }
8865fc40de0SRobert Mustacchi }
8875fc40de0SRobert Mustacchi }
88853548f91SRobert Mustacchi
889*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_manual_intel_data) == -1) {
89053548f91SRobert Mustacchi warn("failed to write out manual header for %s",
89153548f91SRobert Mustacchi map->cmap_name);
89253548f91SRobert Mustacchi return (B_FALSE);
89353548f91SRobert Mustacchi }
89453548f91SRobert Mustacchi
89553548f91SRobert Mustacchi free(upper);
89653548f91SRobert Mustacchi return (B_TRUE);
89753548f91SRobert Mustacchi }
89853548f91SRobert Mustacchi
89953548f91SRobert Mustacchi static boolean_t
cpcgen_manual_intel_file_after(FILE * f,cpc_map_t * map)900*3db3a4acSRobert Mustacchi cpcgen_manual_intel_file_after(FILE *f, cpc_map_t *map)
90153548f91SRobert Mustacchi {
902*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_manual_intel_trailer) == -1) {
90353548f91SRobert Mustacchi warn("failed to write out manual header for %s",
90453548f91SRobert Mustacchi map->cmap_name);
90553548f91SRobert Mustacchi return (B_FALSE);
90653548f91SRobert Mustacchi }
90753548f91SRobert Mustacchi
90853548f91SRobert Mustacchi return (B_TRUE);
90953548f91SRobert Mustacchi }
91053548f91SRobert Mustacchi
91153548f91SRobert Mustacchi static boolean_t
cpcgen_manual_intel_event(FILE * f,nvlist_t * nvl,const char * path,uint32_t ent)912*3db3a4acSRobert Mustacchi cpcgen_manual_intel_event(FILE *f, nvlist_t *nvl, const char *path,
913*3db3a4acSRobert Mustacchi uint32_t ent)
91453548f91SRobert Mustacchi {
91553548f91SRobert Mustacchi char *event, *lname, *brief = NULL, *public = NULL, *errata = NULL;
91653548f91SRobert Mustacchi size_t i;
91753548f91SRobert Mustacchi
91853548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "EventName", &event) != 0) {
91953548f91SRobert Mustacchi warnx("Found event without 'EventName' property "
92053548f91SRobert Mustacchi "in %s, entry %u", path, ent);
92153548f91SRobert Mustacchi return (B_FALSE);
92253548f91SRobert Mustacchi }
92353548f91SRobert Mustacchi
92453548f91SRobert Mustacchi /*
92553548f91SRobert Mustacchi * Intel uses capital names. CPC historically uses lower case names.
92653548f91SRobert Mustacchi */
92753548f91SRobert Mustacchi if ((lname = strdup(event)) == NULL) {
92853548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to duplicate event name %s", event);
92953548f91SRobert Mustacchi }
93053548f91SRobert Mustacchi for (i = 0; lname[i] != '\0'; i++) {
93153548f91SRobert Mustacchi lname[i] = tolower(event[i]);
93253548f91SRobert Mustacchi }
93353548f91SRobert Mustacchi
93453548f91SRobert Mustacchi /*
93553548f91SRobert Mustacchi * Try to get the other event fields, but if they're not there, don't
93653548f91SRobert Mustacchi * worry about it.
93753548f91SRobert Mustacchi */
93853548f91SRobert Mustacchi (void) nvlist_lookup_string(nvl, "BriefDescription", &brief);
93953548f91SRobert Mustacchi (void) nvlist_lookup_string(nvl, "PublicDescription", &public);
94053548f91SRobert Mustacchi (void) nvlist_lookup_string(nvl, "Errata", &errata);
94153548f91SRobert Mustacchi if (errata != NULL && (strcmp(errata, "0") == 0 ||
94253548f91SRobert Mustacchi strcmp(errata, "null") == 0)) {
94353548f91SRobert Mustacchi errata = NULL;
94453548f91SRobert Mustacchi }
94553548f91SRobert Mustacchi
94653548f91SRobert Mustacchi if (fprintf(f, ".It Sy %s\n", lname) == -1) {
947*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", event);
94853548f91SRobert Mustacchi free(lname);
94953548f91SRobert Mustacchi return (B_FALSE);
95053548f91SRobert Mustacchi }
95153548f91SRobert Mustacchi
95253548f91SRobert Mustacchi if (public != NULL) {
95353548f91SRobert Mustacchi if (fprintf(f, "%s\n", public) == -1) {
954*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", event);
95553548f91SRobert Mustacchi free(lname);
95653548f91SRobert Mustacchi return (B_FALSE);
95753548f91SRobert Mustacchi }
95853548f91SRobert Mustacchi } else if (brief != NULL) {
95953548f91SRobert Mustacchi if (fprintf(f, "%s\n", brief) == -1) {
960*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", event);
96153548f91SRobert Mustacchi free(lname);
96253548f91SRobert Mustacchi return (B_FALSE);
96353548f91SRobert Mustacchi }
96453548f91SRobert Mustacchi }
96553548f91SRobert Mustacchi
96653548f91SRobert Mustacchi if (errata != NULL) {
96753548f91SRobert Mustacchi if (fprintf(f, ".Pp\nThe following errata may apply to this: "
96853548f91SRobert Mustacchi "%s\n", errata) == -1) {
96953548f91SRobert Mustacchi
970*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", event);
97153548f91SRobert Mustacchi free(lname);
97253548f91SRobert Mustacchi return (B_FALSE);
97353548f91SRobert Mustacchi }
97453548f91SRobert Mustacchi }
97553548f91SRobert Mustacchi
97653548f91SRobert Mustacchi free(lname);
97753548f91SRobert Mustacchi return (B_TRUE);
97853548f91SRobert Mustacchi }
97953548f91SRobert Mustacchi
98053548f91SRobert Mustacchi static char *
cpcgen_cfile_intel_name(cpc_map_t * map)981*3db3a4acSRobert Mustacchi cpcgen_cfile_intel_name(cpc_map_t *map)
98253548f91SRobert Mustacchi {
98353548f91SRobert Mustacchi char *name;
98453548f91SRobert Mustacchi
98553548f91SRobert Mustacchi if (asprintf(&name, "core_pcbe_%s.c", map->cmap_name) == -1) {
98653548f91SRobert Mustacchi warn("failed to assemble file name for %s", map->cmap_path);
98753548f91SRobert Mustacchi return (NULL);
98853548f91SRobert Mustacchi }
98953548f91SRobert Mustacchi
99053548f91SRobert Mustacchi return (name);
99153548f91SRobert Mustacchi }
99253548f91SRobert Mustacchi
99353548f91SRobert Mustacchi static boolean_t
cpcgen_cfile_intel_before(FILE * f,cpc_map_t * map)994*3db3a4acSRobert Mustacchi cpcgen_cfile_intel_before(FILE *f, cpc_map_t *map)
99553548f91SRobert Mustacchi {
996*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_intel_header, map->cmap_path) == -1) {
99753548f91SRobert Mustacchi warn("failed to write header to temporary file for %s",
99853548f91SRobert Mustacchi map->cmap_path);
99953548f91SRobert Mustacchi return (B_FALSE);
100053548f91SRobert Mustacchi }
100153548f91SRobert Mustacchi
1002*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_intel_table_start, map->cmap_name) == -1) {
100353548f91SRobert Mustacchi warn("failed to write header to temporary file for %s",
100453548f91SRobert Mustacchi map->cmap_path);
100553548f91SRobert Mustacchi return (B_FALSE);
100653548f91SRobert Mustacchi }
100753548f91SRobert Mustacchi
100853548f91SRobert Mustacchi return (B_TRUE);
100953548f91SRobert Mustacchi }
101053548f91SRobert Mustacchi
101153548f91SRobert Mustacchi static boolean_t
cpcgen_cfile_intel_after(FILE * f,cpc_map_t * map)1012*3db3a4acSRobert Mustacchi cpcgen_cfile_intel_after(FILE *f, cpc_map_t *map)
101353548f91SRobert Mustacchi {
1014*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_intel_table_end) == -1) {
101553548f91SRobert Mustacchi warn("failed to write footer to temporary file for %s",
101653548f91SRobert Mustacchi map->cmap_path);
101753548f91SRobert Mustacchi return (B_FALSE);
101853548f91SRobert Mustacchi }
101953548f91SRobert Mustacchi
102053548f91SRobert Mustacchi return (B_TRUE);
102153548f91SRobert Mustacchi }
102253548f91SRobert Mustacchi
102353548f91SRobert Mustacchi static boolean_t
cpcgen_cfile_intel_event(FILE * f,nvlist_t * nvl,const char * path,uint_t ent)1024*3db3a4acSRobert Mustacchi cpcgen_cfile_intel_event(FILE *f, nvlist_t *nvl, const char *path, uint_t ent)
102553548f91SRobert Mustacchi {
102653548f91SRobert Mustacchi char *ecode, *umask, *name, *counter, *lname, *cmask;
102753548f91SRobert Mustacchi size_t i;
102853548f91SRobert Mustacchi
102953548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "EventName", &name) != 0) {
103053548f91SRobert Mustacchi warnx("Found event without 'EventName' property "
103153548f91SRobert Mustacchi "in %s, entry %u", path, ent);
103253548f91SRobert Mustacchi return (B_FALSE);
103353548f91SRobert Mustacchi }
103453548f91SRobert Mustacchi
103553548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "EventCode", &ecode) != 0 ||
103653548f91SRobert Mustacchi nvlist_lookup_string(nvl, "UMask", &umask) != 0 ||
103753548f91SRobert Mustacchi nvlist_lookup_string(nvl, "Counter", &counter) != 0) {
103853548f91SRobert Mustacchi warnx("event %s (index %u) from %s, missing "
103953548f91SRobert Mustacchi "required properties for C file translation",
104053548f91SRobert Mustacchi name, ent, path);
104153548f91SRobert Mustacchi return (B_FALSE);
104253548f91SRobert Mustacchi }
104353548f91SRobert Mustacchi
104453548f91SRobert Mustacchi /*
104553548f91SRobert Mustacchi * While we could try and parse the counters manually, just do this the
104653548f91SRobert Mustacchi * max power way for now based on all possible values.
104753548f91SRobert Mustacchi */
104853548f91SRobert Mustacchi if (strcmp(counter, "0") == 0 || strcmp(counter, "0,") == 0) {
104953548f91SRobert Mustacchi cmask = "C0";
105053548f91SRobert Mustacchi } else if (strcmp(counter, "1") == 0) {
105153548f91SRobert Mustacchi cmask = "C1";
105253548f91SRobert Mustacchi } else if (strcmp(counter, "2") == 0) {
105353548f91SRobert Mustacchi cmask = "C2";
105453548f91SRobert Mustacchi } else if (strcmp(counter, "3") == 0) {
105553548f91SRobert Mustacchi cmask = "C3";
105653548f91SRobert Mustacchi } else if (strcmp(counter, "0,1") == 0) {
105753548f91SRobert Mustacchi cmask = "C0|C1";
105853548f91SRobert Mustacchi } else if (strcmp(counter, "0,1,2") == 0) {
105953548f91SRobert Mustacchi cmask = "C0|C1|C2";
106053548f91SRobert Mustacchi } else if (strcmp(counter, "0,1,2,3") == 0) {
106153548f91SRobert Mustacchi cmask = "C0|C1|C2|C3";
106253548f91SRobert Mustacchi } else if (strcmp(counter, "0,2,3") == 0) {
106353548f91SRobert Mustacchi cmask = "C0|C2|C3";
106453548f91SRobert Mustacchi } else if (strcmp(counter, "1,2,3") == 0) {
106553548f91SRobert Mustacchi cmask = "C1|C2|C3";
106653548f91SRobert Mustacchi } else if (strcmp(counter, "2,3") == 0) {
106753548f91SRobert Mustacchi cmask = "C2|C3";
106853548f91SRobert Mustacchi } else {
106953548f91SRobert Mustacchi warnx("event %s (index %u) from %s, has unknown "
107053548f91SRobert Mustacchi "counter value \"%s\"", name, ent, path, counter);
107153548f91SRobert Mustacchi return (B_FALSE);
107253548f91SRobert Mustacchi }
107353548f91SRobert Mustacchi
107453548f91SRobert Mustacchi
107553548f91SRobert Mustacchi /*
107653548f91SRobert Mustacchi * Intel uses capital names. CPC historically uses lower case names.
107753548f91SRobert Mustacchi */
107853548f91SRobert Mustacchi if ((lname = strdup(name)) == NULL) {
107953548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to duplicate event name %s", name);
108053548f91SRobert Mustacchi }
108153548f91SRobert Mustacchi for (i = 0; lname[i] != '\0'; i++) {
108253548f91SRobert Mustacchi lname[i] = tolower(name[i]);
108353548f91SRobert Mustacchi }
108453548f91SRobert Mustacchi
108553548f91SRobert Mustacchi if (fprintf(f, "\t{ %s, %s, %s, \"%s\" },\n", ecode, umask, cmask,
108653548f91SRobert Mustacchi lname) == -1) {
108753548f91SRobert Mustacchi warn("failed to write out entry %s from %s", name, path);
108853548f91SRobert Mustacchi free(lname);
108953548f91SRobert Mustacchi return (B_FALSE);
109053548f91SRobert Mustacchi }
109153548f91SRobert Mustacchi
109253548f91SRobert Mustacchi free(lname);
109353548f91SRobert Mustacchi
109453548f91SRobert Mustacchi /*
109553548f91SRobert Mustacchi * Check if we have any PAPI aliases.
109653548f91SRobert Mustacchi */
1097*3db3a4acSRobert Mustacchi for (i = 0; cpcgen_intel_papi_map[i].cpapi_intc != NULL; i++) {
1098*3db3a4acSRobert Mustacchi if (strcmp(name, cpcgen_intel_papi_map[i].cpapi_intc) != 0)
109953548f91SRobert Mustacchi continue;
110053548f91SRobert Mustacchi
110153548f91SRobert Mustacchi if (fprintf(f, "\t{ %s, %s, %s, \"%s\" },\n", ecode, umask,
1102*3db3a4acSRobert Mustacchi cmask, cpcgen_intel_papi_map[i].cpapi_papi) == -1) {
110353548f91SRobert Mustacchi warn("failed to write out entry %s from %s", name,
110453548f91SRobert Mustacchi path);
110553548f91SRobert Mustacchi return (B_FALSE);
110653548f91SRobert Mustacchi }
110753548f91SRobert Mustacchi }
110853548f91SRobert Mustacchi
110953548f91SRobert Mustacchi return (B_TRUE);
111053548f91SRobert Mustacchi }
111153548f91SRobert Mustacchi
11125fc40de0SRobert Mustacchi static boolean_t
cpcgen_generate_map(FILE * f,cpc_map_t * map,boolean_t start)11135fc40de0SRobert Mustacchi cpcgen_generate_map(FILE *f, cpc_map_t *map, boolean_t start)
11145fc40de0SRobert Mustacchi {
11155fc40de0SRobert Mustacchi cpc_proc_t *p;
11165fc40de0SRobert Mustacchi
11175fc40de0SRobert Mustacchi if (fprintf(f, "\t%sif (", start ? "" : "} else ") == -1) {
11185fc40de0SRobert Mustacchi return (B_FALSE);
11195fc40de0SRobert Mustacchi }
11205fc40de0SRobert Mustacchi
11215fc40de0SRobert Mustacchi for (p = map->cmap_procs; p != NULL; p = p->cproc_next) {
11225fc40de0SRobert Mustacchi /*
11235fc40de0SRobert Mustacchi * Make sure the line is padded so the generated C code looks
11245fc40de0SRobert Mustacchi * like reasonable C style.
11255fc40de0SRobert Mustacchi */
11265fc40de0SRobert Mustacchi if (p != map->cmap_procs) {
11275fc40de0SRobert Mustacchi if (fputs("\t ", f) == -1) {
11285fc40de0SRobert Mustacchi return (B_FALSE);
11295fc40de0SRobert Mustacchi }
11305fc40de0SRobert Mustacchi }
11315fc40de0SRobert Mustacchi
11325fc40de0SRobert Mustacchi if (p->cproc_nsteps > 0) {
11335fc40de0SRobert Mustacchi uint_t i;
11345fc40de0SRobert Mustacchi
11355fc40de0SRobert Mustacchi if (fprintf(f, "(model == 0x%x &&\n\t (",
11365fc40de0SRobert Mustacchi p->cproc_model) == -1) {
11375fc40de0SRobert Mustacchi return (B_FALSE);
11385fc40de0SRobert Mustacchi }
11395fc40de0SRobert Mustacchi
11405fc40de0SRobert Mustacchi for (i = 0; i < p->cproc_nsteps; i++) {
11415fc40de0SRobert Mustacchi if (fprintf(f, "stepping == 0x%x%s",
11425fc40de0SRobert Mustacchi p->cproc_steppings[i],
11435fc40de0SRobert Mustacchi i + 1 != p->cproc_nsteps ?
11445fc40de0SRobert Mustacchi " ||\n\t " : "") == -1) {
11455fc40de0SRobert Mustacchi return (B_FALSE);
11465fc40de0SRobert Mustacchi }
11475fc40de0SRobert Mustacchi }
11485fc40de0SRobert Mustacchi
11495fc40de0SRobert Mustacchi if (fputs("))", f) == -1) {
11505fc40de0SRobert Mustacchi return (B_FALSE);
11515fc40de0SRobert Mustacchi }
11525fc40de0SRobert Mustacchi } else if (fprintf(f, "model == 0x%x", p->cproc_model) == -1) {
11535fc40de0SRobert Mustacchi return (B_FALSE);
11545fc40de0SRobert Mustacchi }
11555fc40de0SRobert Mustacchi
11565fc40de0SRobert Mustacchi if (fprintf(f, "%s\n",
11575fc40de0SRobert Mustacchi p->cproc_next != NULL ? " ||" : ") {") == -1) {
11585fc40de0SRobert Mustacchi return (B_FALSE);
11595fc40de0SRobert Mustacchi }
11605fc40de0SRobert Mustacchi }
11615fc40de0SRobert Mustacchi
11625fc40de0SRobert Mustacchi if (fprintf(f, "\t\t\treturn (pcbe_core_events_%s);\n",
11635fc40de0SRobert Mustacchi map->cmap_name) == -1) {
11645fc40de0SRobert Mustacchi return (B_FALSE);
11655fc40de0SRobert Mustacchi }
11665fc40de0SRobert Mustacchi
11675fc40de0SRobert Mustacchi return (B_TRUE);
11685fc40de0SRobert Mustacchi }
11695fc40de0SRobert Mustacchi
117053548f91SRobert Mustacchi /*
1171*3db3a4acSRobert Mustacchi * This is a wrapper around unlinkat that makes sure that we don't clobber
1172*3db3a4acSRobert Mustacchi * errno, which is used for properly printing out error messages below.
1173*3db3a4acSRobert Mustacchi */
1174*3db3a4acSRobert Mustacchi static void
cpcgen_remove_tmpfile(int dirfd,const char * path)1175*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(int dirfd, const char *path)
1176*3db3a4acSRobert Mustacchi {
1177*3db3a4acSRobert Mustacchi int e = errno;
1178*3db3a4acSRobert Mustacchi (void) unlinkat(dirfd, path, 0);
1179*3db3a4acSRobert Mustacchi errno = e;
1180*3db3a4acSRobert Mustacchi }
1181*3db3a4acSRobert Mustacchi
1182*3db3a4acSRobert Mustacchi /*
118353548f91SRobert Mustacchi * Generate a header file that declares all of these arrays and provide a map
118453548f91SRobert Mustacchi * for models to the corresponding table to use.
118553548f91SRobert Mustacchi */
118653548f91SRobert Mustacchi static void
cpcgen_common_intel_files(int dirfd)1187*3db3a4acSRobert Mustacchi cpcgen_common_intel_files(int dirfd)
118853548f91SRobert Mustacchi {
118953548f91SRobert Mustacchi const char *fname = "core_pcbe_cpcgen.h";
119053548f91SRobert Mustacchi char *tmpname;
119153548f91SRobert Mustacchi int fd;
119253548f91SRobert Mustacchi FILE *f;
119353548f91SRobert Mustacchi cpc_map_t *map;
119453548f91SRobert Mustacchi
119553548f91SRobert Mustacchi if (asprintf(&tmpname, ".%s.%d", fname, getpid()) == -1) {
119653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct temporary file name");
119753548f91SRobert Mustacchi }
119853548f91SRobert Mustacchi
119953548f91SRobert Mustacchi if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) {
120053548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to create temporary file %s",
120153548f91SRobert Mustacchi tmpname);
120253548f91SRobert Mustacchi }
120353548f91SRobert Mustacchi
120453548f91SRobert Mustacchi if ((f = fdopen(fd, "w")) == NULL) {
1205*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
120653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to fdopen temporary file");
120753548f91SRobert Mustacchi }
120853548f91SRobert Mustacchi
1209*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_intel_header, cpcgen_intel_mapfile) == -1) {
1210*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
121153548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to temporary file "
121253548f91SRobert Mustacchi "for %s", fname);
121353548f91SRobert Mustacchi }
121453548f91SRobert Mustacchi
121553548f91SRobert Mustacchi if (fprintf(f, "#ifndef _CORE_PCBE_CPCGEN_H\n"
121653548f91SRobert Mustacchi "#define\t_CORE_PCBE_CPCGEN_H\n"
121753548f91SRobert Mustacchi "\n"
121853548f91SRobert Mustacchi "#ifdef __cplusplus\n"
121953548f91SRobert Mustacchi "extern \"C\" {\n"
122053548f91SRobert Mustacchi "#endif\n"
122153548f91SRobert Mustacchi "\n"
12225fc40de0SRobert Mustacchi "extern const struct events_table_t *core_cpcgen_table(uint_t, "
12235fc40de0SRobert Mustacchi "uint_t);\n"
122453548f91SRobert Mustacchi "\n") == -1) {
1225*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
122653548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to "
122753548f91SRobert Mustacchi "temporary file for %s", fname);
122853548f91SRobert Mustacchi }
122953548f91SRobert Mustacchi
123053548f91SRobert Mustacchi for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
123153548f91SRobert Mustacchi if (fprintf(f, "extern const struct events_table_t "
123253548f91SRobert Mustacchi "pcbe_core_events_%s[];\n", map->cmap_name) == -1) {
1233*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
123453548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write entry to "
123553548f91SRobert Mustacchi "temporary file for %s", fname);
123653548f91SRobert Mustacchi }
123753548f91SRobert Mustacchi }
123853548f91SRobert Mustacchi
123953548f91SRobert Mustacchi if (fprintf(f, "\n"
124053548f91SRobert Mustacchi "#ifdef __cplusplus\n"
124153548f91SRobert Mustacchi "}\n"
124253548f91SRobert Mustacchi "#endif\n"
124353548f91SRobert Mustacchi "\n"
124453548f91SRobert Mustacchi "#endif /* _CORE_PCBE_CPCGEN_H */\n") == -1) {
1245*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
124653548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to "
124753548f91SRobert Mustacchi "temporary file for %s", fname);
124853548f91SRobert Mustacchi }
124953548f91SRobert Mustacchi
125053548f91SRobert Mustacchi if (fflush(f) != 0 || fclose(f) != 0) {
1251*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
125253548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to flush and close temporary file");
125353548f91SRobert Mustacchi }
125453548f91SRobert Mustacchi
125553548f91SRobert Mustacchi if (renameat(dirfd, tmpname, dirfd, fname) != 0) {
125653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to rename temporary file %s",
125753548f91SRobert Mustacchi tmpname);
125853548f91SRobert Mustacchi }
125953548f91SRobert Mustacchi
126053548f91SRobert Mustacchi free(tmpname);
126153548f91SRobert Mustacchi
126253548f91SRobert Mustacchi /* Now again for the .c file. */
126353548f91SRobert Mustacchi fname = "core_pcbe_cpcgen.c";
126453548f91SRobert Mustacchi if (asprintf(&tmpname, ".%s.%d", fname, getpid()) == -1) {
126553548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct temporary file name");
126653548f91SRobert Mustacchi }
126753548f91SRobert Mustacchi
126853548f91SRobert Mustacchi if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) {
126953548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to create temporary file %s",
127053548f91SRobert Mustacchi tmpname);
127153548f91SRobert Mustacchi }
127253548f91SRobert Mustacchi
127353548f91SRobert Mustacchi if ((f = fdopen(fd, "w")) == NULL) {
1274*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
127553548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to fdopen temporary file");
127653548f91SRobert Mustacchi }
127753548f91SRobert Mustacchi
1278*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_intel_header, cpcgen_intel_mapfile) == -1) {
1279*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
128053548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to temporary file "
128153548f91SRobert Mustacchi "for %s", fname);
128253548f91SRobert Mustacchi }
128353548f91SRobert Mustacchi
128453548f91SRobert Mustacchi if (fprintf(f, "#include <core_pcbe_table.h>\n"
128553548f91SRobert Mustacchi "#include <sys/null.h>\n"
128653548f91SRobert Mustacchi "#include \"core_pcbe_cpcgen.h\"\n"
128753548f91SRobert Mustacchi "\n"
128853548f91SRobert Mustacchi "const struct events_table_t *\n"
12895fc40de0SRobert Mustacchi "core_cpcgen_table(uint_t model, uint_t stepping)\n"
12905fc40de0SRobert Mustacchi "{\n") == -1) {
1291*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
129253548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to "
129353548f91SRobert Mustacchi "temporary file for %s", fname);
129453548f91SRobert Mustacchi }
129553548f91SRobert Mustacchi
129653548f91SRobert Mustacchi for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
12975fc40de0SRobert Mustacchi if (!cpcgen_generate_map(f, map, map == cpcgen_maps)) {
1298*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
12995fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "failed to write to temporary "
13005fc40de0SRobert Mustacchi "file for %s", fname);
130153548f91SRobert Mustacchi }
130253548f91SRobert Mustacchi }
130353548f91SRobert Mustacchi
13045fc40de0SRobert Mustacchi if (fprintf(f, "\t} else {\n"
130553548f91SRobert Mustacchi "\t\t\treturn (NULL);\n"
130653548f91SRobert Mustacchi "\t}\n"
130753548f91SRobert Mustacchi "}\n") == -1) {
1308*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
130953548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to "
131053548f91SRobert Mustacchi "temporary file for %s", fname);
131153548f91SRobert Mustacchi }
131253548f91SRobert Mustacchi
131353548f91SRobert Mustacchi if (fflush(f) != 0 || fclose(f) != 0) {
1314*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
131553548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to flush and close temporary file");
131653548f91SRobert Mustacchi }
131753548f91SRobert Mustacchi
131853548f91SRobert Mustacchi if (renameat(dirfd, tmpname, dirfd, fname) != 0) {
131953548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to rename temporary file %s",
132053548f91SRobert Mustacchi tmpname);
132153548f91SRobert Mustacchi }
132253548f91SRobert Mustacchi
132353548f91SRobert Mustacchi free(tmpname);
132453548f91SRobert Mustacchi }
132553548f91SRobert Mustacchi
132653548f91SRobert Mustacchi /*
132753548f91SRobert Mustacchi * Look at a rule to determine whether or not we should consider including it or
132853548f91SRobert Mustacchi * not. At this point we've already filtered things such that we only get core
132953548f91SRobert Mustacchi * events.
133053548f91SRobert Mustacchi *
133153548f91SRobert Mustacchi * To consider an entry, we currently apply the following criteria:
133253548f91SRobert Mustacchi *
133353548f91SRobert Mustacchi * - The MSRIndex and MSRValue are zero. Programming additional MSRs is no
133453548f91SRobert Mustacchi * supported right now.
133553548f91SRobert Mustacchi * - TakenAlone is non-zero, which means that it cannot run at the same time as
133653548f91SRobert Mustacchi * another field.
133753548f91SRobert Mustacchi * - Offcore is one, indicating that it is off the core and we need to figure
133853548f91SRobert Mustacchi * out if we can support this.
133953548f91SRobert Mustacchi * - If the counter is fixed, don't use it for now.
134053548f91SRobert Mustacchi * - If more than one value is specified in the EventCode or UMask values
134153548f91SRobert Mustacchi */
134253548f91SRobert Mustacchi static boolean_t
cpcgen_skip_intel_entry(nvlist_t * nvl,const char * path,uint_t ent)1343*3db3a4acSRobert Mustacchi cpcgen_skip_intel_entry(nvlist_t *nvl, const char *path, uint_t ent)
134453548f91SRobert Mustacchi {
134553548f91SRobert Mustacchi char *event, *msridx, *msrval, *taken, *offcore, *counter;
134653548f91SRobert Mustacchi char *ecode, *umask;
134753548f91SRobert Mustacchi
134853548f91SRobert Mustacchi /*
134953548f91SRobert Mustacchi * Require EventName, it's kind of useless without that.
135053548f91SRobert Mustacchi */
135153548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "EventName", &event) != 0) {
135253548f91SRobert Mustacchi errx(EXIT_FAILURE, "Found event without 'EventName' property "
135353548f91SRobert Mustacchi "in %s, entry %u", path, ent);
135453548f91SRobert Mustacchi }
135553548f91SRobert Mustacchi
135653548f91SRobert Mustacchi /*
135753548f91SRobert Mustacchi * If we can't find an expected value, whine about it.
135853548f91SRobert Mustacchi */
135953548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "MSRIndex", &msridx) != 0 ||
136053548f91SRobert Mustacchi nvlist_lookup_string(nvl, "MSRValue", &msrval) != 0 ||
136153548f91SRobert Mustacchi nvlist_lookup_string(nvl, "Counter", &counter) != 0 ||
136253548f91SRobert Mustacchi nvlist_lookup_string(nvl, "EventCode", &ecode) != 0 ||
136353548f91SRobert Mustacchi nvlist_lookup_string(nvl, "UMask", &umask) != 0 ||
136453548f91SRobert Mustacchi nvlist_lookup_string(nvl, "Offcore", &offcore) != 0) {
136553548f91SRobert Mustacchi warnx("Skipping event %s (index %u) from %s, missing required "
136653548f91SRobert Mustacchi "property", event, ent, path);
136753548f91SRobert Mustacchi return (B_TRUE);
136853548f91SRobert Mustacchi }
136953548f91SRobert Mustacchi
137053548f91SRobert Mustacchi /*
137153548f91SRobert Mustacchi * MSRIndex and MSRvalue comes as either "0" or "0x00".
137253548f91SRobert Mustacchi */
137353548f91SRobert Mustacchi if ((strcmp(msridx, "0") != 0 && strcmp(msridx, "0x00") != 0) ||
137453548f91SRobert Mustacchi (strcmp(msrval, "0") != 0 && strcmp(msridx, "0x00") != 0) ||
137553548f91SRobert Mustacchi strcmp(offcore, "0") != 0 || strchr(ecode, ',') != NULL ||
137653548f91SRobert Mustacchi strchr(umask, ',') != NULL) {
137753548f91SRobert Mustacchi return (B_TRUE);
137853548f91SRobert Mustacchi }
137953548f91SRobert Mustacchi
138053548f91SRobert Mustacchi /*
138153548f91SRobert Mustacchi * Unfortunately, not everything actually has "TakenAlone". If it
138253548f91SRobert Mustacchi * doesn't, we assume that it doesn't have to be.
138353548f91SRobert Mustacchi */
138453548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "TakenAlone", &taken) == 0 &&
138553548f91SRobert Mustacchi strcmp(taken, "0") != 0) {
138653548f91SRobert Mustacchi return (B_TRUE);
138753548f91SRobert Mustacchi }
138853548f91SRobert Mustacchi
138953548f91SRobert Mustacchi
139053548f91SRobert Mustacchi if (strncasecmp(counter, "fixed", strlen("fixed")) == 0)
139153548f91SRobert Mustacchi return (B_TRUE);
139253548f91SRobert Mustacchi
139353548f91SRobert Mustacchi return (B_FALSE);
139453548f91SRobert Mustacchi }
1395*3db3a4acSRobert Mustacchi static char *
cpcgen_manual_amd_name(cpc_map_t * map)1396*3db3a4acSRobert Mustacchi cpcgen_manual_amd_name(cpc_map_t *map)
1397*3db3a4acSRobert Mustacchi {
1398*3db3a4acSRobert Mustacchi char *name;
1399*3db3a4acSRobert Mustacchi
1400*3db3a4acSRobert Mustacchi if (asprintf(&name, "amd_%s_events.3cpc", map->cmap_name) == -1) {
1401*3db3a4acSRobert Mustacchi warn("failed to assemble file name for %s", map->cmap_path);
1402*3db3a4acSRobert Mustacchi return (NULL);
1403*3db3a4acSRobert Mustacchi }
1404*3db3a4acSRobert Mustacchi
1405*3db3a4acSRobert Mustacchi return (name);
1406*3db3a4acSRobert Mustacchi }
1407*3db3a4acSRobert Mustacchi
1408*3db3a4acSRobert Mustacchi static boolean_t
cpcgen_manual_amd_file_before(FILE * f,cpc_map_t * map)1409*3db3a4acSRobert Mustacchi cpcgen_manual_amd_file_before(FILE *f, cpc_map_t *map)
1410*3db3a4acSRobert Mustacchi {
1411*3db3a4acSRobert Mustacchi size_t i;
1412*3db3a4acSRobert Mustacchi char *upper;
1413*3db3a4acSRobert Mustacchi const char *family;
1414*3db3a4acSRobert Mustacchi
1415*3db3a4acSRobert Mustacchi if ((upper = strdup(map->cmap_name)) == NULL) {
1416*3db3a4acSRobert Mustacchi warn("failed to duplicate manual name for %s", map->cmap_name);
1417*3db3a4acSRobert Mustacchi return (B_FALSE);
1418*3db3a4acSRobert Mustacchi }
1419*3db3a4acSRobert Mustacchi
1420*3db3a4acSRobert Mustacchi for (i = 0; upper[i] != '\0'; i++) {
1421*3db3a4acSRobert Mustacchi upper[i] = toupper(upper[i]);
1422*3db3a4acSRobert Mustacchi }
1423*3db3a4acSRobert Mustacchi
1424*3db3a4acSRobert Mustacchi family = map->cmap_name + 1;
1425*3db3a4acSRobert Mustacchi
1426*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_manual_amd_header, map->cmap_path, upper,
1427*3db3a4acSRobert Mustacchi family, family, family) == -1) {
1428*3db3a4acSRobert Mustacchi warn("failed to write out manual header for %s",
1429*3db3a4acSRobert Mustacchi map->cmap_name);
1430*3db3a4acSRobert Mustacchi free(upper);
1431*3db3a4acSRobert Mustacchi return (B_FALSE);
1432*3db3a4acSRobert Mustacchi }
1433*3db3a4acSRobert Mustacchi
1434*3db3a4acSRobert Mustacchi free(upper);
1435*3db3a4acSRobert Mustacchi return (B_TRUE);
1436*3db3a4acSRobert Mustacchi }
1437*3db3a4acSRobert Mustacchi
1438*3db3a4acSRobert Mustacchi static boolean_t
cpcgen_manual_amd_file_after(FILE * f,cpc_map_t * map)1439*3db3a4acSRobert Mustacchi cpcgen_manual_amd_file_after(FILE *f, cpc_map_t *map)
1440*3db3a4acSRobert Mustacchi {
1441*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_manual_amd_trailer) == -1) {
1442*3db3a4acSRobert Mustacchi warn("failed to write out manual header for %s",
1443*3db3a4acSRobert Mustacchi map->cmap_name);
1444*3db3a4acSRobert Mustacchi return (B_FALSE);
1445*3db3a4acSRobert Mustacchi }
1446*3db3a4acSRobert Mustacchi
1447*3db3a4acSRobert Mustacchi return (B_TRUE);
1448*3db3a4acSRobert Mustacchi }
1449*3db3a4acSRobert Mustacchi
1450*3db3a4acSRobert Mustacchi static boolean_t
cpcgen_manual_amd_event(FILE * f,nvlist_t * nvl,const char * path,uint32_t ent)1451*3db3a4acSRobert Mustacchi cpcgen_manual_amd_event(FILE *f, nvlist_t *nvl, const char *path, uint32_t ent)
1452*3db3a4acSRobert Mustacchi {
1453*3db3a4acSRobert Mustacchi char *name, *mnemonic = NULL, *summary = NULL, *desc = NULL;
1454*3db3a4acSRobert Mustacchi char *umode;
1455*3db3a4acSRobert Mustacchi nvlist_t *units = NULL;
1456*3db3a4acSRobert Mustacchi uint32_t i, length;
1457*3db3a4acSRobert Mustacchi
1458*3db3a4acSRobert Mustacchi if (nvlist_lookup_string(nvl, "name", &name) != 0) {
1459*3db3a4acSRobert Mustacchi warnx("Found event without 'name' property in %s, entry %u",
1460*3db3a4acSRobert Mustacchi path, ent);
1461*3db3a4acSRobert Mustacchi return (B_FALSE);
1462*3db3a4acSRobert Mustacchi }
1463*3db3a4acSRobert Mustacchi
1464*3db3a4acSRobert Mustacchi if (nvlist_lookup_string(nvl, "mnemonic", &mnemonic) != 0 ||
1465*3db3a4acSRobert Mustacchi nvlist_lookup_string(nvl, "summary", &summary) != 0) {
1466*3db3a4acSRobert Mustacchi warnx("event %s in %s, entry %u, missing required fields",
1467*3db3a4acSRobert Mustacchi name, path, ent);
1468*3db3a4acSRobert Mustacchi return (B_FALSE);
1469*3db3a4acSRobert Mustacchi }
1470*3db3a4acSRobert Mustacchi
1471*3db3a4acSRobert Mustacchi /*
1472*3db3a4acSRobert Mustacchi * Allow the other fields to be missing.
1473*3db3a4acSRobert Mustacchi */
1474*3db3a4acSRobert Mustacchi (void) nvlist_lookup_string(nvl, "description", &desc);
1475*3db3a4acSRobert Mustacchi (void) nvlist_lookup_nvlist(nvl, "units", &units);
1476*3db3a4acSRobert Mustacchi
1477*3db3a4acSRobert Mustacchi if (fprintf(f, ".It Sy %s\n", name) == -1) {
1478*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", name);
1479*3db3a4acSRobert Mustacchi }
1480*3db3a4acSRobert Mustacchi
1481*3db3a4acSRobert Mustacchi if (fprintf(f, ".Sy %s -\n"
1482*3db3a4acSRobert Mustacchi "%s\n", mnemonic, summary) == -1) {
1483*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", name);
1484*3db3a4acSRobert Mustacchi return (B_FALSE);
1485*3db3a4acSRobert Mustacchi }
1486*3db3a4acSRobert Mustacchi
1487*3db3a4acSRobert Mustacchi if (desc != NULL) {
1488*3db3a4acSRobert Mustacchi if (fprintf(f, ".Pp\n%s\n", desc) == -1) {
1489*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", name);
1490*3db3a4acSRobert Mustacchi return (B_FALSE);
1491*3db3a4acSRobert Mustacchi }
1492*3db3a4acSRobert Mustacchi }
1493*3db3a4acSRobert Mustacchi
1494*3db3a4acSRobert Mustacchi if (units == NULL)
1495*3db3a4acSRobert Mustacchi return (B_TRUE);
1496*3db3a4acSRobert Mustacchi
1497*3db3a4acSRobert Mustacchi /*
1498*3db3a4acSRobert Mustacchi * Skip units we don't know how to handle.
1499*3db3a4acSRobert Mustacchi */
1500*3db3a4acSRobert Mustacchi if (nvlist_lookup_string(nvl, "unit_mode", &umode) == 0) {
1501*3db3a4acSRobert Mustacchi return (B_TRUE);
1502*3db3a4acSRobert Mustacchi }
1503*3db3a4acSRobert Mustacchi
1504*3db3a4acSRobert Mustacchi if (fprintf(f, ".Pp\n"
1505*3db3a4acSRobert Mustacchi "This event has the following units which may be used\n"
1506*3db3a4acSRobert Mustacchi "to modify the behavior of the event:\n"
1507*3db3a4acSRobert Mustacchi ".Bl -tag -width Sy\n") == -1) {
1508*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", name);
1509*3db3a4acSRobert Mustacchi return (B_FALSE);
1510*3db3a4acSRobert Mustacchi }
1511*3db3a4acSRobert Mustacchi
1512*3db3a4acSRobert Mustacchi if (nvlist_lookup_uint32(units, "length", &length) != 0) {
1513*3db3a4acSRobert Mustacchi warnx("found units array, but could not look up length "
1514*3db3a4acSRobert Mustacchi "property for events %s (index %u) in file %s",
1515*3db3a4acSRobert Mustacchi name, ent, path);
1516*3db3a4acSRobert Mustacchi return (B_FALSE);
1517*3db3a4acSRobert Mustacchi }
1518*3db3a4acSRobert Mustacchi
1519*3db3a4acSRobert Mustacchi for (i = 0; i < length; i++) {
1520*3db3a4acSRobert Mustacchi nvlist_t *uvl;
1521*3db3a4acSRobert Mustacchi char num[64];
1522*3db3a4acSRobert Mustacchi char *uname, *udesc = NULL;
1523*3db3a4acSRobert Mustacchi
1524*3db3a4acSRobert Mustacchi (void) snprintf(num, sizeof (num), "%u", i);
1525*3db3a4acSRobert Mustacchi if (nvlist_lookup_nvlist(units, num, &uvl) != 0) {
1526*3db3a4acSRobert Mustacchi warnx("failed to look up unit %u for event %s (index "
1527*3db3a4acSRobert Mustacchi "%u) in file %s", i, name, ent, path);
1528*3db3a4acSRobert Mustacchi return (B_FALSE);
1529*3db3a4acSRobert Mustacchi }
1530*3db3a4acSRobert Mustacchi
1531*3db3a4acSRobert Mustacchi if (nvlist_lookup_string(uvl, "name", &uname) != 0) {
1532*3db3a4acSRobert Mustacchi warnx("failed to find required members for unit array "
1533*3db3a4acSRobert Mustacchi "entry %u of event %s (index %u) from file %s",
1534*3db3a4acSRobert Mustacchi i, name, ent, path);
1535*3db3a4acSRobert Mustacchi return (B_FALSE);
1536*3db3a4acSRobert Mustacchi }
1537*3db3a4acSRobert Mustacchi (void) nvlist_lookup_string(uvl, "description", &udesc);
1538*3db3a4acSRobert Mustacchi if (fprintf(f, ".It Sy %s\n", uname) == -1) {
1539*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s", name);
1540*3db3a4acSRobert Mustacchi return (B_FALSE);
1541*3db3a4acSRobert Mustacchi }
1542*3db3a4acSRobert Mustacchi
1543*3db3a4acSRobert Mustacchi if (udesc != NULL) {
1544*3db3a4acSRobert Mustacchi if (fprintf(f, "%s\n", udesc) == -1) {
1545*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s",
1546*3db3a4acSRobert Mustacchi name);
1547*3db3a4acSRobert Mustacchi return (B_FALSE);
1548*3db3a4acSRobert Mustacchi }
1549*3db3a4acSRobert Mustacchi }
1550*3db3a4acSRobert Mustacchi }
1551*3db3a4acSRobert Mustacchi
1552*3db3a4acSRobert Mustacchi if (fprintf(f, ".El\n") == -1) {
1553*3db3a4acSRobert Mustacchi warn("failed to write out event entry %s",
1554*3db3a4acSRobert Mustacchi name);
1555*3db3a4acSRobert Mustacchi return (B_FALSE);
1556*3db3a4acSRobert Mustacchi }
1557*3db3a4acSRobert Mustacchi
1558*3db3a4acSRobert Mustacchi return (B_TRUE);
1559*3db3a4acSRobert Mustacchi }
1560*3db3a4acSRobert Mustacchi
1561*3db3a4acSRobert Mustacchi static char *
cpcgen_cfile_amd_name(cpc_map_t * map)1562*3db3a4acSRobert Mustacchi cpcgen_cfile_amd_name(cpc_map_t *map)
1563*3db3a4acSRobert Mustacchi {
1564*3db3a4acSRobert Mustacchi char *name;
1565*3db3a4acSRobert Mustacchi
1566*3db3a4acSRobert Mustacchi if (asprintf(&name, "opteron_pcbe_%s.c", map->cmap_name) == -1) {
1567*3db3a4acSRobert Mustacchi warn("failed to assemble file name for %s", map->cmap_path);
1568*3db3a4acSRobert Mustacchi return (NULL);
1569*3db3a4acSRobert Mustacchi }
1570*3db3a4acSRobert Mustacchi
1571*3db3a4acSRobert Mustacchi return (name);
1572*3db3a4acSRobert Mustacchi }
1573*3db3a4acSRobert Mustacchi
1574*3db3a4acSRobert Mustacchi /*
1575*3db3a4acSRobert Mustacchi * Generate a header file that can be used to synthesize the data events we care
1576*3db3a4acSRobert Mustacchi * about.
1577*3db3a4acSRobert Mustacchi */
1578*3db3a4acSRobert Mustacchi static void
cpcgen_common_amd_files(int dirfd)1579*3db3a4acSRobert Mustacchi cpcgen_common_amd_files(int dirfd)
1580*3db3a4acSRobert Mustacchi {
1581*3db3a4acSRobert Mustacchi const char *fname = "opteron_pcbe_cpcgen.h";
1582*3db3a4acSRobert Mustacchi char *tmpname;
1583*3db3a4acSRobert Mustacchi int fd;
1584*3db3a4acSRobert Mustacchi FILE *f;
1585*3db3a4acSRobert Mustacchi cpc_map_t *map;
1586*3db3a4acSRobert Mustacchi
1587*3db3a4acSRobert Mustacchi if (asprintf(&tmpname, ".%s.%d", fname, getpid()) == -1) {
1588*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to construct temporary file name");
1589*3db3a4acSRobert Mustacchi }
1590*3db3a4acSRobert Mustacchi
1591*3db3a4acSRobert Mustacchi if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) {
1592*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to create temporary file %s",
1593*3db3a4acSRobert Mustacchi tmpname);
1594*3db3a4acSRobert Mustacchi }
1595*3db3a4acSRobert Mustacchi
1596*3db3a4acSRobert Mustacchi if ((f = fdopen(fd, "w")) == NULL) {
1597*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
1598*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to fdopen temporary file");
1599*3db3a4acSRobert Mustacchi }
1600*3db3a4acSRobert Mustacchi
1601*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_cddl_header) == -1) {
1602*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
1603*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to write header to "
1604*3db3a4acSRobert Mustacchi "temporary file for %s", fname);
1605*3db3a4acSRobert Mustacchi }
1606*3db3a4acSRobert Mustacchi
1607*3db3a4acSRobert Mustacchi if (fprintf(f, "#ifndef _OPTERON_PCBE_CPCGEN_H\n"
1608*3db3a4acSRobert Mustacchi "#define\t_OPTERON_PCBE_CPCGEN_H\n"
1609*3db3a4acSRobert Mustacchi "\n"
1610*3db3a4acSRobert Mustacchi "#ifdef __cplusplus\n"
1611*3db3a4acSRobert Mustacchi "extern \"C\" {\n"
1612*3db3a4acSRobert Mustacchi "#endif\n"
1613*3db3a4acSRobert Mustacchi "\n") == -1) {
1614*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
1615*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to write header to "
1616*3db3a4acSRobert Mustacchi "temporary file for %s", fname);
1617*3db3a4acSRobert Mustacchi }
1618*3db3a4acSRobert Mustacchi
1619*3db3a4acSRobert Mustacchi for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
1620*3db3a4acSRobert Mustacchi if (fprintf(f, "extern const amd_event_t "
1621*3db3a4acSRobert Mustacchi "opteron_pcbe_%s_events[];\n", map->cmap_name) == -1) {
1622*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
1623*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to write header to "
1624*3db3a4acSRobert Mustacchi "temporary file for %s", fname);
1625*3db3a4acSRobert Mustacchi }
1626*3db3a4acSRobert Mustacchi }
1627*3db3a4acSRobert Mustacchi
1628*3db3a4acSRobert Mustacchi if (fprintf(f, "\n"
1629*3db3a4acSRobert Mustacchi "#ifdef __cplusplus\n"
1630*3db3a4acSRobert Mustacchi "}\n"
1631*3db3a4acSRobert Mustacchi "#endif\n"
1632*3db3a4acSRobert Mustacchi "\n"
1633*3db3a4acSRobert Mustacchi "#endif /* _OPTERON_PCBE_CPCGEN_H */\n") == -1) {
1634*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
1635*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to write header to "
1636*3db3a4acSRobert Mustacchi "temporary file for %s", fname);
1637*3db3a4acSRobert Mustacchi }
1638*3db3a4acSRobert Mustacchi
1639*3db3a4acSRobert Mustacchi
1640*3db3a4acSRobert Mustacchi
1641*3db3a4acSRobert Mustacchi if (fflush(f) != 0 || fclose(f) != 0) {
1642*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
1643*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to flush and close temporary file");
1644*3db3a4acSRobert Mustacchi }
1645*3db3a4acSRobert Mustacchi
1646*3db3a4acSRobert Mustacchi if (renameat(dirfd, tmpname, dirfd, fname) != 0) {
1647*3db3a4acSRobert Mustacchi err(EXIT_FAILURE, "failed to rename temporary file %s",
1648*3db3a4acSRobert Mustacchi tmpname);
1649*3db3a4acSRobert Mustacchi }
1650*3db3a4acSRobert Mustacchi
1651*3db3a4acSRobert Mustacchi free(tmpname);
1652*3db3a4acSRobert Mustacchi }
1653*3db3a4acSRobert Mustacchi
1654*3db3a4acSRobert Mustacchi static boolean_t
cpcgen_cfile_amd_before(FILE * f,cpc_map_t * map)1655*3db3a4acSRobert Mustacchi cpcgen_cfile_amd_before(FILE *f, cpc_map_t *map)
1656*3db3a4acSRobert Mustacchi {
1657*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_amd_header, map->cmap_name) == -1) {
1658*3db3a4acSRobert Mustacchi warn("failed to write header to temporary file for %s",
1659*3db3a4acSRobert Mustacchi map->cmap_path);
1660*3db3a4acSRobert Mustacchi return (B_FALSE);
1661*3db3a4acSRobert Mustacchi }
1662*3db3a4acSRobert Mustacchi
1663*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_amd_table_start, map->cmap_name) == -1) {
1664*3db3a4acSRobert Mustacchi warn("failed to write header to temporary file for %s",
1665*3db3a4acSRobert Mustacchi map->cmap_path);
1666*3db3a4acSRobert Mustacchi return (B_FALSE);
1667*3db3a4acSRobert Mustacchi }
1668*3db3a4acSRobert Mustacchi
1669*3db3a4acSRobert Mustacchi
1670*3db3a4acSRobert Mustacchi return (B_TRUE);
1671*3db3a4acSRobert Mustacchi }
1672*3db3a4acSRobert Mustacchi
1673*3db3a4acSRobert Mustacchi static boolean_t
cpcgen_cfile_amd_after(FILE * f,cpc_map_t * map)1674*3db3a4acSRobert Mustacchi cpcgen_cfile_amd_after(FILE *f, cpc_map_t *map)
1675*3db3a4acSRobert Mustacchi {
1676*3db3a4acSRobert Mustacchi if (fprintf(f, cpcgen_cfile_amd_table_end) == -1) {
1677*3db3a4acSRobert Mustacchi warn("failed to write footer to temporary file for %s",
1678*3db3a4acSRobert Mustacchi map->cmap_path);
1679*3db3a4acSRobert Mustacchi return (B_FALSE);
1680*3db3a4acSRobert Mustacchi }
1681*3db3a4acSRobert Mustacchi
1682*3db3a4acSRobert Mustacchi return (B_TRUE);
1683*3db3a4acSRobert Mustacchi }
1684*3db3a4acSRobert Mustacchi
1685*3db3a4acSRobert Mustacchi static boolean_t
cpcgen_cfile_amd_event(FILE * f,nvlist_t * nvl,const char * path,uint_t ent)1686*3db3a4acSRobert Mustacchi cpcgen_cfile_amd_event(FILE *f, nvlist_t *nvl, const char *path, uint_t ent)
1687*3db3a4acSRobert Mustacchi {
1688*3db3a4acSRobert Mustacchi char *name, *code, *umode;
1689*3db3a4acSRobert Mustacchi uint32_t i, length;
1690*3db3a4acSRobert Mustacchi nvlist_t *units;
1691*3db3a4acSRobert Mustacchi
1692*3db3a4acSRobert Mustacchi if (nvlist_lookup_string(nvl, "name", &name) != 0) {
1693*3db3a4acSRobert Mustacchi warnx("Found event without 'name' property in %s, entry %u",
1694*3db3a4acSRobert Mustacchi path, ent);
1695*3db3a4acSRobert Mustacchi return (B_FALSE);
1696*3db3a4acSRobert Mustacchi }
1697*3db3a4acSRobert Mustacchi
1698*3db3a4acSRobert Mustacchi if (nvlist_lookup_string(nvl, "code", &code) != 0) {
1699*3db3a4acSRobert Mustacchi warnx("event %s (index %u) from %s missing required properties "
1700*3db3a4acSRobert Mustacchi "for C translation", name, path, ent);
1701*3db3a4acSRobert Mustacchi return (B_FALSE);
1702*3db3a4acSRobert Mustacchi }
1703*3db3a4acSRobert Mustacchi
1704*3db3a4acSRobert Mustacchi if (fprintf(f, "\t{ \"%s\", %s, 0 },\n", name, code) == -1) {
1705*3db3a4acSRobert Mustacchi warn("failed to write out entry %s from %s", name, path);
1706*3db3a4acSRobert Mustacchi return (B_FALSE);
1707*3db3a4acSRobert Mustacchi }
1708*3db3a4acSRobert Mustacchi
1709*3db3a4acSRobert Mustacchi /*
1710*3db3a4acSRobert Mustacchi * The 'units' array is optional. If the rule has a specific 'unit_mode'
1711*3db3a4acSRobert Mustacchi * indicating how the units should be combined, skip that. We don't know
1712*3db3a4acSRobert Mustacchi * how to properly process that right now.
1713*3db3a4acSRobert Mustacchi */
1714*3db3a4acSRobert Mustacchi if (nvlist_lookup_nvlist(nvl, "units", &units) != 0) {
1715*3db3a4acSRobert Mustacchi return (B_TRUE);
1716*3db3a4acSRobert Mustacchi }
1717*3db3a4acSRobert Mustacchi
1718*3db3a4acSRobert Mustacchi if (nvlist_lookup_string(nvl, "unit_mode", &umode) == 0) {
1719*3db3a4acSRobert Mustacchi return (B_TRUE);
1720*3db3a4acSRobert Mustacchi }
1721*3db3a4acSRobert Mustacchi
1722*3db3a4acSRobert Mustacchi if (nvlist_lookup_uint32(units, "length", &length) != 0) {
1723*3db3a4acSRobert Mustacchi warnx("found units array, but could not look up length "
1724*3db3a4acSRobert Mustacchi "property for events %s (index %u) in file %s",
1725*3db3a4acSRobert Mustacchi name, ent, path);
1726*3db3a4acSRobert Mustacchi return (B_FALSE);
1727*3db3a4acSRobert Mustacchi }
1728*3db3a4acSRobert Mustacchi
1729*3db3a4acSRobert Mustacchi for (i = 0; i < length; i++) {
1730*3db3a4acSRobert Mustacchi nvlist_t *uvl;
1731*3db3a4acSRobert Mustacchi char num[64];
1732*3db3a4acSRobert Mustacchi char *uname, *urw;
1733*3db3a4acSRobert Mustacchi int32_t bit;
1734*3db3a4acSRobert Mustacchi
1735*3db3a4acSRobert Mustacchi (void) snprintf(num, sizeof (num), "%u", i);
1736*3db3a4acSRobert Mustacchi if (nvlist_lookup_nvlist(units, num, &uvl) != 0) {
1737*3db3a4acSRobert Mustacchi warnx("failed to look up unit %u for event %s (index "
1738*3db3a4acSRobert Mustacchi "%u) in file %s", i, name, ent, path);
1739*3db3a4acSRobert Mustacchi return (B_FALSE);
1740*3db3a4acSRobert Mustacchi }
1741*3db3a4acSRobert Mustacchi
1742*3db3a4acSRobert Mustacchi if (nvlist_lookup_string(uvl, "name", &uname) != 0 ||
1743*3db3a4acSRobert Mustacchi nvlist_lookup_string(uvl, "rw", &urw) != 0 ||
1744*3db3a4acSRobert Mustacchi nvlist_lookup_int32(uvl, "bit", &bit) != 0) {
1745*3db3a4acSRobert Mustacchi warnx("failed to find required members for unit array "
1746*3db3a4acSRobert Mustacchi "entry %u of event %s (index %u) from file %s",
1747*3db3a4acSRobert Mustacchi i, name, ent, path);
1748*3db3a4acSRobert Mustacchi dump_nvlist(uvl, 0);
1749*3db3a4acSRobert Mustacchi return (B_FALSE);
1750*3db3a4acSRobert Mustacchi }
1751*3db3a4acSRobert Mustacchi
1752*3db3a4acSRobert Mustacchi if (bit < 0 || bit > 31) {
1753*3db3a4acSRobert Mustacchi warnx("event %s (index %u) from file %s has invalid "
1754*3db3a4acSRobert Mustacchi "bit value: %d; skipping", name, ent, path, bit);
1755*3db3a4acSRobert Mustacchi continue;
1756*3db3a4acSRobert Mustacchi }
1757*3db3a4acSRobert Mustacchi
1758*3db3a4acSRobert Mustacchi if (strcasecmp(urw, "Read-write") != 0)
1759*3db3a4acSRobert Mustacchi continue;
1760*3db3a4acSRobert Mustacchi
1761*3db3a4acSRobert Mustacchi if (fprintf(f, "\t{ \"%s.%s\", %s, 0x%x },\n", name, uname,
1762*3db3a4acSRobert Mustacchi code, 1U << bit) == -1) {
1763*3db3a4acSRobert Mustacchi warn("failed to write out entry %s from %s", name,
1764*3db3a4acSRobert Mustacchi path);
1765*3db3a4acSRobert Mustacchi return (B_FALSE);
1766*3db3a4acSRobert Mustacchi }
1767*3db3a4acSRobert Mustacchi }
1768*3db3a4acSRobert Mustacchi
1769*3db3a4acSRobert Mustacchi return (B_TRUE);
1770*3db3a4acSRobert Mustacchi }
177153548f91SRobert Mustacchi
177253548f91SRobert Mustacchi /*
177353548f91SRobert Mustacchi * For each processor family, generate a data file that contains all of the
177453548f91SRobert Mustacchi * events that we support. Also generate a header that can be included that
177553548f91SRobert Mustacchi * declares all of the tables.
177653548f91SRobert Mustacchi */
177753548f91SRobert Mustacchi static void
cpcgen_gen(int dirfd)177853548f91SRobert Mustacchi cpcgen_gen(int dirfd)
177953548f91SRobert Mustacchi {
178053548f91SRobert Mustacchi cpc_map_t *map = cpcgen_maps;
178153548f91SRobert Mustacchi
178253548f91SRobert Mustacchi if (map == NULL) {
178353548f91SRobert Mustacchi errx(EXIT_FAILURE, "no platforms found or matched");
178453548f91SRobert Mustacchi }
178553548f91SRobert Mustacchi
178653548f91SRobert Mustacchi for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
178753548f91SRobert Mustacchi int fd, ret;
178853548f91SRobert Mustacchi FILE *f;
178953548f91SRobert Mustacchi char *tmpname, *name;
179053548f91SRobert Mustacchi uint32_t length, i;
179153548f91SRobert Mustacchi
179253548f91SRobert Mustacchi if ((name = cpcgen_ops.cgen_op_name(map)) == NULL) {
179353548f91SRobert Mustacchi exit(EXIT_FAILURE);
179453548f91SRobert Mustacchi }
179553548f91SRobert Mustacchi
179653548f91SRobert Mustacchi if (asprintf(&tmpname, ".%s.%d", name, getpid()) == -1) {
179753548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct temporary file "
179853548f91SRobert Mustacchi "name");
179953548f91SRobert Mustacchi }
180053548f91SRobert Mustacchi
180153548f91SRobert Mustacchi if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0444)) < 0) {
180253548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to create temporary file %s",
180353548f91SRobert Mustacchi tmpname);
180453548f91SRobert Mustacchi }
180553548f91SRobert Mustacchi
180653548f91SRobert Mustacchi if ((f = fdopen(fd, "w")) == NULL) {
1807*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
180853548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to fdopen temporary file");
180953548f91SRobert Mustacchi }
181053548f91SRobert Mustacchi
181153548f91SRobert Mustacchi if (!cpcgen_ops.cgen_op_file_before(f, map)) {
1812*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
181353548f91SRobert Mustacchi exit(EXIT_FAILURE);
181453548f91SRobert Mustacchi }
181553548f91SRobert Mustacchi
181653548f91SRobert Mustacchi /*
181753548f91SRobert Mustacchi * Iterate over array contents.
181853548f91SRobert Mustacchi */
181953548f91SRobert Mustacchi if ((ret = nvlist_lookup_uint32(map->cmap_data, "length",
182053548f91SRobert Mustacchi &length)) != 0) {
182153548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to look up length property "
182253548f91SRobert Mustacchi "in parsed data for %s: %s", map->cmap_path,
182353548f91SRobert Mustacchi strerror(ret));
182453548f91SRobert Mustacchi }
182553548f91SRobert Mustacchi
182653548f91SRobert Mustacchi for (i = 0; i < length; i++) {
182753548f91SRobert Mustacchi nvlist_t *nvl;
182853548f91SRobert Mustacchi char num[64];
182953548f91SRobert Mustacchi
183053548f91SRobert Mustacchi (void) snprintf(num, sizeof (num), "%u", i);
183153548f91SRobert Mustacchi if ((ret = nvlist_lookup_nvlist(map->cmap_data,
183253548f91SRobert Mustacchi num, &nvl)) != 0) {
1833*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
183453548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to look up array "
183553548f91SRobert Mustacchi "entry %u in parsed data for %s: %s", i,
183653548f91SRobert Mustacchi map->cmap_path, strerror(ret));
183753548f91SRobert Mustacchi }
183853548f91SRobert Mustacchi
1839*3db3a4acSRobert Mustacchi if (cpcgen_ops.cgen_op_skip != NULL &&
1840*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_skip(nvl, map->cmap_path, i)) {
184153548f91SRobert Mustacchi continue;
1842*3db3a4acSRobert Mustacchi }
184353548f91SRobert Mustacchi
184453548f91SRobert Mustacchi if (!cpcgen_ops.cgen_op_event(f, nvl, map->cmap_path,
184553548f91SRobert Mustacchi i)) {
1846*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
184753548f91SRobert Mustacchi exit(EXIT_FAILURE);
184853548f91SRobert Mustacchi }
184953548f91SRobert Mustacchi }
185053548f91SRobert Mustacchi
185153548f91SRobert Mustacchi if (!cpcgen_ops.cgen_op_file_after(f, map)) {
1852*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
185353548f91SRobert Mustacchi exit(EXIT_FAILURE);
185453548f91SRobert Mustacchi }
185553548f91SRobert Mustacchi
185653548f91SRobert Mustacchi if (fflush(f) != 0 || fclose(f) != 0) {
1857*3db3a4acSRobert Mustacchi cpcgen_remove_tmpfile(dirfd, tmpname);
185853548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to flush and close "
185953548f91SRobert Mustacchi "temporary file");
186053548f91SRobert Mustacchi }
186153548f91SRobert Mustacchi
186253548f91SRobert Mustacchi if (renameat(dirfd, tmpname, dirfd, name) != 0) {
186353548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to rename temporary file %s",
186453548f91SRobert Mustacchi tmpname);
186553548f91SRobert Mustacchi }
186653548f91SRobert Mustacchi
186753548f91SRobert Mustacchi free(name);
186853548f91SRobert Mustacchi free(tmpname);
186953548f91SRobert Mustacchi }
187053548f91SRobert Mustacchi }
187153548f91SRobert Mustacchi
187253548f91SRobert Mustacchi static void
cpcgen_usage(const char * fmt,...)187353548f91SRobert Mustacchi cpcgen_usage(const char *fmt, ...)
187453548f91SRobert Mustacchi {
187553548f91SRobert Mustacchi if (fmt != NULL) {
187653548f91SRobert Mustacchi va_list ap;
187753548f91SRobert Mustacchi
187853548f91SRobert Mustacchi (void) fprintf(stderr, "%s: ", cpcgen_progname);
187953548f91SRobert Mustacchi va_start(ap, fmt);
188053548f91SRobert Mustacchi (void) vfprintf(stderr, fmt, ap);
188153548f91SRobert Mustacchi va_end(ap);
188253548f91SRobert Mustacchi }
188353548f91SRobert Mustacchi
188453548f91SRobert Mustacchi (void) fprintf(stderr, "Usage: %s -a|-p platform -c|-H|-m -d datadir "
188553548f91SRobert Mustacchi "-o outdir\n"
188653548f91SRobert Mustacchi "\n"
188753548f91SRobert Mustacchi "\t-a generate data for all platforms\n"
188853548f91SRobert Mustacchi "\t-c generate C file for CPC\n"
188953548f91SRobert Mustacchi "\t-d specify the directory containt perfmon data\n"
1890*3db3a4acSRobert Mustacchi "\t-H generate header file and common files\n"
189153548f91SRobert Mustacchi "\t-m generate manual pages for CPC data\n"
1892*3db3a4acSRobert Mustacchi "\t-o output files in directory outdir\n"
189353548f91SRobert Mustacchi "\t-p generate data for a specified platform\n",
189453548f91SRobert Mustacchi cpcgen_progname);
189553548f91SRobert Mustacchi }
189653548f91SRobert Mustacchi
189753548f91SRobert Mustacchi int
main(int argc,char * argv[])189853548f91SRobert Mustacchi main(int argc, char *argv[])
189953548f91SRobert Mustacchi {
190053548f91SRobert Mustacchi int c, outdirfd;
190153548f91SRobert Mustacchi boolean_t do_mpage = B_FALSE, do_cfile = B_FALSE, do_header = B_FALSE,
190253548f91SRobert Mustacchi do_all = B_FALSE;
190353548f91SRobert Mustacchi const char *datadir = NULL, *outdir = NULL, *platform = NULL;
190453548f91SRobert Mustacchi uint_t count = 0;
190553548f91SRobert Mustacchi
190653548f91SRobert Mustacchi cpcgen_progname = basename(argv[0]);
190753548f91SRobert Mustacchi
190853548f91SRobert Mustacchi while ((c = getopt(argc, argv, ":acd:hHmo:p:")) != -1) {
190953548f91SRobert Mustacchi switch (c) {
191053548f91SRobert Mustacchi case 'a':
191153548f91SRobert Mustacchi do_all = B_TRUE;
191253548f91SRobert Mustacchi break;
191353548f91SRobert Mustacchi case 'c':
191453548f91SRobert Mustacchi do_cfile = B_TRUE;
191553548f91SRobert Mustacchi break;
191653548f91SRobert Mustacchi case 'd':
191753548f91SRobert Mustacchi datadir = optarg;
191853548f91SRobert Mustacchi break;
191953548f91SRobert Mustacchi case 'm':
192053548f91SRobert Mustacchi do_mpage = B_TRUE;
192153548f91SRobert Mustacchi break;
192253548f91SRobert Mustacchi case 'H':
192353548f91SRobert Mustacchi do_header = B_TRUE;
192453548f91SRobert Mustacchi break;
192553548f91SRobert Mustacchi case 'o':
192653548f91SRobert Mustacchi outdir = optarg;
192753548f91SRobert Mustacchi break;
192853548f91SRobert Mustacchi case 'p':
192953548f91SRobert Mustacchi platform = optarg;
193053548f91SRobert Mustacchi break;
193153548f91SRobert Mustacchi case ':':
193253548f91SRobert Mustacchi cpcgen_usage("Option -%c requires an operand\n",
193353548f91SRobert Mustacchi optopt);
193453548f91SRobert Mustacchi return (2);
193553548f91SRobert Mustacchi case '?':
193653548f91SRobert Mustacchi cpcgen_usage("Unknown option: -%c\n", optopt);
193753548f91SRobert Mustacchi return (2);
193853548f91SRobert Mustacchi case 'h':
193953548f91SRobert Mustacchi default:
194053548f91SRobert Mustacchi cpcgen_usage(NULL);
194153548f91SRobert Mustacchi return (2);
194253548f91SRobert Mustacchi }
194353548f91SRobert Mustacchi }
194453548f91SRobert Mustacchi
194553548f91SRobert Mustacchi count = 0;
194653548f91SRobert Mustacchi if (do_mpage)
194753548f91SRobert Mustacchi count++;
194853548f91SRobert Mustacchi if (do_cfile)
194953548f91SRobert Mustacchi count++;
195053548f91SRobert Mustacchi if (do_header)
195153548f91SRobert Mustacchi count++;
195253548f91SRobert Mustacchi if (count > 1) {
195353548f91SRobert Mustacchi cpcgen_usage("Only one of -c, -h, and -m may be specified\n");
195453548f91SRobert Mustacchi return (2);
195553548f91SRobert Mustacchi } else if (count == 0) {
195653548f91SRobert Mustacchi cpcgen_usage("One of -c, -h, and -m is required\n");
195753548f91SRobert Mustacchi return (2);
195853548f91SRobert Mustacchi }
195953548f91SRobert Mustacchi
196053548f91SRobert Mustacchi count = 0;
196153548f91SRobert Mustacchi if (do_all)
196253548f91SRobert Mustacchi count++;
196353548f91SRobert Mustacchi if (platform != NULL)
196453548f91SRobert Mustacchi count++;
196553548f91SRobert Mustacchi if (count > 1) {
196653548f91SRobert Mustacchi cpcgen_usage("Only one of -a and -p may be specified\n");
196753548f91SRobert Mustacchi return (2);
196853548f91SRobert Mustacchi } else if (count == 0) {
196953548f91SRobert Mustacchi cpcgen_usage("One of -a and -p is required\n");
197053548f91SRobert Mustacchi return (2);
197153548f91SRobert Mustacchi }
197253548f91SRobert Mustacchi
197353548f91SRobert Mustacchi if (outdir == NULL) {
197453548f91SRobert Mustacchi cpcgen_usage("Missing required output directory (-o)\n");
197553548f91SRobert Mustacchi return (2);
197653548f91SRobert Mustacchi }
197753548f91SRobert Mustacchi
197853548f91SRobert Mustacchi if ((outdirfd = open(outdir, O_RDONLY)) < 0) {
197953548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to open output directory %s", outdir);
198053548f91SRobert Mustacchi }
198153548f91SRobert Mustacchi
198253548f91SRobert Mustacchi if (datadir == NULL) {
198353548f91SRobert Mustacchi cpcgen_usage("Missing required data directory (-d)\n");
198453548f91SRobert Mustacchi return (2);
198553548f91SRobert Mustacchi }
198653548f91SRobert Mustacchi
1987*3db3a4acSRobert Mustacchi cpcgen_determine_vendor(datadir);
1988*3db3a4acSRobert Mustacchi
1989*3db3a4acSRobert Mustacchi switch (cpcgen_mode) {
1990*3db3a4acSRobert Mustacchi case CPCGEN_MODE_INTEL:
1991*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_gather = cpcgen_read_intel;
1992*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_common = cpcgen_common_intel_files;
1993*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_skip = cpcgen_skip_intel_entry;
1994*3db3a4acSRobert Mustacchi if (do_mpage) {
1995*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_name = cpcgen_manual_intel_name;
1996*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_file_before =
1997*3db3a4acSRobert Mustacchi cpcgen_manual_intel_file_before;
1998*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_file_after =
1999*3db3a4acSRobert Mustacchi cpcgen_manual_intel_file_after;
2000*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_event = cpcgen_manual_intel_event;
2001*3db3a4acSRobert Mustacchi } else {
2002*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_name = cpcgen_cfile_intel_name;
2003*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_file_before =
2004*3db3a4acSRobert Mustacchi cpcgen_cfile_intel_before;
2005*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_file_after =
2006*3db3a4acSRobert Mustacchi cpcgen_cfile_intel_after;
2007*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_event = cpcgen_cfile_intel_event;
2008*3db3a4acSRobert Mustacchi }
2009*3db3a4acSRobert Mustacchi break;
2010*3db3a4acSRobert Mustacchi case CPCGEN_MODE_AMD:
2011*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_gather = cpcgen_read_amd;
2012*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_common = cpcgen_common_amd_files;
2013*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_skip = NULL;
2014*3db3a4acSRobert Mustacchi if (do_mpage) {
2015*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_name = cpcgen_manual_amd_name;
2016*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_file_before =
2017*3db3a4acSRobert Mustacchi cpcgen_manual_amd_file_before;
2018*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_file_after =
2019*3db3a4acSRobert Mustacchi cpcgen_manual_amd_file_after;
2020*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_event = cpcgen_manual_amd_event;
2021*3db3a4acSRobert Mustacchi } else {
2022*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_name = cpcgen_cfile_amd_name;
2023*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_file_before =
2024*3db3a4acSRobert Mustacchi cpcgen_cfile_amd_before;
2025*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_file_after = cpcgen_cfile_amd_after;
2026*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_event = cpcgen_cfile_amd_event;
2027*3db3a4acSRobert Mustacchi
2028*3db3a4acSRobert Mustacchi }
2029*3db3a4acSRobert Mustacchi break;
2030*3db3a4acSRobert Mustacchi default:
2031*3db3a4acSRobert Mustacchi errx(EXIT_FAILURE, "failed to determine if operating on AMD or "
2032*3db3a4acSRobert Mustacchi "Intel");
2033*3db3a4acSRobert Mustacchi break;
2034*3db3a4acSRobert Mustacchi }
2035*3db3a4acSRobert Mustacchi
2036*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_gather(datadir, platform);
203753548f91SRobert Mustacchi
203853548f91SRobert Mustacchi if (do_header) {
2039*3db3a4acSRobert Mustacchi cpcgen_ops.cgen_op_common(outdirfd);
204053548f91SRobert Mustacchi return (0);
204153548f91SRobert Mustacchi }
204253548f91SRobert Mustacchi
204353548f91SRobert Mustacchi cpcgen_gen(outdirfd);
204453548f91SRobert Mustacchi
204553548f91SRobert Mustacchi return (0);
204653548f91SRobert Mustacchi }
2047