Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <asm/cpu_device_id.h>
0003 #include <asm/cpufeature.h>
0004 #include <linux/cpu.h>
0005 #include <linux/export.h>
0006 #include <linux/slab.h>
0007 
0008 /**
0009  * x86_match_cpu - match current CPU again an array of x86_cpu_ids
0010  * @match: Pointer to array of x86_cpu_ids. Last entry terminated with
0011  *         {}.
0012  *
0013  * Return the entry if the current CPU matches the entries in the
0014  * passed x86_cpu_id match table. Otherwise NULL.  The match table
0015  * contains vendor (X86_VENDOR_*), family, model and feature bits or
0016  * respective wildcard entries.
0017  *
0018  * A typical table entry would be to match a specific CPU
0019  *
0020  * X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, INTEL_FAM6_BROADWELL,
0021  *                    X86_FEATURE_ANY, NULL);
0022  *
0023  * Fields can be wildcarded with %X86_VENDOR_ANY, %X86_FAMILY_ANY,
0024  * %X86_MODEL_ANY, %X86_FEATURE_ANY (except for vendor)
0025  *
0026  * asm/cpu_device_id.h contains a set of useful macros which are shortcuts
0027  * for various common selections. The above can be shortened to:
0028  *
0029  * X86_MATCH_INTEL_FAM6_MODEL(BROADWELL, NULL);
0030  *
0031  * Arrays used to match for this should also be declared using
0032  * MODULE_DEVICE_TABLE(x86cpu, ...)
0033  *
0034  * This always matches against the boot cpu, assuming models and features are
0035  * consistent over all CPUs.
0036  */
0037 const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
0038 {
0039     const struct x86_cpu_id *m;
0040     struct cpuinfo_x86 *c = &boot_cpu_data;
0041 
0042     for (m = match;
0043          m->vendor | m->family | m->model | m->steppings | m->feature;
0044          m++) {
0045         if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor)
0046             continue;
0047         if (m->family != X86_FAMILY_ANY && c->x86 != m->family)
0048             continue;
0049         if (m->model != X86_MODEL_ANY && c->x86_model != m->model)
0050             continue;
0051         if (m->steppings != X86_STEPPING_ANY &&
0052             !(BIT(c->x86_stepping) & m->steppings))
0053             continue;
0054         if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature))
0055             continue;
0056         return m;
0057     }
0058     return NULL;
0059 }
0060 EXPORT_SYMBOL(x86_match_cpu);
0061 
0062 static const struct x86_cpu_desc *
0063 x86_match_cpu_with_stepping(const struct x86_cpu_desc *match)
0064 {
0065     struct cpuinfo_x86 *c = &boot_cpu_data;
0066     const struct x86_cpu_desc *m;
0067 
0068     for (m = match; m->x86_family | m->x86_model; m++) {
0069         if (c->x86_vendor != m->x86_vendor)
0070             continue;
0071         if (c->x86 != m->x86_family)
0072             continue;
0073         if (c->x86_model != m->x86_model)
0074             continue;
0075         if (c->x86_stepping != m->x86_stepping)
0076             continue;
0077         return m;
0078     }
0079     return NULL;
0080 }
0081 
0082 bool x86_cpu_has_min_microcode_rev(const struct x86_cpu_desc *table)
0083 {
0084     const struct x86_cpu_desc *res = x86_match_cpu_with_stepping(table);
0085 
0086     if (!res || res->x86_microcode_rev > boot_cpu_data.microcode)
0087         return false;
0088 
0089     return true;
0090 }
0091 EXPORT_SYMBOL_GPL(x86_cpu_has_min_microcode_rev);