diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/microcode.c | 71 | ||||
-rw-r--r-- | arch/i386/lib/usercopy.c | 9 | ||||
-rw-r--r-- | arch/um/sys-i386/delay.c | 11 | ||||
-rw-r--r-- | arch/um/sys-x86_64/delay.c | 11 |
4 files changed, 76 insertions, 26 deletions
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index b8f16633a6ec..cbe7ec8dbb9f 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c | |||
@@ -567,6 +567,53 @@ static int cpu_request_microcode(int cpu) | |||
567 | return error; | 567 | return error; |
568 | } | 568 | } |
569 | 569 | ||
570 | static int apply_microcode_on_cpu(int cpu) | ||
571 | { | ||
572 | struct cpuinfo_x86 *c = cpu_data + cpu; | ||
573 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
574 | cpumask_t old; | ||
575 | unsigned int val[2]; | ||
576 | int err = 0; | ||
577 | |||
578 | if (!uci->mc) | ||
579 | return -EINVAL; | ||
580 | |||
581 | old = current->cpus_allowed; | ||
582 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | ||
583 | |||
584 | /* Check if the microcode we have in memory matches the CPU */ | ||
585 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | ||
586 | cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001)) | ||
587 | err = -EINVAL; | ||
588 | |||
589 | if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) { | ||
590 | /* get processor flags from MSR 0x17 */ | ||
591 | rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | ||
592 | if (uci->pf != (1 << ((val[1] >> 18) & 7))) | ||
593 | err = -EINVAL; | ||
594 | } | ||
595 | |||
596 | if (!err) { | ||
597 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
598 | /* see notes above for revision 1.07. Apparent chip bug */ | ||
599 | sync_core(); | ||
600 | /* get the current revision from MSR 0x8B */ | ||
601 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | ||
602 | if (uci->rev != val[1]) | ||
603 | err = -EINVAL; | ||
604 | } | ||
605 | |||
606 | if (!err) | ||
607 | apply_microcode(cpu); | ||
608 | else | ||
609 | printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:" | ||
610 | " sig=0x%x, pf=0x%x, rev=0x%x\n", | ||
611 | cpu, uci->sig, uci->pf, uci->rev); | ||
612 | |||
613 | set_cpus_allowed(current, old); | ||
614 | return err; | ||
615 | } | ||
616 | |||
570 | static void microcode_init_cpu(int cpu) | 617 | static void microcode_init_cpu(int cpu) |
571 | { | 618 | { |
572 | cpumask_t old; | 619 | cpumask_t old; |
@@ -577,7 +624,8 @@ static void microcode_init_cpu(int cpu) | |||
577 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | 624 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); |
578 | mutex_lock(µcode_mutex); | 625 | mutex_lock(µcode_mutex); |
579 | collect_cpu_info(cpu); | 626 | collect_cpu_info(cpu); |
580 | if (uci->valid && system_state == SYSTEM_RUNNING) | 627 | if (uci->valid && system_state == SYSTEM_RUNNING && |
628 | !suspend_cpu_hotplug) | ||
581 | cpu_request_microcode(cpu); | 629 | cpu_request_microcode(cpu); |
582 | mutex_unlock(µcode_mutex); | 630 | mutex_unlock(µcode_mutex); |
583 | set_cpus_allowed(current, old); | 631 | set_cpus_allowed(current, old); |
@@ -663,13 +711,24 @@ static int mc_sysdev_add(struct sys_device *sys_dev) | |||
663 | return 0; | 711 | return 0; |
664 | 712 | ||
665 | pr_debug("Microcode:CPU %d added\n", cpu); | 713 | pr_debug("Microcode:CPU %d added\n", cpu); |
666 | memset(uci, 0, sizeof(*uci)); | 714 | /* If suspend_cpu_hotplug is set, the system is resuming and we should |
715 | * use the data from before the suspend. | ||
716 | */ | ||
717 | if (suspend_cpu_hotplug) { | ||
718 | err = apply_microcode_on_cpu(cpu); | ||
719 | if (err) | ||
720 | microcode_fini_cpu(cpu); | ||
721 | } | ||
722 | if (!uci->valid) | ||
723 | memset(uci, 0, sizeof(*uci)); | ||
667 | 724 | ||
668 | err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); | 725 | err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); |
669 | if (err) | 726 | if (err) |
670 | return err; | 727 | return err; |
671 | 728 | ||
672 | microcode_init_cpu(cpu); | 729 | if (!uci->valid) |
730 | microcode_init_cpu(cpu); | ||
731 | |||
673 | return 0; | 732 | return 0; |
674 | } | 733 | } |
675 | 734 | ||
@@ -680,7 +739,11 @@ static int mc_sysdev_remove(struct sys_device *sys_dev) | |||
680 | if (!cpu_online(cpu)) | 739 | if (!cpu_online(cpu)) |
681 | return 0; | 740 | return 0; |
682 | pr_debug("Microcode:CPU %d removed\n", cpu); | 741 | pr_debug("Microcode:CPU %d removed\n", cpu); |
683 | microcode_fini_cpu(cpu); | 742 | /* If suspend_cpu_hotplug is set, the system is suspending and we should |
743 | * keep the microcode in memory for the resume. | ||
744 | */ | ||
745 | if (!suspend_cpu_hotplug) | ||
746 | microcode_fini_cpu(cpu); | ||
684 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); | 747 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); |
685 | return 0; | 748 | return 0; |
686 | } | 749 | } |
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index d22cfc9d656c..086b3726862a 100644 --- a/arch/i386/lib/usercopy.c +++ b/arch/i386/lib/usercopy.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/blkdev.h> | 10 | #include <linux/blkdev.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/backing-dev.h> | 12 | #include <linux/backing-dev.h> |
13 | #include <linux/interrupt.h> | ||
13 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
14 | #include <asm/mmx.h> | 15 | #include <asm/mmx.h> |
15 | 16 | ||
@@ -719,6 +720,14 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, | |||
719 | #ifndef CONFIG_X86_WP_WORKS_OK | 720 | #ifndef CONFIG_X86_WP_WORKS_OK |
720 | if (unlikely(boot_cpu_data.wp_works_ok == 0) && | 721 | if (unlikely(boot_cpu_data.wp_works_ok == 0) && |
721 | ((unsigned long )to) < TASK_SIZE) { | 722 | ((unsigned long )to) < TASK_SIZE) { |
723 | /* | ||
724 | * When we are in an atomic section (see | ||
725 | * mm/filemap.c:file_read_actor), return the full | ||
726 | * length to take the slow path. | ||
727 | */ | ||
728 | if (in_atomic()) | ||
729 | return n; | ||
730 | |||
722 | /* | 731 | /* |
723 | * CPU does not honor the WP bit when writing | 732 | * CPU does not honor the WP bit when writing |
724 | * from supervisory mode, and due to preemption or SMP, | 733 | * from supervisory mode, and due to preemption or SMP, |
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c index 2c11b9770e8b..d623e074f41d 100644 --- a/arch/um/sys-i386/delay.c +++ b/arch/um/sys-i386/delay.c | |||
@@ -27,14 +27,3 @@ void __udelay(unsigned long usecs) | |||
27 | } | 27 | } |
28 | 28 | ||
29 | EXPORT_SYMBOL(__udelay); | 29 | EXPORT_SYMBOL(__udelay); |
30 | |||
31 | void __const_udelay(unsigned long usecs) | ||
32 | { | ||
33 | int i, n; | ||
34 | |||
35 | n = (loops_per_jiffy * HZ * usecs) / MILLION; | ||
36 | for(i=0;i<n;i++) | ||
37 | cpu_relax(); | ||
38 | } | ||
39 | |||
40 | EXPORT_SYMBOL(__const_udelay); | ||
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c index 137f4446b439..dee5be66da82 100644 --- a/arch/um/sys-x86_64/delay.c +++ b/arch/um/sys-x86_64/delay.c | |||
@@ -28,14 +28,3 @@ void __udelay(unsigned long usecs) | |||
28 | } | 28 | } |
29 | 29 | ||
30 | EXPORT_SYMBOL(__udelay); | 30 | EXPORT_SYMBOL(__udelay); |
31 | |||
32 | void __const_udelay(unsigned long usecs) | ||
33 | { | ||
34 | unsigned long i, n; | ||
35 | |||
36 | n = (loops_per_jiffy * HZ * usecs) / MILLION; | ||
37 | for(i=0;i<n;i++) | ||
38 | cpu_relax(); | ||
39 | } | ||
40 | |||
41 | EXPORT_SYMBOL(__const_udelay); | ||