Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : #include <asm/cpu_device_id.h> 3 : : #include <asm/cpufeature.h> 4 : : #include <linux/cpu.h> 5 : : #include <linux/export.h> 6 : : #include <linux/slab.h> 7 : : 8 : : /** 9 : : * x86_match_cpu - match current CPU again an array of x86_cpu_ids 10 : : * @match: Pointer to array of x86_cpu_ids. Last entry terminated with 11 : : * {}. 12 : : * 13 : : * Return the entry if the current CPU matches the entries in the 14 : : * passed x86_cpu_id match table. Otherwise NULL. The match table 15 : : * contains vendor (X86_VENDOR_*), family, model and feature bits or 16 : : * respective wildcard entries. 17 : : * 18 : : * A typical table entry would be to match a specific CPU 19 : : * { X86_VENDOR_INTEL, 6, 0x12 } 20 : : * or to match a specific CPU feature 21 : : * { X86_FEATURE_MATCH(X86_FEATURE_FOOBAR) } 22 : : * 23 : : * Fields can be wildcarded with %X86_VENDOR_ANY, %X86_FAMILY_ANY, 24 : : * %X86_MODEL_ANY, %X86_FEATURE_ANY or 0 (except for vendor) 25 : : * 26 : : * Arrays used to match for this should also be declared using 27 : : * MODULE_DEVICE_TABLE(x86cpu, ...) 28 : : * 29 : : * This always matches against the boot cpu, assuming models and features are 30 : : * consistent over all CPUs. 31 : : */ 32 : 210 : const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) 33 : : { 34 : 210 : const struct x86_cpu_id *m; 35 : 210 : struct cpuinfo_x86 *c = &boot_cpu_data; 36 : : 37 [ + + ]: 5250 : for (m = match; m->vendor | m->family | m->model | m->feature; m++) { 38 [ + + + + ]: 5187 : if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor) 39 : 4263 : continue; 40 [ + + + - ]: 924 : if (m->family != X86_FAMILY_ANY && c->x86 != m->family) 41 : 777 : continue; 42 [ - + - - ]: 147 : if (m->model != X86_MODEL_ANY && c->x86_model != m->model) 43 : 0 : continue; 44 [ - + - - : 147 : if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature)) - - - - - - - - - - - - - - - - ] 45 : 0 : continue; 46 : : return m; 47 : : } 48 : : return NULL; 49 : : } 50 : : EXPORT_SYMBOL(x86_match_cpu); 51 : : 52 : : static const struct x86_cpu_desc * 53 : 0 : x86_match_cpu_with_stepping(const struct x86_cpu_desc *match) 54 : : { 55 : 0 : struct cpuinfo_x86 *c = &boot_cpu_data; 56 : 0 : const struct x86_cpu_desc *m; 57 : : 58 [ # # ]: 0 : for (m = match; m->x86_family | m->x86_model; m++) { 59 [ # # ]: 0 : if (c->x86_vendor != m->x86_vendor) 60 : 0 : continue; 61 [ # # ]: 0 : if (c->x86 != m->x86_family) 62 : 0 : continue; 63 [ # # ]: 0 : if (c->x86_model != m->x86_model) 64 : 0 : continue; 65 [ # # ]: 0 : if (c->x86_stepping != m->x86_stepping) 66 : 0 : continue; 67 : : return m; 68 : : } 69 : : return NULL; 70 : : } 71 : : 72 : 0 : bool x86_cpu_has_min_microcode_rev(const struct x86_cpu_desc *table) 73 : : { 74 : 0 : const struct x86_cpu_desc *res = x86_match_cpu_with_stepping(table); 75 : : 76 [ # # # # ]: 0 : if (!res || res->x86_microcode_rev > boot_cpu_data.microcode) 77 : 0 : return false; 78 : : 79 : : return true; 80 : : } 81 : : EXPORT_SYMBOL_GPL(x86_cpu_has_min_microcode_rev);