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 /* 1753548f91SRobert Mustacchi * This file transforms the perfmon data files into C files and manual pages. 1853548f91SRobert Mustacchi */ 1953548f91SRobert Mustacchi 2053548f91SRobert Mustacchi #include <stdio.h> 2153548f91SRobert Mustacchi #include <stdarg.h> 2253548f91SRobert Mustacchi #include <unistd.h> 2353548f91SRobert Mustacchi #include <err.h> 2453548f91SRobert Mustacchi #include <libgen.h> 2553548f91SRobert Mustacchi #include <libnvpair.h> 2653548f91SRobert Mustacchi #include <strings.h> 2753548f91SRobert Mustacchi #include <errno.h> 2853548f91SRobert Mustacchi #include <limits.h> 2953548f91SRobert Mustacchi #include <sys/mman.h> 3053548f91SRobert Mustacchi #include <sys/param.h> 3153548f91SRobert Mustacchi #include <assert.h> 3253548f91SRobert Mustacchi #include <ctype.h> 3353548f91SRobert Mustacchi #include <sys/types.h> 3453548f91SRobert Mustacchi #include <sys/stat.h> 3553548f91SRobert Mustacchi #include <fcntl.h> 3653548f91SRobert Mustacchi 3753548f91SRobert Mustacchi #include <json_nvlist.h> 3853548f91SRobert Mustacchi 3953548f91SRobert Mustacchi #define EXIT_USAGE 2 40*5fc40de0SRobert Mustacchi #define CPROC_MAX_STEPPINGS 16 4153548f91SRobert Mustacchi 4253548f91SRobert Mustacchi typedef struct cpc_proc { 4353548f91SRobert Mustacchi struct cpc_proc *cproc_next; 4453548f91SRobert Mustacchi uint_t cproc_family; 4553548f91SRobert Mustacchi uint_t cproc_model; 46*5fc40de0SRobert Mustacchi uint_t cproc_nsteps; 47*5fc40de0SRobert Mustacchi uint_t cproc_steppings[CPROC_MAX_STEPPINGS]; 4853548f91SRobert Mustacchi } cpc_proc_t; 4953548f91SRobert Mustacchi 5053548f91SRobert Mustacchi typedef enum cpc_file_type { 5153548f91SRobert Mustacchi CPC_FILE_CORE = 1 << 0, 5253548f91SRobert Mustacchi CPC_FILE_OFF_CORE = 1 << 1, 5353548f91SRobert Mustacchi CPC_FILE_UNCORE = 1 << 2, 5453548f91SRobert Mustacchi CPC_FILE_FP_MATH = 1 << 3, 5553548f91SRobert Mustacchi CPC_FILE_UNCORE_EXP = 1 << 4 5653548f91SRobert Mustacchi } cpc_type_t; 5753548f91SRobert Mustacchi 5853548f91SRobert Mustacchi typedef struct cpc_map { 5953548f91SRobert Mustacchi struct cpc_map *cmap_next; 6053548f91SRobert Mustacchi cpc_type_t cmap_type; 6153548f91SRobert Mustacchi nvlist_t *cmap_data; 6253548f91SRobert Mustacchi char *cmap_path; 6353548f91SRobert Mustacchi const char *cmap_name; 6453548f91SRobert Mustacchi cpc_proc_t *cmap_procs; 6553548f91SRobert Mustacchi } cpc_map_t; 6653548f91SRobert Mustacchi 6753548f91SRobert Mustacchi typedef struct cpc_whitelist { 6853548f91SRobert Mustacchi const char *cwhite_short; 6953548f91SRobert Mustacchi const char *cwhite_human; 7053548f91SRobert Mustacchi uint_t cwhite_mask; 7153548f91SRobert Mustacchi } cpc_whitelist_t; 7253548f91SRobert Mustacchi 7353548f91SRobert Mustacchi /* 7453548f91SRobert Mustacchi * List of architectures that we support generating this data for. This is done 7553548f91SRobert Mustacchi * so that processors that illumos doesn't support or run on aren't generated 7653548f91SRobert Mustacchi * (generally the Xeon Phi). 7753548f91SRobert Mustacchi */ 7853548f91SRobert Mustacchi static cpc_whitelist_t cpcgen_whitelist[] = { 7953548f91SRobert Mustacchi /* Nehalem */ 8053548f91SRobert Mustacchi { "NHM-EP", "nhm_ep", CPC_FILE_CORE }, 8153548f91SRobert Mustacchi { "NHM-EX", "nhm_ex", CPC_FILE_CORE }, 8253548f91SRobert Mustacchi /* Westmere */ 8353548f91SRobert Mustacchi { "WSM-EP-DP", "wsm_ep_dp", CPC_FILE_CORE }, 8453548f91SRobert Mustacchi { "WSM-EP-SP", "wsm_ep_sp", CPC_FILE_CORE }, 8553548f91SRobert Mustacchi { "WSM-EX", "wsm_ex", CPC_FILE_CORE }, 8653548f91SRobert Mustacchi /* Sandy Bridge */ 8753548f91SRobert Mustacchi { "SNB", "snb", CPC_FILE_CORE }, 8853548f91SRobert Mustacchi { "JKT", "jkt", CPC_FILE_CORE }, 8953548f91SRobert Mustacchi /* Ivy Bridge */ 9053548f91SRobert Mustacchi { "IVB", "ivb", CPC_FILE_CORE }, 9153548f91SRobert Mustacchi { "IVT", "ivt", CPC_FILE_CORE }, 9253548f91SRobert Mustacchi /* Haswell */ 9353548f91SRobert Mustacchi { "HSW", "hsw", CPC_FILE_CORE }, 9453548f91SRobert Mustacchi { "HSX", "hsx", CPC_FILE_CORE }, 9553548f91SRobert Mustacchi /* Broadwell */ 9653548f91SRobert Mustacchi { "BDW", "bdw", CPC_FILE_CORE }, 9753548f91SRobert Mustacchi { "BDW-DE", "bdw_de", CPC_FILE_CORE }, 9853548f91SRobert Mustacchi { "BDX", "bdx", CPC_FILE_CORE }, 9953548f91SRobert Mustacchi /* Skylake */ 10053548f91SRobert Mustacchi { "SKL", "skl", CPC_FILE_CORE }, 10153548f91SRobert Mustacchi { "SKX", "skx", CPC_FILE_CORE }, 102*5fc40de0SRobert Mustacchi /* Cascade Lake */ 103*5fc40de0SRobert Mustacchi { "CLX", "clx", CPC_FILE_CORE }, 10453548f91SRobert Mustacchi /* Atom */ 10553548f91SRobert Mustacchi { "BNL", "bnl", CPC_FILE_CORE }, 10653548f91SRobert Mustacchi { "SLM", "slm", CPC_FILE_CORE }, 10753548f91SRobert Mustacchi { "GLM", "glm", CPC_FILE_CORE }, 10853548f91SRobert Mustacchi { "GLP", "glp", CPC_FILE_CORE }, 10953548f91SRobert Mustacchi { NULL } 11053548f91SRobert Mustacchi }; 11153548f91SRobert Mustacchi 11253548f91SRobert Mustacchi typedef struct cpc_papi { 11353548f91SRobert Mustacchi const char *cpapi_intc; 11453548f91SRobert Mustacchi const char *cpapi_papi; 11553548f91SRobert Mustacchi } cpc_papi_t; 11653548f91SRobert Mustacchi 11753548f91SRobert Mustacchi /* 11853548f91SRobert Mustacchi * This table maps events with an Intel specific name to the corresponding PAPI 119*5fc40de0SRobert Mustacchi * name. There may be multiple Intel events which map to the same PAPI event. 12053548f91SRobert Mustacchi * This is usually because different processors have different names for an 12153548f91SRobert Mustacchi * event. We use the title as opposed to the event codes because those can 12253548f91SRobert Mustacchi * change somewhat arbitrarily between processor generations. 12353548f91SRobert Mustacchi */ 12453548f91SRobert Mustacchi static cpc_papi_t cpcgen_papi_map[] = { 12553548f91SRobert Mustacchi { "CPU_CLK_UNHALTED.THREAD_P", "PAPI_tot_cyc" }, 12653548f91SRobert Mustacchi { "INST_RETIRED.ANY_P", "PAPI_tot_ins" }, 12753548f91SRobert Mustacchi { "BR_INST_RETIRED.ALL_BRANCHES", "PAPI_br_ins" }, 12853548f91SRobert Mustacchi { "BR_MISP_RETIRED.ALL_BRANCHES", "PAPI_br_msp" }, 12953548f91SRobert Mustacchi { "BR_INST_RETIRED.CONDITIONAL", "PAPI_br_cn" }, 13053548f91SRobert Mustacchi { "CYCLE_ACTIVITY.CYCLES_L1D_MISS", "PAPI_l1_dcm" }, 13153548f91SRobert Mustacchi { "L1I.HITS", "PAPI_l1_ich" }, 13253548f91SRobert Mustacchi { "ICACHE.HIT", "PAPI_l1_ich" }, 13353548f91SRobert Mustacchi { "L1I.MISS", "PAPI_L1_icm" }, 13453548f91SRobert Mustacchi { "ICACHE.MISSES", "PAPI_l1_icm" }, 13553548f91SRobert Mustacchi { "L1I.READS", "PAPI_l1_ica" }, 13653548f91SRobert Mustacchi { "ICACHE.ACCESSES", "PAPI_l1_ica" }, 13753548f91SRobert Mustacchi { "L1I.READS", "PAPI_l1_icr" }, 13853548f91SRobert Mustacchi { "ICACHE.ACCESSES", "PAPI_l1_icr" }, 13953548f91SRobert Mustacchi { "L2_RQSTS.CODE_RD_MISS", "PAPI_l2_icm" }, 14053548f91SRobert Mustacchi { "L2_RQSTS.MISS", "PAPI_l2_tcm" }, 14153548f91SRobert Mustacchi { "ITLB_MISSES.MISS_CAUSES_A_WALK", "PAPI_tlb_im" }, 14253548f91SRobert Mustacchi { "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK", "PAPI_tlb_dm" }, 14353548f91SRobert Mustacchi { "PAGE_WALKS.D_SIDE_WALKS", "PAPI_tlb_dm" }, 14453548f91SRobert Mustacchi { "PAGE_WALKS.I_SIDE_WALKS", "PAPI_tlb_im" }, 14553548f91SRobert Mustacchi { "PAGE_WALKS.WALKS", "PAPI_tlb_tl" }, 14653548f91SRobert Mustacchi { "INST_QUEUE_WRITES", "PAPI_tot_iis" }, 14753548f91SRobert Mustacchi { "MEM_INST_RETIRED.STORES" "PAPI_sr_ins" }, 14853548f91SRobert Mustacchi { "MEM_INST_RETIRED.LOADS" "PAPI_ld_ins" }, 14953548f91SRobert Mustacchi { NULL, NULL } 15053548f91SRobert Mustacchi }; 15153548f91SRobert Mustacchi 15253548f91SRobert Mustacchi typedef struct cpcgen_ops { 15353548f91SRobert Mustacchi char *(*cgen_op_name)(cpc_map_t *); 15453548f91SRobert Mustacchi boolean_t (*cgen_op_file_before)(FILE *, cpc_map_t *); 15553548f91SRobert Mustacchi boolean_t (*cgen_op_file_after)(FILE *, cpc_map_t *); 15653548f91SRobert Mustacchi boolean_t (*cgen_op_event)(FILE *, nvlist_t *, const char *, uint32_t); 15753548f91SRobert Mustacchi } cpcgen_ops_t; 15853548f91SRobert Mustacchi 15953548f91SRobert Mustacchi static cpcgen_ops_t cpcgen_ops; 16053548f91SRobert Mustacchi static const char *cpcgen_mapfile = "/mapfile.csv"; 16153548f91SRobert Mustacchi static const char *cpcgen_progname; 16253548f91SRobert Mustacchi static cpc_map_t *cpcgen_maps; 16353548f91SRobert Mustacchi 16453548f91SRobert Mustacchi /* 16553548f91SRobert Mustacchi * Constants used for generating data. 16653548f91SRobert Mustacchi */ 16753548f91SRobert Mustacchi /* BEGIN CSTYLED */ 16853548f91SRobert Mustacchi static const char *cpcgen_cfile_header = "" 16953548f91SRobert Mustacchi "/*\n" 17053548f91SRobert Mustacchi " * Copyright (c) 2018, Intel Corporation\n" 17153548f91SRobert Mustacchi " * Copyright (c) 2018, Joyent, Inc\n" 17253548f91SRobert Mustacchi " * All rights reserved.\n" 17353548f91SRobert Mustacchi " *\n" 17453548f91SRobert Mustacchi " * Redistribution and use in source and binary forms, with or without\n" 17553548f91SRobert Mustacchi " * modification, are permitted provided that the following conditions are met:\n" 17653548f91SRobert Mustacchi " * \n" 17753548f91SRobert Mustacchi " * 1. Redistributions of source code must retain the above copyright notice,\n" 17853548f91SRobert Mustacchi " * this list of conditions and the following disclaimer.\n" 17953548f91SRobert Mustacchi " * \n" 18053548f91SRobert Mustacchi " * 2. Redistributions in binary form must reproduce the above copyright \n" 18153548f91SRobert Mustacchi " * notice, this list of conditions and the following disclaimer in the\n" 18253548f91SRobert Mustacchi " * documentation and/or other materials provided with the distribution.\n" 18353548f91SRobert Mustacchi " * \n" 18453548f91SRobert Mustacchi " * 3. Neither the name of the Intel Corporation nor the names of its \n" 18553548f91SRobert Mustacchi " * contributors may be used to endorse or promote products derived from\n" 18653548f91SRobert Mustacchi " * this software without specific prior written permission.\n" 18753548f91SRobert Mustacchi " *\n" 18853548f91SRobert Mustacchi " * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n" 18953548f91SRobert Mustacchi " * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n" 19053548f91SRobert Mustacchi " * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n" 19153548f91SRobert Mustacchi " * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n" 19253548f91SRobert Mustacchi " * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n" 19353548f91SRobert Mustacchi " * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n" 19453548f91SRobert Mustacchi " * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n" 19553548f91SRobert Mustacchi " * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n" 19653548f91SRobert Mustacchi " * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n" 19753548f91SRobert Mustacchi " * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" 19853548f91SRobert Mustacchi " * POSSIBILITY OF SUCH DAMAGE.\n" 19953548f91SRobert Mustacchi " *\n" 20053548f91SRobert Mustacchi " * This file was automatically generated by cpcgen from the data file\n" 20153548f91SRobert Mustacchi " * data/perfmon%s\n" 20253548f91SRobert Mustacchi " *\n" 20353548f91SRobert Mustacchi " * Do not modify this file. Your changes will be lost!\n" 20453548f91SRobert Mustacchi " */\n" 20553548f91SRobert Mustacchi "\n"; 20653548f91SRobert Mustacchi /* END CSTYLED */ 20753548f91SRobert Mustacchi 20853548f91SRobert Mustacchi static const char *cpcgen_cfile_table_start = "" 20953548f91SRobert Mustacchi "#include <core_pcbe_table.h>\n" 21053548f91SRobert Mustacchi "\n" 21153548f91SRobert Mustacchi "const struct events_table_t pcbe_core_events_%s[] = {\n"; 21253548f91SRobert Mustacchi 21353548f91SRobert Mustacchi static const char *cpcgen_cfile_table_end = "" 21453548f91SRobert Mustacchi "\t{ NT_END, 0, 0, \"\" }\n" 21553548f91SRobert Mustacchi "};\n"; 21653548f91SRobert Mustacchi 21753548f91SRobert Mustacchi /* BEGIN CSTYLED */ 21853548f91SRobert Mustacchi static const char *cpcgen_manual_header = "" 21953548f91SRobert Mustacchi ".\\\" Copyright (c) 2018, Intel Corporation \n" 22053548f91SRobert Mustacchi ".\\\" Copyright (c) 2018, Joyent, Inc.\n" 22153548f91SRobert Mustacchi ".\\\" All rights reserved.\n" 22253548f91SRobert Mustacchi ".\\\"\n" 22353548f91SRobert Mustacchi ".\\\" Redistribution and use in source and binary forms, with or without \n" 22453548f91SRobert Mustacchi ".\\\" modification, are permitted provided that the following conditions are met:\n" 22553548f91SRobert Mustacchi ".\\\"\n" 22653548f91SRobert Mustacchi ".\\\" 1. Redistributions of source code must retain the above copyright notice,\n" 22753548f91SRobert Mustacchi ".\\\" this list of conditions and the following disclaimer.\n" 22853548f91SRobert Mustacchi ".\\\"\n" 22953548f91SRobert Mustacchi ".\\\" 2. Redistributions in binary form must reproduce the above copyright\n" 23053548f91SRobert Mustacchi ".\\\" notice, this list of conditions and the following disclaimer in the\n" 23153548f91SRobert Mustacchi ".\\\" documentation and/or other materials provided with the distribution.\n" 23253548f91SRobert Mustacchi ".\\\"\n" 23353548f91SRobert Mustacchi ".\\\" 3. Neither the name of the Intel Corporation nor the names of its\n" 23453548f91SRobert Mustacchi ".\\\" contributors may be used to endorse or promote products derived from\n" 23553548f91SRobert Mustacchi ".\\\" this software without specific prior written permission.\n" 23653548f91SRobert Mustacchi ".\\\"\n" 23753548f91SRobert Mustacchi ".\\\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n" 23853548f91SRobert Mustacchi ".\\\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n" 23953548f91SRobert Mustacchi ".\\\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n" 24053548f91SRobert Mustacchi ".\\\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n" 24153548f91SRobert Mustacchi ".\\\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n" 24253548f91SRobert Mustacchi ".\\\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n" 24353548f91SRobert Mustacchi ".\\\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n" 24453548f91SRobert Mustacchi ".\\\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n" 24553548f91SRobert Mustacchi ".\\\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n" 24653548f91SRobert Mustacchi ".\\\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" 24753548f91SRobert Mustacchi ".\\\" POSSIBILITY OF SUCH DAMAGE.\n" 24853548f91SRobert Mustacchi ".\\\"\n" 24953548f91SRobert Mustacchi ".\\\" This file was automatically generated by cpcgen from the data file\n" 25053548f91SRobert Mustacchi ".\\\" data/perfmon%s\n" 25153548f91SRobert Mustacchi ".\\\"\n" 25253548f91SRobert Mustacchi ".\\\" Do not modify this file. Your changes will be lost!\n" 25353548f91SRobert Mustacchi ".\\\"\n" 25453548f91SRobert Mustacchi ".\\\" We would like to thank Intel for providing the perfmon data for use in\n" 25553548f91SRobert Mustacchi ".\\\" our manual pages.\n" 25653548f91SRobert Mustacchi ".Dd June 18, 2018\n" 25753548f91SRobert Mustacchi ".Dt %s_EVENTS 3CPC\n" 25853548f91SRobert Mustacchi ".Os\n" 25953548f91SRobert Mustacchi ".Sh NAME\n" 26053548f91SRobert Mustacchi ".Nm %s_events\n" 26153548f91SRobert Mustacchi ".Nd processor model specific performance counter events\n" 26253548f91SRobert Mustacchi ".Sh DESCRIPTION\n" 26353548f91SRobert Mustacchi "This manual page describes events specific to the following Intel CPU\n" 26453548f91SRobert Mustacchi "models and is derived from Intel's perfmon data.\n" 26553548f91SRobert Mustacchi "For more information, please consult the Intel Software Developer's Manual " 26653548f91SRobert Mustacchi "or Intel's perfmon website.\n" 26753548f91SRobert Mustacchi ".Pp\n" 26853548f91SRobert Mustacchi "CPU models described by this document:\n" 26953548f91SRobert Mustacchi ".Bl -bullet\n"; 27053548f91SRobert Mustacchi /* END CSTYLED */ 27153548f91SRobert Mustacchi 27253548f91SRobert Mustacchi static const char *cpcgen_manual_data = "" 27353548f91SRobert Mustacchi ".El\n" 27453548f91SRobert Mustacchi ".Pp\n" 27553548f91SRobert Mustacchi "The following events are supported:\n" 27653548f91SRobert Mustacchi ".Bl -tag -width Sy\n"; 27753548f91SRobert Mustacchi 27853548f91SRobert Mustacchi static const char *cpcgen_manual_trailer = "" 27953548f91SRobert Mustacchi ".El\n" 28053548f91SRobert Mustacchi ".Sh SEE ALSO\n" 28153548f91SRobert Mustacchi ".Xr cpc 3CPC\n" 28253548f91SRobert Mustacchi ".Pp\n" 28353548f91SRobert Mustacchi ".Lk https://download.01.org/perfmon/index/"; 28453548f91SRobert Mustacchi 28553548f91SRobert Mustacchi static cpc_map_t * 28653548f91SRobert Mustacchi cpcgen_map_lookup(const char *path) 28753548f91SRobert Mustacchi { 28853548f91SRobert Mustacchi cpc_map_t *m; 28953548f91SRobert Mustacchi 29053548f91SRobert Mustacchi for (m = cpcgen_maps; m != NULL; m = m->cmap_next) { 29153548f91SRobert Mustacchi if (strcmp(path, m->cmap_path) == 0) { 29253548f91SRobert Mustacchi return (m); 29353548f91SRobert Mustacchi } 29453548f91SRobert Mustacchi } 29553548f91SRobert Mustacchi 29653548f91SRobert Mustacchi return (NULL); 29753548f91SRobert Mustacchi } 29853548f91SRobert Mustacchi 29953548f91SRobert Mustacchi /* 30053548f91SRobert Mustacchi * Parse a string of the form 'GenuineIntel-6-2E' and get out the family and 30153548f91SRobert Mustacchi * model. 30253548f91SRobert Mustacchi */ 30353548f91SRobert Mustacchi static void 304*5fc40de0SRobert Mustacchi cpcgen_parse_model(char *fsr, uint_t *family, uint_t *model, uint_t *nstepp, 305*5fc40de0SRobert Mustacchi uint_t *steppings) 30653548f91SRobert Mustacchi { 30753548f91SRobert Mustacchi const char *bstr = "GenuineIntel"; 308*5fc40de0SRobert Mustacchi const char *brand, *fam, *mod, *step; 30953548f91SRobert Mustacchi char *last; 31053548f91SRobert Mustacchi long l; 311*5fc40de0SRobert Mustacchi uint_t nstep = 0; 31253548f91SRobert Mustacchi 313*5fc40de0SRobert Mustacchi /* 314*5fc40de0SRobert Mustacchi * Tokeninze the string. There may be an optional stepping portion, 315*5fc40de0SRobert Mustacchi * which has a range of steppings enclosed by '[' and ']' characters. 316*5fc40de0SRobert Mustacchi * While the other parts are required, the stepping may be missing. 317*5fc40de0SRobert Mustacchi */ 31853548f91SRobert Mustacchi if ((brand = strtok_r(fsr, "-", &last)) == NULL || 31953548f91SRobert Mustacchi (fam = strtok_r(NULL, "-", &last)) == NULL || 32053548f91SRobert Mustacchi (mod = strtok_r(NULL, "-", &last)) == NULL) { 32153548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse processor id \"%s\"", fsr); 32253548f91SRobert Mustacchi } 323*5fc40de0SRobert Mustacchi step = strtok_r(NULL, "-", &last); 32453548f91SRobert Mustacchi 32553548f91SRobert Mustacchi if (strcmp(bstr, brand) != 0) { 32653548f91SRobert Mustacchi errx(EXIT_FAILURE, "brand string \"%s\" did not match \"%s\"", 32753548f91SRobert Mustacchi brand, bstr); 32853548f91SRobert Mustacchi } 32953548f91SRobert Mustacchi 33053548f91SRobert Mustacchi errno = 0; 33153548f91SRobert Mustacchi l = strtol(fam, &last, 16); 332*5fc40de0SRobert Mustacchi if (errno != 0 || l < 0 || l > UINT_MAX || *last != '\0') { 33353548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse family \"%s\"", fam); 33453548f91SRobert Mustacchi } 33553548f91SRobert Mustacchi *family = (uint_t)l; 33653548f91SRobert Mustacchi 33753548f91SRobert Mustacchi l = strtol(mod, &last, 16); 338*5fc40de0SRobert Mustacchi if (errno != 0 || l < 0 || l > UINT_MAX || *last != '\0') { 33953548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse model \"%s\"", mod); 34053548f91SRobert Mustacchi } 34153548f91SRobert Mustacchi *model = (uint_t)l; 342*5fc40de0SRobert Mustacchi 343*5fc40de0SRobert Mustacchi if (step == NULL) { 344*5fc40de0SRobert Mustacchi *nstepp = 0; 345*5fc40de0SRobert Mustacchi return; 346*5fc40de0SRobert Mustacchi } 347*5fc40de0SRobert Mustacchi 348*5fc40de0SRobert Mustacchi if (*step != '[' || ((last = strrchr(step, ']')) == NULL)) { 349*5fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse stepping \"%s\": missing " 350*5fc40de0SRobert Mustacchi "stepping range brackets", step); 351*5fc40de0SRobert Mustacchi } 352*5fc40de0SRobert Mustacchi step++; 353*5fc40de0SRobert Mustacchi *last = '\0'; 354*5fc40de0SRobert Mustacchi while (*step != '\0') { 355*5fc40de0SRobert Mustacchi if (!isxdigit(*step)) { 356*5fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse stepping: invalid " 357*5fc40de0SRobert Mustacchi "stepping identifier '0x%x'", *step); 358*5fc40de0SRobert Mustacchi } 359*5fc40de0SRobert Mustacchi 360*5fc40de0SRobert Mustacchi if (nstep >= CPROC_MAX_STEPPINGS) { 361*5fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse stepping: " 362*5fc40de0SRobert Mustacchi "encountered too many steppings"); 363*5fc40de0SRobert Mustacchi } 364*5fc40de0SRobert Mustacchi 365*5fc40de0SRobert Mustacchi switch (*step) { 366*5fc40de0SRobert Mustacchi case '0': 367*5fc40de0SRobert Mustacchi steppings[nstep] = 0x0; 368*5fc40de0SRobert Mustacchi break; 369*5fc40de0SRobert Mustacchi case '1': 370*5fc40de0SRobert Mustacchi steppings[nstep] = 0x1; 371*5fc40de0SRobert Mustacchi break; 372*5fc40de0SRobert Mustacchi case '2': 373*5fc40de0SRobert Mustacchi steppings[nstep] = 0x2; 374*5fc40de0SRobert Mustacchi break; 375*5fc40de0SRobert Mustacchi case '3': 376*5fc40de0SRobert Mustacchi steppings[nstep] = 0x3; 377*5fc40de0SRobert Mustacchi break; 378*5fc40de0SRobert Mustacchi case '4': 379*5fc40de0SRobert Mustacchi steppings[nstep] = 0x4; 380*5fc40de0SRobert Mustacchi break; 381*5fc40de0SRobert Mustacchi case '5': 382*5fc40de0SRobert Mustacchi steppings[nstep] = 0x5; 383*5fc40de0SRobert Mustacchi break; 384*5fc40de0SRobert Mustacchi case '6': 385*5fc40de0SRobert Mustacchi steppings[nstep] = 0x6; 386*5fc40de0SRobert Mustacchi break; 387*5fc40de0SRobert Mustacchi case '7': 388*5fc40de0SRobert Mustacchi steppings[nstep] = 0x7; 389*5fc40de0SRobert Mustacchi break; 390*5fc40de0SRobert Mustacchi case '8': 391*5fc40de0SRobert Mustacchi steppings[nstep] = 0x8; 392*5fc40de0SRobert Mustacchi break; 393*5fc40de0SRobert Mustacchi case '9': 394*5fc40de0SRobert Mustacchi steppings[nstep] = 0x9; 395*5fc40de0SRobert Mustacchi break; 396*5fc40de0SRobert Mustacchi case 'a': 397*5fc40de0SRobert Mustacchi case 'A': 398*5fc40de0SRobert Mustacchi steppings[nstep] = 0xa; 399*5fc40de0SRobert Mustacchi break; 400*5fc40de0SRobert Mustacchi case 'b': 401*5fc40de0SRobert Mustacchi case 'B': 402*5fc40de0SRobert Mustacchi steppings[nstep] = 0xb; 403*5fc40de0SRobert Mustacchi break; 404*5fc40de0SRobert Mustacchi case 'c': 405*5fc40de0SRobert Mustacchi case 'C': 406*5fc40de0SRobert Mustacchi steppings[nstep] = 0xc; 407*5fc40de0SRobert Mustacchi break; 408*5fc40de0SRobert Mustacchi case 'd': 409*5fc40de0SRobert Mustacchi case 'D': 410*5fc40de0SRobert Mustacchi steppings[nstep] = 0xd; 411*5fc40de0SRobert Mustacchi break; 412*5fc40de0SRobert Mustacchi case 'e': 413*5fc40de0SRobert Mustacchi case 'E': 414*5fc40de0SRobert Mustacchi steppings[nstep] = 0xe; 415*5fc40de0SRobert Mustacchi break; 416*5fc40de0SRobert Mustacchi case 'f': 417*5fc40de0SRobert Mustacchi case 'F': 418*5fc40de0SRobert Mustacchi steppings[nstep] = 0xf; 419*5fc40de0SRobert Mustacchi break; 420*5fc40de0SRobert Mustacchi default: 421*5fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "encountered non-hex stepping " 422*5fc40de0SRobert Mustacchi "character: '%c'", *step); 423*5fc40de0SRobert Mustacchi } 424*5fc40de0SRobert Mustacchi nstep++; 425*5fc40de0SRobert Mustacchi step++; 426*5fc40de0SRobert Mustacchi } 427*5fc40de0SRobert Mustacchi 428*5fc40de0SRobert Mustacchi *nstepp = nstep; 42953548f91SRobert Mustacchi } 43053548f91SRobert Mustacchi 43153548f91SRobert Mustacchi static nvlist_t * 43253548f91SRobert Mustacchi cpcgen_read_datafile(const char *datadir, const char *file) 43353548f91SRobert Mustacchi { 43453548f91SRobert Mustacchi int fd; 43553548f91SRobert Mustacchi char *path; 43653548f91SRobert Mustacchi struct stat st; 43753548f91SRobert Mustacchi void *map; 43853548f91SRobert Mustacchi nvlist_t *nvl; 43953548f91SRobert Mustacchi nvlist_parse_json_error_t jerr; 44053548f91SRobert Mustacchi 44153548f91SRobert Mustacchi if (asprintf(&path, "%s/%s", datadir, file) == -1) { 44253548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct path to data file %s", 44353548f91SRobert Mustacchi file); 44453548f91SRobert Mustacchi } 44553548f91SRobert Mustacchi 44653548f91SRobert Mustacchi if ((fd = open(path, O_RDONLY)) < 0) { 44753548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to open data file %s", path); 44853548f91SRobert Mustacchi } 44953548f91SRobert Mustacchi 45053548f91SRobert Mustacchi if (fstat(fd, &st) != 0) { 45153548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to stat %s", path); 45253548f91SRobert Mustacchi } 45353548f91SRobert Mustacchi 45453548f91SRobert Mustacchi if ((map = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, 45553548f91SRobert Mustacchi fd, 0)) == MAP_FAILED) { 45653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to mmap %s", path); 45753548f91SRobert Mustacchi } 45853548f91SRobert Mustacchi 45953548f91SRobert Mustacchi if (nvlist_parse_json(map, st.st_size, &nvl, NVJSON_FORCE_INTEGER, 46053548f91SRobert Mustacchi &jerr) != 0) { 46153548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse file %s at pos %ld: %s", 46253548f91SRobert Mustacchi path, jerr.nje_pos, jerr.nje_message); 46353548f91SRobert Mustacchi } 46453548f91SRobert Mustacchi 46553548f91SRobert Mustacchi if (munmap(map, st.st_size) != 0) { 46653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to munmap %s", path); 46753548f91SRobert Mustacchi } 46853548f91SRobert Mustacchi 46953548f91SRobert Mustacchi if (close(fd) != 0) { 47053548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to close data file %s", path); 47153548f91SRobert Mustacchi } 47253548f91SRobert Mustacchi free(path); 47353548f91SRobert Mustacchi 47453548f91SRobert Mustacchi return (nvl); 47553548f91SRobert Mustacchi } 47653548f91SRobert Mustacchi 47753548f91SRobert Mustacchi /* 47853548f91SRobert Mustacchi * Check the whitelist to see if we should use this model. 47953548f91SRobert Mustacchi */ 48053548f91SRobert Mustacchi static const char * 48153548f91SRobert Mustacchi cpcgen_use_arch(const char *path, cpc_type_t type, const char *platform) 48253548f91SRobert Mustacchi { 48353548f91SRobert Mustacchi const char *slash; 48453548f91SRobert Mustacchi size_t len; 48553548f91SRobert Mustacchi uint_t i; 48653548f91SRobert Mustacchi 48753548f91SRobert Mustacchi if (*path != '/') { 48853548f91SRobert Mustacchi errx(EXIT_FAILURE, "invalid path in mapfile: \"%s\": missing " 48953548f91SRobert Mustacchi "leading '/'", path); 49053548f91SRobert Mustacchi } 49153548f91SRobert Mustacchi if ((slash = strchr(path + 1, '/')) == NULL) { 49253548f91SRobert Mustacchi errx(EXIT_FAILURE, "invalid path in mapfile: \"%s\": missing " 49353548f91SRobert Mustacchi "second '/'", path); 49453548f91SRobert Mustacchi } 49553548f91SRobert Mustacchi /* Account for the last '/' character. */ 49653548f91SRobert Mustacchi len = slash - path - 1; 49753548f91SRobert Mustacchi assert(len > 0); 49853548f91SRobert Mustacchi 49953548f91SRobert Mustacchi for (i = 0; cpcgen_whitelist[i].cwhite_short != NULL; i++) { 50053548f91SRobert Mustacchi if (platform != NULL && strcasecmp(platform, 50153548f91SRobert Mustacchi cpcgen_whitelist[i].cwhite_short) != 0) 50253548f91SRobert Mustacchi continue; 50353548f91SRobert Mustacchi if (strncmp(path + 1, cpcgen_whitelist[i].cwhite_short, 50453548f91SRobert Mustacchi len) == 0 && 50553548f91SRobert Mustacchi (cpcgen_whitelist[i].cwhite_mask & type) == type) { 50653548f91SRobert Mustacchi return (cpcgen_whitelist[i].cwhite_human); 50753548f91SRobert Mustacchi } 50853548f91SRobert Mustacchi } 50953548f91SRobert Mustacchi 51053548f91SRobert Mustacchi return (NULL); 51153548f91SRobert Mustacchi } 51253548f91SRobert Mustacchi 51353548f91SRobert Mustacchi /* 51453548f91SRobert Mustacchi * Read in the mapfile.csv that is used to map between processor families and 51553548f91SRobert Mustacchi * parse this. Each line has a comma separated value. 51653548f91SRobert Mustacchi */ 51753548f91SRobert Mustacchi static void 51853548f91SRobert Mustacchi cpcgen_read_mapfile(const char *datadir, const char *platform) 51953548f91SRobert Mustacchi { 52053548f91SRobert Mustacchi FILE *map; 52153548f91SRobert Mustacchi char *mappath, *last; 52253548f91SRobert Mustacchi char *data = NULL; 52353548f91SRobert Mustacchi size_t datalen = 0; 52453548f91SRobert Mustacchi uint_t lineno; 52553548f91SRobert Mustacchi 52653548f91SRobert Mustacchi if (asprintf(&mappath, "%s/%s", datadir, cpcgen_mapfile) == -1) { 52753548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct path to mapfile"); 52853548f91SRobert Mustacchi } 52953548f91SRobert Mustacchi 53053548f91SRobert Mustacchi if ((map = fopen(mappath, "r")) == NULL) { 53153548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to open data mapfile %s", mappath); 53253548f91SRobert Mustacchi } 53353548f91SRobert Mustacchi 53453548f91SRobert Mustacchi lineno = 0; 53553548f91SRobert Mustacchi while (getline(&data, &datalen, map) != -1) { 53653548f91SRobert Mustacchi char *fstr, *path, *tstr; 53753548f91SRobert Mustacchi const char *name; 538*5fc40de0SRobert Mustacchi uint_t family, model, nsteps; 539*5fc40de0SRobert Mustacchi uint_t steppings[CPROC_MAX_STEPPINGS]; 540*5fc40de0SRobert Mustacchi 54153548f91SRobert Mustacchi cpc_type_t type; 54253548f91SRobert Mustacchi cpc_map_t *map; 54353548f91SRobert Mustacchi cpc_proc_t *proc; 54453548f91SRobert Mustacchi 54553548f91SRobert Mustacchi /* 54653548f91SRobert Mustacchi * The first line contains the header: 54753548f91SRobert Mustacchi * Family-model,Version,Filename,EventType 54853548f91SRobert Mustacchi */ 54953548f91SRobert Mustacchi lineno++; 55053548f91SRobert Mustacchi if (lineno == 1) { 55153548f91SRobert Mustacchi continue; 55253548f91SRobert Mustacchi } 55353548f91SRobert Mustacchi 55453548f91SRobert Mustacchi if ((fstr = strtok_r(data, ",", &last)) == NULL || 55553548f91SRobert Mustacchi strtok_r(NULL, ",", &last) == NULL || 55653548f91SRobert Mustacchi (path = strtok_r(NULL, ",", &last)) == NULL || 55753548f91SRobert Mustacchi (tstr = strtok_r(NULL, "\n", &last)) == NULL) { 55853548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse mapfile line " 55953548f91SRobert Mustacchi "%u in %s", lineno, mappath); 56053548f91SRobert Mustacchi } 56153548f91SRobert Mustacchi 562*5fc40de0SRobert Mustacchi cpcgen_parse_model(fstr, &family, &model, &nsteps, steppings); 56353548f91SRobert Mustacchi 56453548f91SRobert Mustacchi if (strcmp(tstr, "core") == 0) { 56553548f91SRobert Mustacchi type = CPC_FILE_CORE; 56653548f91SRobert Mustacchi } else if (strcmp(tstr, "offcore") == 0) { 56753548f91SRobert Mustacchi type = CPC_FILE_OFF_CORE; 56853548f91SRobert Mustacchi } else if (strcmp(tstr, "uncore") == 0) { 56953548f91SRobert Mustacchi type = CPC_FILE_UNCORE; 57053548f91SRobert Mustacchi } else if (strcmp(tstr, "fp_arith_inst") == 0) { 57153548f91SRobert Mustacchi type = CPC_FILE_FP_MATH; 57253548f91SRobert Mustacchi } else if (strcmp(tstr, "uncore experimental") == 0) { 57353548f91SRobert Mustacchi type = CPC_FILE_UNCORE_EXP; 57453548f91SRobert Mustacchi } else { 57553548f91SRobert Mustacchi errx(EXIT_FAILURE, "unknown file type \"%s\" on line " 57653548f91SRobert Mustacchi "%u", tstr, lineno); 57753548f91SRobert Mustacchi } 57853548f91SRobert Mustacchi 57953548f91SRobert Mustacchi if ((name = cpcgen_use_arch(path, type, platform)) == NULL) 58053548f91SRobert Mustacchi continue; 58153548f91SRobert Mustacchi 58253548f91SRobert Mustacchi if ((map = cpcgen_map_lookup(path)) == NULL) { 58353548f91SRobert Mustacchi nvlist_t *parsed; 58453548f91SRobert Mustacchi 58553548f91SRobert Mustacchi parsed = cpcgen_read_datafile(datadir, path); 58653548f91SRobert Mustacchi 58753548f91SRobert Mustacchi if ((map = calloc(1, sizeof (cpc_map_t))) == NULL) { 58853548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to allocate space " 58953548f91SRobert Mustacchi "for cpc file"); 59053548f91SRobert Mustacchi } 59153548f91SRobert Mustacchi 59253548f91SRobert Mustacchi if ((map->cmap_path = strdup(path)) == NULL) { 59353548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to duplicate path " 59453548f91SRobert Mustacchi "string"); 59553548f91SRobert Mustacchi } 59653548f91SRobert Mustacchi 59753548f91SRobert Mustacchi map->cmap_type = type; 59853548f91SRobert Mustacchi map->cmap_data = parsed; 59953548f91SRobert Mustacchi map->cmap_next = cpcgen_maps; 60053548f91SRobert Mustacchi map->cmap_name = name; 601*5fc40de0SRobert Mustacchi map->cmap_procs = NULL; 60253548f91SRobert Mustacchi cpcgen_maps = map; 60353548f91SRobert Mustacchi } 60453548f91SRobert Mustacchi 605*5fc40de0SRobert Mustacchi if ((proc = calloc(1, sizeof (cpc_proc_t))) == NULL) { 60653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to allocate memory for " 60753548f91SRobert Mustacchi "family and model tracking"); 60853548f91SRobert Mustacchi } 60953548f91SRobert Mustacchi 61053548f91SRobert Mustacchi proc->cproc_family = family; 61153548f91SRobert Mustacchi proc->cproc_model = model; 612*5fc40de0SRobert Mustacchi proc->cproc_nsteps = nsteps; 613*5fc40de0SRobert Mustacchi if (nsteps > 0) { 614*5fc40de0SRobert Mustacchi bcopy(steppings, proc->cproc_steppings, 615*5fc40de0SRobert Mustacchi sizeof (steppings)); 616*5fc40de0SRobert Mustacchi } 61753548f91SRobert Mustacchi proc->cproc_next = map->cmap_procs; 61853548f91SRobert Mustacchi map->cmap_procs = proc; 61953548f91SRobert Mustacchi } 62053548f91SRobert Mustacchi 62153548f91SRobert Mustacchi if (errno != 0 || ferror(map)) { 62253548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to read %s", mappath); 62353548f91SRobert Mustacchi } 62453548f91SRobert Mustacchi 62553548f91SRobert Mustacchi if (fclose(map) == EOF) { 62653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to close %s", mappath); 62753548f91SRobert Mustacchi } 62853548f91SRobert Mustacchi free(data); 62953548f91SRobert Mustacchi free(mappath); 63053548f91SRobert Mustacchi } 63153548f91SRobert Mustacchi 63253548f91SRobert Mustacchi static char * 63353548f91SRobert Mustacchi cpcgen_manual_name(cpc_map_t *map) 63453548f91SRobert Mustacchi { 63553548f91SRobert Mustacchi char *name; 63653548f91SRobert Mustacchi 63753548f91SRobert Mustacchi if (asprintf(&name, "%s_events.3cpc", map->cmap_name) == -1) { 63853548f91SRobert Mustacchi warn("failed to assemble manual page name for %s", 63953548f91SRobert Mustacchi map->cmap_path); 64053548f91SRobert Mustacchi return (NULL); 64153548f91SRobert Mustacchi } 64253548f91SRobert Mustacchi 64353548f91SRobert Mustacchi return (name); 64453548f91SRobert Mustacchi } 64553548f91SRobert Mustacchi 64653548f91SRobert Mustacchi static boolean_t 64753548f91SRobert Mustacchi cpcgen_manual_file_before(FILE *f, cpc_map_t *map) 64853548f91SRobert Mustacchi { 64953548f91SRobert Mustacchi size_t i; 65053548f91SRobert Mustacchi char *upper; 65153548f91SRobert Mustacchi cpc_proc_t *proc; 65253548f91SRobert Mustacchi 65353548f91SRobert Mustacchi if ((upper = strdup(map->cmap_name)) == NULL) { 65453548f91SRobert Mustacchi warn("failed to duplicate manual name for %s", map->cmap_name); 65553548f91SRobert Mustacchi return (B_FALSE); 65653548f91SRobert Mustacchi } 65753548f91SRobert Mustacchi 65853548f91SRobert Mustacchi for (i = 0; upper[i] != '\0'; i++) { 65953548f91SRobert Mustacchi upper[i] = toupper(upper[i]); 66053548f91SRobert Mustacchi } 66153548f91SRobert Mustacchi 66253548f91SRobert Mustacchi if (fprintf(f, cpcgen_manual_header, map->cmap_path, upper, 66353548f91SRobert Mustacchi map->cmap_name) == -1) { 66453548f91SRobert Mustacchi warn("failed to write out manual header for %s", 66553548f91SRobert Mustacchi map->cmap_name); 66653548f91SRobert Mustacchi free(upper); 66753548f91SRobert Mustacchi return (B_FALSE); 66853548f91SRobert Mustacchi } 66953548f91SRobert Mustacchi 67053548f91SRobert Mustacchi for (proc = map->cmap_procs; proc != NULL; proc = proc->cproc_next) { 671*5fc40de0SRobert Mustacchi if (proc->cproc_nsteps > 0) { 672*5fc40de0SRobert Mustacchi uint_t step; 673*5fc40de0SRobert Mustacchi 674*5fc40de0SRobert Mustacchi for (step = 0; step < proc->cproc_nsteps; step++) { 675*5fc40de0SRobert Mustacchi if (fprintf(f, ".It\n.Sy Family 0x%x, Model " 676*5fc40de0SRobert Mustacchi "0x%x, Stepping 0x%x\n", 677*5fc40de0SRobert Mustacchi proc->cproc_family, proc->cproc_model, 678*5fc40de0SRobert Mustacchi proc->cproc_steppings[step]) == -1) { 679*5fc40de0SRobert Mustacchi warn("failed to write out model " 680*5fc40de0SRobert Mustacchi "information for %s", 68153548f91SRobert Mustacchi map->cmap_name); 68253548f91SRobert Mustacchi free(upper); 68353548f91SRobert Mustacchi return (B_FALSE); 68453548f91SRobert Mustacchi } 68553548f91SRobert Mustacchi } 686*5fc40de0SRobert Mustacchi } else { 687*5fc40de0SRobert Mustacchi if (fprintf(f, ".It\n.Sy Family 0x%x, Model 0x%x\n", 688*5fc40de0SRobert Mustacchi proc->cproc_family, proc->cproc_model) == -1) { 689*5fc40de0SRobert Mustacchi warn("failed to write out model information " 690*5fc40de0SRobert Mustacchi "for %s", map->cmap_name); 691*5fc40de0SRobert Mustacchi free(upper); 692*5fc40de0SRobert Mustacchi return (B_FALSE); 693*5fc40de0SRobert Mustacchi } 694*5fc40de0SRobert Mustacchi } 695*5fc40de0SRobert Mustacchi } 69653548f91SRobert Mustacchi 69753548f91SRobert Mustacchi if (fprintf(f, cpcgen_manual_data, map->cmap_path, upper, 69853548f91SRobert Mustacchi map->cmap_name) == -1) { 69953548f91SRobert Mustacchi warn("failed to write out manual header for %s", 70053548f91SRobert Mustacchi map->cmap_name); 70153548f91SRobert Mustacchi free(upper); 70253548f91SRobert Mustacchi return (B_FALSE); 70353548f91SRobert Mustacchi } 70453548f91SRobert Mustacchi 70553548f91SRobert Mustacchi free(upper); 70653548f91SRobert Mustacchi return (B_TRUE); 70753548f91SRobert Mustacchi } 70853548f91SRobert Mustacchi 70953548f91SRobert Mustacchi static boolean_t 71053548f91SRobert Mustacchi cpcgen_manual_file_after(FILE *f, cpc_map_t *map) 71153548f91SRobert Mustacchi { 71253548f91SRobert Mustacchi if (fprintf(f, cpcgen_manual_trailer) == -1) { 71353548f91SRobert Mustacchi warn("failed to write out manual header for %s", 71453548f91SRobert Mustacchi map->cmap_name); 71553548f91SRobert Mustacchi return (B_FALSE); 71653548f91SRobert Mustacchi } 71753548f91SRobert Mustacchi 71853548f91SRobert Mustacchi return (B_TRUE); 71953548f91SRobert Mustacchi } 72053548f91SRobert Mustacchi 72153548f91SRobert Mustacchi static boolean_t 72253548f91SRobert Mustacchi cpcgen_manual_event(FILE *f, nvlist_t *nvl, const char *path, uint32_t ent) 72353548f91SRobert Mustacchi { 72453548f91SRobert Mustacchi char *event, *lname, *brief = NULL, *public = NULL, *errata = NULL; 72553548f91SRobert Mustacchi size_t i; 72653548f91SRobert Mustacchi 72753548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "EventName", &event) != 0) { 72853548f91SRobert Mustacchi warnx("Found event without 'EventName' property " 72953548f91SRobert Mustacchi "in %s, entry %u", path, ent); 73053548f91SRobert Mustacchi return (B_FALSE); 73153548f91SRobert Mustacchi } 73253548f91SRobert Mustacchi 73353548f91SRobert Mustacchi /* 73453548f91SRobert Mustacchi * Intel uses capital names. CPC historically uses lower case names. 73553548f91SRobert Mustacchi */ 73653548f91SRobert Mustacchi if ((lname = strdup(event)) == NULL) { 73753548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to duplicate event name %s", event); 73853548f91SRobert Mustacchi } 73953548f91SRobert Mustacchi for (i = 0; lname[i] != '\0'; i++) { 74053548f91SRobert Mustacchi lname[i] = tolower(event[i]); 74153548f91SRobert Mustacchi } 74253548f91SRobert Mustacchi 74353548f91SRobert Mustacchi /* 74453548f91SRobert Mustacchi * Try to get the other event fields, but if they're not there, don't 74553548f91SRobert Mustacchi * worry about it. 74653548f91SRobert Mustacchi */ 74753548f91SRobert Mustacchi (void) nvlist_lookup_string(nvl, "BriefDescription", &brief); 74853548f91SRobert Mustacchi (void) nvlist_lookup_string(nvl, "PublicDescription", &public); 74953548f91SRobert Mustacchi (void) nvlist_lookup_string(nvl, "Errata", &errata); 75053548f91SRobert Mustacchi if (errata != NULL && (strcmp(errata, "0") == 0 || 75153548f91SRobert Mustacchi strcmp(errata, "null") == 0)) { 75253548f91SRobert Mustacchi errata = NULL; 75353548f91SRobert Mustacchi } 75453548f91SRobert Mustacchi 75553548f91SRobert Mustacchi if (fprintf(f, ".It Sy %s\n", lname) == -1) { 75653548f91SRobert Mustacchi warn("failed to write out probe entry %s", event); 75753548f91SRobert Mustacchi free(lname); 75853548f91SRobert Mustacchi return (B_FALSE); 75953548f91SRobert Mustacchi } 76053548f91SRobert Mustacchi 76153548f91SRobert Mustacchi if (public != NULL) { 76253548f91SRobert Mustacchi if (fprintf(f, "%s\n", public) == -1) { 76353548f91SRobert Mustacchi warn("failed to write out probe entry %s", event); 76453548f91SRobert Mustacchi free(lname); 76553548f91SRobert Mustacchi return (B_FALSE); 76653548f91SRobert Mustacchi } 76753548f91SRobert Mustacchi } else if (brief != NULL) { 76853548f91SRobert Mustacchi if (fprintf(f, "%s\n", brief) == -1) { 76953548f91SRobert Mustacchi warn("failed to write out probe entry %s", event); 77053548f91SRobert Mustacchi free(lname); 77153548f91SRobert Mustacchi return (B_FALSE); 77253548f91SRobert Mustacchi } 77353548f91SRobert Mustacchi } 77453548f91SRobert Mustacchi 77553548f91SRobert Mustacchi if (errata != NULL) { 77653548f91SRobert Mustacchi if (fprintf(f, ".Pp\nThe following errata may apply to this: " 77753548f91SRobert Mustacchi "%s\n", errata) == -1) { 77853548f91SRobert Mustacchi 77953548f91SRobert Mustacchi warn("failed to write out probe entry %s", event); 78053548f91SRobert Mustacchi free(lname); 78153548f91SRobert Mustacchi return (B_FALSE); 78253548f91SRobert Mustacchi } 78353548f91SRobert Mustacchi } 78453548f91SRobert Mustacchi 78553548f91SRobert Mustacchi free(lname); 78653548f91SRobert Mustacchi return (B_TRUE); 78753548f91SRobert Mustacchi } 78853548f91SRobert Mustacchi 78953548f91SRobert Mustacchi static char * 79053548f91SRobert Mustacchi cpcgen_cfile_name(cpc_map_t *map) 79153548f91SRobert Mustacchi { 79253548f91SRobert Mustacchi char *name; 79353548f91SRobert Mustacchi 79453548f91SRobert Mustacchi if (asprintf(&name, "core_pcbe_%s.c", map->cmap_name) == -1) { 79553548f91SRobert Mustacchi warn("failed to assemble file name for %s", map->cmap_path); 79653548f91SRobert Mustacchi return (NULL); 79753548f91SRobert Mustacchi } 79853548f91SRobert Mustacchi 79953548f91SRobert Mustacchi return (name); 80053548f91SRobert Mustacchi } 80153548f91SRobert Mustacchi 80253548f91SRobert Mustacchi static boolean_t 80353548f91SRobert Mustacchi cpcgen_cfile_file_before(FILE *f, cpc_map_t *map) 80453548f91SRobert Mustacchi { 80553548f91SRobert Mustacchi if (fprintf(f, cpcgen_cfile_header, map->cmap_path) == -1) { 80653548f91SRobert Mustacchi warn("failed to write header to temporary file for %s", 80753548f91SRobert Mustacchi map->cmap_path); 80853548f91SRobert Mustacchi return (B_FALSE); 80953548f91SRobert Mustacchi } 81053548f91SRobert Mustacchi 81153548f91SRobert Mustacchi if (fprintf(f, cpcgen_cfile_table_start, map->cmap_name) == -1) { 81253548f91SRobert Mustacchi warn("failed to write header to temporary file for %s", 81353548f91SRobert Mustacchi map->cmap_path); 81453548f91SRobert Mustacchi return (B_FALSE); 81553548f91SRobert Mustacchi } 81653548f91SRobert Mustacchi 81753548f91SRobert Mustacchi return (B_TRUE); 81853548f91SRobert Mustacchi } 81953548f91SRobert Mustacchi 82053548f91SRobert Mustacchi static boolean_t 82153548f91SRobert Mustacchi cpcgen_cfile_file_after(FILE *f, cpc_map_t *map) 82253548f91SRobert Mustacchi { 82353548f91SRobert Mustacchi if (fprintf(f, cpcgen_cfile_table_end) == -1) { 82453548f91SRobert Mustacchi warn("failed to write footer to temporary file for %s", 82553548f91SRobert Mustacchi map->cmap_path); 82653548f91SRobert Mustacchi return (B_FALSE); 82753548f91SRobert Mustacchi } 82853548f91SRobert Mustacchi 82953548f91SRobert Mustacchi return (B_TRUE); 83053548f91SRobert Mustacchi } 83153548f91SRobert Mustacchi 83253548f91SRobert Mustacchi static boolean_t 83353548f91SRobert Mustacchi cpcgen_cfile_event(FILE *f, nvlist_t *nvl, const char *path, uint_t ent) 83453548f91SRobert Mustacchi { 83553548f91SRobert Mustacchi char *ecode, *umask, *name, *counter, *lname, *cmask; 83653548f91SRobert Mustacchi size_t i; 83753548f91SRobert Mustacchi 83853548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "EventName", &name) != 0) { 83953548f91SRobert Mustacchi warnx("Found event without 'EventName' property " 84053548f91SRobert Mustacchi "in %s, entry %u", path, ent); 84153548f91SRobert Mustacchi return (B_FALSE); 84253548f91SRobert Mustacchi } 84353548f91SRobert Mustacchi 84453548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "EventCode", &ecode) != 0 || 84553548f91SRobert Mustacchi nvlist_lookup_string(nvl, "UMask", &umask) != 0 || 84653548f91SRobert Mustacchi nvlist_lookup_string(nvl, "Counter", &counter) != 0) { 84753548f91SRobert Mustacchi warnx("event %s (index %u) from %s, missing " 84853548f91SRobert Mustacchi "required properties for C file translation", 84953548f91SRobert Mustacchi name, ent, path); 85053548f91SRobert Mustacchi return (B_FALSE); 85153548f91SRobert Mustacchi } 85253548f91SRobert Mustacchi 85353548f91SRobert Mustacchi /* 85453548f91SRobert Mustacchi * While we could try and parse the counters manually, just do this the 85553548f91SRobert Mustacchi * max power way for now based on all possible values. 85653548f91SRobert Mustacchi */ 85753548f91SRobert Mustacchi if (strcmp(counter, "0") == 0 || strcmp(counter, "0,") == 0) { 85853548f91SRobert Mustacchi cmask = "C0"; 85953548f91SRobert Mustacchi } else if (strcmp(counter, "1") == 0) { 86053548f91SRobert Mustacchi cmask = "C1"; 86153548f91SRobert Mustacchi } else if (strcmp(counter, "2") == 0) { 86253548f91SRobert Mustacchi cmask = "C2"; 86353548f91SRobert Mustacchi } else if (strcmp(counter, "3") == 0) { 86453548f91SRobert Mustacchi cmask = "C3"; 86553548f91SRobert Mustacchi } else if (strcmp(counter, "0,1") == 0) { 86653548f91SRobert Mustacchi cmask = "C0|C1"; 86753548f91SRobert Mustacchi } else if (strcmp(counter, "0,1,2") == 0) { 86853548f91SRobert Mustacchi cmask = "C0|C1|C2"; 86953548f91SRobert Mustacchi } else if (strcmp(counter, "0,1,2,3") == 0) { 87053548f91SRobert Mustacchi cmask = "C0|C1|C2|C3"; 87153548f91SRobert Mustacchi } else if (strcmp(counter, "0,2,3") == 0) { 87253548f91SRobert Mustacchi cmask = "C0|C2|C3"; 87353548f91SRobert Mustacchi } else if (strcmp(counter, "1,2,3") == 0) { 87453548f91SRobert Mustacchi cmask = "C1|C2|C3"; 87553548f91SRobert Mustacchi } else if (strcmp(counter, "2,3") == 0) { 87653548f91SRobert Mustacchi cmask = "C2|C3"; 87753548f91SRobert Mustacchi } else { 87853548f91SRobert Mustacchi warnx("event %s (index %u) from %s, has unknown " 87953548f91SRobert Mustacchi "counter value \"%s\"", name, ent, path, counter); 88053548f91SRobert Mustacchi return (B_FALSE); 88153548f91SRobert Mustacchi } 88253548f91SRobert Mustacchi 88353548f91SRobert Mustacchi 88453548f91SRobert Mustacchi /* 88553548f91SRobert Mustacchi * Intel uses capital names. CPC historically uses lower case names. 88653548f91SRobert Mustacchi */ 88753548f91SRobert Mustacchi if ((lname = strdup(name)) == NULL) { 88853548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to duplicate event name %s", name); 88953548f91SRobert Mustacchi } 89053548f91SRobert Mustacchi for (i = 0; lname[i] != '\0'; i++) { 89153548f91SRobert Mustacchi lname[i] = tolower(name[i]); 89253548f91SRobert Mustacchi } 89353548f91SRobert Mustacchi 89453548f91SRobert Mustacchi if (fprintf(f, "\t{ %s, %s, %s, \"%s\" },\n", ecode, umask, cmask, 89553548f91SRobert Mustacchi lname) == -1) { 89653548f91SRobert Mustacchi warn("failed to write out entry %s from %s", name, path); 89753548f91SRobert Mustacchi free(lname); 89853548f91SRobert Mustacchi return (B_FALSE); 89953548f91SRobert Mustacchi } 90053548f91SRobert Mustacchi 90153548f91SRobert Mustacchi free(lname); 90253548f91SRobert Mustacchi 90353548f91SRobert Mustacchi /* 90453548f91SRobert Mustacchi * Check if we have any PAPI aliases. 90553548f91SRobert Mustacchi */ 90653548f91SRobert Mustacchi for (i = 0; cpcgen_papi_map[i].cpapi_intc != NULL; i++) { 90753548f91SRobert Mustacchi if (strcmp(name, cpcgen_papi_map[i].cpapi_intc) != 0) 90853548f91SRobert Mustacchi continue; 90953548f91SRobert Mustacchi 91053548f91SRobert Mustacchi if (fprintf(f, "\t{ %s, %s, %s, \"%s\" },\n", ecode, umask, 91153548f91SRobert Mustacchi cmask, cpcgen_papi_map[i].cpapi_papi) == -1) { 91253548f91SRobert Mustacchi warn("failed to write out entry %s from %s", name, 91353548f91SRobert Mustacchi path); 91453548f91SRobert Mustacchi return (B_FALSE); 91553548f91SRobert Mustacchi } 91653548f91SRobert Mustacchi } 91753548f91SRobert Mustacchi 91853548f91SRobert Mustacchi return (B_TRUE); 91953548f91SRobert Mustacchi } 92053548f91SRobert Mustacchi 921*5fc40de0SRobert Mustacchi static boolean_t 922*5fc40de0SRobert Mustacchi cpcgen_generate_map(FILE *f, cpc_map_t *map, boolean_t start) 923*5fc40de0SRobert Mustacchi { 924*5fc40de0SRobert Mustacchi cpc_proc_t *p; 925*5fc40de0SRobert Mustacchi 926*5fc40de0SRobert Mustacchi if (fprintf(f, "\t%sif (", start ? "" : "} else ") == -1) { 927*5fc40de0SRobert Mustacchi return (B_FALSE); 928*5fc40de0SRobert Mustacchi } 929*5fc40de0SRobert Mustacchi 930*5fc40de0SRobert Mustacchi for (p = map->cmap_procs; p != NULL; p = p->cproc_next) { 931*5fc40de0SRobert Mustacchi /* 932*5fc40de0SRobert Mustacchi * Make sure the line is padded so the generated C code looks 933*5fc40de0SRobert Mustacchi * like reasonable C style. 934*5fc40de0SRobert Mustacchi */ 935*5fc40de0SRobert Mustacchi if (p != map->cmap_procs) { 936*5fc40de0SRobert Mustacchi if (fputs("\t ", f) == -1) { 937*5fc40de0SRobert Mustacchi return (B_FALSE); 938*5fc40de0SRobert Mustacchi } 939*5fc40de0SRobert Mustacchi } 940*5fc40de0SRobert Mustacchi 941*5fc40de0SRobert Mustacchi if (p->cproc_nsteps > 0) { 942*5fc40de0SRobert Mustacchi uint_t i; 943*5fc40de0SRobert Mustacchi 944*5fc40de0SRobert Mustacchi if (fprintf(f, "(model == 0x%x &&\n\t (", 945*5fc40de0SRobert Mustacchi p->cproc_model) == -1) { 946*5fc40de0SRobert Mustacchi return (B_FALSE); 947*5fc40de0SRobert Mustacchi } 948*5fc40de0SRobert Mustacchi 949*5fc40de0SRobert Mustacchi for (i = 0; i < p->cproc_nsteps; i++) { 950*5fc40de0SRobert Mustacchi if (fprintf(f, "stepping == 0x%x%s", 951*5fc40de0SRobert Mustacchi p->cproc_steppings[i], 952*5fc40de0SRobert Mustacchi i + 1 != p->cproc_nsteps ? 953*5fc40de0SRobert Mustacchi " ||\n\t " : "") == -1) { 954*5fc40de0SRobert Mustacchi return (B_FALSE); 955*5fc40de0SRobert Mustacchi } 956*5fc40de0SRobert Mustacchi } 957*5fc40de0SRobert Mustacchi 958*5fc40de0SRobert Mustacchi if (fputs("))", f) == -1) { 959*5fc40de0SRobert Mustacchi return (B_FALSE); 960*5fc40de0SRobert Mustacchi } 961*5fc40de0SRobert Mustacchi } else if (fprintf(f, "model == 0x%x", p->cproc_model) == -1) { 962*5fc40de0SRobert Mustacchi return (B_FALSE); 963*5fc40de0SRobert Mustacchi } 964*5fc40de0SRobert Mustacchi 965*5fc40de0SRobert Mustacchi if (fprintf(f, "%s\n", 966*5fc40de0SRobert Mustacchi p->cproc_next != NULL ? " ||" : ") {") == -1) { 967*5fc40de0SRobert Mustacchi return (B_FALSE); 968*5fc40de0SRobert Mustacchi } 969*5fc40de0SRobert Mustacchi } 970*5fc40de0SRobert Mustacchi 971*5fc40de0SRobert Mustacchi if (fprintf(f, "\t\t\treturn (pcbe_core_events_%s);\n", 972*5fc40de0SRobert Mustacchi map->cmap_name) == -1) { 973*5fc40de0SRobert Mustacchi return (B_FALSE); 974*5fc40de0SRobert Mustacchi } 975*5fc40de0SRobert Mustacchi 976*5fc40de0SRobert Mustacchi return (B_TRUE); 977*5fc40de0SRobert Mustacchi } 978*5fc40de0SRobert Mustacchi 97953548f91SRobert Mustacchi /* 98053548f91SRobert Mustacchi * Generate a header file that declares all of these arrays and provide a map 98153548f91SRobert Mustacchi * for models to the corresponding table to use. 98253548f91SRobert Mustacchi */ 98353548f91SRobert Mustacchi static void 98453548f91SRobert Mustacchi cpcgen_common_files(int dirfd) 98553548f91SRobert Mustacchi { 98653548f91SRobert Mustacchi const char *fname = "core_pcbe_cpcgen.h"; 98753548f91SRobert Mustacchi char *tmpname; 98853548f91SRobert Mustacchi int fd; 98953548f91SRobert Mustacchi FILE *f; 99053548f91SRobert Mustacchi cpc_map_t *map; 99153548f91SRobert Mustacchi 99253548f91SRobert Mustacchi if (asprintf(&tmpname, ".%s.%d", fname, getpid()) == -1) { 99353548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct temporary file name"); 99453548f91SRobert Mustacchi } 99553548f91SRobert Mustacchi 99653548f91SRobert Mustacchi if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) { 99753548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to create temporary file %s", 99853548f91SRobert Mustacchi tmpname); 99953548f91SRobert Mustacchi } 100053548f91SRobert Mustacchi 100153548f91SRobert Mustacchi if ((f = fdopen(fd, "w")) == NULL) { 100253548f91SRobert Mustacchi int e = errno; 100353548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 100453548f91SRobert Mustacchi errno = e; 100553548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to fdopen temporary file"); 100653548f91SRobert Mustacchi } 100753548f91SRobert Mustacchi 100853548f91SRobert Mustacchi if (fprintf(f, cpcgen_cfile_header, cpcgen_mapfile) == -1) { 100953548f91SRobert Mustacchi int e = errno; 101053548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 101153548f91SRobert Mustacchi errno = e; 101253548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to temporary file " 101353548f91SRobert Mustacchi "for %s", fname); 101453548f91SRobert Mustacchi } 101553548f91SRobert Mustacchi 101653548f91SRobert Mustacchi if (fprintf(f, "#ifndef _CORE_PCBE_CPCGEN_H\n" 101753548f91SRobert Mustacchi "#define\t_CORE_PCBE_CPCGEN_H\n" 101853548f91SRobert Mustacchi "\n" 101953548f91SRobert Mustacchi "#ifdef __cplusplus\n" 102053548f91SRobert Mustacchi "extern \"C\" {\n" 102153548f91SRobert Mustacchi "#endif\n" 102253548f91SRobert Mustacchi "\n" 1023*5fc40de0SRobert Mustacchi "extern const struct events_table_t *core_cpcgen_table(uint_t, " 1024*5fc40de0SRobert Mustacchi "uint_t);\n" 102553548f91SRobert Mustacchi "\n") == -1) { 102653548f91SRobert Mustacchi int e = errno; 102753548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 102853548f91SRobert Mustacchi errno = e; 102953548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to " 103053548f91SRobert Mustacchi "temporary file for %s", fname); 103153548f91SRobert Mustacchi } 103253548f91SRobert Mustacchi 103353548f91SRobert Mustacchi for (map = cpcgen_maps; map != NULL; map = map->cmap_next) { 103453548f91SRobert Mustacchi if (fprintf(f, "extern const struct events_table_t " 103553548f91SRobert Mustacchi "pcbe_core_events_%s[];\n", map->cmap_name) == -1) { 103653548f91SRobert Mustacchi int e = errno; 103753548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 103853548f91SRobert Mustacchi errno = e; 103953548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write entry to " 104053548f91SRobert Mustacchi "temporary file for %s", fname); 104153548f91SRobert Mustacchi } 104253548f91SRobert Mustacchi } 104353548f91SRobert Mustacchi 104453548f91SRobert Mustacchi if (fprintf(f, "\n" 104553548f91SRobert Mustacchi "#ifdef __cplusplus\n" 104653548f91SRobert Mustacchi "}\n" 104753548f91SRobert Mustacchi "#endif\n" 104853548f91SRobert Mustacchi "\n" 104953548f91SRobert Mustacchi "#endif /* _CORE_PCBE_CPCGEN_H */\n") == -1) { 105053548f91SRobert Mustacchi int e = errno; 105153548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 105253548f91SRobert Mustacchi errno = e; 105353548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to " 105453548f91SRobert Mustacchi "temporary file for %s", fname); 105553548f91SRobert Mustacchi } 105653548f91SRobert Mustacchi 105753548f91SRobert Mustacchi if (fflush(f) != 0 || fclose(f) != 0) { 105853548f91SRobert Mustacchi int e = errno; 105953548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 106053548f91SRobert Mustacchi errno = e; 106153548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to flush and close temporary file"); 106253548f91SRobert Mustacchi } 106353548f91SRobert Mustacchi 106453548f91SRobert Mustacchi if (renameat(dirfd, tmpname, dirfd, fname) != 0) { 106553548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to rename temporary file %s", 106653548f91SRobert Mustacchi tmpname); 106753548f91SRobert Mustacchi } 106853548f91SRobert Mustacchi 106953548f91SRobert Mustacchi free(tmpname); 107053548f91SRobert Mustacchi 107153548f91SRobert Mustacchi /* Now again for the .c file. */ 107253548f91SRobert Mustacchi fname = "core_pcbe_cpcgen.c"; 107353548f91SRobert Mustacchi if (asprintf(&tmpname, ".%s.%d", fname, getpid()) == -1) { 107453548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct temporary file name"); 107553548f91SRobert Mustacchi } 107653548f91SRobert Mustacchi 107753548f91SRobert Mustacchi if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) { 107853548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to create temporary file %s", 107953548f91SRobert Mustacchi tmpname); 108053548f91SRobert Mustacchi } 108153548f91SRobert Mustacchi 108253548f91SRobert Mustacchi if ((f = fdopen(fd, "w")) == NULL) { 108353548f91SRobert Mustacchi int e = errno; 108453548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 108553548f91SRobert Mustacchi errno = e; 108653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to fdopen temporary file"); 108753548f91SRobert Mustacchi } 108853548f91SRobert Mustacchi 108953548f91SRobert Mustacchi if (fprintf(f, cpcgen_cfile_header, cpcgen_mapfile) == -1) { 109053548f91SRobert Mustacchi int e = errno; 109153548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 109253548f91SRobert Mustacchi errno = e; 109353548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to temporary file " 109453548f91SRobert Mustacchi "for %s", fname); 109553548f91SRobert Mustacchi } 109653548f91SRobert Mustacchi 109753548f91SRobert Mustacchi if (fprintf(f, "#include <core_pcbe_table.h>\n" 109853548f91SRobert Mustacchi "#include <sys/null.h>\n" 109953548f91SRobert Mustacchi "#include \"core_pcbe_cpcgen.h\"\n" 110053548f91SRobert Mustacchi "\n" 110153548f91SRobert Mustacchi "const struct events_table_t *\n" 1102*5fc40de0SRobert Mustacchi "core_cpcgen_table(uint_t model, uint_t stepping)\n" 1103*5fc40de0SRobert Mustacchi "{\n") == -1) { 110453548f91SRobert Mustacchi int e = errno; 110553548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 110653548f91SRobert Mustacchi errno = e; 110753548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to " 110853548f91SRobert Mustacchi "temporary file for %s", fname); 110953548f91SRobert Mustacchi } 111053548f91SRobert Mustacchi 111153548f91SRobert Mustacchi for (map = cpcgen_maps; map != NULL; map = map->cmap_next) { 1112*5fc40de0SRobert Mustacchi if (!cpcgen_generate_map(f, map, map == cpcgen_maps)) { 111353548f91SRobert Mustacchi int e = errno; 111453548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 111553548f91SRobert Mustacchi errno = e; 1116*5fc40de0SRobert Mustacchi errx(EXIT_FAILURE, "failed to write to temporary " 1117*5fc40de0SRobert Mustacchi "file for %s", fname); 111853548f91SRobert Mustacchi } 111953548f91SRobert Mustacchi } 112053548f91SRobert Mustacchi 1121*5fc40de0SRobert Mustacchi if (fprintf(f, "\t} else {\n" 112253548f91SRobert Mustacchi "\t\t\treturn (NULL);\n" 112353548f91SRobert Mustacchi "\t}\n" 112453548f91SRobert Mustacchi "}\n") == -1) { 112553548f91SRobert Mustacchi int e = errno; 112653548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 112753548f91SRobert Mustacchi errno = e; 112853548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to write header to " 112953548f91SRobert Mustacchi "temporary file for %s", fname); 113053548f91SRobert Mustacchi } 113153548f91SRobert Mustacchi 113253548f91SRobert Mustacchi if (fflush(f) != 0 || fclose(f) != 0) { 113353548f91SRobert Mustacchi int e = errno; 113453548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 113553548f91SRobert Mustacchi errno = e; 113653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to flush and close temporary file"); 113753548f91SRobert Mustacchi } 113853548f91SRobert Mustacchi 113953548f91SRobert Mustacchi if (renameat(dirfd, tmpname, dirfd, fname) != 0) { 114053548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to rename temporary file %s", 114153548f91SRobert Mustacchi tmpname); 114253548f91SRobert Mustacchi } 114353548f91SRobert Mustacchi 114453548f91SRobert Mustacchi free(tmpname); 114553548f91SRobert Mustacchi } 114653548f91SRobert Mustacchi 114753548f91SRobert Mustacchi /* 114853548f91SRobert Mustacchi * Look at a rule to determine whether or not we should consider including it or 114953548f91SRobert Mustacchi * not. At this point we've already filtered things such that we only get core 115053548f91SRobert Mustacchi * events. 115153548f91SRobert Mustacchi * 115253548f91SRobert Mustacchi * To consider an entry, we currently apply the following criteria: 115353548f91SRobert Mustacchi * 115453548f91SRobert Mustacchi * - The MSRIndex and MSRValue are zero. Programming additional MSRs is no 115553548f91SRobert Mustacchi * supported right now. 115653548f91SRobert Mustacchi * - TakenAlone is non-zero, which means that it cannot run at the same time as 115753548f91SRobert Mustacchi * another field. 115853548f91SRobert Mustacchi * - Offcore is one, indicating that it is off the core and we need to figure 115953548f91SRobert Mustacchi * out if we can support this. 116053548f91SRobert Mustacchi * - If the counter is fixed, don't use it for now. 116153548f91SRobert Mustacchi * - If more than one value is specified in the EventCode or UMask values 116253548f91SRobert Mustacchi */ 116353548f91SRobert Mustacchi static boolean_t 116453548f91SRobert Mustacchi cpcgen_skip_entry(nvlist_t *nvl, const char *path, uint_t ent) 116553548f91SRobert Mustacchi { 116653548f91SRobert Mustacchi char *event, *msridx, *msrval, *taken, *offcore, *counter; 116753548f91SRobert Mustacchi char *ecode, *umask; 116853548f91SRobert Mustacchi 116953548f91SRobert Mustacchi /* 117053548f91SRobert Mustacchi * Require EventName, it's kind of useless without that. 117153548f91SRobert Mustacchi */ 117253548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "EventName", &event) != 0) { 117353548f91SRobert Mustacchi errx(EXIT_FAILURE, "Found event without 'EventName' property " 117453548f91SRobert Mustacchi "in %s, entry %u", path, ent); 117553548f91SRobert Mustacchi } 117653548f91SRobert Mustacchi 117753548f91SRobert Mustacchi /* 117853548f91SRobert Mustacchi * If we can't find an expected value, whine about it. 117953548f91SRobert Mustacchi */ 118053548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "MSRIndex", &msridx) != 0 || 118153548f91SRobert Mustacchi nvlist_lookup_string(nvl, "MSRValue", &msrval) != 0 || 118253548f91SRobert Mustacchi nvlist_lookup_string(nvl, "Counter", &counter) != 0 || 118353548f91SRobert Mustacchi nvlist_lookup_string(nvl, "EventCode", &ecode) != 0 || 118453548f91SRobert Mustacchi nvlist_lookup_string(nvl, "UMask", &umask) != 0 || 118553548f91SRobert Mustacchi nvlist_lookup_string(nvl, "Offcore", &offcore) != 0) { 118653548f91SRobert Mustacchi warnx("Skipping event %s (index %u) from %s, missing required " 118753548f91SRobert Mustacchi "property", event, ent, path); 118853548f91SRobert Mustacchi return (B_TRUE); 118953548f91SRobert Mustacchi } 119053548f91SRobert Mustacchi 119153548f91SRobert Mustacchi /* 119253548f91SRobert Mustacchi * MSRIndex and MSRvalue comes as either "0" or "0x00". 119353548f91SRobert Mustacchi */ 119453548f91SRobert Mustacchi if ((strcmp(msridx, "0") != 0 && strcmp(msridx, "0x00") != 0) || 119553548f91SRobert Mustacchi (strcmp(msrval, "0") != 0 && strcmp(msridx, "0x00") != 0) || 119653548f91SRobert Mustacchi strcmp(offcore, "0") != 0 || strchr(ecode, ',') != NULL || 119753548f91SRobert Mustacchi strchr(umask, ',') != NULL) { 119853548f91SRobert Mustacchi return (B_TRUE); 119953548f91SRobert Mustacchi } 120053548f91SRobert Mustacchi 120153548f91SRobert Mustacchi /* 120253548f91SRobert Mustacchi * Unfortunately, not everything actually has "TakenAlone". If it 120353548f91SRobert Mustacchi * doesn't, we assume that it doesn't have to be. 120453548f91SRobert Mustacchi */ 120553548f91SRobert Mustacchi if (nvlist_lookup_string(nvl, "TakenAlone", &taken) == 0 && 120653548f91SRobert Mustacchi strcmp(taken, "0") != 0) { 120753548f91SRobert Mustacchi return (B_TRUE); 120853548f91SRobert Mustacchi } 120953548f91SRobert Mustacchi 121053548f91SRobert Mustacchi 121153548f91SRobert Mustacchi if (strncasecmp(counter, "fixed", strlen("fixed")) == 0) 121253548f91SRobert Mustacchi return (B_TRUE); 121353548f91SRobert Mustacchi 121453548f91SRobert Mustacchi return (B_FALSE); 121553548f91SRobert Mustacchi } 121653548f91SRobert Mustacchi 121753548f91SRobert Mustacchi /* 121853548f91SRobert Mustacchi * For each processor family, generate a data file that contains all of the 121953548f91SRobert Mustacchi * events that we support. Also generate a header that can be included that 122053548f91SRobert Mustacchi * declares all of the tables. 122153548f91SRobert Mustacchi */ 122253548f91SRobert Mustacchi static void 122353548f91SRobert Mustacchi cpcgen_gen(int dirfd) 122453548f91SRobert Mustacchi { 122553548f91SRobert Mustacchi cpc_map_t *map = cpcgen_maps; 122653548f91SRobert Mustacchi 122753548f91SRobert Mustacchi if (map == NULL) { 122853548f91SRobert Mustacchi errx(EXIT_FAILURE, "no platforms found or matched"); 122953548f91SRobert Mustacchi } 123053548f91SRobert Mustacchi 123153548f91SRobert Mustacchi for (map = cpcgen_maps; map != NULL; map = map->cmap_next) { 123253548f91SRobert Mustacchi int fd, ret; 123353548f91SRobert Mustacchi FILE *f; 123453548f91SRobert Mustacchi char *tmpname, *name; 123553548f91SRobert Mustacchi uint32_t length, i; 123653548f91SRobert Mustacchi 123753548f91SRobert Mustacchi if ((name = cpcgen_ops.cgen_op_name(map)) == NULL) { 123853548f91SRobert Mustacchi exit(EXIT_FAILURE); 123953548f91SRobert Mustacchi } 124053548f91SRobert Mustacchi 124153548f91SRobert Mustacchi if (asprintf(&tmpname, ".%s.%d", name, getpid()) == -1) { 124253548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to construct temporary file " 124353548f91SRobert Mustacchi "name"); 124453548f91SRobert Mustacchi } 124553548f91SRobert Mustacchi 124653548f91SRobert Mustacchi if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0444)) < 0) { 124753548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to create temporary file %s", 124853548f91SRobert Mustacchi tmpname); 124953548f91SRobert Mustacchi } 125053548f91SRobert Mustacchi 125153548f91SRobert Mustacchi if ((f = fdopen(fd, "w")) == NULL) { 125253548f91SRobert Mustacchi int e = errno; 125353548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 125453548f91SRobert Mustacchi errno = e; 125553548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to fdopen temporary file"); 125653548f91SRobert Mustacchi } 125753548f91SRobert Mustacchi 125853548f91SRobert Mustacchi if (!cpcgen_ops.cgen_op_file_before(f, map)) { 125953548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 126053548f91SRobert Mustacchi exit(EXIT_FAILURE); 126153548f91SRobert Mustacchi } 126253548f91SRobert Mustacchi 126353548f91SRobert Mustacchi /* 126453548f91SRobert Mustacchi * Iterate over array contents. 126553548f91SRobert Mustacchi */ 126653548f91SRobert Mustacchi if ((ret = nvlist_lookup_uint32(map->cmap_data, "length", 126753548f91SRobert Mustacchi &length)) != 0) { 126853548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to look up length property " 126953548f91SRobert Mustacchi "in parsed data for %s: %s", map->cmap_path, 127053548f91SRobert Mustacchi strerror(ret)); 127153548f91SRobert Mustacchi } 127253548f91SRobert Mustacchi 127353548f91SRobert Mustacchi for (i = 0; i < length; i++) { 127453548f91SRobert Mustacchi nvlist_t *nvl; 127553548f91SRobert Mustacchi char num[64]; 127653548f91SRobert Mustacchi 127753548f91SRobert Mustacchi (void) snprintf(num, sizeof (num), "%u", i); 127853548f91SRobert Mustacchi if ((ret = nvlist_lookup_nvlist(map->cmap_data, 127953548f91SRobert Mustacchi num, &nvl)) != 0) { 128053548f91SRobert Mustacchi errx(EXIT_FAILURE, "failed to look up array " 128153548f91SRobert Mustacchi "entry %u in parsed data for %s: %s", i, 128253548f91SRobert Mustacchi map->cmap_path, strerror(ret)); 128353548f91SRobert Mustacchi } 128453548f91SRobert Mustacchi 128553548f91SRobert Mustacchi if (cpcgen_skip_entry(nvl, map->cmap_path, i)) 128653548f91SRobert Mustacchi continue; 128753548f91SRobert Mustacchi 128853548f91SRobert Mustacchi if (!cpcgen_ops.cgen_op_event(f, nvl, map->cmap_path, 128953548f91SRobert Mustacchi i)) { 129053548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 129153548f91SRobert Mustacchi exit(EXIT_FAILURE); 129253548f91SRobert Mustacchi } 129353548f91SRobert Mustacchi } 129453548f91SRobert Mustacchi 129553548f91SRobert Mustacchi if (!cpcgen_ops.cgen_op_file_after(f, map)) { 129653548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 129753548f91SRobert Mustacchi exit(EXIT_FAILURE); 129853548f91SRobert Mustacchi } 129953548f91SRobert Mustacchi 130053548f91SRobert Mustacchi if (fflush(f) != 0 || fclose(f) != 0) { 130153548f91SRobert Mustacchi int e = errno; 130253548f91SRobert Mustacchi (void) unlinkat(dirfd, tmpname, 0); 130353548f91SRobert Mustacchi errno = e; 130453548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to flush and close " 130553548f91SRobert Mustacchi "temporary file"); 130653548f91SRobert Mustacchi } 130753548f91SRobert Mustacchi 130853548f91SRobert Mustacchi if (renameat(dirfd, tmpname, dirfd, name) != 0) { 130953548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to rename temporary file %s", 131053548f91SRobert Mustacchi tmpname); 131153548f91SRobert Mustacchi } 131253548f91SRobert Mustacchi 131353548f91SRobert Mustacchi free(name); 131453548f91SRobert Mustacchi free(tmpname); 131553548f91SRobert Mustacchi } 131653548f91SRobert Mustacchi } 131753548f91SRobert Mustacchi 131853548f91SRobert Mustacchi static void 131953548f91SRobert Mustacchi cpcgen_usage(const char *fmt, ...) 132053548f91SRobert Mustacchi { 132153548f91SRobert Mustacchi if (fmt != NULL) { 132253548f91SRobert Mustacchi va_list ap; 132353548f91SRobert Mustacchi 132453548f91SRobert Mustacchi (void) fprintf(stderr, "%s: ", cpcgen_progname); 132553548f91SRobert Mustacchi va_start(ap, fmt); 132653548f91SRobert Mustacchi (void) vfprintf(stderr, fmt, ap); 132753548f91SRobert Mustacchi va_end(ap); 132853548f91SRobert Mustacchi } 132953548f91SRobert Mustacchi 133053548f91SRobert Mustacchi (void) fprintf(stderr, "Usage: %s -a|-p platform -c|-H|-m -d datadir " 133153548f91SRobert Mustacchi "-o outdir\n" 133253548f91SRobert Mustacchi "\n" 133353548f91SRobert Mustacchi "\t-a generate data for all platforms\n" 133453548f91SRobert Mustacchi "\t-c generate C file for CPC\n" 133553548f91SRobert Mustacchi "\t-d specify the directory containt perfmon data\n" 133653548f91SRobert Mustacchi "\t-h generate header file and common files\n" 133753548f91SRobert Mustacchi "\t-m generate manual pages for CPC data\n" 133853548f91SRobert Mustacchi "\t-o outut files in directory outdir\n" 133953548f91SRobert Mustacchi "\t-p generate data for a specified platform\n", 134053548f91SRobert Mustacchi cpcgen_progname); 134153548f91SRobert Mustacchi } 134253548f91SRobert Mustacchi 134353548f91SRobert Mustacchi int 134453548f91SRobert Mustacchi main(int argc, char *argv[]) 134553548f91SRobert Mustacchi { 134653548f91SRobert Mustacchi int c, outdirfd; 134753548f91SRobert Mustacchi boolean_t do_mpage = B_FALSE, do_cfile = B_FALSE, do_header = B_FALSE, 134853548f91SRobert Mustacchi do_all = B_FALSE; 134953548f91SRobert Mustacchi const char *datadir = NULL, *outdir = NULL, *platform = NULL; 135053548f91SRobert Mustacchi uint_t count = 0; 135153548f91SRobert Mustacchi 135253548f91SRobert Mustacchi cpcgen_progname = basename(argv[0]); 135353548f91SRobert Mustacchi 135453548f91SRobert Mustacchi while ((c = getopt(argc, argv, ":acd:hHmo:p:")) != -1) { 135553548f91SRobert Mustacchi switch (c) { 135653548f91SRobert Mustacchi case 'a': 135753548f91SRobert Mustacchi do_all = B_TRUE; 135853548f91SRobert Mustacchi break; 135953548f91SRobert Mustacchi case 'c': 136053548f91SRobert Mustacchi do_cfile = B_TRUE; 136153548f91SRobert Mustacchi break; 136253548f91SRobert Mustacchi case 'd': 136353548f91SRobert Mustacchi datadir = optarg; 136453548f91SRobert Mustacchi break; 136553548f91SRobert Mustacchi case 'm': 136653548f91SRobert Mustacchi do_mpage = B_TRUE; 136753548f91SRobert Mustacchi break; 136853548f91SRobert Mustacchi case 'H': 136953548f91SRobert Mustacchi do_header = B_TRUE; 137053548f91SRobert Mustacchi break; 137153548f91SRobert Mustacchi case 'o': 137253548f91SRobert Mustacchi outdir = optarg; 137353548f91SRobert Mustacchi break; 137453548f91SRobert Mustacchi case 'p': 137553548f91SRobert Mustacchi platform = optarg; 137653548f91SRobert Mustacchi break; 137753548f91SRobert Mustacchi case ':': 137853548f91SRobert Mustacchi cpcgen_usage("Option -%c requires an operand\n", 137953548f91SRobert Mustacchi optopt); 138053548f91SRobert Mustacchi return (2); 138153548f91SRobert Mustacchi case '?': 138253548f91SRobert Mustacchi cpcgen_usage("Unknown option: -%c\n", optopt); 138353548f91SRobert Mustacchi return (2); 138453548f91SRobert Mustacchi case 'h': 138553548f91SRobert Mustacchi default: 138653548f91SRobert Mustacchi cpcgen_usage(NULL); 138753548f91SRobert Mustacchi return (2); 138853548f91SRobert Mustacchi } 138953548f91SRobert Mustacchi } 139053548f91SRobert Mustacchi 139153548f91SRobert Mustacchi count = 0; 139253548f91SRobert Mustacchi if (do_mpage) 139353548f91SRobert Mustacchi count++; 139453548f91SRobert Mustacchi if (do_cfile) 139553548f91SRobert Mustacchi count++; 139653548f91SRobert Mustacchi if (do_header) 139753548f91SRobert Mustacchi count++; 139853548f91SRobert Mustacchi if (count > 1) { 139953548f91SRobert Mustacchi cpcgen_usage("Only one of -c, -h, and -m may be specified\n"); 140053548f91SRobert Mustacchi return (2); 140153548f91SRobert Mustacchi } else if (count == 0) { 140253548f91SRobert Mustacchi cpcgen_usage("One of -c, -h, and -m is required\n"); 140353548f91SRobert Mustacchi return (2); 140453548f91SRobert Mustacchi } 140553548f91SRobert Mustacchi 140653548f91SRobert Mustacchi count = 0; 140753548f91SRobert Mustacchi if (do_all) 140853548f91SRobert Mustacchi count++; 140953548f91SRobert Mustacchi if (platform != NULL) 141053548f91SRobert Mustacchi count++; 141153548f91SRobert Mustacchi if (count > 1) { 141253548f91SRobert Mustacchi cpcgen_usage("Only one of -a and -p may be specified\n"); 141353548f91SRobert Mustacchi return (2); 141453548f91SRobert Mustacchi } else if (count == 0) { 141553548f91SRobert Mustacchi cpcgen_usage("One of -a and -p is required\n"); 141653548f91SRobert Mustacchi return (2); 141753548f91SRobert Mustacchi } 141853548f91SRobert Mustacchi 141953548f91SRobert Mustacchi 142053548f91SRobert Mustacchi if (outdir == NULL) { 142153548f91SRobert Mustacchi cpcgen_usage("Missing required output directory (-o)\n"); 142253548f91SRobert Mustacchi return (2); 142353548f91SRobert Mustacchi } 142453548f91SRobert Mustacchi 142553548f91SRobert Mustacchi if ((outdirfd = open(outdir, O_RDONLY)) < 0) { 142653548f91SRobert Mustacchi err(EXIT_FAILURE, "failed to open output directory %s", outdir); 142753548f91SRobert Mustacchi } 142853548f91SRobert Mustacchi 142953548f91SRobert Mustacchi if (datadir == NULL) { 143053548f91SRobert Mustacchi cpcgen_usage("Missing required data directory (-d)\n"); 143153548f91SRobert Mustacchi return (2); 143253548f91SRobert Mustacchi } 143353548f91SRobert Mustacchi 143453548f91SRobert Mustacchi cpcgen_read_mapfile(datadir, platform); 143553548f91SRobert Mustacchi 143653548f91SRobert Mustacchi if (do_header) { 143753548f91SRobert Mustacchi cpcgen_common_files(outdirfd); 143853548f91SRobert Mustacchi return (0); 143953548f91SRobert Mustacchi } 144053548f91SRobert Mustacchi 144153548f91SRobert Mustacchi if (do_mpage) { 144253548f91SRobert Mustacchi cpcgen_ops.cgen_op_name = cpcgen_manual_name; 144353548f91SRobert Mustacchi cpcgen_ops.cgen_op_file_before = cpcgen_manual_file_before; 144453548f91SRobert Mustacchi cpcgen_ops.cgen_op_file_after = cpcgen_manual_file_after; 144553548f91SRobert Mustacchi cpcgen_ops.cgen_op_event = cpcgen_manual_event; 144653548f91SRobert Mustacchi } 144753548f91SRobert Mustacchi 144853548f91SRobert Mustacchi if (do_cfile) { 144953548f91SRobert Mustacchi cpcgen_ops.cgen_op_name = cpcgen_cfile_name; 145053548f91SRobert Mustacchi cpcgen_ops.cgen_op_file_before = cpcgen_cfile_file_before; 145153548f91SRobert Mustacchi cpcgen_ops.cgen_op_file_after = cpcgen_cfile_file_after; 145253548f91SRobert Mustacchi cpcgen_ops.cgen_op_event = cpcgen_cfile_event; 145353548f91SRobert Mustacchi } 145453548f91SRobert Mustacchi 145553548f91SRobert Mustacchi 145653548f91SRobert Mustacchi cpcgen_gen(outdirfd); 145753548f91SRobert Mustacchi 145853548f91SRobert Mustacchi return (0); 145953548f91SRobert Mustacchi } 1460