ia64/xen-unstable

changeset 19060:fb0dc8143932

x86: update microcode support

- Container header file holding the patches changed. Update to new
format.
- in cpu_request_microcode() move heap re-allocation & copy out of the
loop.
Side-effect: Remove limitation in only supporting fixed sized
microcode patches. Also simplifies code a lot.
- cleanup: use rdmsr and wrmsrl instead of inlined assembler
- pass ucode_cpu_info as arguments. Improves reentrancy.
- cleanup: simplify struct ucode_cpu_info and remove
get_matching_microcode hook. Side-effect: reduces kernel size.
- bugfix: fix xen kernel memory leak in error path. equiv_cpu_table
was not freed.

Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jan 20 13:27:08 2009 +0000 (2009-01-20)
parents 0ab2b283e892
children 681af1946724
files xen/arch/x86/microcode.c xen/arch/x86/microcode_amd.c xen/arch/x86/microcode_intel.c xen/include/asm-x86/microcode.h
line diff
     1.1 --- a/xen/arch/x86/microcode.c	Tue Jan 20 13:22:28 2009 +0000
     1.2 +++ b/xen/arch/x86/microcode.c	Tue Jan 20 13:27:08 2009 +0000
     1.3 @@ -49,39 +49,28 @@ struct microcode_info {
     1.4      char buffer[1];
     1.5  };
     1.6  
     1.7 -static void microcode_fini_cpu(int cpu)
     1.8 +static void microcode_fini_cpu(struct ucode_cpu_info *uci, int cpu)
     1.9  {
    1.10 -    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
    1.11 -
    1.12      spin_lock(&microcode_mutex);
    1.13 -    xfree(uci->mc.valid_mc);
    1.14 -    uci->mc.valid_mc = NULL;
    1.15 -    uci->valid = 0;
    1.16 +    xfree(uci->mc.mc_valid);
    1.17 +    uci->mc.mc_valid = NULL;
    1.18      spin_unlock(&microcode_mutex);
    1.19  }
    1.20  
    1.21 -static int collect_cpu_info(int cpu)
    1.22 +static int collect_cpu_info(struct ucode_cpu_info *uci, int cpu)
    1.23 +{
    1.24 +    memset(uci, 0, sizeof(*uci));
    1.25 +    return microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
    1.26 +}
    1.27 +
    1.28 +static int microcode_resume_cpu(struct ucode_cpu_info *uci, int cpu)
    1.29  {
    1.30      int err = 0;
    1.31 -    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
    1.32 -
    1.33 -    memset(uci, 0, sizeof(*uci));
    1.34 -    err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
    1.35 -    if ( !err )
    1.36 -        uci->valid = 1;
    1.37 -
    1.38 -    return err;
    1.39 -}
    1.40 -
    1.41 -static int microcode_resume_cpu(int cpu)
    1.42 -{
    1.43 -    int err = 0;
    1.44 -    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
    1.45      struct cpu_signature nsig;
    1.46  
    1.47      gdprintk(XENLOG_INFO, "microcode: CPU%d resumed\n", cpu);
    1.48  
    1.49 -    if ( !uci->mc.valid_mc )
    1.50 +    if ( !uci->mc.mc_valid )
    1.51          return -EIO;
    1.52  
    1.53      /*
    1.54 @@ -91,43 +80,38 @@ static int microcode_resume_cpu(int cpu)
    1.55      err = microcode_ops->collect_cpu_info(cpu, &nsig);
    1.56      if ( err )
    1.57      {
    1.58 -        microcode_fini_cpu(cpu);
    1.59 +        microcode_fini_cpu(uci, cpu);
    1.60          return err;
    1.61      }
    1.62  
    1.63      if ( memcmp(&nsig, &uci->cpu_sig, sizeof(nsig)) )
    1.64      {
    1.65 -        microcode_fini_cpu(cpu);
    1.66 +        microcode_fini_cpu(uci, cpu);
    1.67          /* Should we look for a new ucode here? */
    1.68          return -EIO;
    1.69      }
    1.70  
    1.71 -    err = microcode_ops->apply_microcode(cpu);
    1.72 -
    1.73 -    return err;
    1.74 +    return microcode_ops->apply_microcode(uci, cpu);
    1.75  }
    1.76  
    1.77  static int microcode_update_cpu(const void *buf, size_t size)
    1.78  {
    1.79      int err;
    1.80      unsigned int cpu = smp_processor_id();
    1.81 -    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
    1.82 +    struct ucode_cpu_info *uci = &ucode_cpu_info[cpu];
    1.83  
    1.84      spin_lock(&microcode_mutex);
    1.85  
    1.86      /*
    1.87 -     * Check if the system resume is in progress (uci->valid != NULL),
    1.88 +     * Check if the system resume is in progress (uci->mc.mc_valid != NULL),
    1.89       * otherwise just request a firmware:
    1.90       */
    1.91 -    if ( uci->valid )
    1.92 -    {
    1.93 -        err = microcode_resume_cpu(cpu);
    1.94 -    }
    1.95 -    else
    1.96 -    {
    1.97 -        err = collect_cpu_info(cpu);
    1.98 -        if ( !err && uci->valid )
    1.99 -            err = microcode_ops->cpu_request_microcode(cpu, buf, size);
   1.100 +    if ( uci->mc.mc_valid ) {
   1.101 +        err = microcode_resume_cpu(uci, cpu);
   1.102 +    } else {
   1.103 +        err = collect_cpu_info(uci, cpu);
   1.104 +        if ( !err )
   1.105 +            err = microcode_ops->cpu_request_microcode(uci, cpu, buf, size);
   1.106      }
   1.107  
   1.108      spin_unlock(&microcode_mutex);
   1.109 @@ -153,7 +137,6 @@ static long do_microcode_update(void *_i
   1.110      error = info->error;
   1.111      xfree(info);
   1.112      return error;
   1.113 -
   1.114  }
   1.115  
   1.116  int microcode_update(XEN_GUEST_HANDLE(const_void) buf, unsigned long len)
     2.1 --- a/xen/arch/x86/microcode_amd.c	Tue Jan 20 13:22:28 2009 +0000
     2.2 +++ b/xen/arch/x86/microcode_amd.c	Tue Jan 20 13:27:08 2009 +0000
     2.3 @@ -38,21 +38,16 @@
     2.4  #define MC_HEADER_SIZE          (sizeof(struct microcode_header_amd))
     2.5  #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
     2.6  #define DWSIZE                  (sizeof(uint32_t))
     2.7 -/* For now we support a fixed ucode total size only */
     2.8 -#define get_totalsize(mc) \
     2.9 -        ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \
    2.10 -         + MC_HEADER_SIZE)
    2.11  
    2.12  /* serialize access to the physical write */
    2.13  static DEFINE_SPINLOCK(microcode_update_lock);
    2.14  
    2.15  struct equiv_cpu_entry *equiv_cpu_table;
    2.16  
    2.17 -static long install_equiv_cpu_table(const void *, uint32_t, long);
    2.18 -
    2.19  static int collect_cpu_info(int cpu, struct cpu_signature *csig)
    2.20  {
    2.21      struct cpuinfo_x86 *c = &cpu_data[cpu];
    2.22 +    uint32_t dummy;
    2.23  
    2.24      memset(csig, 0, sizeof(*csig));
    2.25  
    2.26 @@ -60,13 +55,10 @@ static int collect_cpu_info(int cpu, str
    2.27      {
    2.28          printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n",
    2.29                 cpu);
    2.30 -        return -1;
    2.31 +        return -EINVAL;
    2.32      }
    2.33  
    2.34 -    asm volatile (
    2.35 -        "movl %1, %%ecx; rdmsr"
    2.36 -        : "=a" (csig->rev)
    2.37 -        : "i" (MSR_AMD_PATCHLEVEL) : "ecx" );
    2.38 +    rdmsr(MSR_AMD_PATCHLEVEL, csig->rev, dummy);
    2.39  
    2.40      printk(KERN_INFO "microcode: collect_cpu_info: patch_id=0x%x\n",
    2.41             csig->rev);
    2.42 @@ -74,29 +66,17 @@ static int collect_cpu_info(int cpu, str
    2.43      return 0;
    2.44  }
    2.45  
    2.46 -static int get_matching_microcode(void *mc, int cpu)
    2.47 +static int microcode_fits(void *mc, int cpu)
    2.48  {
    2.49      struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
    2.50      struct microcode_header_amd *mc_header = mc;
    2.51 -    unsigned long total_size = get_totalsize(mc_header);
    2.52 -    void *new_mc;
    2.53      unsigned int current_cpu_id;
    2.54 -    unsigned int equiv_cpu_id = 0x00;
    2.55 +    unsigned int equiv_cpu_id = 0x0;
    2.56      unsigned int i;
    2.57  
    2.58      /* We should bind the task to the CPU */
    2.59      BUG_ON(cpu != raw_smp_processor_id());
    2.60  
    2.61 -    /* This is a tricky part. We might be called from a write operation
    2.62 -     * to the device file instead of the usual process of firmware
    2.63 -     * loading. This routine needs to be able to distinguish both
    2.64 -     * cases. This is done by checking if there already is a equivalent
    2.65 -     * CPU table installed. If not, we're written through
    2.66 -     * /dev/cpu/microcode.
    2.67 -     * Since we ignore all checks. The error case in which going through
    2.68 -     * firmware loading and that table is not loaded has already been
    2.69 -     * checked earlier.
    2.70 -     */
    2.71      if ( equiv_cpu_table == NULL )
    2.72      {
    2.73          printk(KERN_INFO "microcode: CPU%d microcode update with "
    2.74 @@ -111,7 +91,7 @@ static int get_matching_microcode(void *
    2.75      {
    2.76          if ( current_cpu_id == equiv_cpu_table[i].installed_cpu )
    2.77          {
    2.78 -            equiv_cpu_id = equiv_cpu_table[i].equiv_cpu;
    2.79 +            equiv_cpu_id = equiv_cpu_table[i].equiv_cpu & 0xffff;
    2.80              break;
    2.81          }
    2.82      }
    2.83 @@ -119,171 +99,135 @@ static int get_matching_microcode(void *
    2.84      if ( !equiv_cpu_id )
    2.85      {
    2.86          printk(KERN_ERR "microcode: CPU%d cpu_id "
    2.87 -               "not found in equivalent cpu table \n", cpu);
    2.88 -        return 0;
    2.89 +               "not found in equivalent cpu table\n", cpu);
    2.90 +        return -EINVAL;
    2.91      }
    2.92  
    2.93 -    if ( (mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff) )
    2.94 -    {
    2.95 -        printk(KERN_INFO
    2.96 -               "microcode: CPU%d patch does not match "
    2.97 -               "(patch is %x, cpu extended is %x) \n",
    2.98 -               cpu, mc_header->processor_rev_id[0],
    2.99 -               (equiv_cpu_id & 0xff));
   2.100 -        return 0;
   2.101 -    }
   2.102 -
   2.103 -    if ( (mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff) )
   2.104 +    if ( (mc_header->processor_rev_id) != equiv_cpu_id )
   2.105      {
   2.106          printk(KERN_INFO "microcode: CPU%d patch does not match "
   2.107                 "(patch is %x, cpu base id is %x) \n",
   2.108 -               cpu, mc_header->processor_rev_id[1],
   2.109 -               ((equiv_cpu_id >> 16) & 0xff));
   2.110 -        return 0;
   2.111 +               cpu, mc_header->processor_rev_id, equiv_cpu_id);
   2.112 +        return -EINVAL;
   2.113      }
   2.114  
   2.115      if ( mc_header->patch_id <= uci->cpu_sig.rev )
   2.116 -        return 0;
   2.117 +        return -EINVAL;
   2.118  
   2.119      printk(KERN_INFO "microcode: CPU%d found a matching microcode "
   2.120             "update with version 0x%x (current=0x%x)\n",
   2.121             cpu, mc_header->patch_id, uci->cpu_sig.rev);
   2.122  
   2.123 - out:
   2.124 -    new_mc = xmalloc_bytes(UCODE_MAX_SIZE);
   2.125 -    if ( new_mc == NULL )
   2.126 -    {
   2.127 -        printk(KERN_ERR "microcode: error, can't allocate memory\n");
   2.128 -        return -ENOMEM;
   2.129 -    }
   2.130 -    memset(new_mc, 0, UCODE_MAX_SIZE);
   2.131 -
   2.132 -    /* free previous update file */
   2.133 -    xfree(uci->mc.mc_amd);
   2.134 -
   2.135 -    memcpy(new_mc, mc, total_size);
   2.136 -
   2.137 -    uci->mc.mc_amd = new_mc;
   2.138 -    return 1;
   2.139 +out:
   2.140 +    return 0;
   2.141  }
   2.142  
   2.143 -static int apply_microcode(int cpu)
   2.144 +static int apply_microcode(struct ucode_cpu_info *uci, int cpu)
   2.145  {
   2.146      unsigned long flags;
   2.147 -    uint32_t eax, edx, rev;
   2.148 -    int cpu_num = raw_smp_processor_id();
   2.149 -    struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
   2.150 -    uint64_t addr;
   2.151 +    uint32_t rev, dummy;
   2.152 +    struct microcode_amd *mc_amd = uci->mc.mc_amd;
   2.153  
   2.154      /* We should bind the task to the CPU */
   2.155 -    BUG_ON(cpu_num != cpu);
   2.156 +    BUG_ON(raw_smp_processor_id() != cpu);
   2.157  
   2.158 -    if ( uci->mc.mc_amd == NULL )
   2.159 +    if ( mc_amd == NULL )
   2.160          return -EINVAL;
   2.161  
   2.162      spin_lock_irqsave(&microcode_update_lock, flags);
   2.163  
   2.164 -    addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code;
   2.165 -    edx = (uint32_t)(addr >> 32);
   2.166 -    eax = (uint32_t)addr;
   2.167 -
   2.168 -    asm volatile (
   2.169 -        "movl %0, %%ecx; wrmsr" :
   2.170 -        : "i" (MSR_AMD_PATCHLOADER), "a" (eax), "d" (edx) : "ecx" );
   2.171 +    wrmsrl(MSR_AMD_PATCHLOADER, (unsigned long)&mc_amd->hdr.data_code);
   2.172  
   2.173      /* get patch id after patching */
   2.174 -    asm volatile (
   2.175 -        "movl %1, %%ecx; rdmsr"
   2.176 -        : "=a" (rev)
   2.177 -        : "i" (MSR_AMD_PATCHLEVEL) : "ecx");
   2.178 +    rdmsr(MSR_AMD_PATCHLEVEL, rev, dummy);
   2.179  
   2.180      spin_unlock_irqrestore(&microcode_update_lock, flags);
   2.181  
   2.182      /* check current patch id and patch's id for match */
   2.183 -    if ( rev != uci->mc.mc_amd->hdr.patch_id )
   2.184 +    if ( rev != mc_amd->hdr.patch_id )
   2.185      {
   2.186          printk(KERN_ERR "microcode: CPU%d update from revision "
   2.187 -               "0x%x to 0x%x failed\n", cpu_num,
   2.188 -               uci->mc.mc_amd->hdr.patch_id, rev);
   2.189 +               "0x%x to 0x%x failed\n", cpu,
   2.190 +               mc_amd->hdr.patch_id, rev);
   2.191          return -EIO;
   2.192      }
   2.193  
   2.194      printk("microcode: CPU%d updated from revision "
   2.195             "0x%x to 0x%x \n",
   2.196 -           cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id);
   2.197 +           cpu, uci->cpu_sig.rev, mc_amd->hdr.patch_id);
   2.198  
   2.199      uci->cpu_sig.rev = rev;
   2.200  
   2.201      return 0;
   2.202  }
   2.203  
   2.204 -static long get_next_ucode_from_buffer_amd(void **mc, const void *buf,
   2.205 -                                           unsigned long size, long offset)
   2.206 +static int get_next_ucode_from_buffer_amd(void *mc, const void *buf,
   2.207 +                                         size_t size, unsigned long *offset)
   2.208  {
   2.209      struct microcode_header_amd *mc_header;
   2.210 -    unsigned long total_size;
   2.211 -    const uint8_t *buf_pos = buf;
   2.212 +    size_t total_size;
   2.213 +    const uint8_t *bufp = buf;
   2.214 +    unsigned long off;
   2.215 +
   2.216 +    off = *offset;
   2.217  
   2.218      /* No more data */
   2.219 -    if ( offset >= size )
   2.220 -        return 0;
   2.221 +    if ( off >= size )
   2.222 +        return 1;
   2.223  
   2.224 -    if ( buf_pos[offset] != UCODE_UCODE_TYPE )
   2.225 +    if ( bufp[off] != UCODE_UCODE_TYPE )
   2.226      {
   2.227          printk(KERN_ERR "microcode: error! "
   2.228                 "Wrong microcode payload type field\n");
   2.229          return -EINVAL;
   2.230      }
   2.231  
   2.232 -    mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
   2.233 +    mc_header = (struct microcode_header_amd *)(&bufp[off+8]);
   2.234  
   2.235 -    total_size = (unsigned long) (buf_pos[offset+4] +
   2.236 -                                  (buf_pos[offset+5] << 8));
   2.237 +    total_size = (unsigned long) (bufp[off+4] + (bufp[off+5] << 8));
   2.238  
   2.239      printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n",
   2.240 -           size, total_size, offset);
   2.241 +           (unsigned long)size, total_size, off);
   2.242  
   2.243 -    if ( (offset + total_size) > size )
   2.244 +    if ( (off + total_size) > size )
   2.245      {
   2.246          printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
   2.247          return -EINVAL;
   2.248      }
   2.249  
   2.250 -    *mc = xmalloc_bytes(UCODE_MAX_SIZE);
   2.251 -    if ( *mc == NULL )
   2.252 -    {
   2.253 -        printk(KERN_ERR "microcode: error! "
   2.254 -               "Can not allocate memory for microcode patch\n");
   2.255 -        return -ENOMEM;
   2.256 -    }
   2.257 +    memset(mc, 0, UCODE_MAX_SIZE);
   2.258 +    memcpy(mc, (const void *)(&bufp[off + 8]), total_size);
   2.259  
   2.260 -    memset(*mc, 0, UCODE_MAX_SIZE);
   2.261 -    memcpy(*mc, (const void *)(buf + offset + 8), total_size);
   2.262 +    *offset = off + total_size + 8;
   2.263  
   2.264 -    return offset + total_size + 8;
   2.265 +    return 0;
   2.266  }
   2.267  
   2.268 -static long install_equiv_cpu_table(const void *buf,
   2.269 -                                    uint32_t size, long offset)
   2.270 +static int install_equiv_cpu_table(const void *buf, uint32_t size,
   2.271 +                                   unsigned long *offset)
   2.272  {
   2.273      const uint32_t *buf_pos = buf;
   2.274 +    unsigned long off;
   2.275 +
   2.276 +    off = *offset;
   2.277 +    *offset = 0;
   2.278  
   2.279      /* No more data */
   2.280 -    if ( offset >= size )
   2.281 -        return 0;
   2.282 +    if ( off >= size )
   2.283 +        return -EINVAL;
   2.284  
   2.285      if ( buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE )
   2.286      {
   2.287          printk(KERN_ERR "microcode: error! "
   2.288 -               "Wrong microcode equivalnet cpu table type field\n");
   2.289 -        return 0;
   2.290 +               "Wrong microcode equivalent cpu table type field\n");
   2.291 +        return -EINVAL;
   2.292      }
   2.293  
   2.294      if ( size == 0 )
   2.295      {
   2.296          printk(KERN_ERR "microcode: error! "
   2.297                 "Wrong microcode equivalnet cpu table length\n");
   2.298 -        return 0;
   2.299 +        return -EINVAL;
   2.300      }
   2.301  
   2.302      equiv_cpu_table = xmalloc_bytes(size);
   2.303 @@ -291,24 +235,29 @@ static long install_equiv_cpu_table(cons
   2.304      {
   2.305          printk(KERN_ERR "microcode: error, can't allocate "
   2.306                 "memory for equiv CPU table\n");
   2.307 -        return 0;
   2.308 +        return -ENOMEM;
   2.309      }
   2.310  
   2.311      memset(equiv_cpu_table, 0, size);
   2.312      memcpy(equiv_cpu_table, (const void *)&buf_pos[3], size);
   2.313  
   2.314 -    return size + 12; /* add header length */
   2.315 +    *offset = size + 12;	/* add header length */
   2.316 +
   2.317 +    return 0;
   2.318  }
   2.319  
   2.320 -static int cpu_request_microcode(int cpu, const void *buf, size_t size)
   2.321 +static int cpu_request_microcode(struct ucode_cpu_info *uci,
   2.322 +				int cpu, const void *buf, size_t size)
   2.323  {
   2.324      const uint32_t *buf_pos;
   2.325 -    long offset = 0;
   2.326 +    unsigned long offset = 0;
   2.327      int error = 0;
   2.328 +    int ret;
   2.329      void *mc;
   2.330  
   2.331      /* We should bind the task to the CPU */
   2.332      BUG_ON(cpu != raw_smp_processor_id());
   2.333 +    BUG_ON(uci != &ucode_cpu_info[cpu]);
   2.334  
   2.335      buf_pos = (const uint32_t *)buf;
   2.336  
   2.337 @@ -319,41 +268,57 @@ static int cpu_request_microcode(int cpu
   2.338          return -EINVAL;
   2.339      }
   2.340  
   2.341 -    offset = install_equiv_cpu_table(buf, (uint32_t)(buf_pos[2]), offset);
   2.342 -    if ( !offset )
   2.343 +    error = install_equiv_cpu_table(buf, (uint32_t)(buf_pos[2]), &offset);
   2.344 +    if ( error )
   2.345      {
   2.346          printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
   2.347          return -EINVAL;
   2.348      }
   2.349  
   2.350 -    while ( (offset =
   2.351 -             get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0 )
   2.352 +    mc = xmalloc_bytes(UCODE_MAX_SIZE);
   2.353 +    if ( mc == NULL )
   2.354      {
   2.355 -        error = get_matching_microcode(mc, cpu);
   2.356 -        if ( error < 0 )
   2.357 +        printk(KERN_ERR "microcode: error! "
   2.358 +               "Can not allocate memory for microcode patch\n");
   2.359 +        error = -ENOMEM;
   2.360 +        goto out;
   2.361 +    }
   2.362 +
   2.363 +    /* implicitely validates uci->mc.mc_valid */
   2.364 +    uci->mc.mc_amd = mc;
   2.365 +
   2.366 +    /*
   2.367 +     * It's possible the data file has multiple matching ucode,
   2.368 +     * lets keep searching till the latest version
   2.369 +     */
   2.370 +    while ( (ret = get_next_ucode_from_buffer_amd(mc, buf, size, &offset)) == 0)
   2.371 +    {
   2.372 +        error = microcode_fits(mc, cpu);
   2.373 +        if (error != 0)
   2.374 +            continue;
   2.375 +
   2.376 +        error = apply_microcode(uci, cpu);
   2.377 +        if (error == 0)
   2.378              break;
   2.379 -        /*
   2.380 -         * It's possible the data file has multiple matching ucode,
   2.381 -         * lets keep searching till the latest version
   2.382 -         */
   2.383 -        if ( error == 1 )
   2.384 -            error = apply_microcode(cpu);
   2.385 -        xfree(mc);
   2.386      }
   2.387 -    if ( offset > 0 )
   2.388 -    {
   2.389 +
   2.390 +    /* On success keep the microcode patch for
   2.391 +     * re-apply on resume.
   2.392 +     */
   2.393 +    if (error) {
   2.394          xfree(mc);
   2.395 -        xfree(equiv_cpu_table);
   2.396 -        equiv_cpu_table = NULL;
   2.397 +        mc = NULL;
   2.398      }
   2.399 -    if ( offset < 0 )
   2.400 -        error = offset;
   2.401 +    uci->mc.mc_amd = mc;
   2.402 +
   2.403 +out:
   2.404 +    xfree(equiv_cpu_table);
   2.405 +    equiv_cpu_table = NULL;
   2.406  
   2.407      return error;
   2.408  }
   2.409  
   2.410  static struct microcode_ops microcode_amd_ops = {
   2.411 -    .get_matching_microcode           = get_matching_microcode,
   2.412      .cpu_request_microcode            = cpu_request_microcode,
   2.413      .collect_cpu_info                 = collect_cpu_info,
   2.414      .apply_microcode                  = apply_microcode,
     3.1 --- a/xen/arch/x86/microcode_intel.c	Tue Jan 20 13:22:28 2009 +0000
     3.2 +++ b/xen/arch/x86/microcode_intel.c	Tue Jan 20 13:27:08 2009 +0000
     3.3 @@ -244,12 +244,11 @@ static int get_matching_microcode(void *
     3.4      return 1;
     3.5  }
     3.6  
     3.7 -static int apply_microcode(int cpu)
     3.8 +static int apply_microcode(struct ucode_cpu_info *uci, int cpu)
     3.9  {
    3.10      unsigned long flags;
    3.11      unsigned int val[2];
    3.12      int cpu_num = raw_smp_processor_id();
    3.13 -    struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
    3.14  
    3.15      /* We should bind the task to the CPU */
    3.16      BUG_ON(cpu_num != cpu);
    3.17 @@ -318,7 +317,8 @@ static long get_next_ucode_from_buffer(v
    3.18      return offset + total_size;
    3.19  }
    3.20  
    3.21 -static int cpu_request_microcode(int cpu, const void *buf, size_t size)
    3.22 +static int cpu_request_microcode(struct ucode_cpu_info *uci,
    3.23 +                                int cpu, const void *buf, size_t size)
    3.24  {
    3.25      long offset = 0;
    3.26      int error = 0;
    3.27 @@ -341,7 +341,7 @@ static int cpu_request_microcode(int cpu
    3.28           */
    3.29          if ( error == 1 )
    3.30          {
    3.31 -            apply_microcode(cpu);
    3.32 +            apply_microcode(uci, cpu);
    3.33              error = 0;
    3.34          }
    3.35          xfree(mc);
    3.36 @@ -355,7 +355,6 @@ static int cpu_request_microcode(int cpu
    3.37  }
    3.38  
    3.39  static struct microcode_ops microcode_intel_ops = {
    3.40 -    .get_matching_microcode           = get_matching_microcode,
    3.41      .cpu_request_microcode            = cpu_request_microcode,
    3.42      .collect_cpu_info                 = collect_cpu_info,
    3.43      .apply_microcode                  = apply_microcode,
     4.1 --- a/xen/include/asm-x86/microcode.h	Tue Jan 20 13:22:28 2009 +0000
     4.2 +++ b/xen/include/asm-x86/microcode.h	Tue Jan 20 13:27:08 2009 +0000
     4.3 @@ -2,12 +2,13 @@
     4.4  #define ASM_X86__MICROCODE_H
     4.5  
     4.6  struct cpu_signature;
     4.7 +struct ucode_cpu_info;
     4.8  
     4.9  struct microcode_ops {
    4.10 -    int (*get_matching_microcode)(void *mc, int cpu);
    4.11 -    int (*cpu_request_microcode)(int cpu, const void *buf, size_t size);
    4.12 -    int (*collect_cpu_info)(int cpu_num, struct cpu_signature *csig);
    4.13 -    int (*apply_microcode)(int cpu);
    4.14 +    int (*cpu_request_microcode)(struct ucode_cpu_info *uci,
    4.15 +                                 int cpu, const void *buf, size_t size);
    4.16 +    int (*collect_cpu_info)(int cpu, struct cpu_signature *csig);
    4.17 +    int (*apply_microcode)(struct ucode_cpu_info *uci, int cpu);
    4.18  };
    4.19  
    4.20  struct microcode_header_intel {
    4.21 @@ -43,28 +44,29 @@ struct extended_sigtable {
    4.22  };
    4.23  
    4.24  struct equiv_cpu_entry {
    4.25 -    unsigned int installed_cpu;
    4.26 -    unsigned int fixed_errata_mask;
    4.27 -    unsigned int fixed_errata_compare;
    4.28 -    unsigned int equiv_cpu;
    4.29 -};
    4.30 +    uint32_t installed_cpu;
    4.31 +    uint32_t fixed_errata_mask;
    4.32 +    uint32_t fixed_errata_compare;
    4.33 +    uint16_t equiv_cpu;
    4.34 +    uint16_t reserved;
    4.35 +} __attribute__((packed));
    4.36  
    4.37  struct microcode_header_amd {
    4.38 -    unsigned int  data_code;
    4.39 -    unsigned int  patch_id;
    4.40 -    unsigned char mc_patch_data_id[2];
    4.41 -    unsigned char mc_patch_data_len;
    4.42 -    unsigned char init_flag;
    4.43 -    unsigned int  mc_patch_data_checksum;
    4.44 -    unsigned int  nb_dev_id;
    4.45 -    unsigned int  sb_dev_id;
    4.46 -    unsigned char processor_rev_id[2];
    4.47 -    unsigned char nb_rev_id;
    4.48 -    unsigned char sb_rev_id;
    4.49 -    unsigned char bios_api_rev;
    4.50 -    unsigned char reserved1[3];
    4.51 -    unsigned int  match_reg[8];
    4.52 -};
    4.53 +    uint32_t data_code;
    4.54 +    uint32_t patch_id;
    4.55 +    uint8_t  mc_patch_data_id[2];
    4.56 +    uint8_t  mc_patch_data_len;
    4.57 +    uint8_t  init_flag;
    4.58 +    uint32_t mc_patch_data_checksum;
    4.59 +    uint32_t nb_dev_id;
    4.60 +    uint32_t sb_dev_id;
    4.61 +    uint16_t processor_rev_id;
    4.62 +    uint8_t  nb_rev_id;
    4.63 +    uint8_t  sb_rev_id;
    4.64 +    uint8_t  bios_api_rev;
    4.65 +    uint8_t  reserved1[3];
    4.66 +    uint32_t match_reg[8];
    4.67 +} __attribute__((packed));
    4.68  
    4.69  struct microcode_amd {
    4.70      struct microcode_header_amd hdr;
    4.71 @@ -79,11 +81,10 @@ struct cpu_signature {
    4.72  
    4.73  struct ucode_cpu_info {
    4.74      struct cpu_signature cpu_sig;
    4.75 -    int valid;
    4.76      union {
    4.77          struct microcode_intel *mc_intel;
    4.78          struct microcode_amd *mc_amd;
    4.79 -        void *valid_mc;
    4.80 +        void *mc_valid;
    4.81      } mc;
    4.82  };
    4.83