diff options
| author | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
| commit | ff877ea80efa2015b6263766f78ee42c2a1b32f9 (patch) | |
| tree | 85205005c611ab774702148558321c6fb92f1ccd /arch/x86/kernel/microcode.c | |
| parent | 30821fee4f0cb3e6d241d9f7ddc37742212e3eb7 (diff) | |
| parent | d37e6bf68fc1eb34a4ad21d9ae8890ed37ea80e7 (diff) | |
Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubi-2.6
Diffstat (limited to 'arch/x86/kernel/microcode.c')
| -rw-r--r-- | arch/x86/kernel/microcode.c | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 69729e38b78a..6994c751590e 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c | |||
| @@ -5,13 +5,14 @@ | |||
| 5 | * 2006 Shaohua Li <shaohua.li@intel.com> | 5 | * 2006 Shaohua Li <shaohua.li@intel.com> |
| 6 | * | 6 | * |
| 7 | * This driver allows to upgrade microcode on Intel processors | 7 | * This driver allows to upgrade microcode on Intel processors |
| 8 | * belonging to IA-32 family - PentiumPro, Pentium II, | 8 | * belonging to IA-32 family - PentiumPro, Pentium II, |
| 9 | * Pentium III, Xeon, Pentium 4, etc. | 9 | * Pentium III, Xeon, Pentium 4, etc. |
| 10 | * | 10 | * |
| 11 | * Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, | 11 | * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture |
| 12 | * Order Number 245472 or free download from: | 12 | * Software Developer's Manual |
| 13 | * | 13 | * Order Number 253668 or free download from: |
| 14 | * http://developer.intel.com/design/pentium4/manuals/245472.htm | 14 | * |
| 15 | * http://developer.intel.com/design/pentium4/manuals/253668.htm | ||
| 15 | * | 16 | * |
| 16 | * For more information, go to http://www.urbanmyth.org/microcode | 17 | * For more information, go to http://www.urbanmyth.org/microcode |
| 17 | * | 18 | * |
| @@ -58,12 +59,12 @@ | |||
| 58 | * nature of implementation. | 59 | * nature of implementation. |
| 59 | * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com> | 60 | * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com> |
| 60 | * Fix the panic when writing zero-length microcode chunk. | 61 | * Fix the panic when writing zero-length microcode chunk. |
| 61 | * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, | 62 | * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, |
| 62 | * Jun Nakajima <jun.nakajima@intel.com> | 63 | * Jun Nakajima <jun.nakajima@intel.com> |
| 63 | * Support for the microcode updates in the new format. | 64 | * Support for the microcode updates in the new format. |
| 64 | * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com> | 65 | * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com> |
| 65 | * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl | 66 | * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl |
| 66 | * because we no longer hold a copy of applied microcode | 67 | * because we no longer hold a copy of applied microcode |
| 67 | * in kernel memory. | 68 | * in kernel memory. |
| 68 | * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com> | 69 | * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com> |
| 69 | * Fix sigmatch() macro to handle old CPUs with pf == 0. | 70 | * Fix sigmatch() macro to handle old CPUs with pf == 0. |
| @@ -75,6 +76,7 @@ | |||
| 75 | #include <linux/kernel.h> | 76 | #include <linux/kernel.h> |
| 76 | #include <linux/init.h> | 77 | #include <linux/init.h> |
| 77 | #include <linux/sched.h> | 78 | #include <linux/sched.h> |
| 79 | #include <linux/smp_lock.h> | ||
| 78 | #include <linux/cpumask.h> | 80 | #include <linux/cpumask.h> |
| 79 | #include <linux/module.h> | 81 | #include <linux/module.h> |
| 80 | #include <linux/slab.h> | 82 | #include <linux/slab.h> |
| @@ -320,11 +322,11 @@ static void apply_microcode(int cpu) | |||
| 320 | return; | 322 | return; |
| 321 | 323 | ||
| 322 | /* serialize access to the physical write to MSR 0x79 */ | 324 | /* serialize access to the physical write to MSR 0x79 */ |
| 323 | spin_lock_irqsave(µcode_update_lock, flags); | 325 | spin_lock_irqsave(µcode_update_lock, flags); |
| 324 | 326 | ||
| 325 | /* write microcode via MSR 0x79 */ | 327 | /* write microcode via MSR 0x79 */ |
| 326 | wrmsr(MSR_IA32_UCODE_WRITE, | 328 | wrmsr(MSR_IA32_UCODE_WRITE, |
| 327 | (unsigned long) uci->mc->bits, | 329 | (unsigned long) uci->mc->bits, |
| 328 | (unsigned long) uci->mc->bits >> 16 >> 16); | 330 | (unsigned long) uci->mc->bits >> 16 >> 16); |
| 329 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 331 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); |
| 330 | 332 | ||
| @@ -341,7 +343,7 @@ static void apply_microcode(int cpu) | |||
| 341 | return; | 343 | return; |
| 342 | } | 344 | } |
| 343 | printk(KERN_INFO "microcode: CPU%d updated from revision " | 345 | printk(KERN_INFO "microcode: CPU%d updated from revision " |
| 344 | "0x%x to 0x%x, date = %08x \n", | 346 | "0x%x to 0x%x, date = %08x \n", |
| 345 | cpu_num, uci->rev, val[1], uci->mc->hdr.date); | 347 | cpu_num, uci->rev, val[1], uci->mc->hdr.date); |
| 346 | uci->rev = val[1]; | 348 | uci->rev = val[1]; |
| 347 | } | 349 | } |
| @@ -386,6 +388,7 @@ static int do_microcode_update (void) | |||
| 386 | void *new_mc = NULL; | 388 | void *new_mc = NULL; |
| 387 | int cpu; | 389 | int cpu; |
| 388 | cpumask_t old; | 390 | cpumask_t old; |
| 391 | cpumask_of_cpu_ptr_declare(newmask); | ||
| 389 | 392 | ||
| 390 | old = current->cpus_allowed; | 393 | old = current->cpus_allowed; |
| 391 | 394 | ||
| @@ -402,7 +405,8 @@ static int do_microcode_update (void) | |||
| 402 | 405 | ||
| 403 | if (!uci->valid) | 406 | if (!uci->valid) |
| 404 | continue; | 407 | continue; |
| 405 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | 408 | cpumask_of_cpu_ptr_next(newmask, cpu); |
| 409 | set_cpus_allowed_ptr(current, newmask); | ||
| 406 | error = get_maching_microcode(new_mc, cpu); | 410 | error = get_maching_microcode(new_mc, cpu); |
| 407 | if (error < 0) | 411 | if (error < 0) |
| 408 | goto out; | 412 | goto out; |
| @@ -422,6 +426,7 @@ out: | |||
| 422 | 426 | ||
| 423 | static int microcode_open (struct inode *unused1, struct file *unused2) | 427 | static int microcode_open (struct inode *unused1, struct file *unused2) |
| 424 | { | 428 | { |
| 429 | cycle_kernel_lock(); | ||
| 425 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; | 430 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; |
| 426 | } | 431 | } |
| 427 | 432 | ||
| @@ -488,7 +493,7 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); | |||
| 488 | #define microcode_dev_exit() do { } while(0) | 493 | #define microcode_dev_exit() do { } while(0) |
| 489 | #endif | 494 | #endif |
| 490 | 495 | ||
| 491 | static long get_next_ucode_from_buffer(void **mc, void *buf, | 496 | static long get_next_ucode_from_buffer(void **mc, const u8 *buf, |
| 492 | unsigned long size, long offset) | 497 | unsigned long size, long offset) |
| 493 | { | 498 | { |
| 494 | microcode_header_t *mc_header; | 499 | microcode_header_t *mc_header; |
| @@ -522,7 +527,7 @@ static int cpu_request_microcode(int cpu) | |||
| 522 | char name[30]; | 527 | char name[30]; |
| 523 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 528 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| 524 | const struct firmware *firmware; | 529 | const struct firmware *firmware; |
| 525 | void *buf; | 530 | const u8 *buf; |
| 526 | unsigned long size; | 531 | unsigned long size; |
| 527 | long offset = 0; | 532 | long offset = 0; |
| 528 | int error; | 533 | int error; |
| @@ -534,7 +539,7 @@ static int cpu_request_microcode(int cpu) | |||
| 534 | c->x86, c->x86_model, c->x86_mask); | 539 | c->x86, c->x86_model, c->x86_mask); |
| 535 | error = request_firmware(&firmware, name, µcode_pdev->dev); | 540 | error = request_firmware(&firmware, name, µcode_pdev->dev); |
| 536 | if (error) { | 541 | if (error) { |
| 537 | pr_debug("microcode: ucode data file %s load failed\n", name); | 542 | pr_debug("microcode: data file %s load failed\n", name); |
| 538 | return error; | 543 | return error; |
| 539 | } | 544 | } |
| 540 | buf = firmware->data; | 545 | buf = firmware->data; |
| @@ -571,6 +576,7 @@ static int apply_microcode_check_cpu(int cpu) | |||
| 571 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 576 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| 572 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 577 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
| 573 | cpumask_t old; | 578 | cpumask_t old; |
| 579 | cpumask_of_cpu_ptr(newmask, cpu); | ||
| 574 | unsigned int val[2]; | 580 | unsigned int val[2]; |
| 575 | int err = 0; | 581 | int err = 0; |
| 576 | 582 | ||
| @@ -579,7 +585,7 @@ static int apply_microcode_check_cpu(int cpu) | |||
| 579 | return 0; | 585 | return 0; |
| 580 | 586 | ||
| 581 | old = current->cpus_allowed; | 587 | old = current->cpus_allowed; |
| 582 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | 588 | set_cpus_allowed_ptr(current, newmask); |
| 583 | 589 | ||
| 584 | /* Check if the microcode we have in memory matches the CPU */ | 590 | /* Check if the microcode we have in memory matches the CPU */ |
| 585 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | 591 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || |
| @@ -617,11 +623,12 @@ static int apply_microcode_check_cpu(int cpu) | |||
| 617 | static void microcode_init_cpu(int cpu, int resume) | 623 | static void microcode_init_cpu(int cpu, int resume) |
| 618 | { | 624 | { |
| 619 | cpumask_t old; | 625 | cpumask_t old; |
| 626 | cpumask_of_cpu_ptr(newmask, cpu); | ||
| 620 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 627 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
| 621 | 628 | ||
| 622 | old = current->cpus_allowed; | 629 | old = current->cpus_allowed; |
| 623 | 630 | ||
| 624 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | 631 | set_cpus_allowed_ptr(current, newmask); |
| 625 | mutex_lock(µcode_mutex); | 632 | mutex_lock(µcode_mutex); |
| 626 | collect_cpu_info(cpu); | 633 | collect_cpu_info(cpu); |
| 627 | if (uci->valid && system_state == SYSTEM_RUNNING && !resume) | 634 | if (uci->valid && system_state == SYSTEM_RUNNING && !resume) |
| @@ -641,7 +648,9 @@ static void microcode_fini_cpu(int cpu) | |||
| 641 | mutex_unlock(µcode_mutex); | 648 | mutex_unlock(µcode_mutex); |
| 642 | } | 649 | } |
| 643 | 650 | ||
| 644 | static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz) | 651 | static ssize_t reload_store(struct sys_device *dev, |
| 652 | struct sysdev_attribute *attr, | ||
| 653 | const char *buf, size_t sz) | ||
| 645 | { | 654 | { |
| 646 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | 655 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; |
| 647 | char *end; | 656 | char *end; |
| @@ -653,11 +662,12 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz) | |||
| 653 | return -EINVAL; | 662 | return -EINVAL; |
| 654 | if (val == 1) { | 663 | if (val == 1) { |
| 655 | cpumask_t old; | 664 | cpumask_t old; |
| 665 | cpumask_of_cpu_ptr(newmask, cpu); | ||
| 656 | 666 | ||
| 657 | old = current->cpus_allowed; | 667 | old = current->cpus_allowed; |
| 658 | 668 | ||
| 659 | get_online_cpus(); | 669 | get_online_cpus(); |
| 660 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | 670 | set_cpus_allowed_ptr(current, newmask); |
| 661 | 671 | ||
| 662 | mutex_lock(µcode_mutex); | 672 | mutex_lock(µcode_mutex); |
| 663 | if (uci->valid) | 673 | if (uci->valid) |
| @@ -671,14 +681,16 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz) | |||
| 671 | return sz; | 681 | return sz; |
| 672 | } | 682 | } |
| 673 | 683 | ||
| 674 | static ssize_t version_show(struct sys_device *dev, char *buf) | 684 | static ssize_t version_show(struct sys_device *dev, |
| 685 | struct sysdev_attribute *attr, char *buf) | ||
| 675 | { | 686 | { |
| 676 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | 687 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; |
| 677 | 688 | ||
| 678 | return sprintf(buf, "0x%x\n", uci->rev); | 689 | return sprintf(buf, "0x%x\n", uci->rev); |
| 679 | } | 690 | } |
| 680 | 691 | ||
| 681 | static ssize_t pf_show(struct sys_device *dev, char *buf) | 692 | static ssize_t pf_show(struct sys_device *dev, |
| 693 | struct sysdev_attribute *attr, char *buf) | ||
| 682 | { | 694 | { |
| 683 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | 695 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; |
| 684 | 696 | ||
| @@ -805,6 +817,9 @@ static int __init microcode_init (void) | |||
| 805 | { | 817 | { |
| 806 | int error; | 818 | int error; |
| 807 | 819 | ||
| 820 | printk(KERN_INFO | ||
| 821 | "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n"); | ||
| 822 | |||
| 808 | error = microcode_dev_init(); | 823 | error = microcode_dev_init(); |
| 809 | if (error) | 824 | if (error) |
| 810 | return error; | 825 | return error; |
| @@ -825,9 +840,6 @@ static int __init microcode_init (void) | |||
| 825 | } | 840 | } |
| 826 | 841 | ||
| 827 | register_hotcpu_notifier(&mc_cpu_notifier); | 842 | register_hotcpu_notifier(&mc_cpu_notifier); |
| 828 | |||
| 829 | printk(KERN_INFO | ||
| 830 | "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n"); | ||
| 831 | return 0; | 843 | return 0; |
| 832 | } | 844 | } |
| 833 | 845 | ||
