x86/microcode/intel: Move microcode functions out of cpu/intel.c
authorThomas Gleixner <tglx@linutronix.de>
Sat, 12 Aug 2023 19:58:41 +0000 (21:58 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Sun, 13 Aug 2023 16:42:48 +0000 (18:42 +0200)
There is really no point to have that in the CPUID evaluation code. Move it
into the Intel-specific microcode handling along with the data
structures, defines and helpers required by it. The exports need to stay
for IFS.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230812195727.719202319@linutronix.de
arch/x86/include/asm/microcode_intel.h
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/microcode/intel.c

index a279dee8f898f7fcf8201d6acaab27c421266da1..4a32eadb95bfef371d0c4345bd9d692b0a74bd7b 100644 (file)
@@ -23,39 +23,15 @@ struct microcode_intel {
        unsigned int            bits[];
 };
 
-/* microcode format is extended from prescott processors */
-struct extended_signature {
-       unsigned int            sig;
-       unsigned int            pf;
-       unsigned int            cksum;
-};
-
-struct extended_sigtable {
-       unsigned int            count;
-       unsigned int            cksum;
-       unsigned int            reserved[3];
-       struct extended_signature sigs[];
-};
-
-#define DEFAULT_UCODE_DATASIZE (2000)
-#define MC_HEADER_SIZE         (sizeof(struct microcode_header_intel))
-#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
-#define EXT_HEADER_SIZE                (sizeof(struct extended_sigtable))
-#define EXT_SIGNATURE_SIZE     (sizeof(struct extended_signature))
+#define MC_HEADER_SIZE                 (sizeof(struct microcode_header_intel))
 #define MC_HEADER_TYPE_MICROCODE       1
 #define MC_HEADER_TYPE_IFS             2
-
-#define get_totalsize(mc) \
-       (((struct microcode_intel *)mc)->hdr.datasize ? \
-        ((struct microcode_intel *)mc)->hdr.totalsize : \
-        DEFAULT_UCODE_TOTALSIZE)
+#define DEFAULT_UCODE_DATASIZE         (2000)
 
 #define get_datasize(mc) \
        (((struct microcode_intel *)mc)->hdr.datasize ? \
         ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
 
-#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
-
 static inline u32 intel_get_microcode_revision(void)
 {
        u32 rev, dummy;
index 1c4639588ff98ea30c695160e6b01452674bfb3a..5a8f56942a71df0022b58ca55e5c1d91572c8733 100644 (file)
@@ -184,180 +184,6 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
        return false;
 }
 
-int intel_cpu_collect_info(struct ucode_cpu_info *uci)
-{
-       unsigned int val[2];
-       unsigned int family, model;
-       struct cpu_signature csig = { 0 };
-       unsigned int eax, ebx, ecx, edx;
-
-       memset(uci, 0, sizeof(*uci));
-
-       eax = 0x00000001;
-       ecx = 0;
-       native_cpuid(&eax, &ebx, &ecx, &edx);
-       csig.sig = eax;
-
-       family = x86_family(eax);
-       model  = x86_model(eax);
-
-       if (model >= 5 || family > 6) {
-               /* get processor flags from MSR 0x17 */
-               native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-               csig.pf = 1 << ((val[1] >> 18) & 7);
-       }
-
-       csig.rev = intel_get_microcode_revision();
-
-       uci->cpu_sig = csig;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
-
-/*
- * Returns 1 if update has been found, 0 otherwise.
- */
-int intel_find_matching_signature(void *mc, unsigned int csig, int cpf)
-{
-       struct microcode_header_intel *mc_hdr = mc;
-       struct extended_sigtable *ext_hdr;
-       struct extended_signature *ext_sig;
-       int i;
-
-       if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
-               return 1;
-
-       /* Look for ext. headers: */
-       if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
-               return 0;
-
-       ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
-       ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
-
-       for (i = 0; i < ext_hdr->count; i++) {
-               if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
-                       return 1;
-               ext_sig++;
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(intel_find_matching_signature);
-
-/**
- * intel_microcode_sanity_check() - Sanity check microcode file.
- * @mc: Pointer to the microcode file contents.
- * @print_err: Display failure reason if true, silent if false.
- * @hdr_type: Type of file, i.e. normal microcode file or In Field Scan file.
- *            Validate if the microcode header type matches with the type
- *            specified here.
- *
- * Validate certain header fields and verify if computed checksum matches
- * with the one specified in the header.
- *
- * Return: 0 if the file passes all the checks, -EINVAL if any of the checks
- * fail.
- */
-int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type)
-{
-       unsigned long total_size, data_size, ext_table_size;
-       struct microcode_header_intel *mc_header = mc;
-       struct extended_sigtable *ext_header = NULL;
-       u32 sum, orig_sum, ext_sigcount = 0, i;
-       struct extended_signature *ext_sig;
-
-       total_size = get_totalsize(mc_header);
-       data_size = get_datasize(mc_header);
-
-       if (data_size + MC_HEADER_SIZE > total_size) {
-               if (print_err)
-                       pr_err("Error: bad microcode data file size.\n");
-               return -EINVAL;
-       }
-
-       if (mc_header->ldrver != 1 || mc_header->hdrver != hdr_type) {
-               if (print_err)
-                       pr_err("Error: invalid/unknown microcode update format. Header type %d\n",
-                              mc_header->hdrver);
-               return -EINVAL;
-       }
-
-       ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
-       if (ext_table_size) {
-               u32 ext_table_sum = 0;
-               u32 *ext_tablep;
-
-               if (ext_table_size < EXT_HEADER_SIZE ||
-                   ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
-                       if (print_err)
-                               pr_err("Error: truncated extended signature table.\n");
-                       return -EINVAL;
-               }
-
-               ext_header = mc + MC_HEADER_SIZE + data_size;
-               if (ext_table_size != exttable_size(ext_header)) {
-                       if (print_err)
-                               pr_err("Error: extended signature table size mismatch.\n");
-                       return -EFAULT;
-               }
-
-               ext_sigcount = ext_header->count;
-
-               /*
-                * Check extended table checksum: the sum of all dwords that
-                * comprise a valid table must be 0.
-                */
-               ext_tablep = (u32 *)ext_header;
-
-               i = ext_table_size / sizeof(u32);
-               while (i--)
-                       ext_table_sum += ext_tablep[i];
-
-               if (ext_table_sum) {
-                       if (print_err)
-                               pr_warn("Bad extended signature table checksum, aborting.\n");
-                       return -EINVAL;
-               }
-       }
-
-       /*
-        * Calculate the checksum of update data and header. The checksum of
-        * valid update data and header including the extended signature table
-        * must be 0.
-        */
-       orig_sum = 0;
-       i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
-       while (i--)
-               orig_sum += ((u32 *)mc)[i];
-
-       if (orig_sum) {
-               if (print_err)
-                       pr_err("Bad microcode data checksum, aborting.\n");
-               return -EINVAL;
-       }
-
-       if (!ext_table_size)
-               return 0;
-
-       /*
-        * Check extended signature checksum: 0 => valid.
-        */
-       for (i = 0; i < ext_sigcount; i++) {
-               ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
-                         EXT_SIGNATURE_SIZE * i;
-
-               sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
-                     (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
-               if (sum) {
-                       if (print_err)
-                               pr_err("Bad extended signature checksum, aborting.\n");
-                       return -EINVAL;
-               }
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);
-
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
        u64 misc_enable;
index 467cf37ea90a74c9b0fd80bd36728f009ed7a31b..952f1733583e0fde39c841aa75734e3490bbed8d 100644 (file)
@@ -45,6 +45,208 @@ static struct microcode_intel *intel_ucode_patch;
 /* last level cache size per core */
 static int llc_size_per_core;
 
+/* microcode format is extended from prescott processors */
+struct extended_signature {
+       unsigned int    sig;
+       unsigned int    pf;
+       unsigned int    cksum;
+};
+
+struct extended_sigtable {
+       unsigned int                    count;
+       unsigned int                    cksum;
+       unsigned int                    reserved[3];
+       struct extended_signature       sigs[];
+};
+
+#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
+#define EXT_HEADER_SIZE                (sizeof(struct extended_sigtable))
+#define EXT_SIGNATURE_SIZE     (sizeof(struct extended_signature))
+
+static inline unsigned int get_totalsize(struct microcode_header_intel *hdr)
+{
+       return hdr->datasize ? hdr->totalsize : DEFAULT_UCODE_TOTALSIZE;
+}
+
+static inline unsigned int exttable_size(struct extended_sigtable *et)
+{
+       return et->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE;
+}
+
+int intel_cpu_collect_info(struct ucode_cpu_info *uci)
+{
+       unsigned int val[2];
+       unsigned int family, model;
+       struct cpu_signature csig = { 0 };
+       unsigned int eax, ebx, ecx, edx;
+
+       memset(uci, 0, sizeof(*uci));
+
+       eax = 0x00000001;
+       ecx = 0;
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+       csig.sig = eax;
+
+       family = x86_family(eax);
+       model  = x86_model(eax);
+
+       if (model >= 5 || family > 6) {
+               /* get processor flags from MSR 0x17 */
+               native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+               csig.pf = 1 << ((val[1] >> 18) & 7);
+       }
+
+       csig.rev = intel_get_microcode_revision();
+
+       uci->cpu_sig = csig;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
+
+/*
+ * Returns 1 if update has been found, 0 otherwise.
+ */
+int intel_find_matching_signature(void *mc, unsigned int csig, int cpf)
+{
+       struct microcode_header_intel *mc_hdr = mc;
+       struct extended_sigtable *ext_hdr;
+       struct extended_signature *ext_sig;
+       int i;
+
+       if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+               return 1;
+
+       /* Look for ext. headers: */
+       if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
+               return 0;
+
+       ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
+       ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
+
+       for (i = 0; i < ext_hdr->count; i++) {
+               if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+                       return 1;
+               ext_sig++;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_find_matching_signature);
+
+/**
+ * intel_microcode_sanity_check() - Sanity check microcode file.
+ * @mc: Pointer to the microcode file contents.
+ * @print_err: Display failure reason if true, silent if false.
+ * @hdr_type: Type of file, i.e. normal microcode file or In Field Scan file.
+ *            Validate if the microcode header type matches with the type
+ *            specified here.
+ *
+ * Validate certain header fields and verify if computed checksum matches
+ * with the one specified in the header.
+ *
+ * Return: 0 if the file passes all the checks, -EINVAL if any of the checks
+ * fail.
+ */
+int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type)
+{
+       unsigned long total_size, data_size, ext_table_size;
+       struct microcode_header_intel *mc_header = mc;
+       struct extended_sigtable *ext_header = NULL;
+       u32 sum, orig_sum, ext_sigcount = 0, i;
+       struct extended_signature *ext_sig;
+
+       total_size = get_totalsize(mc_header);
+       data_size = get_datasize(mc_header);
+
+       if (data_size + MC_HEADER_SIZE > total_size) {
+               if (print_err)
+                       pr_err("Error: bad microcode data file size.\n");
+               return -EINVAL;
+       }
+
+       if (mc_header->ldrver != 1 || mc_header->hdrver != hdr_type) {
+               if (print_err)
+                       pr_err("Error: invalid/unknown microcode update format. Header type %d\n",
+                              mc_header->hdrver);
+               return -EINVAL;
+       }
+
+       ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+       if (ext_table_size) {
+               u32 ext_table_sum = 0;
+               u32 *ext_tablep;
+
+               if (ext_table_size < EXT_HEADER_SIZE ||
+                   ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
+                       if (print_err)
+                               pr_err("Error: truncated extended signature table.\n");
+                       return -EINVAL;
+               }
+
+               ext_header = mc + MC_HEADER_SIZE + data_size;
+               if (ext_table_size != exttable_size(ext_header)) {
+                       if (print_err)
+                               pr_err("Error: extended signature table size mismatch.\n");
+                       return -EFAULT;
+               }
+
+               ext_sigcount = ext_header->count;
+
+               /*
+                * Check extended table checksum: the sum of all dwords that
+                * comprise a valid table must be 0.
+                */
+               ext_tablep = (u32 *)ext_header;
+
+               i = ext_table_size / sizeof(u32);
+               while (i--)
+                       ext_table_sum += ext_tablep[i];
+
+               if (ext_table_sum) {
+                       if (print_err)
+                               pr_warn("Bad extended signature table checksum, aborting.\n");
+                       return -EINVAL;
+               }
+       }
+
+       /*
+        * Calculate the checksum of update data and header. The checksum of
+        * valid update data and header including the extended signature table
+        * must be 0.
+        */
+       orig_sum = 0;
+       i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
+       while (i--)
+               orig_sum += ((u32 *)mc)[i];
+
+       if (orig_sum) {
+               if (print_err)
+                       pr_err("Bad microcode data checksum, aborting.\n");
+               return -EINVAL;
+       }
+
+       if (!ext_table_size)
+               return 0;
+
+       /*
+        * Check extended signature checksum: 0 => valid.
+        */
+       for (i = 0; i < ext_sigcount; i++) {
+               ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
+                         EXT_SIGNATURE_SIZE * i;
+
+               sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
+                     (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+               if (sum) {
+                       if (print_err)
+                               pr_err("Bad extended signature checksum, aborting.\n");
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);
+
 /*
  * Returns 1 if update has been found, 0 otherwise.
  */