lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ