]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tools/x86/kcpuid: Refactor CPUID range handling for future expansion
authorAhmed S. Darwish <darwi@linutronix.de>
Mon, 24 Mar 2025 14:20:32 +0000 (15:20 +0100)
committerIngo Molnar <mingo@kernel.org>
Tue, 25 Mar 2025 08:53:46 +0000 (09:53 +0100)
The kcpuid code assumes only two CPUID index ranges, standard (0x0...)
and extended (0x80000000...).

Since additional CPUID index ranges will be added in further commits,
replace the "is_ext" boolean with enumeration-based range classification.

Collect all CPUID ranges in a structured array and introduce helper
macros to iterate over it.  Use such helpers throughout the code.

Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lore.kernel.org/r/20250324142042.29010-12-darwi@linutronix.de
tools/arch/x86/kcpuid/kcpuid.c

index 25388a5d40aca425728815faeb8a805a10fa8f9d..7790136f04dc9e6ff87e2ed5a143c2313c94a9a4 100644 (file)
@@ -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();