| 1 |
|
| 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 *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 |
|
| 44 | static 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 |
|
| 62 | struct 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 |
|
| 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_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 | \
|
| 117 | CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \
|
| 118 | CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \
|
| 119 |
|
| 120 | #endif
|