diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-01 00:24:54 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-01 00:24:54 -0400 |
commit | bc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775 (patch) | |
tree | 427fcf2a7287c16d4b5aa6cbf494d59579a6a8b1 /arch/i386/lib | |
parent | 3d29cdff999c37b3876082278a8134a0642a02cd (diff) | |
parent | dc87c3985e9b442c60994308a96f887579addc39 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
drivers/usb/input/Makefile
drivers/usb/input/gtco.c
Diffstat (limited to 'arch/i386/lib')
-rw-r--r-- | arch/i386/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/lib/msr-on-cpu.c | 58 | ||||
-rw-r--r-- | arch/i386/lib/usercopy.c | 9 |
3 files changed, 69 insertions, 0 deletions
diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile index d86a548b8d5..22d8ac5815f 100644 --- a/arch/i386/lib/Makefile +++ b/arch/i386/lib/Makefile @@ -7,3 +7,5 @@ lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \ bitops.o semaphore.o lib-$(CONFIG_X86_USE_3DNOW) += mmx.o + +obj-$(CONFIG_SMP) += msr-on-cpu.o diff --git a/arch/i386/lib/msr-on-cpu.c b/arch/i386/lib/msr-on-cpu.c new file mode 100644 index 00000000000..1c46bda409f --- /dev/null +++ b/arch/i386/lib/msr-on-cpu.c @@ -0,0 +1,58 @@ +#include <linux/module.h> +#include <linux/preempt.h> +#include <linux/smp.h> +#include <asm/msr.h> + +struct msr_info { + u32 msr_no; + u32 l, h; +}; + +static void __rdmsr_on_cpu(void *info) +{ + struct msr_info *rv = info; + + rdmsr(rv->msr_no, rv->l, rv->h); +} + +void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) +{ + preempt_disable(); + if (smp_processor_id() == cpu) + rdmsr(msr_no, *l, *h); + else { + struct msr_info rv; + + rv.msr_no = msr_no; + smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1); + *l = rv.l; + *h = rv.h; + } + preempt_enable(); +} + +static void __wrmsr_on_cpu(void *info) +{ + struct msr_info *rv = info; + + wrmsr(rv->msr_no, rv->l, rv->h); +} + +void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +{ + preempt_disable(); + if (smp_processor_id() == cpu) + wrmsr(msr_no, l, h); + else { + struct msr_info rv; + + rv.msr_no = msr_no; + rv.l = l; + rv.h = h; + smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1); + } + preempt_enable(); +} + +EXPORT_SYMBOL(rdmsr_on_cpu); +EXPORT_SYMBOL(wrmsr_on_cpu); diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index d22cfc9d656..086b3726862 100644 --- a/arch/i386/lib/usercopy.c +++ b/arch/i386/lib/usercopy.c @@ -10,6 +10,7 @@ #include <linux/blkdev.h> #include <linux/module.h> #include <linux/backing-dev.h> +#include <linux/interrupt.h> #include <asm/uaccess.h> #include <asm/mmx.h> @@ -719,6 +720,14 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, #ifndef CONFIG_X86_WP_WORKS_OK if (unlikely(boot_cpu_data.wp_works_ok == 0) && ((unsigned long )to) < TASK_SIZE) { + /* + * When we are in an atomic section (see + * mm/filemap.c:file_read_actor), return the full + * length to take the slow path. + */ + if (in_atomic()) + return n; + /* * CPU does not honor the WP bit when writing * from supervisory mode, and due to preemption or SMP, |