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