aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/microcode.c71
-rw-r--r--arch/i386/lib/usercopy.c9
-rw-r--r--arch/um/sys-i386/delay.c11
-rw-r--r--arch/um/sys-x86_64/delay.c11
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
570static 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
570static void microcode_init_cpu(int cpu) 617static 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(&microcode_mutex); 625 mutex_lock(&microcode_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(&microcode_mutex); 630 mutex_unlock(&microcode_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
29EXPORT_SYMBOL(__udelay); 29EXPORT_SYMBOL(__udelay);
30
31void __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
40EXPORT_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
30EXPORT_SYMBOL(__udelay); 30EXPORT_SYMBOL(__udelay);
31
32void __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
41EXPORT_SYMBOL(__const_udelay);