cpcgen.c (c18e9bc3) cpcgen.c (d0e58ef5)
1/*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12/*
13 * Copyright (c) 2019, Joyent, Inc.
14 */
15
16/*
1/*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12/*
13 * Copyright (c) 2019, Joyent, Inc.
14 */
15
16/*
17 * This file transforms the perfmon data files into C files and manual pages.
17 * This program transforms Intel perfmon and AMD PMC data files into C files and
18 * manual pages.
18 */
19
20#include <stdio.h>
21#include <stdarg.h>
22#include <unistd.h>
23#include <err.h>
24#include <libgen.h>
25#include <libnvpair.h>
26#include <strings.h>
27#include <errno.h>
28#include <limits.h>
29#include <sys/mman.h>
30#include <sys/param.h>
31#include <assert.h>
32#include <ctype.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <fcntl.h>
19 */
20
21#include <stdio.h>
22#include <stdarg.h>
23#include <unistd.h>
24#include <err.h>
25#include <libgen.h>
26#include <libnvpair.h>
27#include <strings.h>
28#include <errno.h>
29#include <limits.h>
30#include <sys/mman.h>
31#include <sys/param.h>
32#include <assert.h>
33#include <ctype.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#include <dirent.h>
36
37#include <json_nvlist.h>
38
39#define EXIT_USAGE 2
40#define CPROC_MAX_STEPPINGS 16
41
38
39#include <json_nvlist.h>
40
41#define EXIT_USAGE 2
42#define CPROC_MAX_STEPPINGS 16
43
44typedef enum {
45 CPCGEN_MODE_UNKNOWN = 0,
46 CPCGEN_MODE_INTEL,
47 CPCGEN_MODE_AMD
48} cpc_mode_t;
49
42typedef struct cpc_proc {
43 struct cpc_proc *cproc_next;
44 uint_t cproc_family;
45 uint_t cproc_model;
46 uint_t cproc_nsteps;
47 uint_t cproc_steppings[CPROC_MAX_STEPPINGS];
48} cpc_proc_t;
49

--- 20 unchanged lines hidden (view full) ---

70 uint_t cwhite_mask;
71} cpc_whitelist_t;
72
73/*
74 * List of architectures that we support generating this data for. This is done
75 * so that processors that illumos doesn't support or run on aren't generated
76 * (generally the Xeon Phi).
77 */
50typedef struct cpc_proc {
51 struct cpc_proc *cproc_next;
52 uint_t cproc_family;
53 uint_t cproc_model;
54 uint_t cproc_nsteps;
55 uint_t cproc_steppings[CPROC_MAX_STEPPINGS];
56} cpc_proc_t;
57

--- 20 unchanged lines hidden (view full) ---

78 uint_t cwhite_mask;
79} cpc_whitelist_t;
80
81/*
82 * List of architectures that we support generating this data for. This is done
83 * so that processors that illumos doesn't support or run on aren't generated
84 * (generally the Xeon Phi).
85 */
78static cpc_whitelist_t cpcgen_whitelist[] = {
86static cpc_whitelist_t cpcgen_intel_whitelist[] = {
79 /* Nehalem */
80 { "NHM-EP", "nhm_ep", CPC_FILE_CORE },
81 { "NHM-EX", "nhm_ex", CPC_FILE_CORE },
82 /* Westmere */
83 { "WSM-EP-DP", "wsm_ep_dp", CPC_FILE_CORE },
84 { "WSM-EP-SP", "wsm_ep_sp", CPC_FILE_CORE },
85 { "WSM-EX", "wsm_ex", CPC_FILE_CORE },
86 /* Sandy Bridge */

--- 29 unchanged lines hidden (view full) ---

116
117/*
118 * This table maps events with an Intel specific name to the corresponding PAPI
119 * name. There may be multiple Intel events which map to the same PAPI event.
120 * This is usually because different processors have different names for an
121 * event. We use the title as opposed to the event codes because those can
122 * change somewhat arbitrarily between processor generations.
123 */
87 /* Nehalem */
88 { "NHM-EP", "nhm_ep", CPC_FILE_CORE },
89 { "NHM-EX", "nhm_ex", CPC_FILE_CORE },
90 /* Westmere */
91 { "WSM-EP-DP", "wsm_ep_dp", CPC_FILE_CORE },
92 { "WSM-EP-SP", "wsm_ep_sp", CPC_FILE_CORE },
93 { "WSM-EX", "wsm_ex", CPC_FILE_CORE },
94 /* Sandy Bridge */

--- 29 unchanged lines hidden (view full) ---

124
125/*
126 * This table maps events with an Intel specific name to the corresponding PAPI
127 * name. There may be multiple Intel events which map to the same PAPI event.
128 * This is usually because different processors have different names for an
129 * event. We use the title as opposed to the event codes because those can
130 * change somewhat arbitrarily between processor generations.
131 */
124static cpc_papi_t cpcgen_papi_map[] = {
132static cpc_papi_t cpcgen_intel_papi_map[] = {
125 { "CPU_CLK_UNHALTED.THREAD_P", "PAPI_tot_cyc" },
126 { "INST_RETIRED.ANY_P", "PAPI_tot_ins" },
127 { "BR_INST_RETIRED.ALL_BRANCHES", "PAPI_br_ins" },
128 { "BR_MISP_RETIRED.ALL_BRANCHES", "PAPI_br_msp" },
129 { "BR_INST_RETIRED.CONDITIONAL", "PAPI_br_cn" },
130 { "CYCLE_ACTIVITY.CYCLES_L1D_MISS", "PAPI_l1_dcm" },
131 { "L1I.HITS", "PAPI_l1_ich" },
132 { "ICACHE.HIT", "PAPI_l1_ich" },

--- 12 unchanged lines hidden (view full) ---

145 { "PAGE_WALKS.WALKS", "PAPI_tlb_tl" },
146 { "INST_QUEUE_WRITES", "PAPI_tot_iis" },
147 { "MEM_INST_RETIRED.STORES" "PAPI_sr_ins" },
148 { "MEM_INST_RETIRED.LOADS" "PAPI_ld_ins" },
149 { NULL, NULL }
150};
151
152typedef struct cpcgen_ops {
133 { "CPU_CLK_UNHALTED.THREAD_P", "PAPI_tot_cyc" },
134 { "INST_RETIRED.ANY_P", "PAPI_tot_ins" },
135 { "BR_INST_RETIRED.ALL_BRANCHES", "PAPI_br_ins" },
136 { "BR_MISP_RETIRED.ALL_BRANCHES", "PAPI_br_msp" },
137 { "BR_INST_RETIRED.CONDITIONAL", "PAPI_br_cn" },
138 { "CYCLE_ACTIVITY.CYCLES_L1D_MISS", "PAPI_l1_dcm" },
139 { "L1I.HITS", "PAPI_l1_ich" },
140 { "ICACHE.HIT", "PAPI_l1_ich" },

--- 12 unchanged lines hidden (view full) ---

153 { "PAGE_WALKS.WALKS", "PAPI_tlb_tl" },
154 { "INST_QUEUE_WRITES", "PAPI_tot_iis" },
155 { "MEM_INST_RETIRED.STORES" "PAPI_sr_ins" },
156 { "MEM_INST_RETIRED.LOADS" "PAPI_ld_ins" },
157 { NULL, NULL }
158};
159
160typedef struct cpcgen_ops {
161 void (*cgen_op_gather)(const char *, const char *);
162 void (*cgen_op_common)(int);
153 char *(*cgen_op_name)(cpc_map_t *);
163 char *(*cgen_op_name)(cpc_map_t *);
164 boolean_t (*cgen_op_skip)(nvlist_t *, const char *, uint_t);
154 boolean_t (*cgen_op_file_before)(FILE *, cpc_map_t *);
155 boolean_t (*cgen_op_file_after)(FILE *, cpc_map_t *);
156 boolean_t (*cgen_op_event)(FILE *, nvlist_t *, const char *, uint32_t);
157} cpcgen_ops_t;
158
159static cpcgen_ops_t cpcgen_ops;
165 boolean_t (*cgen_op_file_before)(FILE *, cpc_map_t *);
166 boolean_t (*cgen_op_file_after)(FILE *, cpc_map_t *);
167 boolean_t (*cgen_op_event)(FILE *, nvlist_t *, const char *, uint32_t);
168} cpcgen_ops_t;
169
170static cpcgen_ops_t cpcgen_ops;
160static const char *cpcgen_mapfile = "/mapfile.csv";
171static const char *cpcgen_intel_mapfile = "/mapfile.csv";
161static const char *cpcgen_progname;
162static cpc_map_t *cpcgen_maps;
172static const char *cpcgen_progname;
173static cpc_map_t *cpcgen_maps;
174static cpc_mode_t cpcgen_mode = CPCGEN_MODE_UNKNOWN;
163
164/*
165 * Constants used for generating data.
166 */
167/* BEGIN CSTYLED */
175
176/*
177 * Constants used for generating data.
178 */
179/* BEGIN CSTYLED */
168static const char *cpcgen_cfile_header = ""
180static const char *cpcgen_cfile_intel_header = ""
169"/*\n"
170" * Copyright (c) 2018, Intel Corporation\n"
171" * Copyright (c) 2018, Joyent, Inc\n"
172" * All rights reserved.\n"
173" *\n"
174" * Redistribution and use in source and binary forms, with or without\n"
175" * modification, are permitted provided that the following conditions are met:\n"
176" * \n"

--- 23 unchanged lines hidden (view full) ---

200" * This file was automatically generated by cpcgen from the data file\n"
201" * data/perfmon%s\n"
202" *\n"
203" * Do not modify this file. Your changes will be lost!\n"
204" */\n"
205"\n";
206/* END CSTYLED */
207
181"/*\n"
182" * Copyright (c) 2018, Intel Corporation\n"
183" * Copyright (c) 2018, Joyent, Inc\n"
184" * All rights reserved.\n"
185" *\n"
186" * Redistribution and use in source and binary forms, with or without\n"
187" * modification, are permitted provided that the following conditions are met:\n"
188" * \n"

--- 23 unchanged lines hidden (view full) ---

212" * This file was automatically generated by cpcgen from the data file\n"
213" * data/perfmon%s\n"
214" *\n"
215" * Do not modify this file. Your changes will be lost!\n"
216" */\n"
217"\n";
218/* END CSTYLED */
219
208static const char *cpcgen_cfile_table_start = ""
220static const char *cpcgen_cfile_intel_table_start = ""
209"#include <core_pcbe_table.h>\n"
210"\n"
211"const struct events_table_t pcbe_core_events_%s[] = {\n";
212
221"#include <core_pcbe_table.h>\n"
222"\n"
223"const struct events_table_t pcbe_core_events_%s[] = {\n";
224
213static const char *cpcgen_cfile_table_end = ""
225static const char *cpcgen_cfile_intel_table_end = ""
214"\t{ NT_END, 0, 0, \"\" }\n"
215"};\n";
216
217/* BEGIN CSTYLED */
226"\t{ NT_END, 0, 0, \"\" }\n"
227"};\n";
228
229/* BEGIN CSTYLED */
218static const char *cpcgen_manual_header = ""
230static const char *cpcgen_manual_intel_intel_header = ""
219".\\\" Copyright (c) 2018, Intel Corporation \n"
220".\\\" Copyright (c) 2018, Joyent, Inc.\n"
221".\\\" All rights reserved.\n"
222".\\\"\n"
223".\\\" Redistribution and use in source and binary forms, with or without \n"
224".\\\" modification, are permitted provided that the following conditions are met:\n"
225".\\\"\n"
226".\\\" 1. Redistributions of source code must retain the above copyright notice,\n"

--- 37 unchanged lines hidden (view full) ---

264"models and is derived from Intel's perfmon data.\n"
265"For more information, please consult the Intel Software Developer's Manual "
266"or Intel's perfmon website.\n"
267".Pp\n"
268"CPU models described by this document:\n"
269".Bl -bullet\n";
270/* END CSTYLED */
271
231".\\\" Copyright (c) 2018, Intel Corporation \n"
232".\\\" Copyright (c) 2018, Joyent, Inc.\n"
233".\\\" All rights reserved.\n"
234".\\\"\n"
235".\\\" Redistribution and use in source and binary forms, with or without \n"
236".\\\" modification, are permitted provided that the following conditions are met:\n"
237".\\\"\n"
238".\\\" 1. Redistributions of source code must retain the above copyright notice,\n"

--- 37 unchanged lines hidden (view full) ---

276"models and is derived from Intel's perfmon data.\n"
277"For more information, please consult the Intel Software Developer's Manual "
278"or Intel's perfmon website.\n"
279".Pp\n"
280"CPU models described by this document:\n"
281".Bl -bullet\n";
282/* END CSTYLED */
283
272static const char *cpcgen_manual_data = ""
284static const char *cpcgen_manual_intel_data = ""
273".El\n"
274".Pp\n"
275"The following events are supported:\n"
276".Bl -tag -width Sy\n";
277
285".El\n"
286".Pp\n"
287"The following events are supported:\n"
288".Bl -tag -width Sy\n";
289
278static const char *cpcgen_manual_trailer = ""
290static const char *cpcgen_manual_intel_trailer = ""
279".El\n"
280".Sh SEE ALSO\n"
281".Xr cpc 3CPC\n"
282".Pp\n"
283".Lk https://download.01.org/perfmon/index/";
284
291".El\n"
292".Sh SEE ALSO\n"
293".Xr cpc 3CPC\n"
294".Pp\n"
295".Lk https://download.01.org/perfmon/index/";
296
297static const char *cpcgen_cfile_cddl_header = ""
298"/*\n"
299" * This file and its contents are supplied under the terms of the\n"
300" * Common Development and Distribution License (\"CDDL\"), version 1.0.\n"
301" * You may only use this file in accordance with the terms of version\n"
302" * 1.0 of the CDDL.\n"
303" *\n"
304" * A full copy of the text of the CDDL should have accompanied this\n"
305" * source. A copy of the CDDL is also available via the Internet at\n"
306" * http://www.illumos.org/license/CDDL.\n"
307" */\n"
308"\n"
309"/*\n"
310" * Copyright 2019 Joyent, Inc\n"
311" */\n"
312"\n"
313"/*\n"
314" * This file was automatically generated by cpcgen.\n"
315" */\n"
316"\n"
317"/*\n"
318" * Do not modify this file. Your changes will be lost!\n"
319" */\n"
320"\n";
321
322static const char *cpcgen_manual_amd_header = ""
323".\\\" This file was automatically generated by cpcgen from the data file\n"
324".\\\" data/amdpmc/%s\n"
325".\\\"\n"
326".\\\" Do not modify this file. Your changes will be lost!\n"
327".\\\"\n"
328".\\\" We would like to thank AMD for providing the PMC data for use in\n"
329".\\\" our manual pages.\n"
330".Dd March 25, 2019\n"
331".Dt AMD_%s_EVENTS 3CPC\n"
332".Os\n"
333".Sh NAME\n"
334".Nm amd_%s_events\n"
335".Nd AMD family %s processor performance monitoring events\n"
336".Sh DESCRIPTION\n"
337"This manual page describes events specfic to AMD family %s processors.\n"
338"For more information, please consult the appropriate AMD BIOS and Kernel\n"
339"Developer's guide or Open-Source Register Reference manual.\n"
340".Pp\n"
341"Each of the events listed below includes the AMD mnemonic which matches\n"
342"the name found in the AMD manual and a brief summary of the event.\n"
343"If available, a more detailed description of the event follows and then\n"
344"any additional unit values that modify the event.\n"
345"Each unit can be combined to create a new event in the system by placing\n"
346"the '.' character between the event name and the unit name.\n"
347".Pp\n"
348"The following events are supported:\n"
349".Bl -tag -width Sy\n";
350
351static const char *cpcgen_manual_amd_trailer = ""
352".El\n"
353".Sh SEE ALSO\n"
354".Xr cpc 3CPC\n";
355
356static const char *cpcgen_cfile_amd_header = ""
357"/*\n"
358" * This file was automatically generated by cpcgen from the data file\n"
359" * data/perfmon%s\n"
360" *\n"
361" * Do not modify this file. Your changes will be lost!\n"
362" */\n"
363"\n";
364
365static const char *cpcgen_cfile_amd_table_start = ""
366"#include <opteron_pcbe_table.h>\n"
367"#include <sys/null.h>\n"
368"\n"
369"const amd_event_t opteron_pcbe_%s_events[] = {\n";
370
371static const char *cpcgen_cfile_amd_table_end = ""
372"\t{ NULL, 0, 0 }\n"
373"};\n";
374
285static cpc_map_t *
286cpcgen_map_lookup(const char *path)
287{
288 cpc_map_t *m;
289
290 for (m = cpcgen_maps; m != NULL; m = m->cmap_next) {
291 if (strcmp(path, m->cmap_path) == 0) {
292 return (m);

--- 198 unchanged lines hidden (view full) ---

491 if ((slash = strchr(path + 1, '/')) == NULL) {
492 errx(EXIT_FAILURE, "invalid path in mapfile: \"%s\": missing "
493 "second '/'", path);
494 }
495 /* Account for the last '/' character. */
496 len = slash - path - 1;
497 assert(len > 0);
498
375static cpc_map_t *
376cpcgen_map_lookup(const char *path)
377{
378 cpc_map_t *m;
379
380 for (m = cpcgen_maps; m != NULL; m = m->cmap_next) {
381 if (strcmp(path, m->cmap_path) == 0) {
382 return (m);

--- 198 unchanged lines hidden (view full) ---

581 if ((slash = strchr(path + 1, '/')) == NULL) {
582 errx(EXIT_FAILURE, "invalid path in mapfile: \"%s\": missing "
583 "second '/'", path);
584 }
585 /* Account for the last '/' character. */
586 len = slash - path - 1;
587 assert(len > 0);
588
499 for (i = 0; cpcgen_whitelist[i].cwhite_short != NULL; i++) {
589 for (i = 0; cpcgen_intel_whitelist[i].cwhite_short != NULL; i++) {
500 if (platform != NULL && strcasecmp(platform,
590 if (platform != NULL && strcasecmp(platform,
501 cpcgen_whitelist[i].cwhite_short) != 0)
591 cpcgen_intel_whitelist[i].cwhite_short) != 0)
502 continue;
592 continue;
503 if (strncmp(path + 1, cpcgen_whitelist[i].cwhite_short,
593 if (strncmp(path + 1, cpcgen_intel_whitelist[i].cwhite_short,
504 len) == 0 &&
594 len) == 0 &&
505 (cpcgen_whitelist[i].cwhite_mask & type) == type) {
506 return (cpcgen_whitelist[i].cwhite_human);
595 (cpcgen_intel_whitelist[i].cwhite_mask & type) == type) {
596 return (cpcgen_intel_whitelist[i].cwhite_human);
507 }
508 }
509
510 return (NULL);
511}
512
513/*
597 }
598 }
599
600 return (NULL);
601}
602
603/*
604 * Determine which CPU Vendor we're transmuting data from.
605 */
606static void
607cpcgen_determine_vendor(const char *datadir)
608{
609 char *mappath;
610 struct stat st;
611
612 if (asprintf(&mappath, "%s/%s", datadir, cpcgen_intel_mapfile) == -1) {
613 err(EXIT_FAILURE, "failed to construct path to mapfile");
614 }
615
616 if (stat(mappath, &st) == 0) {
617 cpcgen_mode = CPCGEN_MODE_INTEL;
618 } else {
619 if (errno != ENOENT) {
620 err(EXIT_FAILURE, "stat(2) of %s failed unexpectedly");
621 }
622
623 cpcgen_mode = CPCGEN_MODE_AMD;
624 }
625
626 free(mappath);
627}
628
629/*
630 * Read in all the data files that exist for AMD.
631 *
632 * Our family names for AMD systems are based on the family and type so a given
633 * name will look like f17h_core.json.
634 */
635static void
636cpcgen_read_amd(const char *datadir, const char *platform)
637{
638 DIR *dir;
639 struct dirent *d;
640 const char *suffix = ".json";
641 const size_t slen = strlen(suffix);
642
643 if ((dir = opendir(datadir)) == NULL) {
644 err(EXIT_FAILURE, "failed to open directory %s", datadir);
645 }
646
647 while ((d = readdir(dir)) != NULL) {
648 char *name, *c;
649 cpc_map_t *map;
650 nvlist_t *parsed;
651
652 if ((name = strdup(d->d_name)) == NULL) {
653 errx(EXIT_FAILURE, "ran out of memory duplicating "
654 "name %s", d->d_name);
655 }
656 c = strstr(name, suffix);
657
658 if (c == NULL) {
659 free(name);
660 continue;
661 }
662
663 if (*(c + slen) != '\0') {
664 free(name);
665 continue;
666 }
667
668 *c = '\0';
669 c = strchr(name, '_');
670 if (c == NULL) {
671 free(name);
672 continue;
673 }
674 *c = '\0';
675 c++;
676 if (strcmp(c, "core") != 0) {
677 errx(EXIT_FAILURE, "unexpected AMD JSON file name: %s",
678 d->d_name);
679 }
680
681 if (platform != NULL && strcmp(platform, name) != 0) {
682 free(name);
683 continue;
684 }
685
686 if ((map = calloc(1, sizeof (cpc_map_t))) == NULL) {
687 err(EXIT_FAILURE, "failed to allocate space for cpc "
688 "file");
689 }
690
691 parsed = cpcgen_read_datafile(datadir, d->d_name);
692 if ((map->cmap_path = strdup(d->d_name)) == NULL) {
693 err(EXIT_FAILURE, "failed to duplicate path string");
694 }
695 map->cmap_type = CPC_FILE_CORE;
696 map->cmap_data = parsed;
697 map->cmap_name = name;
698 map->cmap_procs = NULL;
699
700 map->cmap_next = cpcgen_maps;
701 cpcgen_maps = map;
702 }
703}
704
705/*
514 * Read in the mapfile.csv that is used to map between processor families and
515 * parse this. Each line has a comma separated value.
516 */
517static void
706 * Read in the mapfile.csv that is used to map between processor families and
707 * parse this. Each line has a comma separated value.
708 */
709static void
518cpcgen_read_mapfile(const char *datadir, const char *platform)
710cpcgen_read_intel(const char *datadir, const char *platform)
519{
520 FILE *map;
521 char *mappath, *last;
522 char *data = NULL;
523 size_t datalen = 0;
524 uint_t lineno;
525
711{
712 FILE *map;
713 char *mappath, *last;
714 char *data = NULL;
715 size_t datalen = 0;
716 uint_t lineno;
717
526 if (asprintf(&mappath, "%s/%s", datadir, cpcgen_mapfile) == -1) {
718 if (asprintf(&mappath, "%s/%s", datadir, cpcgen_intel_mapfile) == -1) {
527 err(EXIT_FAILURE, "failed to construct path to mapfile");
528 }
529
530 if ((map = fopen(mappath, "r")) == NULL) {
531 err(EXIT_FAILURE, "failed to open data mapfile %s", mappath);
532 }
533
534 lineno = 0;

--- 56 unchanged lines hidden (view full) ---

591
592 if ((map->cmap_path = strdup(path)) == NULL) {
593 err(EXIT_FAILURE, "failed to duplicate path "
594 "string");
595 }
596
597 map->cmap_type = type;
598 map->cmap_data = parsed;
719 err(EXIT_FAILURE, "failed to construct path to mapfile");
720 }
721
722 if ((map = fopen(mappath, "r")) == NULL) {
723 err(EXIT_FAILURE, "failed to open data mapfile %s", mappath);
724 }
725
726 lineno = 0;

--- 56 unchanged lines hidden (view full) ---

783
784 if ((map->cmap_path = strdup(path)) == NULL) {
785 err(EXIT_FAILURE, "failed to duplicate path "
786 "string");
787 }
788
789 map->cmap_type = type;
790 map->cmap_data = parsed;
599 map->cmap_next = cpcgen_maps;
600 map->cmap_name = name;
601 map->cmap_procs = NULL;
791 map->cmap_name = name;
792 map->cmap_procs = NULL;
793
794 map->cmap_next = cpcgen_maps;
602 cpcgen_maps = map;
603 }
604
605 if ((proc = calloc(1, sizeof (cpc_proc_t))) == NULL) {
606 err(EXIT_FAILURE, "failed to allocate memory for "
607 "family and model tracking");
608 }
609

--- 15 unchanged lines hidden (view full) ---

625 if (fclose(map) == EOF) {
626 err(EXIT_FAILURE, "failed to close %s", mappath);
627 }
628 free(data);
629 free(mappath);
630}
631
632static char *
795 cpcgen_maps = map;
796 }
797
798 if ((proc = calloc(1, sizeof (cpc_proc_t))) == NULL) {
799 err(EXIT_FAILURE, "failed to allocate memory for "
800 "family and model tracking");
801 }
802

--- 15 unchanged lines hidden (view full) ---

818 if (fclose(map) == EOF) {
819 err(EXIT_FAILURE, "failed to close %s", mappath);
820 }
821 free(data);
822 free(mappath);
823}
824
825static char *
633cpcgen_manual_name(cpc_map_t *map)
826cpcgen_manual_intel_name(cpc_map_t *map)
634{
635 char *name;
636
637 if (asprintf(&name, "%s_events.3cpc", map->cmap_name) == -1) {
638 warn("failed to assemble manual page name for %s",
639 map->cmap_path);
640 return (NULL);
641 }
642
643 return (name);
644}
645
646static boolean_t
827{
828 char *name;
829
830 if (asprintf(&name, "%s_events.3cpc", map->cmap_name) == -1) {
831 warn("failed to assemble manual page name for %s",
832 map->cmap_path);
833 return (NULL);
834 }
835
836 return (name);
837}
838
839static boolean_t
647cpcgen_manual_file_before(FILE *f, cpc_map_t *map)
840cpcgen_manual_intel_file_before(FILE *f, cpc_map_t *map)
648{
649 size_t i;
650 char *upper;
651 cpc_proc_t *proc;
652
653 if ((upper = strdup(map->cmap_name)) == NULL) {
654 warn("failed to duplicate manual name for %s", map->cmap_name);
655 return (B_FALSE);
656 }
657
658 for (i = 0; upper[i] != '\0'; i++) {
659 upper[i] = toupper(upper[i]);
660 }
661
841{
842 size_t i;
843 char *upper;
844 cpc_proc_t *proc;
845
846 if ((upper = strdup(map->cmap_name)) == NULL) {
847 warn("failed to duplicate manual name for %s", map->cmap_name);
848 return (B_FALSE);
849 }
850
851 for (i = 0; upper[i] != '\0'; i++) {
852 upper[i] = toupper(upper[i]);
853 }
854
662 if (fprintf(f, cpcgen_manual_header, map->cmap_path, upper,
855 if (fprintf(f, cpcgen_manual_intel_intel_header, map->cmap_path, upper,
663 map->cmap_name) == -1) {
664 warn("failed to write out manual header for %s",
665 map->cmap_name);
666 free(upper);
667 return (B_FALSE);
668 }
856 map->cmap_name) == -1) {
857 warn("failed to write out manual header for %s",
858 map->cmap_name);
859 free(upper);
860 return (B_FALSE);
861 }
862 free(upper);
669
670 for (proc = map->cmap_procs; proc != NULL; proc = proc->cproc_next) {
671 if (proc->cproc_nsteps > 0) {
672 uint_t step;
673
674 for (step = 0; step < proc->cproc_nsteps; step++) {
675 if (fprintf(f, ".It\n.Sy Family 0x%x, Model "
676 "0x%x, Stepping 0x%x\n",
677 proc->cproc_family, proc->cproc_model,
678 proc->cproc_steppings[step]) == -1) {
679 warn("failed to write out model "
680 "information for %s",
681 map->cmap_name);
863
864 for (proc = map->cmap_procs; proc != NULL; proc = proc->cproc_next) {
865 if (proc->cproc_nsteps > 0) {
866 uint_t step;
867
868 for (step = 0; step < proc->cproc_nsteps; step++) {
869 if (fprintf(f, ".It\n.Sy Family 0x%x, Model "
870 "0x%x, Stepping 0x%x\n",
871 proc->cproc_family, proc->cproc_model,
872 proc->cproc_steppings[step]) == -1) {
873 warn("failed to write out model "
874 "information for %s",
875 map->cmap_name);
682 free(upper);
683 return (B_FALSE);
684 }
685 }
686 } else {
687 if (fprintf(f, ".It\n.Sy Family 0x%x, Model 0x%x\n",
688 proc->cproc_family, proc->cproc_model) == -1) {
689 warn("failed to write out model information "
690 "for %s", map->cmap_name);
876 return (B_FALSE);
877 }
878 }
879 } else {
880 if (fprintf(f, ".It\n.Sy Family 0x%x, Model 0x%x\n",
881 proc->cproc_family, proc->cproc_model) == -1) {
882 warn("failed to write out model information "
883 "for %s", map->cmap_name);
691 free(upper);
692 return (B_FALSE);
693 }
694 }
695 }
696
884 return (B_FALSE);
885 }
886 }
887 }
888
697 if (fprintf(f, cpcgen_manual_data, map->cmap_path, upper,
698 map->cmap_name) == -1) {
889 if (fprintf(f, cpcgen_manual_intel_data) == -1) {
699 warn("failed to write out manual header for %s",
700 map->cmap_name);
890 warn("failed to write out manual header for %s",
891 map->cmap_name);
701 free(upper);
702 return (B_FALSE);
703 }
704
705 free(upper);
706 return (B_TRUE);
707}
708
709static boolean_t
892 return (B_FALSE);
893 }
894
895 free(upper);
896 return (B_TRUE);
897}
898
899static boolean_t
710cpcgen_manual_file_after(FILE *f, cpc_map_t *map)
900cpcgen_manual_intel_file_after(FILE *f, cpc_map_t *map)
711{
901{
712 if (fprintf(f, cpcgen_manual_trailer) == -1) {
902 if (fprintf(f, cpcgen_manual_intel_trailer) == -1) {
713 warn("failed to write out manual header for %s",
714 map->cmap_name);
715 return (B_FALSE);
716 }
717
718 return (B_TRUE);
719}
720
721static boolean_t
903 warn("failed to write out manual header for %s",
904 map->cmap_name);
905 return (B_FALSE);
906 }
907
908 return (B_TRUE);
909}
910
911static boolean_t
722cpcgen_manual_event(FILE *f, nvlist_t *nvl, const char *path, uint32_t ent)
912cpcgen_manual_intel_event(FILE *f, nvlist_t *nvl, const char *path,
913 uint32_t ent)
723{
724 char *event, *lname, *brief = NULL, *public = NULL, *errata = NULL;
725 size_t i;
726
727 if (nvlist_lookup_string(nvl, "EventName", &event) != 0) {
728 warnx("Found event without 'EventName' property "
729 "in %s, entry %u", path, ent);
730 return (B_FALSE);

--- 17 unchanged lines hidden (view full) ---

748 (void) nvlist_lookup_string(nvl, "PublicDescription", &public);
749 (void) nvlist_lookup_string(nvl, "Errata", &errata);
750 if (errata != NULL && (strcmp(errata, "0") == 0 ||
751 strcmp(errata, "null") == 0)) {
752 errata = NULL;
753 }
754
755 if (fprintf(f, ".It Sy %s\n", lname) == -1) {
914{
915 char *event, *lname, *brief = NULL, *public = NULL, *errata = NULL;
916 size_t i;
917
918 if (nvlist_lookup_string(nvl, "EventName", &event) != 0) {
919 warnx("Found event without 'EventName' property "
920 "in %s, entry %u", path, ent);
921 return (B_FALSE);

--- 17 unchanged lines hidden (view full) ---

939 (void) nvlist_lookup_string(nvl, "PublicDescription", &public);
940 (void) nvlist_lookup_string(nvl, "Errata", &errata);
941 if (errata != NULL && (strcmp(errata, "0") == 0 ||
942 strcmp(errata, "null") == 0)) {
943 errata = NULL;
944 }
945
946 if (fprintf(f, ".It Sy %s\n", lname) == -1) {
756 warn("failed to write out probe entry %s", event);
947 warn("failed to write out event entry %s", event);
757 free(lname);
758 return (B_FALSE);
759 }
760
761 if (public != NULL) {
762 if (fprintf(f, "%s\n", public) == -1) {
948 free(lname);
949 return (B_FALSE);
950 }
951
952 if (public != NULL) {
953 if (fprintf(f, "%s\n", public) == -1) {
763 warn("failed to write out probe entry %s", event);
954 warn("failed to write out event entry %s", event);
764 free(lname);
765 return (B_FALSE);
766 }
767 } else if (brief != NULL) {
768 if (fprintf(f, "%s\n", brief) == -1) {
955 free(lname);
956 return (B_FALSE);
957 }
958 } else if (brief != NULL) {
959 if (fprintf(f, "%s\n", brief) == -1) {
769 warn("failed to write out probe entry %s", event);
960 warn("failed to write out event entry %s", event);
770 free(lname);
771 return (B_FALSE);
772 }
773 }
774
775 if (errata != NULL) {
776 if (fprintf(f, ".Pp\nThe following errata may apply to this: "
777 "%s\n", errata) == -1) {
778
961 free(lname);
962 return (B_FALSE);
963 }
964 }
965
966 if (errata != NULL) {
967 if (fprintf(f, ".Pp\nThe following errata may apply to this: "
968 "%s\n", errata) == -1) {
969
779 warn("failed to write out probe entry %s", event);
970 warn("failed to write out event entry %s", event);
780 free(lname);
781 return (B_FALSE);
782 }
783 }
784
785 free(lname);
786 return (B_TRUE);
787}
788
789static char *
971 free(lname);
972 return (B_FALSE);
973 }
974 }
975
976 free(lname);
977 return (B_TRUE);
978}
979
980static char *
790cpcgen_cfile_name(cpc_map_t *map)
981cpcgen_cfile_intel_name(cpc_map_t *map)
791{
792 char *name;
793
794 if (asprintf(&name, "core_pcbe_%s.c", map->cmap_name) == -1) {
795 warn("failed to assemble file name for %s", map->cmap_path);
796 return (NULL);
797 }
798
799 return (name);
800}
801
802static boolean_t
982{
983 char *name;
984
985 if (asprintf(&name, "core_pcbe_%s.c", map->cmap_name) == -1) {
986 warn("failed to assemble file name for %s", map->cmap_path);
987 return (NULL);
988 }
989
990 return (name);
991}
992
993static boolean_t
803cpcgen_cfile_file_before(FILE *f, cpc_map_t *map)
994cpcgen_cfile_intel_before(FILE *f, cpc_map_t *map)
804{
995{
805 if (fprintf(f, cpcgen_cfile_header, map->cmap_path) == -1) {
996 if (fprintf(f, cpcgen_cfile_intel_header, map->cmap_path) == -1) {
806 warn("failed to write header to temporary file for %s",
807 map->cmap_path);
808 return (B_FALSE);
809 }
810
997 warn("failed to write header to temporary file for %s",
998 map->cmap_path);
999 return (B_FALSE);
1000 }
1001
811 if (fprintf(f, cpcgen_cfile_table_start, map->cmap_name) == -1) {
1002 if (fprintf(f, cpcgen_cfile_intel_table_start, map->cmap_name) == -1) {
812 warn("failed to write header to temporary file for %s",
813 map->cmap_path);
814 return (B_FALSE);
815 }
816
817 return (B_TRUE);
818}
819
820static boolean_t
1003 warn("failed to write header to temporary file for %s",
1004 map->cmap_path);
1005 return (B_FALSE);
1006 }
1007
1008 return (B_TRUE);
1009}
1010
1011static boolean_t
821cpcgen_cfile_file_after(FILE *f, cpc_map_t *map)
1012cpcgen_cfile_intel_after(FILE *f, cpc_map_t *map)
822{
1013{
823 if (fprintf(f, cpcgen_cfile_table_end) == -1) {
1014 if (fprintf(f, cpcgen_cfile_intel_table_end) == -1) {
824 warn("failed to write footer to temporary file for %s",
825 map->cmap_path);
826 return (B_FALSE);
827 }
828
829 return (B_TRUE);
830}
831
832static boolean_t
1015 warn("failed to write footer to temporary file for %s",
1016 map->cmap_path);
1017 return (B_FALSE);
1018 }
1019
1020 return (B_TRUE);
1021}
1022
1023static boolean_t
833cpcgen_cfile_event(FILE *f, nvlist_t *nvl, const char *path, uint_t ent)
1024cpcgen_cfile_intel_event(FILE *f, nvlist_t *nvl, const char *path, uint_t ent)
834{
835 char *ecode, *umask, *name, *counter, *lname, *cmask;
836 size_t i;
837
838 if (nvlist_lookup_string(nvl, "EventName", &name) != 0) {
839 warnx("Found event without 'EventName' property "
840 "in %s, entry %u", path, ent);
841 return (B_FALSE);

--- 56 unchanged lines hidden (view full) ---

898 return (B_FALSE);
899 }
900
901 free(lname);
902
903 /*
904 * Check if we have any PAPI aliases.
905 */
1025{
1026 char *ecode, *umask, *name, *counter, *lname, *cmask;
1027 size_t i;
1028
1029 if (nvlist_lookup_string(nvl, "EventName", &name) != 0) {
1030 warnx("Found event without 'EventName' property "
1031 "in %s, entry %u", path, ent);
1032 return (B_FALSE);

--- 56 unchanged lines hidden (view full) ---

1089 return (B_FALSE);
1090 }
1091
1092 free(lname);
1093
1094 /*
1095 * Check if we have any PAPI aliases.
1096 */
906 for (i = 0; cpcgen_papi_map[i].cpapi_intc != NULL; i++) {
907 if (strcmp(name, cpcgen_papi_map[i].cpapi_intc) != 0)
1097 for (i = 0; cpcgen_intel_papi_map[i].cpapi_intc != NULL; i++) {
1098 if (strcmp(name, cpcgen_intel_papi_map[i].cpapi_intc) != 0)
908 continue;
909
910 if (fprintf(f, "\t{ %s, %s, %s, \"%s\" },\n", ecode, umask,
1099 continue;
1100
1101 if (fprintf(f, "\t{ %s, %s, %s, \"%s\" },\n", ecode, umask,
911 cmask, cpcgen_papi_map[i].cpapi_papi) == -1) {
1102 cmask, cpcgen_intel_papi_map[i].cpapi_papi) == -1) {
912 warn("failed to write out entry %s from %s", name,
913 path);
914 return (B_FALSE);
915 }
916 }
917
918 return (B_TRUE);
919}

--- 52 unchanged lines hidden (view full) ---

972 map->cmap_name) == -1) {
973 return (B_FALSE);
974 }
975
976 return (B_TRUE);
977}
978
979/*
1103 warn("failed to write out entry %s from %s", name,
1104 path);
1105 return (B_FALSE);
1106 }
1107 }
1108
1109 return (B_TRUE);
1110}

--- 52 unchanged lines hidden (view full) ---

1163 map->cmap_name) == -1) {
1164 return (B_FALSE);
1165 }
1166
1167 return (B_TRUE);
1168}
1169
1170/*
1171 * This is a wrapper around unlinkat that makes sure that we don't clobber
1172 * errno, which is used for properly printing out error messages below.
1173 */
1174static void
1175cpcgen_remove_tmpfile(int dirfd, const char *path)
1176{
1177 int e = errno;
1178 (void) unlinkat(dirfd, path, 0);
1179 errno = e;
1180}
1181
1182/*
980 * Generate a header file that declares all of these arrays and provide a map
981 * for models to the corresponding table to use.
982 */
983static void
1183 * Generate a header file that declares all of these arrays and provide a map
1184 * for models to the corresponding table to use.
1185 */
1186static void
984cpcgen_common_files(int dirfd)
1187cpcgen_common_intel_files(int dirfd)
985{
986 const char *fname = "core_pcbe_cpcgen.h";
987 char *tmpname;
988 int fd;
989 FILE *f;
990 cpc_map_t *map;
991
992 if (asprintf(&tmpname, ".%s.%d", fname, getpid()) == -1) {
993 err(EXIT_FAILURE, "failed to construct temporary file name");
994 }
995
996 if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) {
997 err(EXIT_FAILURE, "failed to create temporary file %s",
998 tmpname);
999 }
1000
1001 if ((f = fdopen(fd, "w")) == NULL) {
1188{
1189 const char *fname = "core_pcbe_cpcgen.h";
1190 char *tmpname;
1191 int fd;
1192 FILE *f;
1193 cpc_map_t *map;
1194
1195 if (asprintf(&tmpname, ".%s.%d", fname, getpid()) == -1) {
1196 err(EXIT_FAILURE, "failed to construct temporary file name");
1197 }
1198
1199 if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) {
1200 err(EXIT_FAILURE, "failed to create temporary file %s",
1201 tmpname);
1202 }
1203
1204 if ((f = fdopen(fd, "w")) == NULL) {
1002 int e = errno;
1003 (void) unlinkat(dirfd, tmpname, 0);
1004 errno = e;
1205 cpcgen_remove_tmpfile(dirfd, tmpname);
1005 err(EXIT_FAILURE, "failed to fdopen temporary file");
1006 }
1007
1206 err(EXIT_FAILURE, "failed to fdopen temporary file");
1207 }
1208
1008 if (fprintf(f, cpcgen_cfile_header, cpcgen_mapfile) == -1) {
1009 int e = errno;
1010 (void) unlinkat(dirfd, tmpname, 0);
1011 errno = e;
1209 if (fprintf(f, cpcgen_cfile_intel_header, cpcgen_intel_mapfile) == -1) {
1210 cpcgen_remove_tmpfile(dirfd, tmpname);
1012 errx(EXIT_FAILURE, "failed to write header to temporary file "
1013 "for %s", fname);
1014 }
1015
1016 if (fprintf(f, "#ifndef _CORE_PCBE_CPCGEN_H\n"
1017 "#define\t_CORE_PCBE_CPCGEN_H\n"
1018 "\n"
1019 "#ifdef __cplusplus\n"
1020 "extern \"C\" {\n"
1021 "#endif\n"
1022 "\n"
1023 "extern const struct events_table_t *core_cpcgen_table(uint_t, "
1024 "uint_t);\n"
1025 "\n") == -1) {
1211 errx(EXIT_FAILURE, "failed to write header to temporary file "
1212 "for %s", fname);
1213 }
1214
1215 if (fprintf(f, "#ifndef _CORE_PCBE_CPCGEN_H\n"
1216 "#define\t_CORE_PCBE_CPCGEN_H\n"
1217 "\n"
1218 "#ifdef __cplusplus\n"
1219 "extern \"C\" {\n"
1220 "#endif\n"
1221 "\n"
1222 "extern const struct events_table_t *core_cpcgen_table(uint_t, "
1223 "uint_t);\n"
1224 "\n") == -1) {
1026 int e = errno;
1027 (void) unlinkat(dirfd, tmpname, 0);
1028 errno = e;
1225 cpcgen_remove_tmpfile(dirfd, tmpname);
1029 errx(EXIT_FAILURE, "failed to write header to "
1030 "temporary file for %s", fname);
1031 }
1032
1033 for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
1034 if (fprintf(f, "extern const struct events_table_t "
1035 "pcbe_core_events_%s[];\n", map->cmap_name) == -1) {
1226 errx(EXIT_FAILURE, "failed to write header to "
1227 "temporary file for %s", fname);
1228 }
1229
1230 for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
1231 if (fprintf(f, "extern const struct events_table_t "
1232 "pcbe_core_events_%s[];\n", map->cmap_name) == -1) {
1036 int e = errno;
1037 (void) unlinkat(dirfd, tmpname, 0);
1038 errno = e;
1233 cpcgen_remove_tmpfile(dirfd, tmpname);
1039 errx(EXIT_FAILURE, "failed to write entry to "
1040 "temporary file for %s", fname);
1041 }
1042 }
1043
1044 if (fprintf(f, "\n"
1045 "#ifdef __cplusplus\n"
1046 "}\n"
1047 "#endif\n"
1048 "\n"
1049 "#endif /* _CORE_PCBE_CPCGEN_H */\n") == -1) {
1234 errx(EXIT_FAILURE, "failed to write entry to "
1235 "temporary file for %s", fname);
1236 }
1237 }
1238
1239 if (fprintf(f, "\n"
1240 "#ifdef __cplusplus\n"
1241 "}\n"
1242 "#endif\n"
1243 "\n"
1244 "#endif /* _CORE_PCBE_CPCGEN_H */\n") == -1) {
1050 int e = errno;
1051 (void) unlinkat(dirfd, tmpname, 0);
1052 errno = e;
1245 cpcgen_remove_tmpfile(dirfd, tmpname);
1053 errx(EXIT_FAILURE, "failed to write header to "
1054 "temporary file for %s", fname);
1055 }
1056
1057 if (fflush(f) != 0 || fclose(f) != 0) {
1246 errx(EXIT_FAILURE, "failed to write header to "
1247 "temporary file for %s", fname);
1248 }
1249
1250 if (fflush(f) != 0 || fclose(f) != 0) {
1058 int e = errno;
1059 (void) unlinkat(dirfd, tmpname, 0);
1060 errno = e;
1251 cpcgen_remove_tmpfile(dirfd, tmpname);
1061 err(EXIT_FAILURE, "failed to flush and close temporary file");
1062 }
1063
1064 if (renameat(dirfd, tmpname, dirfd, fname) != 0) {
1065 err(EXIT_FAILURE, "failed to rename temporary file %s",
1066 tmpname);
1067 }
1068

--- 6 unchanged lines hidden (view full) ---

1075 }
1076
1077 if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) {
1078 err(EXIT_FAILURE, "failed to create temporary file %s",
1079 tmpname);
1080 }
1081
1082 if ((f = fdopen(fd, "w")) == NULL) {
1252 err(EXIT_FAILURE, "failed to flush and close temporary file");
1253 }
1254
1255 if (renameat(dirfd, tmpname, dirfd, fname) != 0) {
1256 err(EXIT_FAILURE, "failed to rename temporary file %s",
1257 tmpname);
1258 }
1259

--- 6 unchanged lines hidden (view full) ---

1266 }
1267
1268 if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) {
1269 err(EXIT_FAILURE, "failed to create temporary file %s",
1270 tmpname);
1271 }
1272
1273 if ((f = fdopen(fd, "w")) == NULL) {
1083 int e = errno;
1084 (void) unlinkat(dirfd, tmpname, 0);
1085 errno = e;
1274 cpcgen_remove_tmpfile(dirfd, tmpname);
1086 err(EXIT_FAILURE, "failed to fdopen temporary file");
1087 }
1088
1275 err(EXIT_FAILURE, "failed to fdopen temporary file");
1276 }
1277
1089 if (fprintf(f, cpcgen_cfile_header, cpcgen_mapfile) == -1) {
1090 int e = errno;
1091 (void) unlinkat(dirfd, tmpname, 0);
1092 errno = e;
1278 if (fprintf(f, cpcgen_cfile_intel_header, cpcgen_intel_mapfile) == -1) {
1279 cpcgen_remove_tmpfile(dirfd, tmpname);
1093 errx(EXIT_FAILURE, "failed to write header to temporary file "
1094 "for %s", fname);
1095 }
1096
1097 if (fprintf(f, "#include <core_pcbe_table.h>\n"
1098 "#include <sys/null.h>\n"
1099 "#include \"core_pcbe_cpcgen.h\"\n"
1100 "\n"
1101 "const struct events_table_t *\n"
1102 "core_cpcgen_table(uint_t model, uint_t stepping)\n"
1103 "{\n") == -1) {
1280 errx(EXIT_FAILURE, "failed to write header to temporary file "
1281 "for %s", fname);
1282 }
1283
1284 if (fprintf(f, "#include <core_pcbe_table.h>\n"
1285 "#include <sys/null.h>\n"
1286 "#include \"core_pcbe_cpcgen.h\"\n"
1287 "\n"
1288 "const struct events_table_t *\n"
1289 "core_cpcgen_table(uint_t model, uint_t stepping)\n"
1290 "{\n") == -1) {
1104 int e = errno;
1105 (void) unlinkat(dirfd, tmpname, 0);
1106 errno = e;
1291 cpcgen_remove_tmpfile(dirfd, tmpname);
1107 errx(EXIT_FAILURE, "failed to write header to "
1108 "temporary file for %s", fname);
1109 }
1110
1111 for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
1112 if (!cpcgen_generate_map(f, map, map == cpcgen_maps)) {
1292 errx(EXIT_FAILURE, "failed to write header to "
1293 "temporary file for %s", fname);
1294 }
1295
1296 for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
1297 if (!cpcgen_generate_map(f, map, map == cpcgen_maps)) {
1113 int e = errno;
1114 (void) unlinkat(dirfd, tmpname, 0);
1115 errno = e;
1298 cpcgen_remove_tmpfile(dirfd, tmpname);
1116 errx(EXIT_FAILURE, "failed to write to temporary "
1117 "file for %s", fname);
1118 }
1119 }
1120
1121 if (fprintf(f, "\t} else {\n"
1122 "\t\t\treturn (NULL);\n"
1123 "\t}\n"
1124 "}\n") == -1) {
1299 errx(EXIT_FAILURE, "failed to write to temporary "
1300 "file for %s", fname);
1301 }
1302 }
1303
1304 if (fprintf(f, "\t} else {\n"
1305 "\t\t\treturn (NULL);\n"
1306 "\t}\n"
1307 "}\n") == -1) {
1125 int e = errno;
1126 (void) unlinkat(dirfd, tmpname, 0);
1127 errno = e;
1308 cpcgen_remove_tmpfile(dirfd, tmpname);
1128 errx(EXIT_FAILURE, "failed to write header to "
1129 "temporary file for %s", fname);
1130 }
1131
1132 if (fflush(f) != 0 || fclose(f) != 0) {
1309 errx(EXIT_FAILURE, "failed to write header to "
1310 "temporary file for %s", fname);
1311 }
1312
1313 if (fflush(f) != 0 || fclose(f) != 0) {
1133 int e = errno;
1134 (void) unlinkat(dirfd, tmpname, 0);
1135 errno = e;
1314 cpcgen_remove_tmpfile(dirfd, tmpname);
1136 err(EXIT_FAILURE, "failed to flush and close temporary file");
1137 }
1138
1139 if (renameat(dirfd, tmpname, dirfd, fname) != 0) {
1140 err(EXIT_FAILURE, "failed to rename temporary file %s",
1141 tmpname);
1142 }
1143

--- 12 unchanged lines hidden (view full) ---

1156 * - TakenAlone is non-zero, which means that it cannot run at the same time as
1157 * another field.
1158 * - Offcore is one, indicating that it is off the core and we need to figure
1159 * out if we can support this.
1160 * - If the counter is fixed, don't use it for now.
1161 * - If more than one value is specified in the EventCode or UMask values
1162 */
1163static boolean_t
1315 err(EXIT_FAILURE, "failed to flush and close temporary file");
1316 }
1317
1318 if (renameat(dirfd, tmpname, dirfd, fname) != 0) {
1319 err(EXIT_FAILURE, "failed to rename temporary file %s",
1320 tmpname);
1321 }
1322

--- 12 unchanged lines hidden (view full) ---

1335 * - TakenAlone is non-zero, which means that it cannot run at the same time as
1336 * another field.
1337 * - Offcore is one, indicating that it is off the core and we need to figure
1338 * out if we can support this.
1339 * - If the counter is fixed, don't use it for now.
1340 * - If more than one value is specified in the EventCode or UMask values
1341 */
1342static boolean_t
1164cpcgen_skip_entry(nvlist_t *nvl, const char *path, uint_t ent)
1343cpcgen_skip_intel_entry(nvlist_t *nvl, const char *path, uint_t ent)
1165{
1166 char *event, *msridx, *msrval, *taken, *offcore, *counter;
1167 char *ecode, *umask;
1168
1169 /*
1170 * Require EventName, it's kind of useless without that.
1171 */
1172 if (nvlist_lookup_string(nvl, "EventName", &event) != 0) {

--- 35 unchanged lines hidden (view full) ---

1208 }
1209
1210
1211 if (strncasecmp(counter, "fixed", strlen("fixed")) == 0)
1212 return (B_TRUE);
1213
1214 return (B_FALSE);
1215}
1344{
1345 char *event, *msridx, *msrval, *taken, *offcore, *counter;
1346 char *ecode, *umask;
1347
1348 /*
1349 * Require EventName, it's kind of useless without that.
1350 */
1351 if (nvlist_lookup_string(nvl, "EventName", &event) != 0) {

--- 35 unchanged lines hidden (view full) ---

1387 }
1388
1389
1390 if (strncasecmp(counter, "fixed", strlen("fixed")) == 0)
1391 return (B_TRUE);
1392
1393 return (B_FALSE);
1394}
1395static char *
1396cpcgen_manual_amd_name(cpc_map_t *map)
1397{
1398 char *name;
1216
1399
1400 if (asprintf(&name, "amd_%s_events.3cpc", map->cmap_name) == -1) {
1401 warn("failed to assemble file name for %s", map->cmap_path);
1402 return (NULL);
1403 }
1404
1405 return (name);
1406}
1407
1408static boolean_t
1409cpcgen_manual_amd_file_before(FILE *f, cpc_map_t *map)
1410{
1411 size_t i;
1412 char *upper;
1413 const char *family;
1414
1415 if ((upper = strdup(map->cmap_name)) == NULL) {
1416 warn("failed to duplicate manual name for %s", map->cmap_name);
1417 return (B_FALSE);
1418 }
1419
1420 for (i = 0; upper[i] != '\0'; i++) {
1421 upper[i] = toupper(upper[i]);
1422 }
1423
1424 family = map->cmap_name + 1;
1425
1426 if (fprintf(f, cpcgen_manual_amd_header, map->cmap_path, upper,
1427 family, family, family) == -1) {
1428 warn("failed to write out manual header for %s",
1429 map->cmap_name);
1430 free(upper);
1431 return (B_FALSE);
1432 }
1433
1434 free(upper);
1435 return (B_TRUE);
1436}
1437
1438static boolean_t
1439cpcgen_manual_amd_file_after(FILE *f, cpc_map_t *map)
1440{
1441 if (fprintf(f, cpcgen_manual_amd_trailer) == -1) {
1442 warn("failed to write out manual header for %s",
1443 map->cmap_name);
1444 return (B_FALSE);
1445 }
1446
1447 return (B_TRUE);
1448}
1449
1450static boolean_t
1451cpcgen_manual_amd_event(FILE *f, nvlist_t *nvl, const char *path, uint32_t ent)
1452{
1453 char *name, *mnemonic = NULL, *summary = NULL, *desc = NULL;
1454 char *umode;
1455 nvlist_t *units = NULL;
1456 uint32_t i, length;
1457
1458 if (nvlist_lookup_string(nvl, "name", &name) != 0) {
1459 warnx("Found event without 'name' property in %s, entry %u",
1460 path, ent);
1461 return (B_FALSE);
1462 }
1463
1464 if (nvlist_lookup_string(nvl, "mnemonic", &mnemonic) != 0 ||
1465 nvlist_lookup_string(nvl, "summary", &summary) != 0) {
1466 warnx("event %s in %s, entry %u, missing required fields",
1467 name, path, ent);
1468 return (B_FALSE);
1469 }
1470
1471 /*
1472 * Allow the other fields to be missing.
1473 */
1474 (void) nvlist_lookup_string(nvl, "description", &desc);
1475 (void) nvlist_lookup_nvlist(nvl, "units", &units);
1476
1477 if (fprintf(f, ".It Sy %s\n", name) == -1) {
1478 warn("failed to write out event entry %s", name);
1479 }
1480
1481 if (fprintf(f, ".Sy %s -\n"
1482 "%s\n", mnemonic, summary) == -1) {
1483 warn("failed to write out event entry %s", name);
1484 return (B_FALSE);
1485 }
1486
1487 if (desc != NULL) {
1488 if (fprintf(f, ".Pp\n%s\n", desc) == -1) {
1489 warn("failed to write out event entry %s", name);
1490 return (B_FALSE);
1491 }
1492 }
1493
1494 if (units == NULL)
1495 return (B_TRUE);
1496
1497 /*
1498 * Skip units we don't know how to handle.
1499 */
1500 if (nvlist_lookup_string(nvl, "unit_mode", &umode) == 0) {
1501 return (B_TRUE);
1502 }
1503
1504 if (fprintf(f, ".Pp\n"
1505 "This event has the following units which may be used\n"
1506 "to modify the behavior of the event:\n"
1507 ".Bl -tag -width Sy\n") == -1) {
1508 warn("failed to write out event entry %s", name);
1509 return (B_FALSE);
1510 }
1511
1512 if (nvlist_lookup_uint32(units, "length", &length) != 0) {
1513 warnx("found units array, but could not look up length "
1514 "property for events %s (index %u) in file %s",
1515 name, ent, path);
1516 return (B_FALSE);
1517 }
1518
1519 for (i = 0; i < length; i++) {
1520 nvlist_t *uvl;
1521 char num[64];
1522 char *uname, *udesc = NULL;
1523
1524 (void) snprintf(num, sizeof (num), "%u", i);
1525 if (nvlist_lookup_nvlist(units, num, &uvl) != 0) {
1526 warnx("failed to look up unit %u for event %s (index "
1527 "%u) in file %s", i, name, ent, path);
1528 return (B_FALSE);
1529 }
1530
1531 if (nvlist_lookup_string(uvl, "name", &uname) != 0) {
1532 warnx("failed to find required members for unit array "
1533 "entry %u of event %s (index %u) from file %s",
1534 i, name, ent, path);
1535 return (B_FALSE);
1536 }
1537 (void) nvlist_lookup_string(uvl, "description", &udesc);
1538 if (fprintf(f, ".It Sy %s\n", uname) == -1) {
1539 warn("failed to write out event entry %s", name);
1540 return (B_FALSE);
1541 }
1542
1543 if (udesc != NULL) {
1544 if (fprintf(f, "%s\n", udesc) == -1) {
1545 warn("failed to write out event entry %s",
1546 name);
1547 return (B_FALSE);
1548 }
1549 }
1550 }
1551
1552 if (fprintf(f, ".El\n") == -1) {
1553 warn("failed to write out event entry %s",
1554 name);
1555 return (B_FALSE);
1556 }
1557
1558 return (B_TRUE);
1559}
1560
1561static char *
1562cpcgen_cfile_amd_name(cpc_map_t *map)
1563{
1564 char *name;
1565
1566 if (asprintf(&name, "opteron_pcbe_%s.c", map->cmap_name) == -1) {
1567 warn("failed to assemble file name for %s", map->cmap_path);
1568 return (NULL);
1569 }
1570
1571 return (name);
1572}
1573
1217/*
1574/*
1575 * Generate a header file that can be used to synthesize the data events we care
1576 * about.
1577 */
1578static void
1579cpcgen_common_amd_files(int dirfd)
1580{
1581 const char *fname = "opteron_pcbe_cpcgen.h";
1582 char *tmpname;
1583 int fd;
1584 FILE *f;
1585 cpc_map_t *map;
1586
1587 if (asprintf(&tmpname, ".%s.%d", fname, getpid()) == -1) {
1588 err(EXIT_FAILURE, "failed to construct temporary file name");
1589 }
1590
1591 if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0644)) < 0) {
1592 err(EXIT_FAILURE, "failed to create temporary file %s",
1593 tmpname);
1594 }
1595
1596 if ((f = fdopen(fd, "w")) == NULL) {
1597 cpcgen_remove_tmpfile(dirfd, tmpname);
1598 err(EXIT_FAILURE, "failed to fdopen temporary file");
1599 }
1600
1601 if (fprintf(f, cpcgen_cfile_cddl_header) == -1) {
1602 cpcgen_remove_tmpfile(dirfd, tmpname);
1603 err(EXIT_FAILURE, "failed to write header to "
1604 "temporary file for %s", fname);
1605 }
1606
1607 if (fprintf(f, "#ifndef _OPTERON_PCBE_CPCGEN_H\n"
1608 "#define\t_OPTERON_PCBE_CPCGEN_H\n"
1609 "\n"
1610 "#ifdef __cplusplus\n"
1611 "extern \"C\" {\n"
1612 "#endif\n"
1613 "\n") == -1) {
1614 cpcgen_remove_tmpfile(dirfd, tmpname);
1615 err(EXIT_FAILURE, "failed to write header to "
1616 "temporary file for %s", fname);
1617 }
1618
1619 for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
1620 if (fprintf(f, "extern const amd_event_t "
1621 "opteron_pcbe_%s_events[];\n", map->cmap_name) == -1) {
1622 cpcgen_remove_tmpfile(dirfd, tmpname);
1623 err(EXIT_FAILURE, "failed to write header to "
1624 "temporary file for %s", fname);
1625 }
1626 }
1627
1628 if (fprintf(f, "\n"
1629 "#ifdef __cplusplus\n"
1630 "}\n"
1631 "#endif\n"
1632 "\n"
1633 "#endif /* _OPTERON_PCBE_CPCGEN_H */\n") == -1) {
1634 cpcgen_remove_tmpfile(dirfd, tmpname);
1635 err(EXIT_FAILURE, "failed to write header to "
1636 "temporary file for %s", fname);
1637 }
1638
1639
1640
1641 if (fflush(f) != 0 || fclose(f) != 0) {
1642 cpcgen_remove_tmpfile(dirfd, tmpname);
1643 err(EXIT_FAILURE, "failed to flush and close temporary file");
1644 }
1645
1646 if (renameat(dirfd, tmpname, dirfd, fname) != 0) {
1647 err(EXIT_FAILURE, "failed to rename temporary file %s",
1648 tmpname);
1649 }
1650
1651 free(tmpname);
1652}
1653
1654static boolean_t
1655cpcgen_cfile_amd_before(FILE *f, cpc_map_t *map)
1656{
1657 if (fprintf(f, cpcgen_cfile_amd_header, map->cmap_name) == -1) {
1658 warn("failed to write header to temporary file for %s",
1659 map->cmap_path);
1660 return (B_FALSE);
1661 }
1662
1663 if (fprintf(f, cpcgen_cfile_amd_table_start, map->cmap_name) == -1) {
1664 warn("failed to write header to temporary file for %s",
1665 map->cmap_path);
1666 return (B_FALSE);
1667 }
1668
1669
1670 return (B_TRUE);
1671}
1672
1673static boolean_t
1674cpcgen_cfile_amd_after(FILE *f, cpc_map_t *map)
1675{
1676 if (fprintf(f, cpcgen_cfile_amd_table_end) == -1) {
1677 warn("failed to write footer to temporary file for %s",
1678 map->cmap_path);
1679 return (B_FALSE);
1680 }
1681
1682 return (B_TRUE);
1683}
1684
1685static boolean_t
1686cpcgen_cfile_amd_event(FILE *f, nvlist_t *nvl, const char *path, uint_t ent)
1687{
1688 char *name, *code, *umode;
1689 uint32_t i, length;
1690 nvlist_t *units;
1691
1692 if (nvlist_lookup_string(nvl, "name", &name) != 0) {
1693 warnx("Found event without 'name' property in %s, entry %u",
1694 path, ent);
1695 return (B_FALSE);
1696 }
1697
1698 if (nvlist_lookup_string(nvl, "code", &code) != 0) {
1699 warnx("event %s (index %u) from %s missing required properties "
1700 "for C translation", name, path, ent);
1701 return (B_FALSE);
1702 }
1703
1704 if (fprintf(f, "\t{ \"%s\", %s, 0 },\n", name, code) == -1) {
1705 warn("failed to write out entry %s from %s", name, path);
1706 return (B_FALSE);
1707 }
1708
1709 /*
1710 * The 'units' array is optional. If the rule has a specific 'unit_mode'
1711 * indicating how the units should be combined, skip that. We don't know
1712 * how to properly process that right now.
1713 */
1714 if (nvlist_lookup_nvlist(nvl, "units", &units) != 0) {
1715 return (B_TRUE);
1716 }
1717
1718 if (nvlist_lookup_string(nvl, "unit_mode", &umode) == 0) {
1719 return (B_TRUE);
1720 }
1721
1722 if (nvlist_lookup_uint32(units, "length", &length) != 0) {
1723 warnx("found units array, but could not look up length "
1724 "property for events %s (index %u) in file %s",
1725 name, ent, path);
1726 return (B_FALSE);
1727 }
1728
1729 for (i = 0; i < length; i++) {
1730 nvlist_t *uvl;
1731 char num[64];
1732 char *uname, *urw;
1733 int32_t bit;
1734
1735 (void) snprintf(num, sizeof (num), "%u", i);
1736 if (nvlist_lookup_nvlist(units, num, &uvl) != 0) {
1737 warnx("failed to look up unit %u for event %s (index "
1738 "%u) in file %s", i, name, ent, path);
1739 return (B_FALSE);
1740 }
1741
1742 if (nvlist_lookup_string(uvl, "name", &uname) != 0 ||
1743 nvlist_lookup_string(uvl, "rw", &urw) != 0 ||
1744 nvlist_lookup_int32(uvl, "bit", &bit) != 0) {
1745 warnx("failed to find required members for unit array "
1746 "entry %u of event %s (index %u) from file %s",
1747 i, name, ent, path);
1748 dump_nvlist(uvl, 0);
1749 return (B_FALSE);
1750 }
1751
1752 if (bit < 0 || bit > 31) {
1753 warnx("event %s (index %u) from file %s has invalid "
1754 "bit value: %d; skipping", name, ent, path, bit);
1755 continue;
1756 }
1757
1758 if (strcasecmp(urw, "Read-write") != 0)
1759 continue;
1760
1761 if (fprintf(f, "\t{ \"%s.%s\", %s, 0x%x },\n", name, uname,
1762 code, 1U << bit) == -1) {
1763 warn("failed to write out entry %s from %s", name,
1764 path);
1765 return (B_FALSE);
1766 }
1767 }
1768
1769 return (B_TRUE);
1770}
1771
1772/*
1218 * For each processor family, generate a data file that contains all of the
1219 * events that we support. Also generate a header that can be included that
1220 * declares all of the tables.
1221 */
1222static void
1223cpcgen_gen(int dirfd)
1224{
1225 cpc_map_t *map = cpcgen_maps;

--- 18 unchanged lines hidden (view full) ---

1244 }
1245
1246 if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0444)) < 0) {
1247 err(EXIT_FAILURE, "failed to create temporary file %s",
1248 tmpname);
1249 }
1250
1251 if ((f = fdopen(fd, "w")) == NULL) {
1773 * For each processor family, generate a data file that contains all of the
1774 * events that we support. Also generate a header that can be included that
1775 * declares all of the tables.
1776 */
1777static void
1778cpcgen_gen(int dirfd)
1779{
1780 cpc_map_t *map = cpcgen_maps;

--- 18 unchanged lines hidden (view full) ---

1799 }
1800
1801 if ((fd = openat(dirfd, tmpname, O_RDWR | O_CREAT, 0444)) < 0) {
1802 err(EXIT_FAILURE, "failed to create temporary file %s",
1803 tmpname);
1804 }
1805
1806 if ((f = fdopen(fd, "w")) == NULL) {
1252 int e = errno;
1253 (void) unlinkat(dirfd, tmpname, 0);
1254 errno = e;
1807 cpcgen_remove_tmpfile(dirfd, tmpname);
1255 err(EXIT_FAILURE, "failed to fdopen temporary file");
1256 }
1257
1258 if (!cpcgen_ops.cgen_op_file_before(f, map)) {
1808 err(EXIT_FAILURE, "failed to fdopen temporary file");
1809 }
1810
1811 if (!cpcgen_ops.cgen_op_file_before(f, map)) {
1259 (void) unlinkat(dirfd, tmpname, 0);
1812 cpcgen_remove_tmpfile(dirfd, tmpname);
1260 exit(EXIT_FAILURE);
1261 }
1262
1263 /*
1264 * Iterate over array contents.
1265 */
1266 if ((ret = nvlist_lookup_uint32(map->cmap_data, "length",
1267 &length)) != 0) {

--- 4 unchanged lines hidden (view full) ---

1272
1273 for (i = 0; i < length; i++) {
1274 nvlist_t *nvl;
1275 char num[64];
1276
1277 (void) snprintf(num, sizeof (num), "%u", i);
1278 if ((ret = nvlist_lookup_nvlist(map->cmap_data,
1279 num, &nvl)) != 0) {
1813 exit(EXIT_FAILURE);
1814 }
1815
1816 /*
1817 * Iterate over array contents.
1818 */
1819 if ((ret = nvlist_lookup_uint32(map->cmap_data, "length",
1820 &length)) != 0) {

--- 4 unchanged lines hidden (view full) ---

1825
1826 for (i = 0; i < length; i++) {
1827 nvlist_t *nvl;
1828 char num[64];
1829
1830 (void) snprintf(num, sizeof (num), "%u", i);
1831 if ((ret = nvlist_lookup_nvlist(map->cmap_data,
1832 num, &nvl)) != 0) {
1833 cpcgen_remove_tmpfile(dirfd, tmpname);
1280 errx(EXIT_FAILURE, "failed to look up array "
1281 "entry %u in parsed data for %s: %s", i,
1282 map->cmap_path, strerror(ret));
1283 }
1284
1834 errx(EXIT_FAILURE, "failed to look up array "
1835 "entry %u in parsed data for %s: %s", i,
1836 map->cmap_path, strerror(ret));
1837 }
1838
1285 if (cpcgen_skip_entry(nvl, map->cmap_path, i))
1839 if (cpcgen_ops.cgen_op_skip != NULL &&
1840 cpcgen_ops.cgen_op_skip(nvl, map->cmap_path, i)) {
1286 continue;
1841 continue;
1842 }
1287
1288 if (!cpcgen_ops.cgen_op_event(f, nvl, map->cmap_path,
1289 i)) {
1843
1844 if (!cpcgen_ops.cgen_op_event(f, nvl, map->cmap_path,
1845 i)) {
1290 (void) unlinkat(dirfd, tmpname, 0);
1846 cpcgen_remove_tmpfile(dirfd, tmpname);
1291 exit(EXIT_FAILURE);
1292 }
1293 }
1294
1295 if (!cpcgen_ops.cgen_op_file_after(f, map)) {
1847 exit(EXIT_FAILURE);
1848 }
1849 }
1850
1851 if (!cpcgen_ops.cgen_op_file_after(f, map)) {
1296 (void) unlinkat(dirfd, tmpname, 0);
1852 cpcgen_remove_tmpfile(dirfd, tmpname);
1297 exit(EXIT_FAILURE);
1298 }
1299
1300 if (fflush(f) != 0 || fclose(f) != 0) {
1853 exit(EXIT_FAILURE);
1854 }
1855
1856 if (fflush(f) != 0 || fclose(f) != 0) {
1301 int e = errno;
1302 (void) unlinkat(dirfd, tmpname, 0);
1303 errno = e;
1857 cpcgen_remove_tmpfile(dirfd, tmpname);
1304 err(EXIT_FAILURE, "failed to flush and close "
1305 "temporary file");
1306 }
1307
1308 if (renameat(dirfd, tmpname, dirfd, name) != 0) {
1309 err(EXIT_FAILURE, "failed to rename temporary file %s",
1310 tmpname);
1311 }

--- 16 unchanged lines hidden (view full) ---

1328 }
1329
1330 (void) fprintf(stderr, "Usage: %s -a|-p platform -c|-H|-m -d datadir "
1331 "-o outdir\n"
1332 "\n"
1333 "\t-a generate data for all platforms\n"
1334 "\t-c generate C file for CPC\n"
1335 "\t-d specify the directory containt perfmon data\n"
1858 err(EXIT_FAILURE, "failed to flush and close "
1859 "temporary file");
1860 }
1861
1862 if (renameat(dirfd, tmpname, dirfd, name) != 0) {
1863 err(EXIT_FAILURE, "failed to rename temporary file %s",
1864 tmpname);
1865 }

--- 16 unchanged lines hidden (view full) ---

1882 }
1883
1884 (void) fprintf(stderr, "Usage: %s -a|-p platform -c|-H|-m -d datadir "
1885 "-o outdir\n"
1886 "\n"
1887 "\t-a generate data for all platforms\n"
1888 "\t-c generate C file for CPC\n"
1889 "\t-d specify the directory containt perfmon data\n"
1336 "\t-h generate header file and common files\n"
1890 "\t-H generate header file and common files\n"
1337 "\t-m generate manual pages for CPC data\n"
1891 "\t-m generate manual pages for CPC data\n"
1338 "\t-o outut files in directory outdir\n"
1892 "\t-o output files in directory outdir\n"
1339 "\t-p generate data for a specified platform\n",
1340 cpcgen_progname);
1341}
1342
1343int
1344main(int argc, char *argv[])
1345{
1346 int c, outdirfd;

--- 64 unchanged lines hidden (view full) ---

1411 if (count > 1) {
1412 cpcgen_usage("Only one of -a and -p may be specified\n");
1413 return (2);
1414 } else if (count == 0) {
1415 cpcgen_usage("One of -a and -p is required\n");
1416 return (2);
1417 }
1418
1893 "\t-p generate data for a specified platform\n",
1894 cpcgen_progname);
1895}
1896
1897int
1898main(int argc, char *argv[])
1899{
1900 int c, outdirfd;

--- 64 unchanged lines hidden (view full) ---

1965 if (count > 1) {
1966 cpcgen_usage("Only one of -a and -p may be specified\n");
1967 return (2);
1968 } else if (count == 0) {
1969 cpcgen_usage("One of -a and -p is required\n");
1970 return (2);
1971 }
1972
1419
1420 if (outdir == NULL) {
1421 cpcgen_usage("Missing required output directory (-o)\n");
1422 return (2);
1423 }
1424
1425 if ((outdirfd = open(outdir, O_RDONLY)) < 0) {
1426 err(EXIT_FAILURE, "failed to open output directory %s", outdir);
1427 }
1428
1429 if (datadir == NULL) {
1430 cpcgen_usage("Missing required data directory (-d)\n");
1431 return (2);
1432 }
1433
1973 if (outdir == NULL) {
1974 cpcgen_usage("Missing required output directory (-o)\n");
1975 return (2);
1976 }
1977
1978 if ((outdirfd = open(outdir, O_RDONLY)) < 0) {
1979 err(EXIT_FAILURE, "failed to open output directory %s", outdir);
1980 }
1981
1982 if (datadir == NULL) {
1983 cpcgen_usage("Missing required data directory (-d)\n");
1984 return (2);
1985 }
1986
1434 cpcgen_read_mapfile(datadir, platform);
1987 cpcgen_determine_vendor(datadir);
1435
1988
1436 if (do_header) {
1437 cpcgen_common_files(outdirfd);
1438 return (0);
1439 }
1989 switch (cpcgen_mode) {
1990 case CPCGEN_MODE_INTEL:
1991 cpcgen_ops.cgen_op_gather = cpcgen_read_intel;
1992 cpcgen_ops.cgen_op_common = cpcgen_common_intel_files;
1993 cpcgen_ops.cgen_op_skip = cpcgen_skip_intel_entry;
1994 if (do_mpage) {
1995 cpcgen_ops.cgen_op_name = cpcgen_manual_intel_name;
1996 cpcgen_ops.cgen_op_file_before =
1997 cpcgen_manual_intel_file_before;
1998 cpcgen_ops.cgen_op_file_after =
1999 cpcgen_manual_intel_file_after;
2000 cpcgen_ops.cgen_op_event = cpcgen_manual_intel_event;
2001 } else {
2002 cpcgen_ops.cgen_op_name = cpcgen_cfile_intel_name;
2003 cpcgen_ops.cgen_op_file_before =
2004 cpcgen_cfile_intel_before;
2005 cpcgen_ops.cgen_op_file_after =
2006 cpcgen_cfile_intel_after;
2007 cpcgen_ops.cgen_op_event = cpcgen_cfile_intel_event;
2008 }
2009 break;
2010 case CPCGEN_MODE_AMD:
2011 cpcgen_ops.cgen_op_gather = cpcgen_read_amd;
2012 cpcgen_ops.cgen_op_common = cpcgen_common_amd_files;
2013 cpcgen_ops.cgen_op_skip = NULL;
2014 if (do_mpage) {
2015 cpcgen_ops.cgen_op_name = cpcgen_manual_amd_name;
2016 cpcgen_ops.cgen_op_file_before =
2017 cpcgen_manual_amd_file_before;
2018 cpcgen_ops.cgen_op_file_after =
2019 cpcgen_manual_amd_file_after;
2020 cpcgen_ops.cgen_op_event = cpcgen_manual_amd_event;
2021 } else {
2022 cpcgen_ops.cgen_op_name = cpcgen_cfile_amd_name;
2023 cpcgen_ops.cgen_op_file_before =
2024 cpcgen_cfile_amd_before;
2025 cpcgen_ops.cgen_op_file_after = cpcgen_cfile_amd_after;
2026 cpcgen_ops.cgen_op_event = cpcgen_cfile_amd_event;
1440
2027
1441 if (do_mpage) {
1442 cpcgen_ops.cgen_op_name = cpcgen_manual_name;
1443 cpcgen_ops.cgen_op_file_before = cpcgen_manual_file_before;
1444 cpcgen_ops.cgen_op_file_after = cpcgen_manual_file_after;
1445 cpcgen_ops.cgen_op_event = cpcgen_manual_event;
2028 }
2029 break;
2030 default:
2031 errx(EXIT_FAILURE, "failed to determine if operating on AMD or "
2032 "Intel");
2033 break;
1446 }
1447
2034 }
2035
1448 if (do_cfile) {
1449 cpcgen_ops.cgen_op_name = cpcgen_cfile_name;
1450 cpcgen_ops.cgen_op_file_before = cpcgen_cfile_file_before;
1451 cpcgen_ops.cgen_op_file_after = cpcgen_cfile_file_after;
1452 cpcgen_ops.cgen_op_event = cpcgen_cfile_event;
2036 cpcgen_ops.cgen_op_gather(datadir, platform);
2037
2038 if (do_header) {
2039 cpcgen_ops.cgen_op_common(outdirfd);
2040 return (0);
1453 }
1454
2041 }
2042
1455
1456 cpcgen_gen(outdirfd);
1457
1458 return (0);
1459}
2043 cpcgen_gen(outdirfd);
2044
2045 return (0);
2046}