[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250506050437.10264-5-darwi@linutronix.de>
Date: Tue, 6 May 2025 07:04:15 +0200
From: "Ahmed S. Darwish" <darwi@...utronix.de>
To: Ingo Molnar <mingo@...hat.com>,
Borislav Petkov <bp@...en8.de>,
Dave Hansen <dave.hansen@...ux.intel.com>
Cc: Thomas Gleixner <tglx@...utronix.de>,
Andrew Cooper <andrew.cooper3@...rix.com>,
"H. Peter Anvin" <hpa@...or.com>,
John Ogness <john.ogness@...utronix.de>,
x86@...nel.org,
x86-cpuid@...ts.linux.dev,
LKML <linux-kernel@...r.kernel.org>,
"Ahmed S. Darwish" <darwi@...utronix.de>
Subject: [PATCH v1 04/26] x86/cpuid: Introduce centralized CPUID data
Define the CPUID_LEAF() macro for building up centralized CPUID data.
It automates defining a CPUID data repository in the form:
struct cpuid_leaves {
struct leaf_0x0_0 leaf_0x0_0[1];
struct leaf_query_info leaf_0x0_0_info;
struct leaf_0x1_0 leaf_0x1_0[1];
struct leaf_query_info leaf_0x0_0_info;
struct leaf_0x4_0 leaf_0x4_0[8];
struct leaf_query_info leaf_0x4_0_info;
...
};
where for each 'struct leaf_0xN_M', N is the leaf number and M is the
subleaf.
The complete C99 bitfield listings of the 'leaf_0xN_M' structures is auto
generated by the x86-cpuid-db project and is merged in parent commits at
<asm/cpuid/leaves.h>. This avoids using ugly bitwise operations on CPUID
register output.
Let the CPUID_LEAF() macro generate an array of output storage entries
for each leaf/subleaf combination. An array is used to accommodate
leaves which produce the same output format for a large subleaf range,
which is typical for CPUID leaves enumerating hierarchical objects;
e.g. leaf 0x4 cache topology enumeration, leaf 0xd XSAVE enumeration, and
leaf 0x12 SGX Enclave Page Cache enumeration. In the CPUID table snippet
above, leaf 0x4 has 8 storage entries.
For each of the leaf/subleaf entries in the CPUID table, attach a
'leaf_query_info' leaf_0xN_M_info structure. It is to be filled by the
generic scanning logic filling the CPUID table. For now, that info
structure has one element: the number of filled slots in the leaf/subleaf
storage array.
Define 'struct cpuid_table' for representing the actual CPUID table, and
embed in it a 'struct cpuid_leaves' instance. This way, global table
data can be later added.
Embed an instance of that 'struct cpuid_table' in the CPU capability
structure 'struct cpuinfo_x86'. This way, centralized CPUID data can be
accessed on early boot (through boot_cpu_data) and later on a per-CPU
basis through the 'cpu_info' per-CPU capability structures. Since
multiple code paths dealing with 'struct cpuinfo_x86' assume that it has
no embedded pointers, embedding the cpuid_table instance avoids creating
special cases for no apparent benefit.
Define entries for leaf 0x0 and leaf 0x1 in the CPUID table. Next
commits will add generic scanning logic for filling the CPUID data.
Suggested-by: Thomas Gleixner <tglx@...utronix.de>
Signed-off-by: Ahmed S. Darwish <darwi@...utronix.de>
---
arch/x86/include/asm/cpuid/internal_api.h | 62 +++++++++++++++++++++++
arch/x86/include/asm/cpuid/types.h | 61 ++++++++++++++++++++++
arch/x86/include/asm/processor.h | 1 +
3 files changed, 124 insertions(+)
create mode 100644 arch/x86/include/asm/cpuid/internal_api.h
diff --git a/arch/x86/include/asm/cpuid/internal_api.h b/arch/x86/include/asm/cpuid/internal_api.h
new file mode 100644
index 000000000000..a1321ed19679
--- /dev/null
+++ b/arch/x86/include/asm/cpuid/internal_api.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_CPUID_INTERNAL_API_H
+#define _ASM_X86_CPUID_INTERNAL_API_H
+
+/*
+ * Raw 'struct cpuid_leaves' accessors
+ */
+
+#include <asm/cpuid/types.h>
+
+/**
+ * __cpuid_get() - Get scanned CPUID output (without sanity checks)
+ * @_leaves: &struct cpuid_leaves instance
+ * @_leaf: Leaf number in the 0xN format
+ * @_subleaf: Subleaf number in decimal
+ * @_idx: @_leaf/@...bleaf query output storage index
+ *
+ * Return the scanned CPUID output in a ready to parse <cpuid/leaves.h> type:
+ * struct leaf_0xN_M, where 0xN is the token provided at @_leaf, and M is the
+ * token provided at @_subleaf.
+ */
+#define __cpuid_get(__leaves, __leaf, __subleaf, __idx) \
+ ((__leaves)->leaf_ ## __leaf ## _ ## __subleaf)[__idx]
+
+/**
+ * __cpuid_info_get() - Get @_leaf/@...bleaf CPUID query info
+ * @_leaves: &struct cpuid_leaves instance
+ * @_leaf: Leaf number in the 0xN format
+ * @_subleaf: Subleaf number in decimal
+ *
+ * Return @_leaves repository scanned @_leaf/@...bleaf CPUID query info, as
+ * &struct leaf_query_info.
+ */
+#define __cpuid_info_get(__leaves, __leaf, __subleaf) \
+ ((__leaves)->leaf_ ## __leaf ## _ ## __subleaf ## _ ## info)
+
+/**
+ * cpuid_get() - Get scanned CPUID output (without sanity checks)
+ * @_leaves: &struct cpuid_leaves instance
+ * @_leaf: Leaf number in the 0xN format
+ *
+ * Like __cpuid_get(), but with the subleaf and output storage index assumed
+ * as zero.
+ */
+#define cpuid_get(_leaves, _leaf) \
+ __cpuid_get(_leaves, _leaf, 0, 0)
+
+/*
+ * struct cpuid_table accessors (with sanity checks)
+ *
+ * Return requested data as a <cpuid/leaves.h> data type, or NULL if the
+ * entry is not available.
+ */
+
+#define __cpudata_cpuid_subleaf_idx(__table, __leaf, __subleaf, __idx) \
+ ((__cpuid_info_get(&((__table)->leaves), __leaf, __subleaf).nr_entries > __idx) ? \
+ &__cpuid_get(&((__table)->leaves), __leaf, __subleaf, __idx) : NULL)
+
+#define __cpudata_cpuid_subleaf(__table, __leaf, __subleaf) \
+ __cpudata_cpuid_subleaf_idx(__table, __leaf, __subleaf, 0)
+
+#endif /* _ASM_X86_CPUID_INTERNAL_API_H */
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index c95fee66e148..df115a8440bc 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -5,6 +5,8 @@
#include <linux/build_bug.h>
#include <linux/types.h>
+#include <asm/cpuid/leaves.h>
+
/*
* Types for raw CPUID access:
*/
@@ -125,4 +127,63 @@ extern const struct leaf_0x2_table cpuid_0x2_table[256];
*/
#define TLB_0x63_2M_4M_ENTRIES 32
+/*
+ * Types for centralized CPUID tables:
+ */
+
+/**
+ * struct leaf_query_info - Info for a CPUID leaf/subleaf query
+ * @nr_entries: Number of filled entries by the CPUID scanner for leaf/subleaf
+ *
+ * Each leaf/subleaf entry in a CPUID table (struct cpuid_leaves) has this
+ * dedicated query info.
+ */
+struct leaf_query_info {
+ unsigned int nr_entries;
+};
+
+/**
+ * __CPUID_LEAF() - Define CPUID storage entries as <cpuid/leaves.h> structures
+ * @_name: leaf_0xN_M structure name and type as found in <cpuid/leaves.h>,
+ * where N is the leaf and M is the subleaf.
+ * @_count: Max storage capacity for the combined leaf/subleaf @_name entry
+ *
+ * Define an array of storage entries for each leaf/subleaf combination.
+ * Use an array to accommodate leaves which produce the same output format
+ * for a large subleaf range, which is common for hierarchical objects
+ * enumeration; e.g., leaf 0x4, 0xd, and 0x12.
+ */
+#define __CPUID_LEAF(_name, _count) \
+ struct _name _name[_count]; \
+ struct leaf_query_info _name ## _ ## info
+
+/**
+ * CPUID_LEAF() - Define CPUID storage entries for @_leaf/@...bleaf
+ * @_leaf: Leaf number in the 0xN format
+ * @_subleaf: Subleaf number in decimal
+ * @_count: Number of repeated storage entries for @_leaf/@...bleaf
+ */
+#define CPUID_LEAF(_leaf, _subleaf, _count) \
+ __CPUID_LEAF(leaf_ ## _leaf ## _ ## _subleaf, _count)
+
+/*
+ * struct cpuid_leaves - CPUID leaf/subleaf output storage
+ */
+struct cpuid_leaves {
+ /* leaf subleaf count */
+ CPUID_LEAF(0x0, 0, 1);
+ CPUID_LEAF(0x1, 0, 1);
+};
+
+/**
+ * struct cpuid_table - System CPUID data table
+ * @leaves: Leaf/subleaf output storage space
+ *
+ * struct cpuinfo_x86 embeds an instance of this table so that CPUID
+ * data can be extracted using a CPU capability structure reference.
+ */
+struct cpuid_table {
+ struct cpuid_leaves leaves;
+};
+
#endif /* _ASM_X86_CPUID_TYPES_H */
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 5d2f7e5aff26..df85dab402b8 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -165,6 +165,7 @@ struct cpuinfo_x86 {
char x86_vendor_id[16];
char x86_model_id[64];
struct cpuinfo_topology topo;
+ struct cpuid_table cpuid_table;
/* in KB - valid for CPUS which support this call: */
unsigned int x86_cache_size;
int x86_cache_alignment; /* In bytes */
--
2.49.0
Powered by blists - more mailing lists