linux/arch/x86/kernel/microcode.c
<<
>>
Prefs
   1/*
   2 *      Intel CPU Microcode Update Driver for Linux
   3 *
   4 *      Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
   5 *                    2006      Shaohua Li <shaohua.li@intel.com>
   6 *
   7 *      This driver allows to upgrade microcode on Intel processors
   8 *      belonging to IA-32 family - PentiumPro, Pentium II, 
   9 *      Pentium III, Xeon, Pentium 4, etc.
  10 *
  11 *      Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
  12 *      Order Number 245472 or free download from:
  13 *              
  14 *      http://developer.intel.com/design/pentium4/manuals/245472.htm
  15 *
  16 *      For more information, go to http://www.urbanmyth.org/microcode
  17 *
  18 *      This program is free software; you can redistribute it and/or
  19 *      modify it under the terms of the GNU General Public License
  20 *      as published by the Free Software Foundation; either version
  21 *      2 of the License, or (at your option) any later version.
  22 *
  23 *      1.0     16 Feb 2000, Tigran Aivazian <tigran@sco.com>
  24 *              Initial release.
  25 *      1.01    18 Feb 2000, Tigran Aivazian <tigran@sco.com>
  26 *              Added read() support + cleanups.
  27 *      1.02    21 Feb 2000, Tigran Aivazian <tigran@sco.com>
  28 *              Added 'device trimming' support. open(O_WRONLY) zeroes
  29 *              and frees the saved copy of applied microcode.
  30 *      1.03    29 Feb 2000, Tigran Aivazian <tigran@sco.com>
  31 *              Made to use devfs (/dev/cpu/microcode) + cleanups.
  32 *      1.04    06 Jun 2000, Simon Trimmer <simon@veritas.com>
  33 *              Added misc device support (now uses both devfs and misc).
  34 *              Added MICROCODE_IOCFREE ioctl to clear memory.
  35 *      1.05    09 Jun 2000, Simon Trimmer <simon@veritas.com>
  36 *              Messages for error cases (non Intel & no suitable microcode).
  37 *      1.06    03 Aug 2000, Tigran Aivazian <tigran@veritas.com>
  38 *              Removed ->release(). Removed exclusive open and status bitmap.
  39 *              Added microcode_rwsem to serialize read()/write()/ioctl().
  40 *              Removed global kernel lock usage.
  41 *      1.07    07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
  42 *              Write 0 to 0x8B msr and then cpuid before reading revision,
  43 *              so that it works even if there were no update done by the
  44 *              BIOS. Otherwise, reading from 0x8B gives junk (which happened
  45 *              to be 0 on my machine which is why it worked even when I
  46 *              disabled update by the BIOS)
  47 *              Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
  48 *      1.08    11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
  49 *                           Tigran Aivazian <tigran@veritas.com>
  50 *              Intel Pentium 4 processor support and bugfixes.
  51 *      1.09    30 Oct 2001, Tigran Aivazian <tigran@veritas.com>
  52 *              Bugfix for HT (Hyper-Threading) enabled processors
  53 *              whereby processor resources are shared by all logical processors
  54 *              in a single CPU package.
  55 *      1.10    28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
  56 *              Tigran Aivazian <tigran@veritas.com>,
  57 *              Serialize updates as required on HT processors due to speculative
  58 *              nature of implementation.
  59 *      1.11    22 Mar 2002 Tigran Aivazian <tigran@veritas.com>
  60 *              Fix the panic when writing zero-length microcode chunk.
  61 *      1.12    29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, 
  62 *              Jun Nakajima <jun.nakajima@intel.com>
  63 *              Support for the microcode updates in the new format.
  64 *      1.13    10 Oct 2003 Tigran Aivazian <tigran@veritas.com>
  65 *              Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
  66 *              because we no longer hold a copy of applied microcode 
  67 *              in kernel memory.
  68 *      1.14    25 Jun 2004 Tigran Aivazian <tigran@veritas.com>
  69 *              Fix sigmatch() macro to handle old CPUs with pf == 0.
  70 *              Thanks to Stuart Swales for pointing out this bug.
  71 */
  72
  73//#define DEBUG /* pr_debug */
  74#include <linux/capability.h>
  75#include <linux/kernel.h>
  76#include <linux/init.h>
  77#include <linux/sched.h>
  78#include <linux/cpumask.h>
  79#include <linux/module.h>
  80#include <linux/slab.h>
  81#include <linux/vmalloc.h>
  82#include <linux/miscdevice.h>
  83#include <linux/spinlock.h>
  84#include <linux/mm.h>
  85#include <linux/fs.h>
  86#include <linux/mutex.h>
  87#include <linux/cpu.h>
  88#include <linux/firmware.h>
  89#include <linux/platform_device.h>
  90
  91#include <asm/msr.h>
  92#include <asm/uaccess.h>
  93#include <asm/processor.h>
  94
  95MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
  96MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
  97MODULE_LICENSE("GPL");
  98
  99#define MICROCODE_VERSION       "1.14a"
 100
 101#define DEFAULT_UCODE_DATASIZE  (2000)    /* 2000 bytes */
 102#define MC_HEADER_SIZE          (sizeof (microcode_header_t))     /* 48 bytes */
 103#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
 104#define EXT_HEADER_SIZE         (sizeof (struct extended_sigtable)) /* 20 bytes */
 105#define EXT_SIGNATURE_SIZE      (sizeof (struct extended_signature)) /* 12 bytes */
 106#define DWSIZE                  (sizeof (u32))
 107#define get_totalsize(mc) \
 108        (((microcode_t *)mc)->hdr.totalsize ? \
 109         ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
 110#define get_datasize(mc) \
 111        (((microcode_t *)mc)->hdr.datasize ? \
 112         ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
 113
 114#define sigmatch(s1, s2, p1, p2) \
 115        (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
 116
 117#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
 118
 119/* serialize access to the physical write to MSR 0x79 */
 120static DEFINE_SPINLOCK(microcode_update_lock);
 121
 122/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
 123static DEFINE_MUTEX(microcode_mutex);
 124
 125static struct ucode_cpu_info {
 126        int valid;
 127        unsigned int sig;
 128        unsigned int pf;
 129        unsigned int rev;
 130        microcode_t *mc;
 131} ucode_cpu_info[NR_CPUS];
 132
 133static void collect_cpu_info(int cpu_num)
 134{
 135        struct cpuinfo_x86 *c = &cpu_data(cpu_num);
 136        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 137        unsigned int val[2];
 138
 139        /* We should bind the task to the CPU */
 140        BUG_ON(raw_smp_processor_id() != cpu_num);
 141        uci->pf = uci->rev = 0;
 142        uci->mc = NULL;
 143        uci->valid = 1;
 144
 145        if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
 146                cpu_has(c, X86_FEATURE_IA64)) {
 147                printk(KERN_ERR "microcode: CPU%d not a capable Intel "
 148                        "processor\n", cpu_num);
 149                uci->valid = 0;
 150                return;
 151        }
 152
 153        uci->sig = cpuid_eax(0x00000001);
 154
 155        if ((c->x86_model >= 5) || (c->x86 > 6)) {
 156                /* get processor flags from MSR 0x17 */
 157                rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
 158                uci->pf = 1 << ((val[1] >> 18) & 7);
 159        }
 160
 161        wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 162        /* see notes above for revision 1.07.  Apparent chip bug */
 163        sync_core();
 164        /* get the current revision from MSR 0x8B */
 165        rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
 166        pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
 167                        uci->sig, uci->pf, uci->rev);
 168}
 169
 170static inline int microcode_update_match(int cpu_num,
 171        microcode_header_t *mc_header, int sig, int pf)
 172{
 173        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 174
 175        if (!sigmatch(sig, uci->sig, pf, uci->pf)
 176                || mc_header->rev <= uci->rev)
 177                return 0;
 178        return 1;
 179}
 180
 181static int microcode_sanity_check(void *mc)
 182{
 183        microcode_header_t *mc_header = mc;
 184        struct extended_sigtable *ext_header = NULL;
 185        struct extended_signature *ext_sig;
 186        unsigned long total_size, data_size, ext_table_size;
 187        int sum, orig_sum, ext_sigcount = 0, i;
 188
 189        total_size = get_totalsize(mc_header);
 190        data_size = get_datasize(mc_header);
 191        if (data_size + MC_HEADER_SIZE > total_size) {
 192                printk(KERN_ERR "microcode: error! "
 193                        "Bad data size in microcode data file\n");
 194                return -EINVAL;
 195        }
 196
 197        if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
 198                printk(KERN_ERR "microcode: error! "
 199                        "Unknown microcode update format\n");
 200                return -EINVAL;
 201        }
 202        ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
 203        if (ext_table_size) {
 204                if ((ext_table_size < EXT_HEADER_SIZE)
 205                 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
 206                        printk(KERN_ERR "microcode: error! "
 207                                "Small exttable size in microcode data file\n");
 208                        return -EINVAL;
 209                }
 210                ext_header = mc + MC_HEADER_SIZE + data_size;
 211                if (ext_table_size != exttable_size(ext_header)) {
 212                        printk(KERN_ERR "microcode: error! "
 213                                "Bad exttable size in microcode data file\n");
 214                        return -EFAULT;
 215                }
 216                ext_sigcount = ext_header->count;
 217        }
 218
 219        /* check extended table checksum */
 220        if (ext_table_size) {
 221                int ext_table_sum = 0;
 222                int *ext_tablep = (int *)ext_header;
 223
 224                i = ext_table_size / DWSIZE;
 225                while (i--)
 226                        ext_table_sum += ext_tablep[i];
 227                if (ext_table_sum) {
 228                        printk(KERN_WARNING "microcode: aborting, "
 229                                "bad extended signature table checksum\n");
 230                        return -EINVAL;
 231                }
 232        }
 233
 234        /* calculate the checksum */
 235        orig_sum = 0;
 236        i = (MC_HEADER_SIZE + data_size) / DWSIZE;
 237        while (i--)
 238                orig_sum += ((int *)mc)[i];
 239        if (orig_sum) {
 240                printk(KERN_ERR "microcode: aborting, bad checksum\n");
 241                return -EINVAL;
 242        }
 243        if (!ext_table_size)
 244                return 0;
 245        /* check extended signature checksum */
 246        for (i = 0; i < ext_sigcount; i++) {
 247                ext_sig = (struct extended_signature *)((void *)ext_header
 248                        + EXT_HEADER_SIZE + EXT_SIGNATURE_SIZE * i);
 249                sum = orig_sum
 250                        - (mc_header->sig + mc_header->pf + mc_header->cksum)
 251                        + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
 252                if (sum) {
 253                        printk(KERN_ERR "microcode: aborting, bad checksum\n");
 254                        return -EINVAL;
 255                }
 256        }
 257        return 0;
 258}
 259
 260/*
 261 * return 0 - no update found
 262 * return 1 - found update
 263 * return < 0 - error
 264 */
 265static int get_maching_microcode(void *mc, int cpu)
 266{
 267        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 268        microcode_header_t *mc_header = mc;
 269        struct extended_sigtable *ext_header;
 270        unsigned long total_size = get_totalsize(mc_header);
 271        int ext_sigcount, i;
 272        struct extended_signature *ext_sig;
 273        void *new_mc;
 274
 275        if (microcode_update_match(cpu, mc_header,
 276                        mc_header->sig, mc_header->pf))
 277                goto find;
 278
 279        if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
 280                return 0;
 281
 282        ext_header = (struct extended_sigtable *)(mc +
 283                        get_datasize(mc_header) + MC_HEADER_SIZE);
 284        ext_sigcount = ext_header->count;
 285        ext_sig = (struct extended_signature *)((void *)ext_header
 286                        + EXT_HEADER_SIZE);
 287        for (i = 0; i < ext_sigcount; i++) {
 288                if (microcode_update_match(cpu, mc_header,
 289                                ext_sig->sig, ext_sig->pf))
 290                        goto find;
 291                ext_sig++;
 292        }
 293        return 0;
 294find:
 295        pr_debug("microcode: CPU %d found a matching microcode update with"
 296                " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
 297        new_mc = vmalloc(total_size);
 298        if (!new_mc) {
 299                printk(KERN_ERR "microcode: error! Can not allocate memory\n");
 300                return -ENOMEM;
 301        }
 302
 303        /* free previous update file */
 304        vfree(uci->mc);
 305
 306        memcpy(new_mc, mc, total_size);
 307        uci->mc = new_mc;
 308        return 1;
 309}
 310
 311static void apply_microcode(int cpu)
 312{
 313        unsigned long flags;
 314        unsigned int val[2];
 315        int cpu_num = raw_smp_processor_id();
 316        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 317
 318        /* We should bind the task to the CPU */
 319        BUG_ON(cpu_num != cpu);
 320
 321        if (uci->mc == NULL)
 322                return;
 323
 324        /* serialize access to the physical write to MSR 0x79 */
 325        spin_lock_irqsave(&microcode_update_lock, flags);          
 326
 327        /* write microcode via MSR 0x79 */
 328        wrmsr(MSR_IA32_UCODE_WRITE,
 329                (unsigned long) uci->mc->bits, 
 330                (unsigned long) uci->mc->bits >> 16 >> 16);
 331        wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 332
 333        /* see notes above for revision 1.07.  Apparent chip bug */
 334        sync_core();
 335
 336        /* get the current revision from MSR 0x8B */
 337        rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 338
 339        spin_unlock_irqrestore(&microcode_update_lock, flags);
 340        if (val[1] != uci->mc->hdr.rev) {
 341                printk(KERN_ERR "microcode: CPU%d updated from revision "
 342                        "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
 343                return;
 344        }
 345        pr_debug("microcode: CPU%d updated from revision "
 346               "0x%x to 0x%x, date = %08x \n", 
 347               cpu_num, uci->rev, val[1], uci->mc->hdr.date);
 348        uci->rev = val[1];
 349}
 350
 351#ifdef CONFIG_MICROCODE_OLD_INTERFACE
 352static void __user *user_buffer;        /* user area microcode data buffer */
 353static unsigned int user_buffer_size;   /* it's size */
 354
 355static long get_next_ucode(void **mc, long offset)
 356{
 357        microcode_header_t mc_header;
 358        unsigned long total_size;
 359
 360        /* No more data */
 361        if (offset >= user_buffer_size)
 362                return 0;
 363        if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
 364                printk(KERN_ERR "microcode: error! Can not read user data\n");
 365                return -EFAULT;
 366        }
 367        total_size = get_totalsize(&mc_header);
 368        if (offset + total_size > user_buffer_size) {
 369                printk(KERN_ERR "microcode: error! Bad total size in microcode "
 370                                "data file\n");
 371                return -EINVAL;
 372        }
 373        *mc = vmalloc(total_size);
 374        if (!*mc)
 375                return -ENOMEM;
 376        if (copy_from_user(*mc, user_buffer + offset, total_size)) {
 377                printk(KERN_ERR "microcode: error! Can not read user data\n");
 378                vfree(*mc);
 379                return -EFAULT;
 380        }
 381        return offset + total_size;
 382}
 383
 384static int do_microcode_update (void)
 385{
 386        long cursor = 0;
 387        int error = 0;
 388        void *new_mc = NULL;
 389        int cpu;
 390        cpumask_t old;
 391
 392        old = current->cpus_allowed;
 393
 394        while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
 395                error = microcode_sanity_check(new_mc);
 396                if (error)
 397                        goto out;
 398                /*
 399                 * It's possible the data file has multiple matching ucode,
 400                 * lets keep searching till the latest version
 401                 */
 402                for_each_online_cpu(cpu) {
 403                        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 404
 405                        if (!uci->valid)
 406                                continue;
 407                        set_cpus_allowed(current, cpumask_of_cpu(cpu));
 408                        error = get_maching_microcode(new_mc, cpu);
 409                        if (error < 0)
 410                                goto out;
 411                        if (error == 1)
 412                                apply_microcode(cpu);
 413                }
 414                vfree(new_mc);
 415        }
 416out:
 417        if (cursor > 0)
 418                vfree(new_mc);
 419        if (cursor < 0)
 420                error = cursor;
 421        set_cpus_allowed(current, old);
 422        return error;
 423}
 424
 425static int microcode_open (struct inode *unused1, struct file *unused2)
 426{
 427        return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
 428}
 429
 430static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
 431{
 432        ssize_t ret;
 433
 434        if ((len >> PAGE_SHIFT) > num_physpages) {
 435                printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
 436                return -EINVAL;
 437        }
 438
 439        lock_cpu_hotplug();
 440        mutex_lock(&microcode_mutex);
 441
 442        user_buffer = (void __user *) buf;
 443        user_buffer_size = (int) len;
 444
 445        ret = do_microcode_update();
 446        if (!ret)
 447                ret = (ssize_t)len;
 448
 449        mutex_unlock(&microcode_mutex);
 450        unlock_cpu_hotplug();
 451
 452        return ret;
 453}
 454
 455static const struct file_operations microcode_fops = {
 456        .owner          = THIS_MODULE,
 457        .write          = microcode_write,
 458        .open           = microcode_open,
 459};
 460
 461static struct miscdevice microcode_dev = {
 462        .minor          = MICROCODE_MINOR,
 463        .name           = "microcode",
 464        .fops           = &microcode_fops,
 465};
 466
 467static int __init microcode_dev_init (void)
 468{
 469        int error;
 470
 471        error = misc_register(&microcode_dev);
 472        if (error) {
 473                printk(KERN_ERR
 474                        "microcode: can't misc_register on minor=%d\n",
 475                        MICROCODE_MINOR);
 476                return error;
 477        }
 478
 479        return 0;
 480}
 481
 482static void microcode_dev_exit (void)
 483{
 484        misc_deregister(&microcode_dev);
 485}
 486
 487MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
 488#else
 489#define microcode_dev_init() 0
 490#define microcode_dev_exit() do { } while(0)
 491#endif
 492
 493static long get_next_ucode_from_buffer(void **mc, void *buf,
 494        unsigned long size, long offset)
 495{
 496        microcode_header_t *mc_header;
 497        unsigned long total_size;
 498
 499        /* No more data */
 500        if (offset >= size)
 501                return 0;
 502        mc_header = (microcode_header_t *)(buf + offset);
 503        total_size = get_totalsize(mc_header);
 504
 505        if (offset + total_size > size) {
 506                printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
 507                return -EINVAL;
 508        }
 509
 510        *mc = vmalloc(total_size);
 511        if (!*mc) {
 512                printk(KERN_ERR "microcode: error! Can not allocate memory\n");
 513                return -ENOMEM;
 514        }
 515        memcpy(*mc, buf + offset, total_size);
 516        return offset + total_size;
 517}
 518
 519/* fake device for request_firmware */
 520static struct platform_device *microcode_pdev;
 521
 522static int cpu_request_microcode(int cpu)
 523{
 524        char name[30];
 525        struct cpuinfo_x86 *c = &cpu_data(cpu);
 526        const struct firmware *firmware;
 527        void *buf;
 528        unsigned long size;
 529        long offset = 0;
 530        int error;
 531        void *mc;
 532
 533        /* We should bind the task to the CPU */
 534        BUG_ON(cpu != raw_smp_processor_id());
 535        sprintf(name,"intel-ucode/%02x-%02x-%02x",
 536                c->x86, c->x86_model, c->x86_mask);
 537        error = request_firmware(&firmware, name, &microcode_pdev->dev);
 538        if (error) {
 539                pr_debug("ucode data file %s load failed\n", name);
 540                return error;
 541        }
 542        buf = (void *)firmware->data;
 543        size = firmware->size;
 544        while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
 545                        > 0) {
 546                error = microcode_sanity_check(mc);
 547                if (error)
 548                        break;
 549                error = get_maching_microcode(mc, cpu);
 550                if (error < 0)
 551                        break;
 552                /*
 553                 * It's possible the data file has multiple matching ucode,
 554                 * lets keep searching till the latest version
 555                 */
 556                if (error == 1) {
 557                        apply_microcode(cpu);
 558                        error = 0;
 559                }
 560                vfree(mc);
 561        }
 562        if (offset > 0)
 563                vfree(mc);
 564        if (offset < 0)
 565                error = offset;
 566        release_firmware(firmware);
 567
 568        return error;
 569}
 570
 571static int apply_microcode_check_cpu(int cpu)
 572{
 573        struct cpuinfo_x86 *c = &cpu_data(cpu);
 574        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 575        cpumask_t old;
 576        unsigned int val[2];
 577        int err = 0;
 578
 579        /* Check if the microcode is available */
 580        if (!uci->mc)
 581                return 0;
 582
 583        old = current->cpus_allowed;
 584        set_cpus_allowed(current, cpumask_of_cpu(cpu));
 585
 586        /* Check if the microcode we have in memory matches the CPU */
 587        if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
 588            cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001))
 589                err = -EINVAL;
 590
 591        if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) {
 592                /* get processor flags from MSR 0x17 */
 593                rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
 594                if (uci->pf != (1 << ((val[1] >> 18) & 7)))
 595                        err = -EINVAL;
 596        }
 597
 598        if (!err) {
 599                wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 600                /* see notes above for revision 1.07.  Apparent chip bug */
 601                sync_core();
 602                /* get the current revision from MSR 0x8B */
 603                rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 604                if (uci->rev != val[1])
 605                        err = -EINVAL;
 606        }
 607
 608        if (!err)
 609                apply_microcode(cpu);
 610        else
 611                printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
 612                        " sig=0x%x, pf=0x%x, rev=0x%x\n",
 613                        cpu, uci->sig, uci->pf, uci->rev);
 614
 615        set_cpus_allowed(current, old);
 616        return err;
 617}
 618
 619static void microcode_init_cpu(int cpu, int resume)
 620{
 621        cpumask_t old;
 622        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 623
 624        old = current->cpus_allowed;
 625
 626        set_cpus_allowed(current, cpumask_of_cpu(cpu));
 627        mutex_lock(&microcode_mutex);
 628        collect_cpu_info(cpu);
 629        if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
 630                cpu_request_microcode(cpu);
 631        mutex_unlock(&microcode_mutex);
 632        set_cpus_allowed(current, old);
 633}
 634
 635static void microcode_fini_cpu(int cpu)
 636{
 637        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 638
 639        mutex_lock(&microcode_mutex);
 640        uci->valid = 0;
 641        vfree(uci->mc);
 642        uci->mc = NULL;
 643        mutex_unlock(&microcode_mutex);
 644}
 645
 646static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
 647{
 648        struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
 649        char *end;
 650        unsigned long val = simple_strtoul(buf, &end, 0);
 651        int err = 0;
 652        int cpu = dev->id;
 653
 654        if (end == buf)
 655                return -EINVAL;
 656        if (val == 1) {
 657                cpumask_t old;
 658
 659                old = current->cpus_allowed;
 660
 661                lock_cpu_hotplug();
 662                set_cpus_allowed(current, cpumask_of_cpu(cpu));
 663
 664                mutex_lock(&microcode_mutex);
 665                if (uci->valid)
 666                        err = cpu_request_microcode(cpu);
 667                mutex_unlock(&microcode_mutex);
 668                unlock_cpu_hotplug();
 669                set_cpus_allowed(current, old);
 670        }
 671        if (err)
 672                return err;
 673        return sz;
 674}
 675
 676static ssize_t version_show(struct sys_device *dev, char *buf)
 677{
 678        struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
 679
 680        return sprintf(buf, "0x%x\n", uci->rev);
 681}
 682
 683static ssize_t pf_show(struct sys_device *dev, char *buf)
 684{
 685        struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
 686
 687        return sprintf(buf, "0x%x\n", uci->pf);
 688}
 689
 690static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
 691static SYSDEV_ATTR(version, 0400, version_show, NULL);
 692static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
 693
 694static struct attribute *mc_default_attrs[] = {
 695        &attr_reload.attr,
 696        &attr_version.attr,
 697        &attr_processor_flags.attr,
 698        NULL
 699};
 700
 701static struct attribute_group mc_attr_group = {
 702        .attrs = mc_default_attrs,
 703        .name = "microcode",
 704};
 705
 706static int __mc_sysdev_add(struct sys_device *sys_dev, int resume)
 707{
 708        int err, cpu = sys_dev->id;
 709        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 710
 711        if (!cpu_online(cpu))
 712                return 0;
 713
 714        pr_debug("Microcode:CPU %d added\n", cpu);
 715        memset(uci, 0, sizeof(*uci));
 716
 717        err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
 718        if (err)
 719                return err;
 720
 721        microcode_init_cpu(cpu, resume);
 722
 723        return 0;
 724}
 725
 726static int mc_sysdev_add(struct sys_device *sys_dev)
 727{
 728        return __mc_sysdev_add(sys_dev, 0);
 729}
 730
 731static int mc_sysdev_remove(struct sys_device *sys_dev)
 732{
 733        int cpu = sys_dev->id;
 734
 735        if (!cpu_online(cpu))
 736                return 0;
 737
 738        pr_debug("Microcode:CPU %d removed\n", cpu);
 739        microcode_fini_cpu(cpu);
 740        sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
 741        return 0;
 742}
 743
 744static int mc_sysdev_resume(struct sys_device *dev)
 745{
 746        int cpu = dev->id;
 747
 748        if (!cpu_online(cpu))
 749                return 0;
 750        pr_debug("Microcode:CPU %d resumed\n", cpu);
 751        /* only CPU 0 will apply ucode here */
 752        apply_microcode(0);
 753        return 0;
 754}
 755
 756static struct sysdev_driver mc_sysdev_driver = {
 757        .add = mc_sysdev_add,
 758        .remove = mc_sysdev_remove,
 759        .resume = mc_sysdev_resume,
 760};
 761
 762static __cpuinit int
 763mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 764{
 765        unsigned int cpu = (unsigned long)hcpu;
 766        struct sys_device *sys_dev;
 767
 768        sys_dev = get_cpu_sysdev(cpu);
 769        switch (action) {
 770        case CPU_UP_CANCELED_FROZEN:
 771                /* The CPU refused to come up during a system resume */
 772                microcode_fini_cpu(cpu);
 773                break;
 774        case CPU_ONLINE:
 775        case CPU_DOWN_FAILED:
 776                mc_sysdev_add(sys_dev);
 777                break;
 778        case CPU_ONLINE_FROZEN:
 779                /* System-wide resume is in progress, try to apply microcode */
 780                if (apply_microcode_check_cpu(cpu)) {
 781                        /* The application of microcode failed */
 782                        microcode_fini_cpu(cpu);
 783                        __mc_sysdev_add(sys_dev, 1);
 784                        break;
 785                }
 786        case CPU_DOWN_FAILED_FROZEN:
 787                if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
 788                        printk(KERN_ERR "Microcode: Failed to create the sysfs "
 789                                "group for CPU%d\n", cpu);
 790                break;
 791        case CPU_DOWN_PREPARE:
 792                mc_sysdev_remove(sys_dev);
 793                break;
 794        case CPU_DOWN_PREPARE_FROZEN:
 795                /* Suspend is in progress, only remove the interface */
 796                sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
 797                break;
 798        }
 799        return NOTIFY_OK;
 800}
 801
 802static struct notifier_block __cpuinitdata mc_cpu_notifier = {
 803        .notifier_call = mc_cpu_callback,
 804};
 805
 806static int __init microcode_init (void)
 807{
 808        int error;
 809
 810        error = microcode_dev_init();
 811        if (error)
 812                return error;
 813        microcode_pdev = platform_device_register_simple("microcode", -1,
 814                                                         NULL, 0);
 815        if (IS_ERR(microcode_pdev)) {
 816                microcode_dev_exit();
 817                return PTR_ERR(microcode_pdev);
 818        }
 819
 820        lock_cpu_hotplug();
 821        error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
 822        unlock_cpu_hotplug();
 823        if (error) {
 824                microcode_dev_exit();
 825                platform_device_unregister(microcode_pdev);
 826                return error;
 827        }
 828
 829        register_hotcpu_notifier(&mc_cpu_notifier);
 830
 831        printk(KERN_INFO 
 832                "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
 833        return 0;
 834}
 835
 836static void __exit microcode_exit (void)
 837{
 838        microcode_dev_exit();
 839
 840        unregister_hotcpu_notifier(&mc_cpu_notifier);
 841
 842        lock_cpu_hotplug();
 843        sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
 844        unlock_cpu_hotplug();
 845
 846        platform_device_unregister(microcode_pdev);
 847}
 848
 849module_init(microcode_init)
 850module_exit(microcode_exit)
 851