projects/linux·blob master · refs

120 lines · 4.3 KiB

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
38static inline struct cpuid_regs *cpuid_table_regs_p(const struct cpuid_table *t,
39 unsigned long regs_offset)
40{
41 return (struct cpuid_regs *)((unsigned long)(&t->leaves) + regs_offset);
42}
43
44static inline struct leaf_parse_info *cpuid_table_info_p(const struct cpuid_table *t,
45 unsigned long info_offset)
46{
47 return (struct leaf_parse_info *)((unsigned long)(&t->leaves) + info_offset);
48}
49
50/**
51 * struct cpuid_output - Output of a CPUID operation
52 * @regs: Pointer to an array of CPUID results, 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 */
62struct cpuid_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_output'->regs array of size >= @maxcnt. It must set
78 * 'struct cpuid_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 */
81struct 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_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 */