diff options
| -rw-r--r-- | tools/arch/x86/kcpuid/kcpuid.c | 100 |
1 files changed, 59 insertions, 41 deletions
diff --git a/tools/arch/x86/kcpuid/kcpuid.c b/tools/arch/x86/kcpuid/kcpuid.c index 25388a5d40ac..7790136f04dc 100644 --- a/tools/arch/x86/kcpuid/kcpuid.c +++ b/tools/arch/x86/kcpuid/kcpuid.c @@ -66,19 +66,50 @@ struct cpuid_func { 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; @@ -173,7 +204,7 @@ static bool cpuid_store(struct cpuid_range *range, u32 f, int subleaf, 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++) { @@ -190,22 +221,12 @@ static void raw_dump_range(struct cpuid_range *range) } #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); @@ -215,7 +236,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax) 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; @@ -254,8 +275,6 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax) } } - - return range; } /* @@ -312,13 +331,13 @@ static void parse_line(char *line) /* 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; @@ -489,9 +508,11 @@ static inline struct cpuid_func *index_to_func(u32 index) 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; @@ -500,12 +521,13 @@ static inline struct cpuid_func *index_to_func(u32 index) 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; } @@ -533,15 +555,8 @@ static void show_info(void) } 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) @@ -617,10 +632,13 @@ static void parse_options(int argc, char *argv[]) */ 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(); |
