[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86, microcode: Clean up for Xen coding style, and disable for now



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1221560779 -3600
# Node ID 087b8b29b6b20165062697305c6651ca2acb7b5b
# Parent  087008dfb00504f8d38ee48e197ea1dc8e5cb203
x86, microcode: Clean up for Xen coding style, and disable for now
(until allocations in irq context are fixed).

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/microcode.c        |  360 +++++++++------------
 xen/arch/x86/microcode_amd.c    |  630 +++++++++++++++++++------------------
 xen/arch/x86/microcode_intel.c  |  674 ++++++++++++++++++----------------------
 xen/include/asm-x86/microcode.h |    5 
 4 files changed, 791 insertions(+), 878 deletions(-)

diff -r 087008dfb005 -r 087b8b29b6b2 xen/arch/x86/microcode.c
--- a/xen/arch/x86/microcode.c  Mon Sep 15 17:10:43 2008 +0100
+++ b/xen/arch/x86/microcode.c  Tue Sep 16 11:26:19 2008 +0100
@@ -1,73 +1,24 @@
 /*
- *      Intel CPU Microcode Update Driver for Linux
- *
- *      Copyright (C) 2000-2006 Tigran Aivazian <tigran@xxxxxxxxxxxxxxxxxxxx>
- *                    2006      Shaohua Li <shaohua.li@xxxxxxxxx> *
- *      This driver allows to upgrade microcode on Intel processors
- *      belonging to IA-32 family - PentiumPro, Pentium II,
- *      Pentium III, Xeon, Pentium 4, etc.
- *
- *      Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
- *      Software Developer's Manual
- *      Order Number 253668 or free download from:
- *
- *      http://developer.intel.com/design/pentium4/manuals/253668.htm
- *
- *      For more information, go to http://www.urbanmyth.org/microcode
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- *
- *      1.0     16 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *              Initial release.
- *      1.01    18 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *              Added read() support + cleanups.
- *      1.02    21 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *              Added 'device trimming' support. open(O_WRONLY) zeroes
- *              and frees the saved copy of applied microcode.
- *      1.03    29 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *              Made to use devfs (/dev/cpu/microcode) + cleanups.
- *      1.04    06 Jun 2000, Simon Trimmer <simon@xxxxxxxxxxx>
- *              Added misc device support (now uses both devfs and misc).
- *              Added MICROCODE_IOCFREE ioctl to clear memory.
- *      1.05    09 Jun 2000, Simon Trimmer <simon@xxxxxxxxxxx>
- *              Messages for error cases (non Intel & no suitable microcode).
- *      1.06    03 Aug 2000, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *              Removed ->release(). Removed exclusive open and status bitmap.
- *              Added microcode_rwsem to serialize read()/write()/ioctl().
- *              Removed global kernel lock usage.
- *      1.07    07 Sep 2000, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *              Write 0 to 0x8B msr and then cpuid before reading revision,
- *              so that it works even if there were no update done by the
- *              BIOS. Otherwise, reading from 0x8B gives junk (which happened
- *              to be 0 on my machine which is why it worked even when I
- *              disabled update by the BIOS)
- *              Thanks to Eric W. Biederman <ebiederman@xxxxxxxx> for the fix.
- *      1.08    11 Dec 2000, Richard Schaal <richard.schaal@xxxxxxxxx> and
- *                           Tigran Aivazian <tigran@xxxxxxxxxxx>
- *              Intel Pentium 4 processor support and bugfixes.
- *      1.09    30 Oct 2001, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *              Bugfix for HT (Hyper-Threading) enabled processors
- *              whereby processor resources are shared by all logical 
processors
- *              in a single CPU package.
- *      1.10    28 Feb 2002 Asit K Mallick <asit.k.mallick@xxxxxxxxx> and
- *              Tigran Aivazian <tigran@xxxxxxxxxxx>,
- *              Serialize updates as required on HT processors due to
- *              speculative nature of implementation.
- *      1.11    22 Mar 2002 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *              Fix the panic when writing zero-length microcode chunk.
- *      1.12    29 Sep 2003 Nitin Kamble <nitin.a.kamble@xxxxxxxxx>,
- *              Jun Nakajima <jun.nakajima@xxxxxxxxx>
- *              Support for the microcode updates in the new format.
- *      1.13    10 Oct 2003 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *              Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
- *              because we no longer hold a copy of applied microcode
- *              in kernel memory.
- *      1.14    25 Jun 2004 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *              Fix sigmatch() macro to handle old CPUs with pf == 0.
- *              Thanks to Stuart Swales for pointing out this bug.
+ * Intel CPU Microcode Update Driver for Linux
+ *
+ * Copyright (C) 2000-2006 Tigran Aivazian <tigran@xxxxxxxxxxxxxxxxxxxx>
+ *               2006      Shaohua Li <shaohua.li@xxxxxxxxx> *
+ * This driver allows to upgrade microcode on Intel processors
+ * belonging to IA-32 family - PentiumPro, Pentium II,
+ * Pentium III, Xeon, Pentium 4, etc.
+ *
+ * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
+ * Software Developer's Manual
+ * Order Number 253668 or free download from:
+ *
+ * http://developer.intel.com/design/pentium4/manuals/253668.htm
+ *
+ * For more information, go to http://www.urbanmyth.org/microcode
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
  */
 
 #include <xen/config.h>
@@ -95,8 +46,8 @@ struct ucode_cpu_info ucode_cpu_info[NR_
 struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
 
 struct microcode_buffer {
-       void *buf;
-       size_t size;
+    void *buf;
+    size_t size;
 };
 
 static struct microcode_buffer microcode_buffer;
@@ -104,164 +55,157 @@ static bool_t microcode_error;
 
 static void microcode_fini_cpu(int cpu)
 {
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-       spin_lock(&microcode_mutex);
-       microcode_ops->microcode_fini_cpu(cpu);
-       uci->valid = 0;
-       spin_unlock(&microcode_mutex);
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+    spin_lock(&microcode_mutex);
+    microcode_ops->microcode_fini_cpu(cpu);
+    uci->valid = 0;
+    spin_unlock(&microcode_mutex);
 }
 
 static int collect_cpu_info(int cpu)
 {
-       int err = 0;
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-       memset(uci, 0, sizeof(*uci));
-       err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
-       if (!err)
-               uci->valid = 1;
-
-       return err;
+    int err = 0;
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+    memset(uci, 0, sizeof(*uci));
+    err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
+    if ( !err )
+        uci->valid = 1;
+
+    return err;
 }
 
 static int microcode_resume_cpu(int cpu)
 {
-       int err = 0;
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-       struct cpu_signature nsig;
-
-       gdprintk(XENLOG_INFO, "microcode: CPU%d resumed\n", cpu);
-
-       if (!uci->mc.valid_mc)
-               return -EIO;
-
-       /*
-        * Let's verify that the 'cached' ucode does belong
-        * to this cpu (a bit of paranoia):
-        */
-       err = microcode_ops->collect_cpu_info(cpu, &nsig);
-       if (err) {
-               microcode_fini_cpu(cpu);
-               return err;
-       }
-
-       if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) {
-               microcode_fini_cpu(cpu);
-               /* Should we look for a new ucode here? */
-               return -EIO;
-       }
-
-       err = microcode_ops->apply_microcode(cpu);
-
-       return err;
+    int err = 0;
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+    struct cpu_signature nsig;
+
+    gdprintk(XENLOG_INFO, "microcode: CPU%d resumed\n", cpu);
+
+    if ( !uci->mc.valid_mc )
+        return -EIO;
+
+    /*
+     * Let's verify that the 'cached' ucode does belong
+     * to this cpu (a bit of paranoia):
+     */
+    err = microcode_ops->collect_cpu_info(cpu, &nsig);
+    if ( err )
+    {
+        microcode_fini_cpu(cpu);
+        return err;
+    }
+
+    if ( memcmp(&nsig, &uci->cpu_sig, sizeof(nsig)) )
+    {
+        microcode_fini_cpu(cpu);
+        /* Should we look for a new ucode here? */
+        return -EIO;
+    }
+
+    err = microcode_ops->apply_microcode(cpu);
+
+    return err;
 }
 
 static int microcode_update_cpu(int cpu, const void *buf, size_t size)
 {
-       int err = 0;
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-       /* We should bind the task to the CPU */
-       BUG_ON(raw_smp_processor_id() != cpu);
-
-       spin_lock(&microcode_mutex);
-       /*
-        * Check if the system resume is in progress (uci->valid != NULL),
-        * otherwise just request a firmware:
-        */
-       if (uci->valid) {
-               err = microcode_resume_cpu(cpu);
-       } else {
-               err = collect_cpu_info(cpu);
-               if (err)
-                       goto out;
-               if (uci->valid) {
-                       err = microcode_ops->cpu_request_microcode(cpu, buf, 
size);
-               }
-       }
-
-out:
-       spin_unlock(&microcode_mutex);
-
-       return err;
+    int err = 0;
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(raw_smp_processor_id() != cpu);
+
+    spin_lock(&microcode_mutex);
+
+    /*
+     * Check if the system resume is in progress (uci->valid != NULL),
+     * otherwise just request a firmware:
+     */
+    if ( uci->valid )
+    {
+        err = microcode_resume_cpu(cpu);
+    }
+    else
+    {
+        err = collect_cpu_info(cpu);
+        if ( !err && uci->valid )
+            err = microcode_ops->cpu_request_microcode(cpu, buf, size);
+    }
+
+    spin_unlock(&microcode_mutex);
+
+    return err;
 }
 
 static void do_microcode_update_one(void *info)
 {
-       int error = 0;
-
-       error = microcode_update_cpu(smp_processor_id(),
-                       microcode_buffer.buf, microcode_buffer.size);
-
-       if (error)
-               microcode_error = error;        
+    int error;
+
+    error = microcode_update_cpu(
+        smp_processor_id(), microcode_buffer.buf, microcode_buffer.size);
+
+    if ( error )
+        microcode_error = error;
 }
 
 static int do_microcode_update(void)
 {
-       int error = 0;
-
-       microcode_error = 0;
-
-       if (on_each_cpu(do_microcode_update_one, NULL, 1, 1) != 0) {
-               printk(KERN_ERR "microcode: Error! Could not run on all 
processors\n");
-               error = -EIO;
-               goto out;
-       }
-
-       if (microcode_error) {
-               error = microcode_error;
-               goto out;
-       }
-
-out:
-       return error;
+    int error = 0;
+
+    microcode_error = 0;
+
+    if ( on_each_cpu(do_microcode_update_one, NULL, 1, 1) != 0 )
+    {
+        printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
+        error = -EIO;
+        goto out;
+    }
+
+    if ( microcode_error )
+    {
+        error = microcode_error;
+        goto out;
+    }
+
+ out:
+    return error;
 }
 
 int microcode_update(XEN_GUEST_HANDLE(const_void) buf, unsigned long len)
 {
-       int ret;
-       struct cpuinfo_x86 *c = &boot_cpu_data;
-
-       if (len != (typeof(microcode_buffer.size))len) {
-               printk(KERN_ERR "microcode: too much data\n");
-               return -E2BIG;
-       }
-
-       switch (c->x86_vendor) {
-       case X86_VENDOR_AMD:
-               ret = microcode_init_amd(c);
-               break;
-
-       case X86_VENDOR_INTEL:
-               ret = microcode_init_intel(c);
-               break;
-       default:
-               printk(KERN_ERR "microcode: CPU vendor not supported\n");
-               ret = -EINVAL;
-               break;
-       }
-
-       if (ret != 0)
-               return ret;
-
-       microcode_buffer.buf = xmalloc_array(uint8_t, len);
-       if (!microcode_buffer.buf)
-               return -ENOMEM;
-
-       ret = copy_from_guest(microcode_buffer.buf, buf, len);
-       if (ret != 0)
-               return ret;
-
-       microcode_buffer.size = len;
-       wmb();
-
-       ret = do_microcode_update();
-
-       xfree(microcode_buffer.buf);
-       microcode_buffer.buf = NULL;
-       microcode_buffer.size = 0;
-
-       return ret;
-}
+    int ret;
+
+    /* XXX FIXME: No allocations in interrupt context. */
+    return -EINVAL;
+
+    if ( len != (typeof(microcode_buffer.size))len )
+    {
+        printk(KERN_ERR "microcode: too much data\n");
+        return -E2BIG;
+    }
+
+    if (microcode_ops == NULL)
+        return -EINVAL;
+
+    microcode_buffer.buf = xmalloc_array(uint8_t, len);
+    if ( microcode_buffer.buf == NULL )
+        return -ENOMEM;
+
+    ret = copy_from_guest(microcode_buffer.buf, buf, len);
+    if ( ret != 0 )
+        return ret;
+
+    microcode_buffer.size = len;
+    wmb();
+
+    ret = do_microcode_update();
+
+    xfree(microcode_buffer.buf);
+    microcode_buffer.buf = NULL;
+    microcode_buffer.size = 0;
+
+    return ret;
+}
diff -r 087008dfb005 -r 087b8b29b6b2 xen/arch/x86/microcode_amd.c
--- a/xen/arch/x86/microcode_amd.c      Mon Sep 15 17:10:43 2008 +0100
+++ b/xen/arch/x86/microcode_amd.c      Tue Sep 16 11:26:19 2008 +0100
@@ -12,7 +12,7 @@
  *
  *  Licensed unter the terms of the GNU General Public
  *  License version 2. See file COPYING for details.
-*/
+ */
 
 #include <xen/config.h>
 #include <xen/lib.h>
@@ -27,28 +27,21 @@
 #include <asm/processor.h>
 #include <asm/microcode.h>
 
-
 #define pr_debug(x...) ((void)0)
-#define DEFINE_MUTEX(_m) DEFINE_SPINLOCK(_m)
-#define mutex_lock(_m) spin_lock(_m)
-#define mutex_unlock(_m) spin_unlock(_m)
-#define vmalloc(_s) xmalloc_bytes(_s)
-#define vfree(_p) xfree(_p)
-
 
 #define UCODE_MAGIC                0x00414d44
 #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
 #define UCODE_UCODE_TYPE           0x00000001
 
 #define UCODE_MAX_SIZE          (2048)
-#define DEFAULT_UCODE_DATASIZE (896)
-#define MC_HEADER_SIZE         (sizeof(struct microcode_header_amd))
+#define DEFAULT_UCODE_DATASIZE  (896)
+#define MC_HEADER_SIZE          (sizeof(struct microcode_header_amd))
 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
-#define DWSIZE                 (sizeof(uint32_t))
+#define DWSIZE                  (sizeof(uint32_t))
 /* For now we support a fixed ucode total size only */
 #define get_totalsize(mc) \
-       ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \
-        + MC_HEADER_SIZE)
+        ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \
+         + MC_HEADER_SIZE)
 
 /* serialize access to the physical write */
 static DEFINE_SPINLOCK(microcode_update_lock);
@@ -57,309 +50,330 @@ struct equiv_cpu_entry *equiv_cpu_table;
 
 static long install_equiv_cpu_table(const void *, uint32_t, long);
 
-static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
-{
-       struct cpuinfo_x86 *c = &cpu_data[cpu];
-
-       memset(csig, 0, sizeof(*csig));
-
-       if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
-               printk(KERN_ERR "microcode: CPU%d not a capable AMD 
processor\n",
-                      cpu);
-               return -1;
-       }
-
-       asm volatile("movl %1, %%ecx; rdmsr"
-                    : "=a" (csig->rev)
-                    : "i" (MSR_AMD_PATCHLEVEL) : "ecx");
-
-       printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n",
-               csig->rev);
-
-       return 0;
-}
-
-static int get_matching_microcode_amd(void *mc, int cpu)
-{
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-       struct microcode_header_amd *mc_header = mc;
-       unsigned long total_size = get_totalsize(mc_header);
-       void *new_mc;
-       unsigned int current_cpu_id;
-       unsigned int equiv_cpu_id = 0x00;
-       unsigned int i = 0;
-
-       /* We should bind the task to the CPU */
-       BUG_ON(cpu != raw_smp_processor_id());
-
-       /* This is a tricky part. We might be called from a write operation
-        * to the device file instead of the usual process of firmware
-        * loading. This routine needs to be able to distinguish both
-        * cases. This is done by checking if there already is a equivalent
-        * CPU table installed. If not, we're written through
-        * /dev/cpu/microcode.
-        * Since we ignore all checks. The error case in which going through
-        * firmware loading and that table is not loaded has already been
-        * checked earlier.
-        */
-       if (equiv_cpu_table == NULL) {
-               printk(KERN_INFO "microcode: CPU%d microcode update with "
-                      "version 0x%x (current=0x%x)\n",
-                      cpu, mc_header->patch_id, uci->cpu_sig.rev);
-               goto out;
-       }
-
-       current_cpu_id = cpuid_eax(0x00000001);
-
-       while (equiv_cpu_table[i].installed_cpu != 0) {
-               if (current_cpu_id == equiv_cpu_table[i].installed_cpu) {
-                       equiv_cpu_id = equiv_cpu_table[i].equiv_cpu;
-                       break;
-               }
-               i++;
-       }
-
-       if (!equiv_cpu_id) {
-               printk(KERN_ERR "microcode: CPU%d cpu_id "
-                      "not found in equivalent cpu table \n", cpu);
-               return 0;
-       }
-
-       if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) {
-               printk(KERN_INFO
-                       "microcode: CPU%d patch does not match "
-                       "(patch is %x, cpu extended is %x) \n",
-                       cpu, mc_header->processor_rev_id[0],
-                       (equiv_cpu_id & 0xff));
-               return 0;
-       }
-
-       if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) {
-               printk(KERN_INFO "microcode: CPU%d patch does not match "
-                       "(patch is %x, cpu base id is %x) \n",
-                       cpu, mc_header->processor_rev_id[1],
-                       ((equiv_cpu_id >> 16) & 0xff));
-
-               return 0;
-       }
-
-       if (mc_header->patch_id <= uci->cpu_sig.rev)
-               return 0;
-
-       printk(KERN_INFO "microcode: CPU%d found a matching microcode "
-              "update with version 0x%x (current=0x%x)\n",
-              cpu, mc_header->patch_id, uci->cpu_sig.rev);
-
-out:
-       new_mc = vmalloc(UCODE_MAX_SIZE);
-       if (!new_mc) {
-               printk(KERN_ERR "microcode: error, can't allocate memory\n");
-               return -ENOMEM;
-       }
-       memset(new_mc, 0, UCODE_MAX_SIZE);
-
-       /* free previous update file */
-       vfree(uci->mc.mc_amd);
-
-       memcpy(new_mc, mc, total_size);
-
-       uci->mc.mc_amd = new_mc;
-       return 1;
-}
-
-static int apply_microcode_amd(int cpu)
-{
-       unsigned long flags;
-       uint32_t eax, edx, rev;
-       int cpu_num = raw_smp_processor_id();
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-       uint64_t addr;
-
-       /* We should bind the task to the CPU */
-       BUG_ON(cpu_num != cpu);
-
-       if (uci->mc.mc_amd == NULL)
-               return -EINVAL;
-
-       spin_lock_irqsave(&microcode_update_lock, flags);
-
-       addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code;
-       edx = (uint32_t)(addr >> 32);
-       eax = (uint32_t)addr;
-
-       asm volatile("movl %0, %%ecx; wrmsr" :
-                    : "i" (MSR_AMD_PATCHLOADER), "a" (eax), "d" (edx) : "ecx");
-
-       /* get patch id after patching */
-       asm volatile("movl %1, %%ecx; rdmsr"
-                    : "=a" (rev)
-                    : "i" (MSR_AMD_PATCHLEVEL) : "ecx");
-
-       spin_unlock_irqrestore(&microcode_update_lock, flags);
-
-       /* check current patch id and patch's id for match */
-       if (rev != uci->mc.mc_amd->hdr.patch_id) {
-               printk(KERN_ERR "microcode: CPU%d update from revision "
-                      "0x%x to 0x%x failed\n", cpu_num,
-                      uci->mc.mc_amd->hdr.patch_id, rev);
-               return -EIO;
-       }
-
-       printk("microcode: CPU%d updated from revision "
-              "0x%x to 0x%x \n",
-              cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id);
-
-       uci->cpu_sig.rev = rev;
-
-       return 0;
+static int collect_cpu_info(int cpu, struct cpu_signature *csig)
+{
+    struct cpuinfo_x86 *c = &cpu_data[cpu];
+
+    memset(csig, 0, sizeof(*csig));
+
+    if ( (c->x86_vendor != X86_VENDOR_AMD) || (c->x86 < 0x10) )
+    {
+        printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n",
+               cpu);
+        return -1;
+    }
+
+    asm volatile("movl %1, %%ecx; rdmsr"
+                 : "=a" (csig->rev)
+                 : "i" (MSR_AMD_PATCHLEVEL) : "ecx");
+
+    printk(KERN_INFO "microcode: collect_cpu_info: patch_id=0x%x\n",
+           csig->rev);
+
+    return 0;
+}
+
+static int get_matching_microcode(void *mc, int cpu)
+{
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+    struct microcode_header_amd *mc_header = mc;
+    unsigned long total_size = get_totalsize(mc_header);
+    void *new_mc;
+    unsigned int current_cpu_id;
+    unsigned int equiv_cpu_id = 0x00;
+    unsigned int i = 0;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu != raw_smp_processor_id());
+
+    /* This is a tricky part. We might be called from a write operation
+     * to the device file instead of the usual process of firmware
+     * loading. This routine needs to be able to distinguish both
+     * cases. This is done by checking if there already is a equivalent
+     * CPU table installed. If not, we're written through
+     * /dev/cpu/microcode.
+     * Since we ignore all checks. The error case in which going through
+     * firmware loading and that table is not loaded has already been
+     * checked earlier.
+     */
+    if ( equiv_cpu_table == NULL )
+    {
+        printk(KERN_INFO "microcode: CPU%d microcode update with "
+               "version 0x%x (current=0x%x)\n",
+               cpu, mc_header->patch_id, uci->cpu_sig.rev);
+        goto out;
+    }
+
+    current_cpu_id = cpuid_eax(0x00000001);
+
+    while ( equiv_cpu_table[i].installed_cpu != 0 )
+    {
+        if ( current_cpu_id == equiv_cpu_table[i].installed_cpu )
+        {
+            equiv_cpu_id = equiv_cpu_table[i].equiv_cpu;
+            break;
+        }
+        i++;
+    }
+
+    if ( !equiv_cpu_id )
+    {
+        printk(KERN_ERR "microcode: CPU%d cpu_id "
+               "not found in equivalent cpu table \n", cpu);
+        return 0;
+    }
+
+    if ( (mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff) )
+    {
+        printk(KERN_INFO
+               "microcode: CPU%d patch does not match "
+               "(patch is %x, cpu extended is %x) \n",
+               cpu, mc_header->processor_rev_id[0],
+               (equiv_cpu_id & 0xff));
+        return 0;
+    }
+
+    if ( (mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff) )
+    {
+        printk(KERN_INFO "microcode: CPU%d patch does not match "
+               "(patch is %x, cpu base id is %x) \n",
+               cpu, mc_header->processor_rev_id[1],
+               ((equiv_cpu_id >> 16) & 0xff));
+        return 0;
+    }
+
+    if ( mc_header->patch_id <= uci->cpu_sig.rev )
+        return 0;
+
+    printk(KERN_INFO "microcode: CPU%d found a matching microcode "
+           "update with version 0x%x (current=0x%x)\n",
+           cpu, mc_header->patch_id, uci->cpu_sig.rev);
+
+ out:
+    new_mc = xmalloc_bytes(UCODE_MAX_SIZE);
+    if ( new_mc == NULL )
+    {
+        printk(KERN_ERR "microcode: error, can't allocate memory\n");
+        return -ENOMEM;
+    }
+    memset(new_mc, 0, UCODE_MAX_SIZE);
+
+    /* free previous update file */
+    xfree(uci->mc.mc_amd);
+
+    memcpy(new_mc, mc, total_size);
+
+    uci->mc.mc_amd = new_mc;
+    return 1;
+}
+
+static int apply_microcode(int cpu)
+{
+    unsigned long flags;
+    uint32_t eax, edx, rev;
+    int cpu_num = raw_smp_processor_id();
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+    uint64_t addr;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu_num != cpu);
+
+    if ( uci->mc.mc_amd == NULL )
+        return -EINVAL;
+
+    spin_lock_irqsave(&microcode_update_lock, flags);
+
+    addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code;
+    edx = (uint32_t)(addr >> 32);
+    eax = (uint32_t)addr;
+
+    asm volatile("movl %0, %%ecx; wrmsr" :
+                 : "i" (MSR_AMD_PATCHLOADER), "a" (eax), "d" (edx) : "ecx");
+
+    /* get patch id after patching */
+    asm volatile("movl %1, %%ecx; rdmsr"
+                 : "=a" (rev)
+                 : "i" (MSR_AMD_PATCHLEVEL) : "ecx");
+
+    spin_unlock_irqrestore(&microcode_update_lock, flags);
+
+    /* check current patch id and patch's id for match */
+    if ( rev != uci->mc.mc_amd->hdr.patch_id )
+    {
+        printk(KERN_ERR "microcode: CPU%d update from revision "
+               "0x%x to 0x%x failed\n", cpu_num,
+               uci->mc.mc_amd->hdr.patch_id, rev);
+        return -EIO;
+    }
+
+    printk("microcode: CPU%d updated from revision "
+           "0x%x to 0x%x \n",
+           cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id);
+
+    uci->cpu_sig.rev = rev;
+
+    return 0;
 }
 
 static long get_next_ucode_from_buffer_amd(void **mc, const void *buf,
-                                      unsigned long size, long offset)
-{
-       struct microcode_header_amd *mc_header;
-       unsigned long total_size;
-       const uint8_t *buf_pos = buf;
-
-       /* No more data */
-       if (offset >= size)
-               return 0;
-
-       if (buf_pos[offset] != UCODE_UCODE_TYPE) {
-               printk(KERN_ERR "microcode: error! "
-                      "Wrong microcode payload type field\n");
-               return -EINVAL;
-       }
-
-       mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
-
-       total_size = (unsigned long) (buf_pos[offset+4] +
-                                     (buf_pos[offset+5] << 8));
-
-       printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n",
-               size, total_size, offset);
-
-       if (offset + total_size > size) {
-               printk(KERN_ERR "microcode: error! Bad data in microcode data 
file\n");
-               return -EINVAL;
-       }
-
-       *mc = vmalloc(UCODE_MAX_SIZE);
-       if (!*mc) {
-               printk(KERN_ERR "microcode: error! "
-                      "Can not allocate memory for microcode patch\n");
-               return -ENOMEM;
-       }
-
-       memset(*mc, 0, UCODE_MAX_SIZE);
-       memcpy(*mc, (const void *)(buf + offset + 8), total_size);
-
-       return offset + total_size + 8;
+                                           unsigned long size, long offset)
+{
+    struct microcode_header_amd *mc_header;
+    unsigned long total_size;
+    const uint8_t *buf_pos = buf;
+
+    /* No more data */
+    if ( offset >= size )
+        return 0;
+
+    if ( buf_pos[offset] != UCODE_UCODE_TYPE )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Wrong microcode payload type field\n");
+        return -EINVAL;
+    }
+
+    mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
+
+    total_size = (unsigned long) (buf_pos[offset+4] +
+                                  (buf_pos[offset+5] << 8));
+
+    printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n",
+           size, total_size, offset);
+
+    if ( (offset + total_size) > size )
+    {
+        printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+        return -EINVAL;
+    }
+
+    *mc = xmalloc_bytes(UCODE_MAX_SIZE);
+    if ( *mc == NULL )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Can not allocate memory for microcode patch\n");
+        return -ENOMEM;
+    }
+
+    memset(*mc, 0, UCODE_MAX_SIZE);
+    memcpy(*mc, (const void *)(buf + offset + 8), total_size);
+
+    return offset + total_size + 8;
 }
 
 static long install_equiv_cpu_table(const void *buf,
-                               uint32_t size, long offset)
-{
-       const uint32_t *buf_pos = buf;
-
-       /* No more data */
-       if (offset >= size)
-               return 0;
-
-       if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) {
-               printk(KERN_ERR "microcode: error! "
-                      "Wrong microcode equivalnet cpu table type field\n");
-               return 0;
-       }
-
-       if (size == 0) {
-               printk(KERN_ERR "microcode: error! "
-                      "Wrong microcode equivalnet cpu table length\n");
-               return 0;
-       }
-
-       equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size);
-       if (!equiv_cpu_table) {
-               printk(KERN_ERR "microcode: error, can't allocate memory for 
equiv CPU table\n");
-               return 0;
-       }
-
-       memset(equiv_cpu_table, 0, size);
-       memcpy(equiv_cpu_table, (const void *)&buf_pos[3], size);
-
-       return size + 12; /* add header length */
-}
-
-static int cpu_request_microcode_amd(int cpu, const void *buf,
-                               size_t size)
-{
-       const uint32_t *buf_pos;
-       long offset = 0;
-       int error = 0;
-       void *mc;
-
-       /* We should bind the task to the CPU */
-       BUG_ON(cpu != raw_smp_processor_id());
-
-       buf_pos = (const uint32_t *)buf;
-
-       if (buf_pos[0] != UCODE_MAGIC) {
-               printk(KERN_ERR "microcode: error! Wrong microcode patch file 
magic\n");
-               return -EINVAL;
-       }
-
-       offset = install_equiv_cpu_table(buf, (uint32_t)(buf_pos[2]), offset);
-       if (!offset) {
-               printk(KERN_ERR "microcode: installing equivalent cpu table 
failed\n");
-               return -EINVAL;
-       }
-
-       while ((offset =
-               get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) {
-               error = get_matching_microcode_amd(mc, cpu);
-               if (error < 0)
-                       break;
-               /*
-                * It's possible the data file has multiple matching ucode,
-                * lets keep searching till the latest version
-                */
-               if (error == 1) {
-                       apply_microcode_amd(cpu);
-                       error = 0;
-               }
-               vfree(mc);
-       }
-       if (offset > 0) {
-               vfree(mc);
-               vfree(equiv_cpu_table);
-               equiv_cpu_table = NULL;
-       }
-       if (offset < 0)
-               error = offset;
-
-       return error;
-}
-
-static void microcode_fini_cpu_amd(int cpu)
-{
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-       vfree(uci->mc.mc_amd);
-       uci->mc.mc_amd = NULL;
+                                    uint32_t size, long offset)
+{
+    const uint32_t *buf_pos = buf;
+
+    /* No more data */
+    if ( offset >= size )
+        return 0;
+
+    if ( buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Wrong microcode equivalnet cpu table type field\n");
+        return 0;
+    }
+
+    if ( size == 0 )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Wrong microcode equivalnet cpu table length\n");
+        return 0;
+    }
+
+    equiv_cpu_table = xmalloc_bytes(size);
+    if ( equiv_cpu_table == NULL )
+    {
+        printk(KERN_ERR "microcode: error, can't allocate "
+               "memory for equiv CPU table\n");
+        return 0;
+    }
+
+    memset(equiv_cpu_table, 0, size);
+    memcpy(equiv_cpu_table, (const void *)&buf_pos[3], size);
+
+    return size + 12; /* add header length */
+}
+
+static int cpu_request_microcode(int cpu, const void *buf, size_t size)
+{
+    const uint32_t *buf_pos;
+    long offset = 0;
+    int error = 0;
+    void *mc;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu != raw_smp_processor_id());
+
+    buf_pos = (const uint32_t *)buf;
+
+    if ( buf_pos[0] != UCODE_MAGIC )
+    {
+        printk(KERN_ERR "microcode: error! Wrong "
+               "microcode patch file magic\n");
+        return -EINVAL;
+    }
+
+    offset = install_equiv_cpu_table(buf, (uint32_t)(buf_pos[2]), offset);
+    if ( !offset )
+    {
+        printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
+        return -EINVAL;
+    }
+
+    while ( (offset =
+             get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0 )
+    {
+        error = get_matching_microcode(mc, cpu);
+        if ( error < 0 )
+            break;
+        /*
+         * It's possible the data file has multiple matching ucode,
+         * lets keep searching till the latest version
+         */
+        if ( error == 1 )
+        {
+            apply_microcode(cpu);
+            error = 0;
+        }
+        xfree(mc);
+    }
+    if ( offset > 0 )
+    {
+        xfree(mc);
+        xfree(equiv_cpu_table);
+        equiv_cpu_table = NULL;
+    }
+    if ( offset < 0 )
+        error = offset;
+
+    return error;
+}
+
+static void microcode_fini_cpu(int cpu)
+{
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+    xfree(uci->mc.mc_amd);
+    uci->mc.mc_amd = NULL;
 }
 
 static struct microcode_ops microcode_amd_ops = {
-       .get_matching_microcode           = get_matching_microcode_amd,
-       .microcode_sanity_check           = NULL,
-       .cpu_request_microcode            = cpu_request_microcode_amd,
-       .collect_cpu_info                 = collect_cpu_info_amd,
-       .apply_microcode                  = apply_microcode_amd,
-       .microcode_fini_cpu               = microcode_fini_cpu_amd,
+    .get_matching_microcode           = get_matching_microcode,
+    .microcode_sanity_check           = NULL,
+    .cpu_request_microcode            = cpu_request_microcode,
+    .collect_cpu_info                 = collect_cpu_info,
+    .apply_microcode                  = apply_microcode,
+    .microcode_fini_cpu               = microcode_fini_cpu,
 };
 
-int microcode_init_amd(struct cpuinfo_x86 *c)
-{
-       microcode_ops = &microcode_amd_ops;
-       return 0;
-}
-
+static __init int microcode_init_amd(void)
+{
+    if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+        microcode_ops = &microcode_amd_ops;
+    return 0;
+}
+__initcall(microcode_init_amd);
diff -r 087008dfb005 -r 087b8b29b6b2 xen/arch/x86/microcode_intel.c
--- a/xen/arch/x86/microcode_intel.c    Mon Sep 15 17:10:43 2008 +0100
+++ b/xen/arch/x86/microcode_intel.c    Tue Sep 16 11:26:19 2008 +0100
@@ -1,73 +1,24 @@
 /*
- *     Intel CPU Microcode Update Driver for Linux
- *
- *     Copyright (C) 2000-2006 Tigran Aivazian <tigran@xxxxxxxxxxxxxxxxxxxx>
- *                   2006      Shaohua Li <shaohua.li@xxxxxxxxx> *
- *     This driver allows to upgrade microcode on Intel processors
- *     belonging to IA-32 family - PentiumPro, Pentium II,
- *     Pentium III, Xeon, Pentium 4, etc.
- *
- *     Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
- *     Software Developer's Manual
- *     Order Number 253668 or free download from:
- *
- *     http://developer.intel.com/design/pentium4/manuals/253668.htm
- *
- *     For more information, go to http://www.urbanmyth.org/microcode
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     1.0     16 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *             Initial release.
- *     1.01    18 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *             Added read() support + cleanups.
- *     1.02    21 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *             Added 'device trimming' support. open(O_WRONLY) zeroes
- *             and frees the saved copy of applied microcode.
- *     1.03    29 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *             Made to use devfs (/dev/cpu/microcode) + cleanups.
- *     1.04    06 Jun 2000, Simon Trimmer <simon@xxxxxxxxxxx>
- *             Added misc device support (now uses both devfs and misc).
- *             Added MICROCODE_IOCFREE ioctl to clear memory.
- *     1.05    09 Jun 2000, Simon Trimmer <simon@xxxxxxxxxxx>
- *             Messages for error cases (non Intel & no suitable microcode).
- *     1.06    03 Aug 2000, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Removed ->release(). Removed exclusive open and status bitmap.
- *             Added microcode_rwsem to serialize read()/write()/ioctl().
- *             Removed global kernel lock usage.
- *     1.07    07 Sep 2000, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Write 0 to 0x8B msr and then cpuid before reading revision,
- *             so that it works even if there were no update done by the
- *             BIOS. Otherwise, reading from 0x8B gives junk (which happened
- *             to be 0 on my machine which is why it worked even when I
- *             disabled update by the BIOS)
- *             Thanks to Eric W. Biederman <ebiederman@xxxxxxxx> for the fix.
- *     1.08    11 Dec 2000, Richard Schaal <richard.schaal@xxxxxxxxx> and
- *                          Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Intel Pentium 4 processor support and bugfixes.
- *     1.09    30 Oct 2001, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Bugfix for HT (Hyper-Threading) enabled processors
- *             whereby processor resources are shared by all logical processors
- *             in a single CPU package.
- *     1.10    28 Feb 2002 Asit K Mallick <asit.k.mallick@xxxxxxxxx> and
- *             Tigran Aivazian <tigran@xxxxxxxxxxx>,
- *             Serialize updates as required on HT processors due to
- *             speculative nature of implementation.
- *     1.11    22 Mar 2002 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Fix the panic when writing zero-length microcode chunk.
- *     1.12    29 Sep 2003 Nitin Kamble <nitin.a.kamble@xxxxxxxxx>,
- *             Jun Nakajima <jun.nakajima@xxxxxxxxx>
- *             Support for the microcode updates in the new format.
- *     1.13    10 Oct 2003 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
- *             because we no longer hold a copy of applied microcode
- *             in kernel memory.
- *     1.14    25 Jun 2004 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Fix sigmatch() macro to handle old CPUs with pf == 0.
- *             Thanks to Stuart Swales for pointing out this bug.
+ * Intel CPU Microcode Update Driver for Linux
+ *
+ * Copyright (C) 2000-2006 Tigran Aivazian <tigran@xxxxxxxxxxxxxxxxxxxx>
+ *               2006 Shaohua Li <shaohua.li@xxxxxxxxx> *
+ * This driver allows to upgrade microcode on Intel processors
+ * belonging to IA-32 family - PentiumPro, Pentium II,
+ * Pentium III, Xeon, Pentium 4, etc.
+ *
+ * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
+ * Software Developer's Manual
+ * Order Number 253668 or free download from:
+ *
+ * http://developer.intel.com/design/pentium4/manuals/253668.htm
+ *
+ * For more information, go to http://www.urbanmyth.org/microcode
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
  */
 
 #include <xen/config.h>
@@ -84,35 +35,24 @@
 #include <asm/microcode.h>
 
 #define pr_debug(x...) ((void)0)
-#define DEFINE_MUTEX(_m) DEFINE_SPINLOCK(_m)
-#define mutex_lock(_m) spin_lock(_m)
-#define mutex_unlock(_m) spin_unlock(_m)
-#define vmalloc(_s) xmalloc_bytes(_s)
-#define vfree(_p) xfree(_p)
-
-#if 0
-MODULE_DESCRIPTION("Microcode Update Driver");
-MODULE_AUTHOR("Tigran Aivazian <tigran@xxxxxxxxxxxxxxxxxxxx>");
-MODULE_LICENSE("GPL");
-#endif
-
-#define DEFAULT_UCODE_DATASIZE         (2000)
-#define MC_HEADER_SIZE         (sizeof(struct microcode_header_intel))
+
+#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 DWSIZE                 (sizeof(u32))
+#define EXT_HEADER_SIZE         (sizeof(struct extended_sigtable))
+#define EXT_SIGNATURE_SIZE      (sizeof(struct extended_signature))
+#define DWSIZE                  (sizeof(u32))
 #define get_totalsize(mc) \
-       (((struct microcode_intel *)mc)->hdr.totalsize ? \
-        ((struct microcode_intel *)mc)->hdr.totalsize : \
-        DEFAULT_UCODE_TOTALSIZE)
+        (((struct microcode_intel *)mc)->hdr.totalsize ? \
+         ((struct microcode_intel *)mc)->hdr.totalsize : \
+         DEFAULT_UCODE_TOTALSIZE)
 
 #define get_datasize(mc) \
-       (((struct microcode_intel *)mc)->hdr.datasize ? \
-        ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
+        (((struct microcode_intel *)mc)->hdr.datasize ? \
+         ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
 
 #define sigmatch(s1, s2, p1, p2) \
-       (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
+        (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
 
 #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
 
@@ -121,125 +61,135 @@ static DEFINE_SPINLOCK(microcode_update_
 
 static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
 {
-       struct cpuinfo_x86 *c = &cpu_data[cpu_num];
-       unsigned int val[2];
-
-       memset(csig, 0, sizeof(*csig));
-
-       if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
-           cpu_has(c, X86_FEATURE_IA64)) {
-               printk(KERN_ERR "microcode: CPU%d not a capable Intel "
-                       "processor\n", cpu_num);
-               return -1;
-       }
-
-       csig->sig = cpuid_eax(0x00000001);
-
-       if ((c->x86_model >= 5) || (c->x86 > 6)) {
-               /* get processor flags from MSR 0x17 */
-               rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-               csig->pf = 1 << ((val[1] >> 18) & 7);
-       }
-
-       wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-       /* see notes above for revision 1.07.  Apparent chip bug */
-       sync_core();
-       /* get the current revision from MSR 0x8B */
-       rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
-       pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
-                       csig->sig, csig->pf, csig->rev);
-
-       return 0;
-}
-
-static inline int microcode_update_match(int cpu_num,
-       struct microcode_header_intel *mc_header, int sig, int pf)
-{
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-       if (!sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf)
-               || mc_header->rev <= uci->cpu_sig.rev)
-               return 0;
-       return 1;
+    struct cpuinfo_x86 *c = &cpu_data[cpu_num];
+    unsigned int val[2];
+
+    memset(csig, 0, sizeof(*csig));
+
+    if ( (c->x86_vendor != X86_VENDOR_INTEL) || (c->x86 < 6) ||
+         cpu_has(c, X86_FEATURE_IA64) )
+    {
+        printk(KERN_ERR "microcode: CPU%d not a capable Intel "
+               "processor\n", cpu_num);
+        return -1;
+    }
+
+    csig->sig = cpuid_eax(0x00000001);
+
+    if ( (c->x86_model >= 5) || (c->x86 > 6) )
+    {
+        /* get processor flags from MSR 0x17 */
+        rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+        csig->pf = 1 << ((val[1] >> 18) & 7);
+    }
+
+    wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+    /* see notes above for revision 1.07.  Apparent chip bug */
+    sync_core();
+    /* get the current revision from MSR 0x8B */
+    rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
+    pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
+             csig->sig, csig->pf, csig->rev);
+
+    return 0;
+}
+
+static inline int microcode_update_match(
+    int cpu_num, struct microcode_header_intel *mc_header, int sig, int pf)
+{
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+
+    return (sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf) &&
+            (mc_header->rev > uci->cpu_sig.rev));
 }
 
 static int microcode_sanity_check(void *mc)
 {
-       struct microcode_header_intel *mc_header = mc;
-       struct extended_sigtable *ext_header = NULL;
-       struct extended_signature *ext_sig;
-       unsigned long total_size, data_size, ext_table_size;
-       int sum, orig_sum, ext_sigcount = 0, i;
-
-       total_size = get_totalsize(mc_header);
-       data_size = get_datasize(mc_header);
-       if (data_size + MC_HEADER_SIZE > total_size) {
-               printk(KERN_ERR "microcode: error! "
-                       "Bad data size in microcode data file\n");
-               return -EINVAL;
-       }
-
-       if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
-               printk(KERN_ERR "microcode: error! "
-                       "Unknown microcode update format\n");
-               return -EINVAL;
-       }
-       ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
-       if (ext_table_size) {
-               if ((ext_table_size < EXT_HEADER_SIZE)
-                || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
-                       printk(KERN_ERR "microcode: error! "
-                               "Small exttable size in microcode data file\n");
-                       return -EINVAL;
-               }
-               ext_header = mc + MC_HEADER_SIZE + data_size;
-               if (ext_table_size != exttable_size(ext_header)) {
-                       printk(KERN_ERR "microcode: error! "
-                               "Bad exttable size in microcode data file\n");
-                       return -EFAULT;
-               }
-               ext_sigcount = ext_header->count;
-       }
-
-       /* check extended table checksum */
-       if (ext_table_size) {
-               int ext_table_sum = 0;
-               int *ext_tablep = (int *)ext_header;
-
-               i = ext_table_size / DWSIZE;
-               while (i--)
-                       ext_table_sum += ext_tablep[i];
-               if (ext_table_sum) {
-                       printk(KERN_WARNING "microcode: aborting, "
-                               "bad extended signature table checksum\n");
-                       return -EINVAL;
-               }
-       }
-
-       /* calculate the checksum */
-       orig_sum = 0;
-       i = (MC_HEADER_SIZE + data_size) / DWSIZE;
-       while (i--)
-               orig_sum += ((int *)mc)[i];
-       if (orig_sum) {
-               printk(KERN_ERR "microcode: aborting, bad checksum\n");
-               return -EINVAL;
-       }
-       if (!ext_table_size)
-               return 0;
-       /* check extended signature checksum */
-       for (i = 0; i < ext_sigcount; i++) {
-               ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
-                         EXT_SIGNATURE_SIZE * i;
-               sum = orig_sum
-                       - (mc_header->sig + mc_header->pf + mc_header->cksum)
-                       + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
-               if (sum) {
-                       printk(KERN_ERR "microcode: aborting, bad checksum\n");
-                       return -EINVAL;
-               }
-       }
-       return 0;
+    struct microcode_header_intel *mc_header = mc;
+    struct extended_sigtable *ext_header = NULL;
+    struct extended_signature *ext_sig;
+    unsigned long total_size, data_size, ext_table_size;
+    int sum, orig_sum, ext_sigcount = 0, i;
+
+    total_size = get_totalsize(mc_header);
+    data_size = get_datasize(mc_header);
+    if ( (data_size + MC_HEADER_SIZE) > total_size )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Bad data size in microcode data file\n");
+        return -EINVAL;
+    }
+
+    if ( (mc_header->ldrver != 1) || (mc_header->hdrver != 1) )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Unknown microcode update format\n");
+        return -EINVAL;
+    }
+    ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+    if ( ext_table_size )
+    {
+        if ( (ext_table_size < EXT_HEADER_SIZE) ||
+             ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE) )
+        {
+            printk(KERN_ERR "microcode: error! "
+                   "Small exttable size in microcode data file\n");
+            return -EINVAL;
+        }
+        ext_header = mc + MC_HEADER_SIZE + data_size;
+        if ( ext_table_size != exttable_size(ext_header) )
+        {
+            printk(KERN_ERR "microcode: error! "
+                   "Bad exttable size in microcode data file\n");
+            return -EFAULT;
+        }
+        ext_sigcount = ext_header->count;
+    }
+
+    /* check extended table checksum */
+    if ( ext_table_size )
+    {
+        int ext_table_sum = 0;
+        int *ext_tablep = (int *)ext_header;
+
+        i = ext_table_size / DWSIZE;
+        while ( i-- )
+            ext_table_sum += ext_tablep[i];
+        if ( ext_table_sum )
+        {
+            printk(KERN_WARNING "microcode: aborting, "
+                   "bad extended signature table checksum\n");
+            return -EINVAL;
+        }
+    }
+
+    /* calculate the checksum */
+    orig_sum = 0;
+    i = (MC_HEADER_SIZE + data_size) / DWSIZE;
+    while ( i-- )
+        orig_sum += ((int *)mc)[i];
+    if ( orig_sum )
+    {
+        printk(KERN_ERR "microcode: aborting, bad checksum\n");
+        return -EINVAL;
+    }
+    if ( !ext_table_size )
+        return 0;
+    /* check extended signature checksum */
+    for ( i = 0; i < ext_sigcount; i++ )
+    {
+        ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
+            EXT_SIGNATURE_SIZE * i;
+        sum = orig_sum
+            - (mc_header->sig + mc_header->pf + mc_header->cksum)
+            + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+        if ( sum )
+        {
+            printk(KERN_ERR "microcode: aborting, bad checksum\n");
+            return -EINVAL;
+        }
+    }
+    return 0;
 }
 
 /*
@@ -249,118 +199,123 @@ static int microcode_sanity_check(void *
  */
 static int get_matching_microcode(void *mc, int cpu)
 {
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-       struct microcode_header_intel *mc_header = mc;
-       struct extended_sigtable *ext_header;
-       unsigned long total_size = get_totalsize(mc_header);
-       int ext_sigcount, i;
-       struct extended_signature *ext_sig;
-       void *new_mc;
-
-       if (microcode_update_match(cpu, mc_header,
-                       mc_header->sig, mc_header->pf))
-               goto find;
-
-       if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
-               return 0;
-
-       ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
-       ext_sigcount = ext_header->count;
-       ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
-       for (i = 0; i < ext_sigcount; i++) {
-               if (microcode_update_match(cpu, mc_header,
-                               ext_sig->sig, ext_sig->pf))
-                       goto find;
-               ext_sig++;
-       }
-       return 0;
-find:
-       pr_debug("microcode: CPU%d found a matching microcode update with"
-                " version 0x%x (current=0x%x)\n",
-                cpu, mc_header->rev, uci->cpu_sig.rev);
-       new_mc = vmalloc(total_size);
-       if (!new_mc) {
-               printk(KERN_ERR "microcode: error! Can not allocate memory\n");
-               return -ENOMEM;
-       }
-
-       /* free previous update file */
-       vfree(uci->mc.mc_intel);
-
-       memcpy(new_mc, mc, total_size);
-       uci->mc.mc_intel = new_mc;
-       return 1;
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+    struct microcode_header_intel *mc_header = mc;
+    struct extended_sigtable *ext_header;
+    unsigned long total_size = get_totalsize(mc_header);
+    int ext_sigcount, i;
+    struct extended_signature *ext_sig;
+    void *new_mc;
+
+    if ( microcode_update_match(cpu, mc_header,
+                                mc_header->sig, mc_header->pf) )
+        goto find;
+
+    if ( total_size <= (get_datasize(mc_header) + MC_HEADER_SIZE) )
+        return 0;
+
+    ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
+    ext_sigcount = ext_header->count;
+    ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
+    for ( i = 0; i < ext_sigcount; i++ )
+    {
+        if ( microcode_update_match(cpu, mc_header,
+                                    ext_sig->sig, ext_sig->pf) )
+            goto find;
+        ext_sig++;
+    }
+    return 0;
+ find:
+    pr_debug("microcode: CPU%d found a matching microcode update with"
+             " version 0x%x (current=0x%x)\n",
+             cpu, mc_header->rev, uci->cpu_sig.rev);
+    new_mc = xmalloc_bytes(total_size);
+    if ( new_mc == NULL )
+    {
+        printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+        return -ENOMEM;
+    }
+
+    /* free previous update file */
+    xfree(uci->mc.mc_intel);
+
+    memcpy(new_mc, mc, total_size);
+    uci->mc.mc_intel = new_mc;
+    return 1;
 }
 
 static int apply_microcode(int cpu)
 {
-       unsigned long flags;
-       unsigned int val[2];
-       int cpu_num = raw_smp_processor_id();
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-       /* We should bind the task to the CPU */
-       BUG_ON(cpu_num != cpu);
-
-       if (uci->mc.mc_intel == NULL)
-               return -EINVAL;
-
-       /* serialize access to the physical write to MSR 0x79 */
-       spin_lock_irqsave(&microcode_update_lock, flags);
-
-       /* write microcode via MSR 0x79 */
-       wrmsr(MSR_IA32_UCODE_WRITE,
-             (unsigned long) uci->mc.mc_intel->bits,
-             (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16);
-       wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-
-       /* see notes above for revision 1.07.  Apparent chip bug */
-       sync_core();
-
-       /* get the current revision from MSR 0x8B */
-       rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-
-       spin_unlock_irqrestore(&microcode_update_lock, flags);
-       if (val[1] != uci->mc.mc_intel->hdr.rev) {
-               printk(KERN_ERR "microcode: CPU%d update from revision "
-                       "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, 
val[1]);
-               return -EIO;
-       }
-       printk(KERN_INFO "microcode: CPU%d updated from revision "
-              "0x%x to 0x%x, date = %04x-%02x-%02x \n",
-               cpu_num, uci->cpu_sig.rev, val[1],
-               uci->mc.mc_intel->hdr.date & 0xffff,
-               uci->mc.mc_intel->hdr.date >> 24,
-               (uci->mc.mc_intel->hdr.date >> 16) & 0xff);
-       uci->cpu_sig.rev = val[1];
-
-       return 0;
+    unsigned long flags;
+    unsigned int val[2];
+    int cpu_num = raw_smp_processor_id();
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu_num != cpu);
+
+    if ( uci->mc.mc_intel == NULL )
+        return -EINVAL;
+
+    /* serialize access to the physical write to MSR 0x79 */
+    spin_lock_irqsave(&microcode_update_lock, flags);
+
+    /* write microcode via MSR 0x79 */
+    wrmsr(MSR_IA32_UCODE_WRITE,
+          (unsigned long) uci->mc.mc_intel->bits,
+          (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16);
+    wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+
+    /* see notes above for revision 1.07.  Apparent chip bug */
+    sync_core();
+
+    /* get the current revision from MSR 0x8B */
+    rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+
+    spin_unlock_irqrestore(&microcode_update_lock, flags);
+    if ( val[1] != uci->mc.mc_intel->hdr.rev )
+    {
+        printk(KERN_ERR "microcode: CPU%d update from revision "
+               "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]);
+        return -EIO;
+    }
+    printk(KERN_INFO "microcode: CPU%d updated from revision "
+           "0x%x to 0x%x, date = %04x-%02x-%02x \n",
+           cpu_num, uci->cpu_sig.rev, val[1],
+           uci->mc.mc_intel->hdr.date & 0xffff,
+           uci->mc.mc_intel->hdr.date >> 24,
+           (uci->mc.mc_intel->hdr.date >> 16) & 0xff);
+    uci->cpu_sig.rev = val[1];
+
+    return 0;
 }
 
 static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
-       unsigned long size, long offset)
-{
-       struct microcode_header_intel *mc_header;
-       unsigned long total_size;
-
-       /* No more data */
-       if (offset >= size)
-               return 0;
-       mc_header = (struct microcode_header_intel *)(buf + offset);
-       total_size = get_totalsize(mc_header);
-
-       if (offset + total_size > size) {
-               printk(KERN_ERR "microcode: error! Bad data in microcode data 
file\n");
-               return -EINVAL;
-       }
-
-       *mc = vmalloc(total_size);
-       if (!*mc) {
-               printk(KERN_ERR "microcode: error! Can not allocate memory\n");
-               return -ENOMEM;
-       }
-       memcpy(*mc, (const void *)(buf + offset), total_size);
-       return offset + total_size;
+                                       unsigned long size, long offset)
+{
+    struct microcode_header_intel *mc_header;
+    unsigned long total_size;
+
+    /* No more data */
+    if ( offset >= size )
+        return 0;
+    mc_header = (struct microcode_header_intel *)(buf + offset);
+    total_size = get_totalsize(mc_header);
+
+    if ( (offset + total_size) > size )
+    {
+        printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+        return -EINVAL;
+    }
+
+    *mc = xmalloc_bytes(total_size);
+    if ( *mc == NULL )
+    {
+        printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+        return -ENOMEM;
+    }
+    memcpy(*mc, (const void *)(buf + offset), total_size);
+    return offset + total_size;
 }
 
 /* fake device for request_firmware */
@@ -368,58 +323,61 @@ extern struct platform_device *microcode
 
 static int cpu_request_microcode(int cpu, const void *buf, size_t size)
 {
-       long offset = 0;
-       int error = 0;
-       void *mc;
-
-       /* We should bind the task to the CPU */
-       BUG_ON(cpu != raw_smp_processor_id());
-
-       while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
-                       > 0) {
-               error = microcode_sanity_check(mc);
-               if (error)
-                       break;
-               error = get_matching_microcode(mc, cpu);
-               if (error < 0)
-                       break;
-               /*
-                * It's possible the data file has multiple matching ucode,
-                * lets keep searching till the latest version
-                */
-               if (error == 1) {
-                       apply_microcode(cpu);
-                       error = 0;
-               }
-               vfree(mc);
-       }
-       if (offset > 0)
-               vfree(mc);
-       if (offset < 0)
-               error = offset;
-
-       return error;
+    long offset = 0;
+    int error = 0;
+    void *mc;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu != raw_smp_processor_id());
+
+    while ( (offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) > 0 )
+    {
+        error = microcode_sanity_check(mc);
+        if ( error )
+            break;
+        error = get_matching_microcode(mc, cpu);
+        if ( error < 0 )
+            break;
+        /*
+         * It's possible the data file has multiple matching ucode,
+         * lets keep searching till the latest version
+         */
+        if ( error == 1 )
+        {
+            apply_microcode(cpu);
+            error = 0;
+        }
+        xfree(mc);
+    }
+    if ( offset > 0 )
+        xfree(mc);
+    if ( offset < 0 )
+        error = offset;
+
+    return error;
 }
 
 static void microcode_fini_cpu(int cpu)
 {
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-       vfree(uci->mc.mc_intel);
-       uci->mc.mc_intel = NULL;
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+    xfree(uci->mc.mc_intel);
+    uci->mc.mc_intel = NULL;
 }
 
 static struct microcode_ops microcode_intel_ops = {
-       .get_matching_microcode           = get_matching_microcode,
-       .microcode_sanity_check           = microcode_sanity_check,
-       .cpu_request_microcode            = cpu_request_microcode,
-       .collect_cpu_info                 = collect_cpu_info,
-       .apply_microcode                  = apply_microcode,
-       .microcode_fini_cpu               = microcode_fini_cpu,
+    .get_matching_microcode           = get_matching_microcode,
+    .microcode_sanity_check           = microcode_sanity_check,
+    .cpu_request_microcode            = cpu_request_microcode,
+    .collect_cpu_info                 = collect_cpu_info,
+    .apply_microcode                  = apply_microcode,
+    .microcode_fini_cpu               = microcode_fini_cpu,
 };
 
-int microcode_init_intel(struct cpuinfo_x86 *c)
-{
-       microcode_ops = &microcode_intel_ops;
-       return 0;
-}
+static __init int microcode_init_intel(void)
+{
+    if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+        microcode_ops = &microcode_intel_ops;
+    return 0;
+}
+__initcall(microcode_init_intel);
diff -r 087008dfb005 -r 087b8b29b6b2 xen/include/asm-x86/microcode.h
--- a/xen/include/asm-x86/microcode.h   Mon Sep 15 17:10:43 2008 +0100
+++ b/xen/include/asm-x86/microcode.h   Tue Sep 16 11:26:19 2008 +0100
@@ -90,11 +90,8 @@ struct ucode_cpu_info {
                void *valid_mc;
        } mc;
 };
+
 extern struct ucode_cpu_info ucode_cpu_info[];
-
 extern const struct microcode_ops *microcode_ops;
 
-int microcode_init_amd(struct cpuinfo_x86 *c);
-int microcode_init_intel(struct cpuinfo_x86 *c);
-
 #endif /* ASM_X86__MICROCODE_H */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.