int nr;
};
+enum range_index {
+ RANGE_STD = 0, /* Standard */
+ RANGE_EXT = 0x80000000, /* Extended */
+};
+
+#define CPUID_INDEX_MASK 0x80000000
+#define CPUID_FUNCTION_MASK (~CPUID_INDEX_MASK)
+
struct cpuid_range {
/* array of main leafs */
struct cpuid_func *funcs;
/* number of valid leafs */
int nr;
- bool is_ext;
+ enum range_index index;
};
-/*
- * basic: basic functions range: [0... ]
- * ext: extended functions range: [0x80000000... ]
- */
-struct cpuid_range *leafs_basic, *leafs_ext;
+static struct cpuid_range ranges[] = {
+ { .index = RANGE_STD, },
+ { .index = RANGE_EXT, },
+};
+
+static char *range_to_str(struct cpuid_range *range)
+{
+ switch (range->index) {
+ case RANGE_STD: return "Standard";
+ case RANGE_EXT: return "Extended";
+ default: return NULL;
+ }
+}
+
+#define for_each_cpuid_range(range) \
+ for (unsigned int i = 0; i < ARRAY_SIZE(ranges) && ((range) = &ranges[i]); i++)
+
+struct cpuid_range *index_to_cpuid_range(u32 index)
+{
+ struct cpuid_range *range;
+
+ for_each_cpuid_range(range) {
+ if (range->index == (index & CPUID_INDEX_MASK))
+ return range;
+ }
+
+ return NULL;
+}
static bool show_details;
static bool show_raw;
static void raw_dump_range(struct cpuid_range *range)
{
- printf("%s Leafs :\n", range->is_ext ? "Extended" : "Basic");
+ printf("%s Leafs :\n", range_to_str(range));
printf("================\n");
for (u32 f = 0; (int)f < range->nr; f++) {
}
#define MAX_SUBLEAF_NUM 64
-struct cpuid_range *setup_cpuid_range(u32 input_eax)
+void setup_cpuid_range(struct cpuid_range *range)
{
- struct cpuid_range *range;
u32 max_func, idx_func;
u32 eax, ebx, ecx, edx;
- cpuid(input_eax, max_func, ebx, ecx, edx);
-
- range = malloc(sizeof(struct cpuid_range));
- if (!range)
- err(EXIT_FAILURE, NULL);
-
- if (input_eax & 0x80000000)
- range->is_ext = true;
- else
- range->is_ext = false;
+ cpuid(range->index, max_func, ebx, ecx, edx);
idx_func = (max_func & 0xffff) + 1;
range->funcs = malloc(sizeof(struct cpuid_func) * idx_func);
range->nr = idx_func;
memset(range->funcs, 0, sizeof(struct cpuid_func) * idx_func);
- for (u32 f = input_eax; f <= max_func; f++) {
+ for (u32 f = range->index; f <= max_func; f++) {
u32 max_subleaf = MAX_SUBLEAF_NUM;
bool allzero;
}
}
-
- return range;
}
/*
/* index/main-leaf */
index = strtoull(tokens[0], NULL, 0);
- if (index & 0x80000000)
- range = leafs_ext;
- else
- range = leafs_basic;
+ /* Skip line parsing if it's not covered by known ranges */
+ range = index_to_cpuid_range(index);
+ if (!range)
+ return;
/* Skip line parsing for non-existing indexes */
- index &= 0x7FFFFFFF;
+ index &= CPUID_FUNCTION_MASK;
if ((int)index >= range->nr)
return;
struct cpuid_range *range;
u32 func_idx;
- range = (index & 0x80000000) ? leafs_ext : leafs_basic;
- func_idx = index & 0xffff;
+ range = index_to_cpuid_range(index);
+ if (!range)
+ return NULL;
+ func_idx = index & 0xffff;
if ((func_idx + 1) > (u32)range->nr)
return NULL;
static void show_info(void)
{
+ struct cpuid_range *range;
struct cpuid_func *func;
if (show_raw) {
/* Show all of the raw output of 'cpuid' instr */
- raw_dump_range(leafs_basic);
- raw_dump_range(leafs_ext);
+ for_each_cpuid_range(range)
+ raw_dump_range(range);
return;
}
}
printf("CPU features:\n=============\n\n");
- show_range(leafs_basic);
- show_range(leafs_ext);
-}
-
-static void setup_platform_cpuid(void)
-{
- /* Setup leafs for the basic and extended range */
- leafs_basic = setup_cpuid_range(0x0);
- leafs_ext = setup_cpuid_range(0x80000000);
+ for_each_cpuid_range(range)
+ show_range(range);
}
static void __noreturn usage(int exit_code)
*/
int main(int argc, char *argv[])
{
+ struct cpuid_range *range;
+
parse_options(argc, argv);
/* Setup the cpuid leafs of current platform */
- setup_platform_cpuid();
+ for_each_cpuid_range(range)
+ setup_cpuid_range(range);
/* Read and parse the 'cpuid.csv' */
parse_text();