xref: /linux/arch/x86/kernel/cpu/cpuid_parser.h (revision d639d9fa162aadec1ae9980c4dcf6e50bd2f8290)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _ARCH_X86_CPUID_PARSER_H
3 #define _ARCH_X86_CPUID_PARSER_H
4 
5 #include <asm/cpuid/types.h>
6 
7 /*
8  * Since accessing the CPUID leaves at 'struct cpuid_leaves' require compile time
9  * tokenization, split the CPUID parser into two stages: compile time macros for
10  * tokenizing the leaf/subleaf output offsets within the table, and generic runtime
11  * code to write to the relevant CPUID leaves using such offsets.
12  *
13  * The output of the compile time macros is cached by a compile time "parse entry"
14  * table (see 'struct cpuid_parse_entry').  The runtime parser code will utilize
15  * such offsets by passing them to the cpuid_table_*_p() functions.
16  */
17 
18 /*
19  * Compile time CPUID table offset calculations:
20  *
21  * @_leaf:	CPUID leaf, in 0xN format
22  * @_subleaf:	CPUID subleaf, in decimal format
23  */
24 
25 #define __cpuid_leaves_regs_offset(_leaf, _subleaf)			\
26 	offsetof(struct cpuid_leaves, leaf_ ## _leaf ## _ ## _subleaf)
27 
28 #define __cpuid_leaves_info_offset(_leaf, _subleaf)			\
29 	offsetof(struct cpuid_leaves, leaf_ ## _leaf ## _ ## _subleaf ## _ ## info)
30 
31 #define __cpuid_leaves_regs_maxcnt(_leaf, _subleaf)			\
32 	ARRAY_SIZE(((struct cpuid_leaves *)NULL)->leaf_ ## _leaf ## _ ## _subleaf)
33 
34 /*
35  * Translation of compile time offsets to generic runtime pointers:
36  */
37 
38 static inline struct cpuid_regs *
39 cpuid_table_regs_p(const struct cpuid_table *t, unsigned long regs_offset)
40 {
41 	return (struct cpuid_regs *)((unsigned long)(&t->leaves) + regs_offset);
42 }
43 
44 static inline struct leaf_parse_info *
45 cpuid_table_info_p(const struct cpuid_table *t, unsigned long info_offset)
46 {
47 	return (struct leaf_parse_info *)((unsigned long)(&t->leaves) + info_offset);
48 }
49 
50 /**
51  * struct cpuid_read_output - Output of a CPUID read operation
52  * @regs:	Pointer to an array of CPUID outputs, where each array element covers the
53  *		full EAX->EDX output range.
54  * @info:	Pointer to query info; for saving the number of filled elements at @regs.
55  *
56  * A CPUID parser read function like cpuid_read_generic() or cpuid_read_0xN() uses this
57  * structure to save the CPUID query outputs.  Actual storage for @regs and @info is
58  * provided by the read function caller, and is typically within the CPU's CPUID table.
59  *
60  * See struct cpuid_parse_entry.read().
61  */
62 struct cpuid_read_output {
63 	struct cpuid_regs	*regs;
64 	struct leaf_parse_info	*info;
65 };
66 
67 /**
68  * struct cpuid_parse_entry - CPUID parse table entry
69  * @leaf:	Leaf number to be parsed
70  * @subleaf:	Subleaf number to be parsed
71  * @regs_offs:	Offset within 'struct cpuid_leaves' for saving the CPUID query output; to be
72  *		passed to cpuid_table_regs_p().
73  * @info_offs:	Offset within 'struct cpuid_leaves' for saving the CPUID query parse info; to be
74  *		passed to cpuid_table_info_p().
75  * @maxcnt:	Maximum number of output storage entries available for the CPUID query.
76  * @read:	Read function for this entry.  It must save the parsed CPUID output to the passed
77  *		'struct cpuid_read_output'->regs array of size >= @maxcnt.  It must set
78  *		'struct cpuid_read_output'->info.nr_entries to the number of CPUID output entries
79  *		parsed and filled.  A generic implementation is provided at cpuid_read_generic().
80  */
81 struct cpuid_parse_entry {
82 	unsigned int	leaf;
83 	unsigned int	subleaf;
84 	unsigned int	regs_offs;
85 	unsigned int	info_offs;
86 	unsigned int	maxcnt;
87 	void		(*read)(const struct cpuid_parse_entry *e, const struct cpuid_read_output *o);
88 };
89 
90 #define __CPUID_PARSE_ENTRY(_leaf, _subleaf, _suffix, _reader_fn)		\
91 	{									\
92 		.leaf		= _leaf,					\
93 		.subleaf	= _subleaf,					\
94 		.regs_offs	= __cpuid_leaves_regs_offset(_leaf, _suffix),	\
95 		.info_offs	= __cpuid_leaves_info_offset(_leaf, _suffix),	\
96 		.maxcnt		= __cpuid_leaves_regs_maxcnt(_leaf, _suffix),	\
97 		.read		= cpuid_read_ ## _reader_fn,			\
98 	}
99 
100 /*
101  * CPUID_PARSE_ENTRY_N() is for parsing CPUID leaves with a subleaf range.
102  * Check <asm/cpuid/types.h> __CPUID_LEAF() vs. CPUID_LEAF_N().
103  */
104 
105 #define CPUID_PARSE_ENTRY(_leaf, _subleaf, _reader_fn)				\
106 	__CPUID_PARSE_ENTRY(_leaf, _subleaf, _subleaf, _reader_fn)
107 
108 #define CPUID_PARSE_ENTRY_N(_leaf, _reader_fn)					\
109 	__CPUID_PARSE_ENTRY(_leaf, __cpuid_leaf_first_subleaf(_leaf), n, _reader_fn)
110 
111 /*
112  * CPUID parser table:
113  */
114 
115 #define CPUID_PARSE_ENTRIES									\
116 	/*			Leaf		Subleaf		Reader function */		\
117 	CPUID_PARSE_ENTRY   (	0x0,		0,		generic			),	\
118 	CPUID_PARSE_ENTRY   (	0x1,		0,		generic			),	\
119 
120 #endif /* _ARCH_X86_CPUID_PARSER_H */
121