x86,amd_ucode: verify max allowed patch size before apply
authorAravind Gopalakrishnan <aravind.gopalakrishnan@amd.com>
Tue, 6 May 2014 11:39:05 +0000 (13:39 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 6 May 2014 11:39:05 +0000 (13:39 +0200)
Each family has a stipulated max patch_size. Use this as
additional sanity check before we apply it.

Also, tone down the amount of debug messages and
Follow microcode_intel's implementation of pr_debug.

While at it, fix comment at very top to indicate we support ucode
patch loading from fam10h and higher.

Signed-off-by: Aravind Gopalakrishnan <aravind.gopalakrishnan@amd.com>
Reviewed-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
xen/arch/x86/microcode_amd.c

index b2271736917ed7dd84cd9409962a1fef9bb38f9c..e83f4b61edfc79f802c2c1ba6db0a5dc9cf724bb 100644 (file)
@@ -8,7 +8,7 @@
  *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *
  *  This driver allows to upgrade microcode on AMD
- *  family 0x10 and 0x11 processors.
+ *  family 0x10 and later.
  *
  *  Licensed unter the terms of the GNU General Public
  *  License version 2. See file COPYING for details.
@@ -27,6 +27,8 @@
 #include <asm/microcode.h>
 #include <asm/hvm/svm/svm.h>
 
+#define pr_debug(x...) ((void)0)
+
 struct __packed equiv_cpu_entry {
     uint32_t installed_cpu;
     uint32_t fixed_errata_mask;
@@ -88,12 +90,40 @@ static int collect_cpu_info(int cpu, struct cpu_signature *csig)
 
     rdmsrl(MSR_AMD_PATCHLEVEL, csig->rev);
 
-    printk(KERN_DEBUG "microcode: CPU%d collect_cpu_info: patch_id=%#x\n",
-           cpu, csig->rev);
+    pr_debug("microcode: CPU%d collect_cpu_info: patch_id=%#x\n",
+             cpu, csig->rev);
 
     return 0;
 }
 
+static bool_t verify_patch_size(uint32_t patch_size)
+{
+    uint32_t max_size;
+
+#define F1XH_MPB_MAX_SIZE 2048
+#define F14H_MPB_MAX_SIZE 1824
+#define F15H_MPB_MAX_SIZE 4096
+#define F16H_MPB_MAX_SIZE 3458
+
+    switch (boot_cpu_data.x86)
+    {
+    case 0x14:
+        max_size = F14H_MPB_MAX_SIZE;
+        break;
+    case 0x15:
+        max_size = F15H_MPB_MAX_SIZE;
+        break;
+    case 0x16:
+        max_size = F16H_MPB_MAX_SIZE;
+        break;
+    default:
+        max_size = F1XH_MPB_MAX_SIZE;
+        break;
+    }
+
+    return (patch_size <= max_size);
+}
+
 static bool_t microcode_fits(const struct microcode_amd *mc_amd, int cpu)
 {
     struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
@@ -123,12 +153,20 @@ static bool_t microcode_fits(const struct microcode_amd *mc_amd, int cpu)
     if ( (mc_header->processor_rev_id) != equiv_cpu_id )
         return 0;
 
+    if ( !verify_patch_size(mc_amd->mpb_size) )
+    {
+        pr_debug("microcode: patch size mismatch\n");
+        return 0;
+    }
+
     if ( mc_header->patch_id <= uci->cpu_sig.rev )
+    {
+        pr_debug("microcode: patch is already at required level or greater.\n");
         return 0;
+    }
 
-    printk(KERN_DEBUG "microcode: CPU%d found a matching microcode "
-           "update with version %#x (current=%#x)\n",
-           cpu, mc_header->patch_id, uci->cpu_sig.rev);
+    pr_debug("microcode: CPU%d found a matching microcode update with version %#x (current=%#x)\n",
+             cpu, mc_header->patch_id, uci->cpu_sig.rev);
 
     return 1;
 }
@@ -224,10 +262,10 @@ static int get_ucode_from_buffer_amd(
 
     *offset = off + mpbuf->len + 8;
 
-    printk(KERN_DEBUG "microcode: CPU%d size %zu, block size %u offset %zu equivID %#x rev %#x\n",
-           raw_smp_processor_id(), bufsize, mpbuf->len, off,
-           ((struct microcode_header_amd *)mc_amd->mpb)->processor_rev_id,
-           ((struct microcode_header_amd *)mc_amd->mpb)->patch_id);
+    pr_debug("microcode: CPU%d size %zu, block size %u offset %zu equivID %#x rev %#x\n",
+             raw_smp_processor_id(), bufsize, mpbuf->len, off,
+             ((struct microcode_header_amd *)mc_amd->mpb)->processor_rev_id,
+             ((struct microcode_header_amd *)mc_amd->mpb)->patch_id);
 
     return 0;
 }