/* Cover both single-bit flag and multiple-bits fields */ struct bits_desc { /* start and end bits */ int start, end; /* 0 or 1 for 1-bit flag */ int value; char simp[32]; char detail[256];
};
/* descriptor info for eax/ebx/ecx/edx */ struct reg_desc { /* number of valid entries */ int nr; struct bits_desc descs[32];
};
/* Represent one leaf (basic or extended) */ struct cpuid_func { /* * Array of subleafs for this func, if there is no subleafs * then the leafs[0] is the main leaf
*/ struct subleaf *leafs; int nr;
};
/* Return true is the input eax/ebx/ecx/edx are all zero */ staticbool cpuid_store(struct cpuid_range *range, u32 f, int subleaf,
u32 a, u32 b, u32 c, u32 d)
{ struct cpuid_func *func; struct subleaf *leaf; int s = 0;
if (a == 0 && b == 0 && c == 0 && d == 0) returntrue;
/* * Cut off vendor-prefix from CPUID function as we're using it as an * index into ->funcs.
*/
func = &range->funcs[f & CPUID_FUNCTION_MASK];
if (!func->leafs) {
func->leafs = malloc(sizeof(struct subleaf)); if (!func->leafs)
err(EXIT_FAILURE, NULL);
func->nr = 1;
} else {
s = func->nr;
func->leafs = realloc(func->leafs, (s + 1) * sizeof(*leaf)); if (!func->leafs)
err(EXIT_FAILURE, NULL);
/* * If the CPUID range's maximum function value is garbage, then it * is not recognized by this CPU. Set the range's number of valid * leaves to zero so that for_each_valid_cpu_range() can ignore it.
*/ if (max_func < range->index || max_func > (range->index + MAX_RANGE_INDEX_OFFSET)) {
range->nr = 0; return;
}
/* * Some can provide the exact number of subleafs, * others have to be tried (0xf)
*/ if (f == 0x7 || f == 0x14 || f == 0x17 || f == 0x18 || f == 0x1d)
max_subleaf = min((eax & 0xff) + 1, max_subleaf); if (f == 0xb)
max_subleaf = 2; if (f == 0x1f)
max_subleaf = 6; if (f == 0x23)
max_subleaf = 4; if (f == 0x80000020)
max_subleaf = 4; if (f == 0x80000026)
max_subleaf = 5;
/* * The basic row format for cpuid.csv is * LEAF,SUBLEAF,register_name,bits,short name,long description * * like: * 0, 0, EAX, 31:0, max_basic_leafs, Max input value for supported subleafs * 1, 0, ECX, 0, sse3, Streaming SIMD Extensions 3(SSE3)
*/ staticvoid parse_line(char *line)
{ char *str; struct cpuid_range *range; struct cpuid_func *func; struct subleaf *leaf;
u32 index; char buffer[512]; char *buf; /* * Tokens: * 1. leaf * 2. subleaf * 3. register * 4. bits * 5. short name * 6. long detail
*/ char *tokens[6]; struct reg_desc *reg; struct bits_desc *bdesc; int reg_index; char *start, *end;
u32 subleaf_start, subleaf_end; unsigned bit_start, bit_end;
/* Skip comments and NULL line */ if (line[0] == '#' || line[0] == '\n') return;
strncpy(buffer, line, 511);
buffer[511] = 0;
str = buffer; for (int i = 0; i < 5; i++) {
tokens[i] = strtok(str, ","); if (!tokens[i]) goto err_exit;
str = NULL;
}
tokens[5] = strtok(str, "\n"); if (!tokens[5]) goto err_exit;
/* index/main-leaf */
index = strtoull(tokens[0], NULL, 0);
/* * Skip line parsing if the index is not covered by known-valid * CPUID ranges on this CPU.
*/
range = index_to_cpuid_range(index); if (!range) return;
/* Skip line parsing if the index CPUID output is all zero */
index &= CPUID_FUNCTION_MASK;
func = &range->funcs[index]; if (!func->nr) return;
err_exit:
warnx("Wrong line format:\n" "\tline[%d]: %s", flines, line);
}
/* Parse csv file, and construct the array of all leafs and subleafs */ staticvoid parse_text(void)
{
FILE *file; char *filename, *line = NULL;
size_t len = 0; int ret;
if (show_raw) return;
filename = user_csv ? user_csv : def_csv;
file = fopen(filename, "r"); if (!file) { /* Fallback to a csv in the same dir */
file = fopen("./cpuid.csv", "r");
}
if (!file)
err(EXIT_FAILURE, "%s", filename);
while (1) {
ret = getline(&line, &len, file);
flines++; if (ret > 0)
parse_line(line);
if (show_raw) { /* Show all of the raw output of 'cpuid' instr */
for_each_valid_cpuid_range(range)
raw_dump_range(range); return;
}
if (user_index != 0xFFFFFFFF) { /* Only show specific leaf/subleaf info */
func = index_to_func(user_index); if (!func)
errx(EXIT_FAILURE, "Invalid input leaf (0x%x)", user_index);
/* Dump the raw data also */
show_raw = true;
if (user_sub != 0xFFFFFFFF) { if (user_sub + 1 > (u32)func->nr) {
errx(EXIT_FAILURE, "Leaf 0x%x has no valid subleaf = 0x%x",
user_index, user_sub);
}
staticvoid __noreturn usage(int exit_code)
{
errx(exit_code, "kcpuid [-abdfhr] [-l leaf] [-s subleaf]\n" "\t-a|--all Show both bit flags and complex bit fields info\n" "\t-b|--bitflags Show boolean flags only\n" "\t-d|--detail Show details of the flag/fields (default)\n" "\t-f|--flags Specify the CPUID CSV file\n" "\t-h|--help Show usage info\n" "\t-l|--leaf=index Specify the leaf you want to check\n" "\t-r|--raw Show raw CPUID data\n" "\t-s|--subleaf=sub Specify the subleaf you want to check"
);
}
staticstruct option opts[] = {
{ "all", no_argument, NULL, 'a' }, /* show both bit flags and fields */
{ "bitflags", no_argument, NULL, 'b' }, /* only show bit flags, default on */
{ "detail", no_argument, NULL, 'd' }, /* show detail descriptions */
{ "file", required_argument, NULL, 'f' }, /* use user's cpuid file */
{ "help", no_argument, NULL, 'h'}, /* show usage */
{ "leaf", required_argument, NULL, 'l'}, /* only check a specific leaf */
{ "raw", no_argument, NULL, 'r'}, /* show raw CPUID leaf data */
{ "subleaf", required_argument, NULL, 's'}, /* check a specific subleaf */
{ NULL, 0, NULL, 0 }
};
staticvoid parse_options(int argc, char *argv[])
{ int c;
/* * Do 4 things in turn: * 1. Parse user options * 2. Parse and store all the CPUID leaf data supported on this platform * 2. Parse the csv file, while skipping leafs which are not available * on this platform * 3. Print leafs info based on user options
*/ int main(int argc, char *argv[])
{ struct cpuid_range *range;
parse_options(argc, argv);
/* Setup the cpuid leafs of current platform */
for_each_cpuid_range(range)
setup_cpuid_range(range);
/* Read and parse the 'cpuid.csv' */
parse_text();
show_info(); return 0;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.