summaryrefslogtreecommitdiff
path: root/usr/src/tools/cpcgen/cpcgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/tools/cpcgen/cpcgen.c')
-rw-r--r--usr/src/tools/cpcgen/cpcgen.c241
1 files changed, 205 insertions, 36 deletions
diff --git a/usr/src/tools/cpcgen/cpcgen.c b/usr/src/tools/cpcgen/cpcgen.c
index 196f2ebd33..b006c2f6b4 100644
--- a/usr/src/tools/cpcgen/cpcgen.c
+++ b/usr/src/tools/cpcgen/cpcgen.c
@@ -37,12 +37,14 @@
#include <json_nvlist.h>
#define EXIT_USAGE 2
-
+#define CPROC_MAX_STEPPINGS 16
typedef struct cpc_proc {
struct cpc_proc *cproc_next;
uint_t cproc_family;
uint_t cproc_model;
+ uint_t cproc_nsteps;
+ uint_t cproc_steppings[CPROC_MAX_STEPPINGS];
} cpc_proc_t;
typedef enum cpc_file_type {
@@ -97,6 +99,8 @@ static cpc_whitelist_t cpcgen_whitelist[] = {
/* Skylake */
{ "SKL", "skl", CPC_FILE_CORE },
{ "SKX", "skx", CPC_FILE_CORE },
+ /* Cascade Lake */
+ { "CLX", "clx", CPC_FILE_CORE },
/* Atom */
{ "BNL", "bnl", CPC_FILE_CORE },
{ "SLM", "slm", CPC_FILE_CORE },
@@ -112,7 +116,7 @@ typedef struct cpc_papi {
/*
* This table maps events with an Intel specific name to the corresponding PAPI
- * name. There may be multiple INtel events which map to the same PAPI event.
+ * name. There may be multiple Intel events which map to the same PAPI event.
* This is usually because different processors have different names for an
* event. We use the title as opposed to the event codes because those can
* change somewhat arbitrarily between processor generations.
@@ -297,18 +301,26 @@ cpcgen_map_lookup(const char *path)
* model.
*/
static void
-cpcgen_parse_model(char *fsr, uint_t *family, uint_t *model)
+cpcgen_parse_model(char *fsr, uint_t *family, uint_t *model, uint_t *nstepp,
+ uint_t *steppings)
{
const char *bstr = "GenuineIntel";
- const char *brand, *fam, *mod;
+ const char *brand, *fam, *mod, *step;
char *last;
long l;
+ uint_t nstep = 0;
+ /*
+ * Tokeninze the string. There may be an optional stepping portion,
+ * which has a range of steppings enclosed by '[' and ']' characters.
+ * While the other parts are required, the stepping may be missing.
+ */
if ((brand = strtok_r(fsr, "-", &last)) == NULL ||
(fam = strtok_r(NULL, "-", &last)) == NULL ||
(mod = strtok_r(NULL, "-", &last)) == NULL) {
errx(EXIT_FAILURE, "failed to parse processor id \"%s\"", fsr);
}
+ step = strtok_r(NULL, "-", &last);
if (strcmp(bstr, brand) != 0) {
errx(EXIT_FAILURE, "brand string \"%s\" did not match \"%s\"",
@@ -317,16 +329,103 @@ cpcgen_parse_model(char *fsr, uint_t *family, uint_t *model)
errno = 0;
l = strtol(fam, &last, 16);
- if (errno != 0 || l < 0 || l >= INT_MAX || *last != '\0') {
+ if (errno != 0 || l < 0 || l > UINT_MAX || *last != '\0') {
errx(EXIT_FAILURE, "failed to parse family \"%s\"", fam);
}
*family = (uint_t)l;
l = strtol(mod, &last, 16);
- if (errno != 0 || l < 0 || l >= INT_MAX || *last != '\0') {
+ if (errno != 0 || l < 0 || l > UINT_MAX || *last != '\0') {
errx(EXIT_FAILURE, "failed to parse model \"%s\"", mod);
}
*model = (uint_t)l;
+
+ if (step == NULL) {
+ *nstepp = 0;
+ return;
+ }
+
+ if (*step != '[' || ((last = strrchr(step, ']')) == NULL)) {
+ errx(EXIT_FAILURE, "failed to parse stepping \"%s\": missing "
+ "stepping range brackets", step);
+ }
+ step++;
+ *last = '\0';
+ while (*step != '\0') {
+ if (!isxdigit(*step)) {
+ errx(EXIT_FAILURE, "failed to parse stepping: invalid "
+ "stepping identifier '0x%x'", *step);
+ }
+
+ if (nstep >= CPROC_MAX_STEPPINGS) {
+ errx(EXIT_FAILURE, "failed to parse stepping: "
+ "encountered too many steppings");
+ }
+
+ switch (*step) {
+ case '0':
+ steppings[nstep] = 0x0;
+ break;
+ case '1':
+ steppings[nstep] = 0x1;
+ break;
+ case '2':
+ steppings[nstep] = 0x2;
+ break;
+ case '3':
+ steppings[nstep] = 0x3;
+ break;
+ case '4':
+ steppings[nstep] = 0x4;
+ break;
+ case '5':
+ steppings[nstep] = 0x5;
+ break;
+ case '6':
+ steppings[nstep] = 0x6;
+ break;
+ case '7':
+ steppings[nstep] = 0x7;
+ break;
+ case '8':
+ steppings[nstep] = 0x8;
+ break;
+ case '9':
+ steppings[nstep] = 0x9;
+ break;
+ case 'a':
+ case 'A':
+ steppings[nstep] = 0xa;
+ break;
+ case 'b':
+ case 'B':
+ steppings[nstep] = 0xb;
+ break;
+ case 'c':
+ case 'C':
+ steppings[nstep] = 0xc;
+ break;
+ case 'd':
+ case 'D':
+ steppings[nstep] = 0xd;
+ break;
+ case 'e':
+ case 'E':
+ steppings[nstep] = 0xe;
+ break;
+ case 'f':
+ case 'F':
+ steppings[nstep] = 0xf;
+ break;
+ default:
+ errx(EXIT_FAILURE, "encountered non-hex stepping "
+ "character: '%c'", *step);
+ }
+ nstep++;
+ step++;
+ }
+
+ *nstepp = nstep;
}
static nvlist_t *
@@ -436,7 +535,9 @@ cpcgen_read_mapfile(const char *datadir, const char *platform)
while (getline(&data, &datalen, map) != -1) {
char *fstr, *path, *tstr;
const char *name;
- uint_t family, model;
+ uint_t family, model, nsteps;
+ uint_t steppings[CPROC_MAX_STEPPINGS];
+
cpc_type_t type;
cpc_map_t *map;
cpc_proc_t *proc;
@@ -458,7 +559,7 @@ cpcgen_read_mapfile(const char *datadir, const char *platform)
"%u in %s", lineno, mappath);
}
- cpcgen_parse_model(fstr, &family, &model);
+ cpcgen_parse_model(fstr, &family, &model, &nsteps, steppings);
if (strcmp(tstr, "core") == 0) {
type = CPC_FILE_CORE;
@@ -497,16 +598,22 @@ cpcgen_read_mapfile(const char *datadir, const char *platform)
map->cmap_data = parsed;
map->cmap_next = cpcgen_maps;
map->cmap_name = name;
+ map->cmap_procs = NULL;
cpcgen_maps = map;
}
- if ((proc = malloc(sizeof (cpc_proc_t))) == NULL) {
+ if ((proc = calloc(1, sizeof (cpc_proc_t))) == NULL) {
err(EXIT_FAILURE, "failed to allocate memory for "
"family and model tracking");
}
proc->cproc_family = family;
proc->cproc_model = model;
+ proc->cproc_nsteps = nsteps;
+ if (nsteps > 0) {
+ bcopy(steppings, proc->cproc_steppings,
+ sizeof (steppings));
+ }
proc->cproc_next = map->cmap_procs;
map->cmap_procs = proc;
}
@@ -561,12 +668,29 @@ cpcgen_manual_file_before(FILE *f, cpc_map_t *map)
}
for (proc = map->cmap_procs; proc != NULL; proc = proc->cproc_next) {
- if (fprintf(f, ".It\n.Sy Family 0x%x, Model 0x%x\n",
- proc->cproc_family, proc->cproc_model) == -1) {
- warn("failed to write out model information for %s",
- map->cmap_name);
- free(upper);
- return (B_FALSE);
+ if (proc->cproc_nsteps > 0) {
+ uint_t step;
+
+ for (step = 0; step < proc->cproc_nsteps; step++) {
+ if (fprintf(f, ".It\n.Sy Family 0x%x, Model "
+ "0x%x, Stepping 0x%x\n",
+ proc->cproc_family, proc->cproc_model,
+ proc->cproc_steppings[step]) == -1) {
+ warn("failed to write out model "
+ "information for %s",
+ map->cmap_name);
+ free(upper);
+ return (B_FALSE);
+ }
+ }
+ } else {
+ if (fprintf(f, ".It\n.Sy Family 0x%x, Model 0x%x\n",
+ proc->cproc_family, proc->cproc_model) == -1) {
+ warn("failed to write out model information "
+ "for %s", map->cmap_name);
+ free(upper);
+ return (B_FALSE);
+ }
}
}
@@ -794,6 +918,64 @@ cpcgen_cfile_event(FILE *f, nvlist_t *nvl, const char *path, uint_t ent)
return (B_TRUE);
}
+static boolean_t
+cpcgen_generate_map(FILE *f, cpc_map_t *map, boolean_t start)
+{
+ cpc_proc_t *p;
+
+ if (fprintf(f, "\t%sif (", start ? "" : "} else ") == -1) {
+ return (B_FALSE);
+ }
+
+ for (p = map->cmap_procs; p != NULL; p = p->cproc_next) {
+ /*
+ * Make sure the line is padded so the generated C code looks
+ * like reasonable C style.
+ */
+ if (p != map->cmap_procs) {
+ if (fputs("\t ", f) == -1) {
+ return (B_FALSE);
+ }
+ }
+
+ if (p->cproc_nsteps > 0) {
+ uint_t i;
+
+ if (fprintf(f, "(model == 0x%x &&\n\t (",
+ p->cproc_model) == -1) {
+ return (B_FALSE);
+ }
+
+ for (i = 0; i < p->cproc_nsteps; i++) {
+ if (fprintf(f, "stepping == 0x%x%s",
+ p->cproc_steppings[i],
+ i + 1 != p->cproc_nsteps ?
+ " ||\n\t " : "") == -1) {
+ return (B_FALSE);
+ }
+ }
+
+ if (fputs("))", f) == -1) {
+ return (B_FALSE);
+ }
+ } else if (fprintf(f, "model == 0x%x", p->cproc_model) == -1) {
+ return (B_FALSE);
+ }
+
+ if (fprintf(f, "%s\n",
+ p->cproc_next != NULL ? " ||" : ") {") == -1) {
+ return (B_FALSE);
+ }
+ }
+
+ if (fprintf(f, "\t\t\treturn (pcbe_core_events_%s);\n",
+ map->cmap_name) == -1) {
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
/*
* Generate a header file that declares all of these arrays and provide a map
* for models to the corresponding table to use.
@@ -838,7 +1020,8 @@ cpcgen_common_files(int dirfd)
"extern \"C\" {\n"
"#endif\n"
"\n"
- "extern const struct events_table_t *core_cpcgen_table(uint_t);\n"
+ "extern const struct events_table_t *core_cpcgen_table(uint_t, "
+ "uint_t);\n"
"\n") == -1) {
int e = errno;
(void) unlinkat(dirfd, tmpname, 0);
@@ -916,9 +1099,8 @@ cpcgen_common_files(int dirfd)
"#include \"core_pcbe_cpcgen.h\"\n"
"\n"
"const struct events_table_t *\n"
- "core_cpcgen_table(uint_t model)\n"
- "{\n"
- "\tswitch (model) {\n") == -1) {
+ "core_cpcgen_table(uint_t model, uint_t stepping)\n"
+ "{\n") == -1) {
int e = errno;
(void) unlinkat(dirfd, tmpname, 0);
errno = e;
@@ -927,29 +1109,16 @@ cpcgen_common_files(int dirfd)
}
for (map = cpcgen_maps; map != NULL; map = map->cmap_next) {
- cpc_proc_t *p;
- for (p = map->cmap_procs; p != NULL; p = p->cproc_next) {
- assert(p->cproc_family == 6);
- if (fprintf(f, "\t\tcase 0x%x:\n", p->cproc_model) ==
- -1) {
- int e = errno;
- (void) unlinkat(dirfd, tmpname, 0);
- errno = e;
- errx(EXIT_FAILURE, "failed to write header to "
- "temporary file for %s", fname);
- }
- }
- if (fprintf(f, "\t\t\treturn (pcbe_core_events_%s);\n",
- map->cmap_name) == -1) {
+ if (!cpcgen_generate_map(f, map, map == cpcgen_maps)) {
int e = errno;
(void) unlinkat(dirfd, tmpname, 0);
errno = e;
- errx(EXIT_FAILURE, "failed to write entry to "
- "temporary file for %s", fname);
+ errx(EXIT_FAILURE, "failed to write to temporary "
+ "file for %s", fname);
}
}
- if (fprintf(f, "\t\tdefault:\n"
+ if (fprintf(f, "\t} else {\n"
"\t\t\treturn (NULL);\n"
"\t}\n"
"}\n") == -1) {