xref: /illumos-gate/usr/src/tools/cpcgen/cpcgen.c (revision 431a7476)
17e3dbbacSRobert Mustacchi /*
27e3dbbacSRobert Mustacchi  * This file and its contents are supplied under the terms of the
37e3dbbacSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
47e3dbbacSRobert Mustacchi  * You may only use this file in accordance with the terms of version
57e3dbbacSRobert Mustacchi  * 1.0 of the CDDL.
67e3dbbacSRobert Mustacchi  *
77e3dbbacSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
87e3dbbacSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
97e3dbbacSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
107e3dbbacSRobert Mustacchi  */
117e3dbbacSRobert Mustacchi 
127e3dbbacSRobert Mustacchi /*
1300fc50d1SJohn Levon  * Copyright 2019, Joyent, Inc.
1443449cdcSRobert Mustacchi  * Copyright 2021 Oxide Computer Company
157e3dbbacSRobert Mustacchi  */
167e3dbbacSRobert Mustacchi 
177e3dbbacSRobert Mustacchi /*
18d0e58ef5SRobert Mustacchi  * This program transforms Intel perfmon and AMD PMC data files into C files and
19d0e58ef5SRobert Mustacchi  * manual pages.
207e3dbbacSRobert Mustacchi  */
217e3dbbacSRobert Mustacchi 
227e3dbbacSRobert Mustacchi #include <stdio.h>
237e3dbbacSRobert Mustacchi #include <stdarg.h>
247e3dbbacSRobert Mustacchi #include <unistd.h>
257e3dbbacSRobert Mustacchi #include <err.h>
267e3dbbacSRobert Mustacchi #include <libgen.h>
277e3dbbacSRobert Mustacchi #include <libnvpair.h>
287e3dbbacSRobert Mustacchi #include <strings.h>
297e3dbbacSRobert Mustacchi #include <errno.h>
307e3dbbacSRobert Mustacchi #include <limits.h>
317e3dbbacSRobert Mustacchi #include <sys/mman.h>
327e3dbbacSRobert Mustacchi #include <sys/param.h>
337e3dbbacSRobert Mustacchi #include <assert.h>
347e3dbbacSRobert Mustacchi #include <ctype.h>
357e3dbbacSRobert Mustacchi #include <sys/types.h>
367e3dbbacSRobert Mustacchi #include <sys/stat.h>
377e3dbbacSRobert Mustacchi #include <fcntl.h>
38d0e58ef5SRobert Mustacchi #include <dirent.h>
397e3dbbacSRobert Mustacchi 
407e3dbbacSRobert Mustacchi #include <json_nvlist.h>
417e3dbbacSRobert Mustacchi 
427e3dbbacSRobert Mustacchi #define	EXIT_USAGE	2
43c18e9bc3SRobert Mustacchi #define	CPROC_MAX_STEPPINGS	16
447e3dbbacSRobert Mustacchi 
45d0e58ef5SRobert Mustacchi typedef enum {
46d0e58ef5SRobert Mustacchi 	CPCGEN_MODE_UNKNOWN = 0,
47d0e58ef5SRobert Mustacchi 	CPCGEN_MODE_INTEL,
48d0e58ef5SRobert Mustacchi 	CPCGEN_MODE_AMD
49d0e58ef5SRobert Mustacchi } cpc_mode_t;
50d0e58ef5SRobert Mustacchi 
517e3dbbacSRobert Mustacchi typedef struct cpc_proc {
527e3dbbacSRobert Mustacchi 	struct cpc_proc *cproc_next;
537e3dbbacSRobert Mustacchi 	uint_t		cproc_family;
547e3dbbacSRobert Mustacchi 	uint_t		cproc_model;
55c18e9bc3SRobert Mustacchi 	uint_t		cproc_nsteps;
56c18e9bc3SRobert Mustacchi 	uint_t		cproc_steppings[CPROC_MAX_STEPPINGS];
577e3dbbacSRobert Mustacchi } cpc_proc_t;
587e3dbbacSRobert Mustacchi 
597e3dbbacSRobert Mustacchi typedef enum cpc_file_type {
607e3dbbacSRobert Mustacchi 	CPC_FILE_CORE		= 1 << 0,
617e3dbbacSRobert Mustacchi 	CPC_FILE_OFF_CORE	= 1 << 1,
627e3dbbacSRobert Mustacchi 	CPC_FILE_UNCORE		= 1 << 2,
637e3dbbacSRobert Mustacchi 	CPC_FILE_FP_MATH	= 1 << 3,
647e3dbbacSRobert Mustacchi 	CPC_FILE_UNCORE_EXP	= 1 << 4
657e3dbbacSRobert Mustacchi } cpc_type_t;
667e3dbbacSRobert Mustacchi 
677e3dbbacSRobert Mustacchi typedef struct cpc_map {
687e3dbbacSRobert Mustacchi 	struct cpc_map	*cmap_next;
697e3dbbacSRobert Mustacchi 	cpc_type_t	cmap_type;
707e3dbbacSRobert Mustacchi 	nvlist_t	*cmap_data;
717e3dbbacSRobert Mustacchi 	char		*cmap_path;
727e3dbbacSRobert Mustacchi 	const char	*cmap_name;
737e3dbbacSRobert Mustacchi 	cpc_proc_t	*cmap_procs;
747e3dbbacSRobert Mustacchi } cpc_map_t;
757e3dbbacSRobert Mustacchi 
767e3dbbacSRobert Mustacchi typedef struct cpc_whitelist {
777e3dbbacSRobert Mustacchi 	const char	*cwhite_short;
787e3dbbacSRobert Mustacchi 	const char	*cwhite_human;
797e3dbbacSRobert Mustacchi 	uint_t		cwhite_mask;
807e3dbbacSRobert Mustacchi } cpc_whitelist_t;
817e3dbbacSRobert Mustacchi 
827e3dbbacSRobert Mustacchi /*
837e3dbbacSRobert Mustacchi  * List of architectures that we support generating this data for. This is done
847e3dbbacSRobert Mustacchi  * so that processors that illumos doesn't support or run on aren't generated
857e3dbbacSRobert Mustacchi  * (generally the Xeon Phi).
867e3dbbacSRobert Mustacchi  */
87d0e58ef5SRobert Mustacchi static cpc_whitelist_t cpcgen_intel_whitelist[] = {
887e3dbbacSRobert Mustacchi 	/* Nehalem */
897e3dbbacSRobert Mustacchi 	{ "NHM-EP", "nhm_ep", CPC_FILE_CORE },
907e3dbbacSRobert Mustacchi 	{ "NHM-EX", "nhm_ex", CPC_FILE_CORE },
917e3dbbacSRobert Mustacchi 	/* Westmere */
927e3dbbacSRobert Mustacchi 	{ "WSM-EP-DP", "wsm_ep_dp", CPC_FILE_CORE },
937e3dbbacSRobert Mustacchi 	{ "WSM-EP-SP", "wsm_ep_sp", CPC_FILE_CORE },
947e3dbbacSRobert Mustacchi 	{ "WSM-EX", "wsm_ex", CPC_FILE_CORE },
957e3dbbacSRobert Mustacchi 	/* Sandy Bridge */
967e3dbbacSRobert Mustacchi 	{ "SNB", "snb", CPC_FILE_CORE },
977e3dbbacSRobert Mustacchi 	{ "JKT", "jkt", CPC_FILE_CORE },
987e3dbbacSRobert Mustacchi 	/* Ivy Bridge */
997e3dbbacSRobert Mustacchi 	{ "IVB", "ivb", CPC_FILE_CORE },
1007e3dbbacSRobert Mustacchi 	{ "IVT", "ivt", CPC_FILE_CORE },
1017e3dbbacSRobert Mustacchi 	/* Haswell */
1027e3dbbacSRobert Mustacchi 	{ "HSW", "hsw", CPC_FILE_CORE },
1037e3dbbacSRobert Mustacchi 	{ "HSX", "hsx", CPC_FILE_CORE },
1047e3dbbacSRobert Mustacchi 	/* Broadwell */
1057e3dbbacSRobert Mustacchi 	{ "BDW", "bdw", CPC_FILE_CORE },
1067e3dbbacSRobert Mustacchi 	{ "BDW-DE", "bdw_de", CPC_FILE_CORE },
1077e3dbbacSRobert Mustacchi 	{ "BDX", "bdx", CPC_FILE_CORE },
1087e3dbbacSRobert Mustacchi 	/* Skylake */
1097e3dbbacSRobert Mustacchi 	{ "SKL", "skl", CPC_FILE_CORE },
1107e3dbbacSRobert Mustacchi 	{ "SKX", "skx", CPC_FILE_CORE },
111c18e9bc3SRobert Mustacchi 	/* Cascade Lake */
112c18e9bc3SRobert Mustacchi 	{ "CLX", "clx", CPC_FILE_CORE },
11343449cdcSRobert Mustacchi 	/* Ice Lake */
11443449cdcSRobert Mustacchi 	{ "ICL", "icl", CPC_FILE_CORE },
11543449cdcSRobert Mustacchi 	/* Tiger Lake */
11643449cdcSRobert Mustacchi 	{ "TGL", "tgl", CPC_FILE_CORE },
1177e3dbbacSRobert Mustacchi 	/* Atom */
1187e3dbbacSRobert Mustacchi 	{ "BNL", "bnl", CPC_FILE_CORE },
1197e3dbbacSRobert Mustacchi 	{ "SLM", "slm", CPC_FILE_CORE },
1207e3dbbacSRobert Mustacchi 	{ "GLM", "glm", CPC_FILE_CORE },
1217e3dbbacSRobert Mustacchi 	{ "GLP", "glp", CPC_FILE_CORE },
12243449cdcSRobert Mustacchi 	{ "SNR", "snr", CPC_FILE_CORE },
1237e3dbbacSRobert Mustacchi 	{ NULL }
1247e3dbbacSRobert Mustacchi };
1257e3dbbacSRobert Mustacchi 
1267e3dbbacSRobert Mustacchi typedef struct cpc_papi {
1277e3dbbacSRobert Mustacchi 	const char	*cpapi_intc;
1287e3dbbacSRobert Mustacchi 	const char	*cpapi_papi;
1297e3dbbacSRobert Mustacchi } cpc_papi_t;
1307e3dbbacSRobert Mustacchi 
1317e3dbbacSRobert Mustacchi /*
1327e3dbbacSRobert Mustacchi  * This table maps events with an Intel specific name to the corresponding PAPI
133c18e9bc3SRobert Mustacchi  * name. There may be multiple Intel events which map to the same PAPI event.
1347e3dbbacSRobert Mustacchi  * This is usually because different processors have different names for an
1357e3dbbacSRobert Mustacchi  * event. We use the title as opposed to the event codes because those can
1367e3dbbacSRobert Mustacchi  * change somewhat arbitrarily between processor generations.
1377e3dbbacSRobert Mustacchi  */
138d0e58ef5SRobert Mustacchi static cpc_papi_t cpcgen_intel_papi_map[] = {
1397e3dbbacSRobert Mustacchi 	{ "CPU_CLK_UNHALTED.THREAD_P", "PAPI_tot_cyc" },
1407e3dbbacSRobert Mustacchi 	{ "INST_RETIRED.ANY_P", "PAPI_tot_ins" },
1417e3dbbacSRobert Mustacchi 	{ "BR_INST_RETIRED.ALL_BRANCHES", "PAPI_br_ins" },
1427e3dbbacSRobert Mustacchi 	{ "BR_MISP_RETIRED.ALL_BRANCHES", "PAPI_br_msp" },
1437e3dbbacSRobert Mustacchi 	{ "BR_INST_RETIRED.CONDITIONAL", "PAPI_br_cn" },
1447e3dbbacSRobert Mustacchi 	{ "CYCLE_ACTIVITY.CYCLES_L1D_MISS", "PAPI_l1_dcm" },
1457e3dbbacSRobert Mustacchi 	{ "L1I.HITS", "PAPI_l1_ich" },
1467e3dbbacSRobert Mustacchi 	{ "ICACHE.HIT", "PAPI_l1_ich" },
1477e3dbbacSRobert Mustacchi 	{ "L1I.MISS", "PAPI_L1_icm" },
1487e3dbbacSRobert Mustacchi 	{ "ICACHE.MISSES", "PAPI_l1_icm" },
1497e3dbbacSRobert Mustacchi 	{ "L1I.READS", "PAPI_l1_ica" },
1507e3dbbacSRobert Mustacchi 	{ "ICACHE.ACCESSES", "PAPI_l1_ica" },
1517e3dbbacSRobert Mustacchi 	{ "L1I.READS", "PAPI_l1_icr" },
1527e3dbbacSRobert Mustacchi 	{ "ICACHE.ACCESSES", "PAPI_l1_icr" },
1537e3dbbacSRobert Mustacchi 	{ "L2_RQSTS.CODE_RD_MISS", "PAPI_l2_icm" },
1547e3dbbacSRobert Mustacchi 	{ "L2_RQSTS.MISS", "PAPI_l2_tcm" },
1557e3dbbacSRobert Mustacchi 	{ "ITLB_MISSES.MISS_CAUSES_A_WALK", "PAPI_tlb_im" },
1567e3dbbacSRobert Mustacchi 	{ "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK", "PAPI_tlb_dm" },
1577e3dbbacSRobert Mustacchi 	{ "PAGE_WALKS.D_SIDE_WALKS", "PAPI_tlb_dm" },
1587e3dbbacSRobert Mustacchi 	{ "PAGE_WALKS.I_SIDE_WALKS", "PAPI_tlb_im" },
1597e3dbbacSRobert Mustacchi 	{ "PAGE_WALKS.WALKS", "PAPI_tlb_tl" },
1607e3dbbacSRobert Mustacchi 	{ "INST_QUEUE_WRITES", "PAPI_tot_iis" },
1617e3dbbacSRobert Mustacchi 	{ "MEM_INST_RETIRED.STORES" "PAPI_sr_ins" },
1627e3dbbacSRobert Mustacchi 	{ "MEM_INST_RETIRED.LOADS" "PAPI_ld_ins" },
1637e3dbbacSRobert Mustacchi 	{ NULL, NULL }
1647e3dbbacSRobert Mustacchi };
1657e3dbbacSRobert Mustacchi 
1667e3dbbacSRobert Mustacchi typedef struct cpcgen_ops {
167d0e58ef5SRobert Mustacchi 	void (*cgen_op_gather)(const char *, const char *);
168d0e58ef5SRobert Mustacchi 	void (*cgen_op_common)(int);
1697e3dbbacSRobert Mustacchi 	char *(*cgen_op_name)(cpc_map_t *);
170d0e58ef5SRobert Mustacchi 	boolean_t (*cgen_op_skip)(nvlist_t *, const char *, uint_t);
1717e3dbbacSRobert Mustacchi 	boolean_t (*cgen_op_file_before)(FILE *, cpc_map_t *);
1727e3dbbacSRobert Mustacchi 	boolean_t (*cgen_op_file_after)(FILE *, cpc_map_t *);
1737e3dbbacSRobert Mustacchi 	boolean_t (*cgen_op_event)(FILE *, nvlist_t *, const char *, uint32_t);
1747e3dbbacSRobert Mustacchi } cpcgen_ops_t;
1757e3dbbacSRobert Mustacchi 
1767e3dbbacSRobert Mustacchi static cpcgen_ops_t cpcgen_ops;
177d0e58ef5SRobert Mustacchi static const char *cpcgen_intel_mapfile = "/mapfile.csv";
1787e3dbbacSRobert Mustacchi static const char *cpcgen_progname;
1797e3dbbacSRobert Mustacchi static cpc_map_t *cpcgen_maps;
180d0e58ef5SRobert Mustacchi static cpc_mode_t cpcgen_mode = CPCGEN_MODE_UNKNOWN;
1817e3dbbacSRobert Mustacchi 
1827e3dbbacSRobert Mustacchi /*
1837e3dbbacSRobert Mustacchi  * Constants used for generating data.
1847e3dbbacSRobert Mustacchi  */
1857e3dbbacSRobert Mustacchi /* BEGIN CSTYLED */
186d0e58ef5SRobert Mustacchi static const char *cpcgen_cfile_intel_header = ""
1877e3dbbacSRobert Mustacchi "/*\n"
1887e3dbbacSRobert Mustacchi " *  Copyright (c) 2018, Intel Corporation\n"
1897e3dbbacSRobert Mustacchi " *  Copyright (c) 2018, Joyent, Inc\n"
1907e3dbbacSRobert Mustacchi " *  All rights reserved.\n"
1917e3dbbacSRobert Mustacchi " *\n"
1927e3dbbacSRobert Mustacchi " *  Redistribution and use in source and binary forms, with or without\n"
1937e3dbbacSRobert Mustacchi " *  modification, are permitted provided that the following conditions are met:\n"
1947e3dbbacSRobert Mustacchi " * \n"
1957e3dbbacSRobert Mustacchi " *   1. Redistributions of source code must retain the above copyright notice,\n"
1967e3dbbacSRobert Mustacchi " *      this list of conditions and the following disclaimer.\n"
1977e3dbbacSRobert Mustacchi " * \n"
1987e3dbbacSRobert Mustacchi " *   2. Redistributions in binary form must reproduce the above copyright \n"
1997e3dbbacSRobert Mustacchi " *      notice, this list of conditions and the following disclaimer in the\n"
2007e3dbbacSRobert Mustacchi " *      documentation and/or other materials provided with the distribution.\n"
2017e3dbbacSRobert Mustacchi " * \n"
2027e3dbbacSRobert Mustacchi " *   3. Neither the name of the Intel Corporation nor the names of its \n"
2037e3dbbacSRobert Mustacchi " *      contributors may be used to endorse or promote products derived from\n"
2047e3dbbacSRobert Mustacchi " *      this software without specific prior written permission.\n"
2057e3dbbacSRobert Mustacchi " *\n"
2067e3dbbacSRobert Mustacchi " *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n"
2077e3dbbacSRobert Mustacchi " *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
2087e3dbbacSRobert Mustacchi " *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
2097e3dbbacSRobert Mustacchi " *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n"
2107e3dbbacSRobert Mustacchi " *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n"
2117e3dbbacSRobert Mustacchi " *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n"
2127e3dbbacSRobert Mustacchi " *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n"
2137e3dbbacSRobert Mustacchi " *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n"
2147e3dbbacSRobert Mustacchi " *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n"
2157e3dbbacSRobert Mustacchi " *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
2167e3dbbacSRobert Mustacchi " *  POSSIBILITY OF SUCH DAMAGE.\n"
2177e3dbbacSRobert Mustacchi " *\n"
2187e3dbbacSRobert Mustacchi " * This file was automatically generated by cpcgen from the data file\n"
2197e3dbbacSRobert Mustacchi " * data/perfmon%s\n"
2207e3dbbacSRobert Mustacchi " *\n"
2217e3dbbacSRobert Mustacchi " * Do not modify this file. Your changes will be lost!\n"
2227e3dbbacSRobert Mustacchi " */\n"
2237e3dbbacSRobert Mustacchi "\n";
2247e3dbbacSRobert Mustacchi /* END CSTYLED */
2257e3dbbacSRobert Mustacchi 
226d0e58ef5SRobert Mustacchi static const char *cpcgen_cfile_intel_table_start = ""
2277e3dbbacSRobert Mustacchi "#include <core_pcbe_table.h>\n"
2287e3dbbacSRobert Mustacchi "\n"
2297e3dbbacSRobert Mustacchi "const struct events_table_t pcbe_core_events_%s[] = {\n";
2307e3dbbacSRobert Mustacchi 
231d0e58ef5SRobert Mustacchi static const char *cpcgen_cfile_intel_table_end = ""
2327e3dbbacSRobert Mustacchi "\t{ NT_END, 0, 0, \"\" }\n"
2337e3dbbacSRobert Mustacchi "};\n";
2347e3dbbacSRobert Mustacchi 
2357e3dbbacSRobert Mustacchi /* BEGIN CSTYLED */
236d0e58ef5SRobert Mustacchi static const char *cpcgen_manual_intel_intel_header = ""
2377e3dbbacSRobert Mustacchi ".\\\" Copyright (c) 2018, Intel Corporation \n"
2387e3dbbacSRobert Mustacchi ".\\\" Copyright (c) 2018, Joyent, Inc.\n"
2397e3dbbacSRobert Mustacchi ".\\\" All rights reserved.\n"
2407e3dbbacSRobert Mustacchi ".\\\"\n"
2417e3dbbacSRobert Mustacchi ".\\\" Redistribution and use in source and binary forms, with or without \n"
2427e3dbbacSRobert Mustacchi ".\\\" modification, are permitted provided that the following conditions are met:\n"
2437e3dbbacSRobert Mustacchi ".\\\"\n"
2447e3dbbacSRobert Mustacchi ".\\\"  1. Redistributions of source code must retain the above copyright notice,\n"
2457e3dbbacSRobert Mustacchi ".\\\"     this list of conditions and the following disclaimer.\n"
2467e3dbbacSRobert Mustacchi ".\\\"\n"
2477e3dbbacSRobert Mustacchi ".\\\"  2. Redistributions in binary form must reproduce the above copyright\n"
2487e3dbbacSRobert Mustacchi ".\\\"     notice, this list of conditions and the following disclaimer in the\n"
2497e3dbbacSRobert Mustacchi ".\\\"     documentation and/or other materials provided with the distribution.\n"
2507e3dbbacSRobert Mustacchi ".\\\"\n"
2517e3dbbacSRobert Mustacchi ".\\\"  3. Neither the name of the Intel Corporation nor the names of its\n"
2527e3dbbacSRobert Mustacchi ".\\\"     contributors may be used to endorse or promote products derived from\n"
2537e3dbbacSRobert Mustacchi ".\\\"     this software without specific prior written permission.\n"
2547e3dbbacSRobert Mustacchi ".\\\"\n"
2557e3dbbacSRobert Mustacchi ".\\\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n"
2567e3dbbacSRobert Mustacchi ".\\\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
2577e3dbbacSRobert Mustacchi ".\\\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
2587e3dbbacSRobert Mustacchi ".\\\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n"
2597e3dbbacSRobert Mustacchi ".\\\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n"
2607e3dbbacSRobert Mustacchi ".\\\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n"
2617e3dbbacSRobert Mustacchi ".\\\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n"
2627e3dbbacSRobert Mustacchi ".\\\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n"
2637e3dbbacSRobert Mustacchi ".\\\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n"
2647e3dbbacSRobert Mustacchi ".\\\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
2657e3dbbacSRobert Mustacchi ".\\\" POSSIBILITY OF SUCH DAMAGE.\n"
2667e3dbbacSRobert Mustacchi ".\\\"\n"
2677e3dbbacSRobert Mustacchi ".\\\" This file was automatically generated by cpcgen from the data file\n"
2687e3dbbacSRobert Mustacchi ".\\\" data/perfmon%s\n"
2697e3dbbacSRobert Mustacchi ".\\\"\n"
2707e3dbbacSRobert Mustacchi ".\\\" Do not modify this file. Your changes will be lost!\n"
2717e3dbbacSRobert Mustacchi ".\\\"\n"
2727e3dbbacSRobert Mustacchi ".\\\" We would like to thank Intel for providing the perfmon data for use in\n"
2737e3dbbacSRobert Mustacchi ".\\\" our manual pages.\n"
2747e3dbbacSRobert Mustacchi ".Dd June 18, 2018\n"
2757e3dbbacSRobert Mustacchi ".Dt %s_EVENTS 3CPC\n"
2767e3dbbacSRobert Mustacchi ".Os\n"
2777e3dbbacSRobert Mustacchi ".Sh NAME\n"
2787e3dbbacSRobert Mustacchi ".Nm %s_events\n"
2797e3dbbacSRobert Mustacchi ".Nd processor model specific performance counter events\n"
2807e3dbbacSRobert Mustacchi ".Sh DESCRIPTION\n"
2817e3dbbacSRobert Mustacchi "This manual page describes events specific to the following Intel CPU\n"
2827e3dbbacSRobert Mustacchi "models and is derived from Intel's perfmon data.\n"
2837e3dbbacSRobert Mustacchi "For more information, please consult the Intel Software Developer's Manual "
2847e3dbbacSRobert Mustacchi "or Intel's perfmon website.\n"
2857e3dbbacSRobert Mustacchi ".Pp\n"
2867e3dbbacSRobert Mustacchi "CPU models described by this document:\n"
2877e3dbbacSRobert Mustacchi ".Bl -bullet\n";
2887e3dbbacSRobert Mustacchi /* END CSTYLED */
2897e3dbbacSRobert Mustacchi 
290d0e58ef5SRobert Mustacchi static const char *cpcgen_manual_intel_data = ""
2917e3dbbacSRobert Mustacchi ".El\n"
2927e3dbbacSRobert Mustacchi ".Pp\n"
2937e3dbbacSRobert Mustacchi "The following events are supported:\n"
2947e3dbbacSRobert Mustacchi ".Bl -tag -width Sy\n";
2957e3dbbacSRobert Mustacchi 
296d0e58ef5SRobert Mustacchi static const char *cpcgen_manual_intel_trailer = ""
2977e3dbbacSRobert Mustacchi ".El\n"
2987e3dbbacSRobert Mustacchi ".Sh SEE ALSO\n"
2997e3dbbacSRobert Mustacchi ".Xr cpc 3CPC\n"
3007e3dbbacSRobert Mustacchi ".Pp\n"
3017e3dbbacSRobert Mustacchi ".Lk https://download.01.org/perfmon/index/";
3027e3dbbacSRobert Mustacchi 
303d0e58ef5SRobert Mustacchi static const char *cpcgen_cfile_cddl_header = ""
304d0e58ef5SRobert Mustacchi "/*\n"
305d0e58ef5SRobert Mustacchi " * This file and its contents are supplied under the terms of the\n"
306d0e58ef5SRobert Mustacchi " * Common Development and Distribution License (\"CDDL\"), version 1.0.\n"
307d0e58ef5SRobert Mustacchi " * You may only use this file in accordance with the terms of version\n"
308d0e58ef5SRobert Mustacchi " * 1.0 of the CDDL.\n"
309d0e58ef5SRobert Mustacchi " *\n"
310d0e58ef5SRobert Mustacchi " * A full copy of the text of the CDDL should have accompanied this\n"
311d0e58ef5SRobert Mustacchi " * source.  A copy of the CDDL is also available via the Internet at\n"
312d0e58ef5SRobert Mustacchi " * http://www.illumos.org/license/CDDL.\n"
313d0e58ef5SRobert Mustacchi " */\n"
314d0e58ef5SRobert Mustacchi "\n"
315d0e58ef5SRobert Mustacchi "/*\n"
316d0e58ef5SRobert Mustacchi " * Copyright 2019 Joyent, Inc\n"
317d0e58ef5SRobert Mustacchi " */\n"
318d0e58ef5SRobert Mustacchi "\n"
319d0e58ef5SRobert Mustacchi "/*\n"
320d0e58ef5SRobert Mustacchi " * This file was automatically generated by cpcgen.\n"
321d0e58ef5SRobert Mustacchi " */\n"
322d0e58ef5SRobert Mustacchi "\n"
323d0e58ef5SRobert Mustacchi "/*\n"
324d0e58ef5SRobert Mustacchi " * Do not modify this file. Your changes will be lost!\n"
325d0e58ef5SRobert Mustacchi " */\n"
326d0e58ef5SRobert Mustacchi "\n";
327d0e58ef5SRobert Mustacchi 
328d0e58ef5SRobert Mustacchi static const char *cpcgen_manual_amd_header = ""
329d0e58ef5SRobert Mustacchi ".\\\" This file was automatically generated by cpcgen from the data file\n"
330d0e58ef5SRobert Mustacchi ".\\\" data/amdpmc/%s\n"
331d0e58ef5SRobert Mustacchi ".\\\"\n"
332d0e58ef5SRobert Mustacchi ".\\\" Do not modify this file. Your changes will be lost!\n"
333d0e58ef5SRobert Mustacchi ".\\\"\n"
334d0e58ef5SRobert Mustacchi ".\\\" We would like to thank AMD for providing the PMC data for use in\n"
335d0e58ef5SRobert Mustacchi ".\\\" our manual pages.\n"
336d0e58ef5SRobert Mustacchi ".Dd March 25, 2019\n"
337d0e58ef5SRobert Mustacchi ".Dt AMD_%s_EVENTS 3CPC\n"
338d0e58ef5SRobert Mustacchi ".Os\n"
339d0e58ef5SRobert Mustacchi ".Sh NAME\n"
340d0e58ef5SRobert Mustacchi ".Nm amd_%s_events\n"
34131aa6202SRobert Mustacchi ".Nd AMD Family %s processor performance monitoring events\n"
342d0e58ef5SRobert Mustacchi ".Sh DESCRIPTION\n"
34331aa6202SRobert Mustacchi "This manual page describes events specfic to AMD Family %s processors.\n"
344d0e58ef5SRobert Mustacchi "For more information, please consult the appropriate AMD BIOS and Kernel\n"
34531aa6202SRobert Mustacchi "Developer's guide or Open-Source Register Reference.\n"
346d0e58ef5SRobert Mustacchi ".Pp\n"
347d0e58ef5SRobert Mustacchi "Each of the events listed below includes the AMD mnemonic which matches\n"
348d0e58ef5SRobert Mustacchi "the name found in the AMD manual and a brief summary of the event.\n"
349d0e58ef5SRobert Mustacchi "If available, a more detailed description of the event follows and then\n"
350d0e58ef5SRobert Mustacchi "any additional unit values that modify the event.\n"
351d0e58ef5SRobert Mustacchi "Each unit can be combined to create a new event in the system by placing\n"
352d0e58ef5SRobert Mustacchi "the '.' character between the event name and the unit name.\n"
353d0e58ef5SRobert Mustacchi ".Pp\n"
354d0e58ef5SRobert Mustacchi "The following events are supported:\n"
355d0e58ef5SRobert Mustacchi ".Bl -tag -width Sy\n";
356d0e58ef5SRobert Mustacchi 
357d0e58ef5SRobert Mustacchi static const char *cpcgen_manual_amd_trailer = ""
358d0e58ef5SRobert Mustacchi ".El\n"
359d0e58ef5SRobert Mustacchi ".Sh SEE ALSO\n"
360d0e58ef5SRobert Mustacchi ".Xr cpc 3CPC\n";
361d0e58ef5SRobert Mustacchi 
362d0e58ef5SRobert Mustacchi static const char *cpcgen_cfile_amd_header = ""
363d0e58ef5SRobert Mustacchi "/*\n"
364d0e58ef5SRobert Mustacchi " * This file was automatically generated by cpcgen from the data file\n"
365d0e58ef5SRobert Mustacchi " * data/perfmon%s\n"
366d0e58ef5SRobert Mustacchi " *\n"
367d0e58ef5SRobert Mustacchi " * Do not modify this file. Your changes will be lost!\n"
368d0e58ef5SRobert Mustacchi " */\n"
369d0e58ef5SRobert Mustacchi "\n";
370d0e58ef5SRobert Mustacchi 
371d0e58ef5SRobert Mustacchi static const char *cpcgen_cfile_amd_table_start = ""
372d0e58ef5SRobert Mustacchi "#include <opteron_pcbe_table.h>\n"
373d0e58ef5SRobert Mustacchi "#include <sys/null.h>\n"
374d0e58ef5SRobert Mustacchi "\n"
375d0e58ef5SRobert Mustacchi "const amd_event_t opteron_pcbe_%s_events[] = {\n";
376d0e58ef5SRobert Mustacchi 
377d0e58ef5SRobert Mustacchi static const char *cpcgen_cfile_amd_table_end = ""
378d0e58ef5SRobert Mustacchi "\t{ NULL, 0, 0 }\n"
379d0e58ef5SRobert Mustacchi "};\n";
380d0e58ef5SRobert Mustacchi 
3817e3dbbacSRobert Mustacchi static cpc_map_t *
cpcgen_map_lookup(const char * path)3827e3dbbacSRobert Mustacchi cpcgen_map_lookup(const char *path)
3837e3dbbacSRobert Mustacchi {
3847e3dbbacSRobert Mustacchi 	cpc_map_t *m;
3857e3dbbacSRobert Mustacchi 
3867e3dbbacSRobert Mustacchi 	for (m = cpcgen_maps; m != NULL; m = m->cmap_next) {
3877e3dbbacSRobert Mustacchi 		if (strcmp(path, m->cmap_path) == 0) {
3887e3dbbacSRobert Mustacchi 			return (m);
3897e3dbbacSRobert Mustacchi 		}
3907e3dbbacSRobert Mustacchi 	}
3917e3dbbacSRobert Mustacchi 
3927e3dbbacSRobert Mustacchi 	return (NULL);
3937e3dbbacSRobert Mustacchi }
3947e3dbbacSRobert Mustacchi 
3957e3dbbacSRobert Mustacchi /*
3967e3dbbacSRobert Mustacchi  * Parse a string of the form 'GenuineIntel-6-2E' and get out the family and
3977e3dbbacSRobert Mustacchi  * model.
3987e3dbbacSRobert Mustacchi  */
3997e3dbbacSRobert Mustacchi static void
cpcgen_parse_model(char * fsr,uint_t * family,uint_t * model,uint_t * nstepp,uint_t * steppings)400c18e9bc3SRobert Mustacchi cpcgen_parse_model(char *fsr, uint_t *family, uint_t *model, uint_t *nstepp,
401c18e9bc3SRobert Mustacchi     uint_t *steppings)
4027e3dbbacSRobert Mustacchi {
4037e3dbbacSRobert Mustacchi 	const char *bstr = "GenuineIntel";
404c18e9bc3SRobert Mustacchi 	const char *brand, *fam, *mod, *step;
4057e3dbbacSRobert Mustacchi 	char *last;
4067e3dbbacSRobert Mustacchi 	long l;
407c18e9bc3SRobert Mustacchi 	uint_t nstep = 0;
4087e3dbbacSRobert Mustacchi 
409c18e9bc3SRobert Mustacchi 	/*
410c18e9bc3SRobert Mustacchi 	 * Tokeninze the string. There may be an optional stepping portion,
411c18e9bc3SRobert Mustacchi 	 * which has a range of steppings enclosed by '[' and ']' characters.
412c18e9bc3SRobert Mustacchi 	 * While the other parts are required, the stepping may be missing.
413c18e9bc3SRobert Mustacchi 	 */
4147e3dbbacSRobert Mustacchi 	if ((brand = strtok_r(fsr, "-", &last)) == NULL ||
4157e3dbbacSRobert Mustacchi 	    (fam = strtok_r(NULL, "-", &last)) == NULL ||
4167e3dbbacSRobert Mustacchi 	    (mod = strtok_r(NULL, "-", &last)) == NULL) {
4177e3dbbacSRobert Mustacchi 		errx(EXIT_FAILURE, "failed to parse processor id \"%s\"", fsr);
4187e3dbbacSRobert Mustacchi 	}
419c18e9bc3SRobert Mustacchi 	step = strtok_r(NULL, "-", &last);
4207e3dbbacSRobert Mustacchi 
4217e3dbbacSRobert Mustacchi 	if (strcmp(bstr, brand) != 0) {
4227e3dbbacSRobert Mustacchi 		errx(EXIT_FAILURE, "brand string \"%s\" did not match \"%s\"",
4237e3dbbacSRobert Mustacchi 		    brand, bstr);
4247e3dbbacSRobert Mustacchi 	}
4257e3dbbacSRobert Mustacchi 
4267e3dbbacSRobert Mustacchi 	errno = 0;
4277e3dbbacSRobert Mustacchi 	l = strtol(fam, &last, 16);
42800fc50d1SJohn Levon 	if (errno != 0 || l < 0 || l >= INT_MAX || *last != '\0') {
4297e3dbbacSRobert Mustacchi 		errx(EXIT_FAILURE, "failed to parse family \"%s\"", fam);
4307e3dbbacSRobert Mustacchi 	}
4317e3dbbacSRobert Mustacchi 	*family = (uint_t)l;
4327e3dbbacSRobert Mustacchi 
4337e3dbbacSRobert Mustacchi 	l = strtol(mod, &last, 16);
43400fc50d1SJohn Levon 	if (errno != 0 || l < 0 || l >= INT_MAX || *last != '\0') {
4357e3dbbacSRobert Mustacchi 		errx(EXIT_FAILURE, "failed to parse model \"%s\"", mod);
4367e3dbbacSRobert Mustacchi 	}
4377e3dbbacSRobert Mustacchi 	*model = (uint_t)l;
438c18e9bc3SRobert Mustacchi 
439c18e9bc3SRobert Mustacchi 	if (step == NULL) {
440c18e9bc3SRobert Mustacchi 		*nstepp = 0;
441c18e9bc3SRobert Mustacchi 		return;
442c18e9bc3SRobert Mustacchi 	}
443c18e9bc3SRobert Mustacchi 
444c18e9bc3SRobert Mustacchi 	if (*step != '[' || ((last = strrchr(step, ']')) == NULL)) {
445c18e9bc3SRobert Mustacchi 		errx(EXIT_FAILURE, "failed to parse stepping \"%s\": missing "
446c18e9bc3SRobert Mustacchi 		    "stepping range brackets", step);
447c18e9bc3SRobert Mustacchi 	}
448c18e9bc3SRobert Mustacchi 	step++;
449c18e9bc3SRobert Mustacchi 	*last = '\0';
450c18e9bc3SRobert Mustacchi 	while (*step != '\0') {
451c18e9bc3SRobert Mustacchi 		if (!isxdigit(*step)) {
452c18e9bc3SRobert Mustacchi 			errx(EXIT_FAILURE, "failed to parse stepping: invalid "
453c18e9bc3SRobert Mustacchi 			    "stepping identifier '0x%x'", *step);
454c18e9bc3SRobert Mustacchi 		}
455c18e9bc3SRobert Mustacchi 
456c18e9bc3SRobert Mustacchi 		if (nstep >= CPROC_MAX_STEPPINGS) {
457c18e9bc3SRobert Mustacchi 			errx(EXIT_FAILURE, "failed to parse stepping: "
458c18e9bc3SRobert Mustacchi 			    "encountered too many steppings");
459c18e9bc3SRobert Mustacchi 		}
460c18e9bc3SRobert Mustacchi 
461c18e9bc3SRobert Mustacchi 		switch (*step) {
462c18e9bc3SRobert Mustacchi 		case '0':
463c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x0;
464c18e9bc3SRobert Mustacchi 			break;
465c18e9bc3SRobert Mustacchi 		case '1':
466c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x1;
467c18e9bc3SRobert Mustacchi 			break;
468c18e9bc3SRobert Mustacchi 		case '2':
469c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x2;
470c18e9bc3SRobert Mustacchi 			break;
471c18e9bc3SRobert Mustacchi 		case '3':
472c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x3;
473c18e9bc3SRobert Mustacchi 			break;
474c18e9bc3SRobert Mustacchi 		case '4':
475c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x4;
476c18e9bc3SRobert Mustacchi 			break;
477c18e9bc3SRobert Mustacchi 		case '5':
478c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x5;
479c18e9bc3SRobert Mustacchi 			break;
480c18e9bc3SRobert Mustacchi 		case '6':
481c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x6;
482c18e9bc3SRobert Mustacchi 			break;
483c18e9bc3SRobert Mustacchi 		case '7':
484c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x7;
485c18e9bc3SRobert Mustacchi 			break;
486c18e9bc3SRobert Mustacchi 		case '8':
487c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x8;
488c18e9bc3SRobert Mustacchi 			break;
489c18e9bc3SRobert Mustacchi 		case '9':
490c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0x9;
491c18e9bc3SRobert Mustacchi 			break;
492c18e9bc3SRobert Mustacchi 		case 'a':
493c18e9bc3SRobert Mustacchi 		case 'A':
494c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0xa;
495c18e9bc3SRobert Mustacchi 			break;
496c18e9bc3SRobert Mustacchi 		case 'b':
497c18e9bc3SRobert Mustacchi 		case 'B':
498c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0xb;
499c18e9bc3SRobert Mustacchi 			break;
500c18e9bc3SRobert Mustacchi 		case 'c':
501c18e9bc3SRobert Mustacchi 		case 'C':
502c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0xc;
503c18e9bc3SRobert Mustacchi 			break;
504c18e9bc3SRobert Mustacchi 		case 'd':
505c18e9bc3SRobert Mustacchi 		case 'D':
506c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0xd;
507c18e9bc3SRobert Mustacchi 			break;
508c18e9bc3SRobert Mustacchi 		case 'e':
509c18e9bc3SRobert Mustacchi 		case 'E':
510c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0xe;
511c18e9bc3SRobert Mustacchi 			break;
512c18e9bc3SRobert Mustacchi 		case 'f':
513c18e9bc3SRobert Mustacchi 		case 'F':
514c18e9bc3SRobert Mustacchi 			steppings[nstep] = 0xf;
515c18e9bc3SRobert Mustacchi 			break;
516c18e9bc3SRobert Mustacchi 		default:
517c18e9bc3SRobert Mustacchi 			errx(EXIT_FAILURE, "encountered non-hex stepping "
518c18e9bc3SRobert Mustacchi 			    "character: '%c'", *step);
519c18e9bc3SRobert Mustacchi 		}
520c18e9bc3SRobert Mustacchi 		nstep++;
521c18e9bc3SRobert Mustacchi 		step++;
522c18e9bc3SRobert Mustacchi 	}
523c18e9bc3SRobert Mustacchi 
524c18e9bc3SRobert Mustacchi 	*nstepp = nstep;
5257e3dbbacSRobert Mustacchi }
5267e3dbbacSRobert Mustacchi 
5277e3dbbacSRobert Mustacchi static nvlist_t *
cpcgen_read_datafile(const char * datadir,const char * file)5287e3dbbacSRobert Mustacchi cpcgen_read_datafile(const char *datadir, const char *file)
5297e3dbbacSRobert Mustacchi {
5307e3dbbacSRobert Mustacchi 	int fd;
5317e3dbbacSRobert Mustacchi 	char *path;
5327e3dbbacSRobert Mustacchi 	struct stat st;
5337e3dbbacSRobert Mustacchi 	void *map;
5347e3dbbacSRobert Mustacchi 	nvlist_t *nvl;
5357e3dbbacSRobert Mustacchi 	nvlist_parse_json_error_t jerr;
5367e3dbbacSRobert Mustacchi 
5377e3dbbacSRobert Mustacchi 	if (asprintf(&path, "%s/%s", datadir, file) == -1) {
5387e3dbbacSRobert Mustacchi 		err(EXIT_FAILURE, "failed to construct path to data file %s",
5397e3dbbacSRobert Mustacchi 		    file);
5407e3dbbacSRobert Mustacchi 	}
5417e3dbbacSRobert Mustacchi 
5427e3dbbacSRobert Mustacchi 	if ((fd = open(path, O_RDONLY)) < 0) {
5437e3dbbacSRobert Mustacchi 		err(EXIT_FAILURE, "failed to open data file %s", path);
5447e3dbbacSRobert Mustacchi 	}
5457e3dbbacSRobert Mustacchi 
5467e3dbbacSRobert Mustacchi 	if (fstat(fd, &st) != 0) {
5477e3dbbacSRobert Mustacchi 		err(EXIT_FAILURE, "failed to stat %s", path);
5487e3dbbacSRobert Mustacchi 	}
5497e3dbbacSRobert Mustacchi 
5507e3dbbacSRobert Mustacchi 	if ((map = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
5517e3dbbacSRobert Mustacchi 	    fd, 0)) == MAP_FAILED) {
5527e3dbbacSRobert Mustacchi 		err(EXIT_FAILURE, "failed to mmap %s", path);
5537e3dbbacSRobert Mustacchi 	}
5547e3dbbacSRobert Mustacchi 
5557e3dbbacSRobert Mustacchi 	if (nvlist_parse_json(map, st.st_size, &nvl, NVJSON_FORCE_INTEGER,
5567e3dbbacSRobert Mustacchi 	    &jerr) != 0) {
5577e3dbbacSRobert Mustacchi 		errx(EXIT_FAILURE, "failed to parse file %s at pos %ld: %s",
5587e3dbbacSRobert Mustacchi 		    path, jerr.nje_pos, jerr.nje_message);
5597e3dbbacSRobert Mustacchi 	}
5607e3dbbacSRobert Mustacchi 
5617e3dbbacSRobert Mustacchi 	if (munmap(map, st.st_size) != 0) {
5627e3dbbacSRobert Mustacchi 		err(EXIT_FAILURE, "failed to munmap %s", path);
5637e3dbbacSRobert Mustacchi 	}
5647e3dbbacSRobert Mustacchi 
5657e3dbbacSRobert Mustacchi 	if (close(fd) != 0) {
5667e3dbbacSRobert Mustacchi 		err(EXIT_FAILURE, "failed to close data file %s", path);
5677e3dbbacSRobert Mustacchi 	}
5687e3dbbacSRobert Mustacchi 	free(path);
5697e3dbbacSRobert Mustacchi 
5707e3dbbacSRobert Mustacchi 	return (nvl);
5717e3dbbacSRobert Mustacchi }
5727e3dbbacSRobert Mustacchi 
5737e3dbbacSRobert Mustacchi /*
5747e3dbbacSRobert Mustacchi  * Check the whitelist to see if we should use this model.
5757e3dbbacSRobert Mustacchi  */
5767e3dbbacSRobert Mustacchi static const char *
cpcgen_use_arch(const char * path,cpc_type_t type,const char * platform)5777e3dbbacSRobert Mustacchi cpcgen_use_arch(const char *path, cpc_type_t type, const char *platform)
5787e3dbbacSRobert Mustacchi {
5797e3dbbacSRobert Mustacchi 	const char *slash;
5807e3dbbacSRobert Mustacchi 	size_t len;
5817e3dbbacSRobert Mustacchi 	uint_t i;
5827e3dbbacSRobert Mustacchi 
5837e3dbbacSRobert Mustacchi 	if (*path != '/') {
5847e3dbbacSRobert Mustacchi 		errx(EXIT_FAILURE, "invalid path in mapfile: \"%s\": missing "
5857e3dbbacSRobert Mustacchi 		    "leading '/'", path);
5867e3dbbacSRobert Mustacchi 	}
5877e3dbbacSRobert Mustacchi 	if ((slash = strchr(path + 1, '/')) == NULL) {
5887e3dbbacSRobert Mustacchi 		errx(EXIT_FAILURE, "invalid path in mapfile: \"%s\": missing "
5897e3dbbacSRobert Mustacchi 		    "second '/'", path);
5907e3dbbacSRobert Mustacchi 	}
5917e3dbbacSRobert Mustacchi 	/* Account for the last '/' character. */
5927e3dbbacSRobert Mustacchi 	len = slash - path - 1;
5937e3dbbacSRobert Mustacchi 	assert(len > 0);
5947e3dbbacSRobert Mustacchi 
595d0e58ef5SRobert Mustacchi 	for (i = 0; cpcgen_intel_whitelist[i].cwhite_short != NULL; i++) {
5967e3dbbacSRobert Mustacchi 		if (platform != NULL && strcasecmp(platform,
597d0e58ef5SRobert Mustacchi 		    cpcgen_intel_whitelist[i].cwhite_short) != 0)
5987e3dbbacSRobert Mustacchi 			continue;
599d0e58ef5SRobert Mustacchi 		if (strncmp(path + 1, cpcgen_intel_whitelist[i].cwhite_short,
6007e3dbbacSRobert Mustacchi 		    len) == 0 &&
601d0e58ef5SRobert Mustacchi 		    (cpcgen_intel_whitelist[i].cwhite_mask & type) == type) {
602d0e58ef5SRobert Mustacchi 			return (cpcgen_intel_whitelist[i].cwhite_human);
6037e3dbbacSRobert Mustacchi 		}
6047e3dbbacSRobert Mustacchi 	}
6057e3dbbacSRobert Mustacchi 
6067e3dbbacSRobert Mustacchi 	return (NULL);
6077e3dbbacSRobert Mustacchi }
6087e3dbbacSRobert Mustacchi 
609d0e58ef5SRobert Mustacchi /*
610d0e58ef5SRobert Mustacchi  * Determine which CPU Vendor we're transmuting data from.
611d0e58ef5SRobert Mustacchi  */
612d0e58ef5SRobert Mustacchi static void
cpcgen_determine_vendor(const char * datadir)613d0e58ef5SRobert Mustacchi cpcgen_determine_vendor(const char *datadir)
614d0e58ef5SRobert Mustacchi {
615d0e58ef5SRobert Mustacchi 	char *mappath;
616d0e58ef5SRobert Mustacchi 	struct stat st;
617d0e58ef5SRobert Mustacchi 
618d0e58ef5SRobert Mustacchi 	if (asprintf(&mappath, "%s/%s", datadir, cpcgen_intel_mapfile) == -1) {
619d0e58ef5SRobert Mustacchi 		err(EXIT_FAILURE, "failed to construct path to mapfile");
620d0e58ef5SRobert Mustacchi 	}
621d0e58ef5SRobert Mustacchi 
622d0e58ef5SRobert Mustacchi 	if (stat(mappath, &st) == 0) {
623d0e58ef5SRobert Mustacchi 		cpcgen_mode = CPCGEN_MODE_INTEL;
624d0e58ef5SRobert Mustacchi 	} else {
625d0e58ef5SRobert Mustacchi 		if (errno != ENOENT) {
626d0e58ef5SRobert Mustacchi 			err(EXIT_FAILURE, "stat(2) of %s failed unexpectedly");
627d0e58ef5SRobert Mustacchi 		}
628d0e58ef5SRobert Mustacchi 
629d0e58ef5SRobert Mustacchi 		cpcgen_mode = CPCGEN_MODE_AMD;
630d0e58ef5SRobert Mustacchi 	}
631d0e58ef5SRobert Mustacchi 
632d0e58ef5SRobert Mustacchi 	free(mappath);
633d0e58ef5SRobert Mustacchi }
634d0e58ef5SRobert Mustacchi 
635d0e58ef5SRobert Mustacchi /*
636d0e58ef5SRobert Mustacchi  * Read in all the data files that exist for AMD.
637d0e58ef5SRobert Mustacchi  *
638d0e58ef5SRobert Mustacchi  * Our family names for AMD systems are based on the family and type so a given
63931aa6202SRobert Mustacchi  * name will look like f17h_<core>_core.json.
640d0e58ef5SRobert Mustacchi  */
641d0e58ef5SRobert Mustacchi static void
cpcgen_read_amd(const char * datadir,const char * platform)642d0e58ef5SRobert Mustacchi cpcgen_read_amd(const char *datadir, const char *platform)
643d0e58ef5SRobert Mustacchi {
644d0e58ef5SRobert Mustacchi 	DIR *dir;
645d0e58ef5SRobert Mustacchi 	struct dirent *d;
646d0e58ef5SRobert Mustacchi 	const char *suffix = ".json";
647d0e58ef5SRobert Mustacchi 	const size_t slen = strlen(suffix);
648d0e58ef5SRobert Mustacchi 
649d0e58ef5SRobert Mustacchi 	if ((dir = opendir(datadir)) == NULL) {
650d0e58ef5SRobert Mustacchi 		err(EXIT_FAILURE, "failed to open directory %s", datadir);
651d0e58ef5SRobert Mustacchi 	}
652d0e58ef5SRobert Mustacchi 
653d0e58ef5SRobert Mustacchi 	while ((d = readdir(dir)) != NULL) {
654d0e58ef5SRobert Mustacchi 		char *name, *c;
655d0e58ef5SRobert Mustacchi 		cpc_map_t *map;
656d0e58ef5SRobert Mustacchi 		nvlist_t *parsed;
657d0e58ef5SRobert Mustacchi 
658d0e58ef5SRobert Mustacchi 		if ((name = strdup(d->d_name)) == NULL) {
659d0e58ef5SRobert Mustacchi 			errx(EXIT_FAILURE, "ran out of memory duplicating "
660d0e58ef5SRobert Mustacchi 			    "name %s", d->d_name);
661d0e58ef5SRobert Mustacchi 		}
662d0e58ef5SRobert Mustacchi 		c = strstr(name, suffix);
663d0e58ef5SRobert Mustacchi 
664d0e58ef5SRobert Mustacchi 		if (c == NULL) {
665d0e58ef5SRobert Mustacchi 			free(name);
666d0e58ef5SRobert Mustacchi 			continue;
667d0e58ef5SRobert Mustacchi 		}
668d0e58ef5SRobert Mustacchi 
66931aa6202SRobert Mustacchi 		/*
67031aa6202SRobert Mustacchi 		 * Chop off the .json. Next, make sure we have both _ present.
67131aa6202SRobert Mustacchi 		 */
672d0e58ef5SRobert Mustacchi 		if (*(c + slen) != '\0') {
673d0e58ef5SRobert Mustacchi 			free(name);
674d0e58ef5SRobert Mustacchi 			continue;
675d0e58ef5SRobert Mustacchi 		}
676d0e58ef5SRobert Mustacchi 		*c = '\0';
67731aa6202SRobert Mustacchi 
678d0e58ef5SRobert Mustacchi 		c = strchr(name, '_');
679d0e58ef5SRobert Mustacchi 		if (c == NULL) {
68031aa6202SRobert Mustacchi 			errx(EXIT_FAILURE, "unexpected AMD JSON file name: %s",
68131aa6202SRobert Mustacchi 			    d->d_name);
68231aa6202SRobert Mustacchi 		}
68331aa6202SRobert Mustacchi 
68431aa6202SRobert Mustacchi 		c++;
68531aa6202SRobert Mustacchi 		c = strchr(c, '_');
68631aa6202SRobert Mustacchi 		if (c == NULL) {
68731aa6202SRobert Mustacchi 			errx(EXIT_FAILURE, "unexpected AMD JSON file name: %s",
68831aa6202SRobert Mustacchi 			    d->d_name);
689d0e58ef5SRobert Mustacchi 		}
690d0e58ef5SRobert Mustacchi 		*c = '\0';
691d0e58ef5SRobert Mustacchi 		c++;
692d0e58ef5SRobert Mustacchi 		if (strcmp(c, "core") != 0) {
693d0e58ef5SRobert Mustacchi 			errx(EXIT_FAILURE, "unexpected AMD JSON file name: %s",
694d0e58ef5SRobert Mustacchi 			    d->d_name);
695d0e58ef5SRobert Mustacchi 		}
696d0e58ef5SRobert Mustacchi 
697d0e58ef5SRobert Mustacchi 		if (platform != NULL && strcmp(platform, name) != 0) {
698d0e58ef5SRobert Mustacchi 			free(name);
699d0e58ef5SRobert Mustacchi 			continue;
700d0e58ef5SRobert Mustacchi 		}
701d0e58ef5SRobert Mustacchi 
702d0e58ef5SRobert Mustacchi 		if ((map = calloc(1, sizeof (cpc_map_t))) == NULL) {
703d0e58ef5SRobert Mustacchi 			err(EXIT_FAILURE, "failed to allocate space for cpc "
704d0e58ef5SRobert Mustacchi 			    "file");
705d0e58ef5SRobert Mustacchi 		}
706d0e58ef5SRobert Mustacchi 
707d0e58ef5SRobert Mustacchi 		parsed = cpcgen_read_datafile(datadir, d->d_name);
708d0e58ef5SRobert Mustacchi 		if ((map->cmap_path = strdup(d->d_name)) == NULL) {
709d0e58ef5SRobert Mustacchi 			err(EXIT_FAILURE, "failed to duplicate path string");
710d0e58ef5SRobert Mustacchi 		}
711d0e58ef5SRobert Mustacchi 		map->cmap_type = CPC_FILE_CORE;
712d0e58ef5SRobert Mustacchi 		map->cmap_data = parsed;
713d0e58ef5SRobert Mustacchi 		map->cmap_name = name;
714d0e58ef5SRobert Mustacchi 		map->cmap_procs = NULL;
715d0e58ef5SRobert Mustacchi 
716d0e58ef5SRobert Mustacchi 		map->cmap_next = cpcgen_maps;
717d0e58ef5SRobert Mustacchi 		cpcgen_maps = map;
718d0e58ef5SRobert Mustacchi 	}
719d0e58ef5SRobert Mustacchi }
720d0e58ef5SRobert Mustacchi 
7217e3dbbacSRobert Mustacchi /*
7227e3dbbacSRobert Mustacchi  * Read in the mapfile.csv that is used to map between processor families and
7237e3dbbacSRobert Mustacchi  * parse this. Each line has a comma separated value.
7247e3dbbacSRobert Mustacchi  */
7257e3dbbacSRobert Mustacchi static void
cpcgen_read_intel(const char * datadir,const char * platform)726d0e58ef5SRobert Mustacchi cpcgen_read_intel(const char *datadir, const char *platform)
7277e3dbbacSRobert Mustacchi {
7287e3dbbacSRobert Mustacchi 	FILE *map;
7297e3dbbacSRobert Mustacchi 	char *mappath, *last;
7307e3dbbacSRobert Mustacchi 	char *data = NULL;
7317e3dbbacSRobert Mustacchi 	size_t datalen = 0;
7327e3dbbacSRobert Mustacchi 	uint_t lineno;
7337e3dbbacSRobert Mustacchi 
734d0e58ef5SRobert Mustacchi 	if (asprintf(&mappath, "%s/%s", datadir, cpcgen_intel_mapfile) == -1) {
7357e3dbbacSRobert Mustacchi 		err(EXIT_FAILURE, "failed to construct path to mapfile");
7367e3dbbacSRobert Mustacchi 	}
7377e3dbbacSRobert Mustacchi 
7387e3dbbacSRobert Mustacchi 	if ((map = fopen(mappath, "r")) == NULL) {
7397e3dbbacSRobert Mustacchi 		err(EXIT_FAILURE, "failed to open data mapfile %s", mappath);
7407e3dbbacSRobert Mustacchi 	}
7417e3dbbacSRobert Mustacchi 
7427e3dbbacSRobert Mustacchi 	lineno = 0;
7437e3dbbacSRobert Mustacchi 	while (getline(&data, &datalen, map) != -1) {
7447e3dbbacSRobert Mustacchi 		char *fstr, *path, *tstr;
7457e3dbbacSRobert Mustacchi 		const char *name;
746c18e9bc3SRobert Mustacchi 		uint_t family, model, nsteps;
747c18e9bc3SRobert Mustacchi 		uint_t steppings[CPROC_MAX_STEPPINGS];
748c18e9bc3SRobert Mustacchi 
7497e3dbbacSRobert Mustacchi 		cpc_type_t type;
7507e3dbbacSRobert Mustacchi 		cpc_map_t *map;
7517e3dbbacSRobert Mustacchi 		cpc_proc_t *proc;
7527e3dbbacSRobert Mustacchi 
7537e3dbbacSRobert Mustacchi 		/*
7547e3dbbacSRobert Mustacchi 		 * The first line contains the header:
7557e3dbbacSRobert Mustacchi 		 * Family-model,Version,Filename,EventType
7567e3dbbacSRobert Mustacchi 		 */
7577e3dbbacSRobert Mustacchi 		lineno++;
7587e3dbbacSRobert Mustacchi 		if (lineno == 1) {
7597e3dbbacSRobert Mustacchi 			continue;
7607e3dbbacSRobert Mustacchi 		}
7617e3dbbacSRobert Mustacchi 
7627e3dbbacSRobert Mustacchi 		if ((fstr = strtok_r(data, ",", &last)) == NULL ||
7637e3dbbacSRobert Mustacchi 		    strtok_r(NULL, ",", &last) == NULL ||
7647e3dbbacSRobert Mustacchi 		    (path = strtok_r(NULL, ",", &last)) == NULL ||
7657e3dbbacSRobert Mustacchi 		    (tstr = strtok_r(NULL, "\n", &last)) == NULL) {
7667e3dbbacSRobert Mustacchi 			errx(EXIT_FAILURE, "failed to parse mapfile line "
7677e3dbbacSRobert Mustacchi 			    "%u in %s", lineno, mappath);
7687e3dbbacSRobert Mustacchi 		}
7697e3dbbacSRobert Mustacchi 
770c18e9bc3SRobert Mustacchi 		cpcgen_parse_model(fstr, &family, &model, &nsteps, steppings);
7717e3dbbacSRobert Mustacchi 
7727e3dbbacSRobert Mustacchi 		if (strcmp(tstr, "core") == 0) {
7737e3dbbacSRobert Mustacchi 			type = CPC_FILE_CORE;
7747e3dbbacSRobert Mustacchi 		} else if (strcmp(tstr, "offcore") == 0) {
7757e3dbbacSRobert Mustacchi 			type = CPC_FILE_OFF_CORE;
7767e3dbbacSRobert Mustacchi 		} else if (strcmp(tstr, "uncore") == 0) {
7777e3dbbacSRobert Mustacchi 			type = CPC_FILE_UNCORE;
7787e3dbbacSRobert Mustacchi 		} else if (strcmp(tstr, "fp_arith_inst") == 0) {
7797e3dbbacSRobert Mustacchi 			type = CPC_FILE_FP_MATH;
7807e3dbbacSRobert Mustacchi 		} else if (strcmp(tstr, "uncore experimental") == 0) {
7817e3dbbacSRobert Mustacchi 			type = CPC_FILE_UNCORE_EXP;
7827e3dbbacSRobert Mustacchi 		} else {
7837e3dbbacSRobert Mustacchi 			errx(EXIT_FAILURE, "unknown file type \"%s\" on line "
784