diff options
author | Robert Richter <robert.richter@amd.com> | 2011-06-07 05:49:55 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-07-21 14:41:57 -0400 |
commit | 1ac2e6ca44e13a087eb7438d284f887097ee7e84 (patch) | |
tree | 7ee4f00a67850e1e247610cefeae0ee7aa7b239a /arch/x86/lib | |
parent | 9985c20f9e4aee6857c08246b273a3695a52b929 (diff) |
x86, perf: Make copy_from_user_nmi() a library function
copy_from_user_nmi() is used in oprofile and perf. Moving it to other
library functions like copy_from_user(). As this is x86 code for 32
and 64 bits, create a new file usercopy.c for unified code.
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20110607172413.GJ20052@erda.amd.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/lib/usercopy.c | 43 |
2 files changed, 44 insertions, 1 deletions
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index f2479f19ddde..6ba477342b8e 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile | |||
@@ -18,7 +18,7 @@ obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o | |||
18 | 18 | ||
19 | lib-y := delay.o | 19 | lib-y := delay.o |
20 | lib-y += thunk_$(BITS).o | 20 | lib-y += thunk_$(BITS).o |
21 | lib-y += usercopy_$(BITS).o getuser.o putuser.o | 21 | lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o |
22 | lib-y += memcpy_$(BITS).o | 22 | lib-y += memcpy_$(BITS).o |
23 | lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o | 23 | lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o |
24 | 24 | ||
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c new file mode 100644 index 000000000000..97be9cb54483 --- /dev/null +++ b/arch/x86/lib/usercopy.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * User address space access functions. | ||
3 | * | ||
4 | * For licencing details see kernel-base/COPYING | ||
5 | */ | ||
6 | |||
7 | #include <linux/highmem.h> | ||
8 | #include <linux/module.h> | ||
9 | |||
10 | /* | ||
11 | * best effort, GUP based copy_from_user() that is NMI-safe | ||
12 | */ | ||
13 | unsigned long | ||
14 | copy_from_user_nmi(void *to, const void __user *from, unsigned long n) | ||
15 | { | ||
16 | unsigned long offset, addr = (unsigned long)from; | ||
17 | unsigned long size, len = 0; | ||
18 | struct page *page; | ||
19 | void *map; | ||
20 | int ret; | ||
21 | |||
22 | do { | ||
23 | ret = __get_user_pages_fast(addr, 1, 0, &page); | ||
24 | if (!ret) | ||
25 | break; | ||
26 | |||
27 | offset = addr & (PAGE_SIZE - 1); | ||
28 | size = min(PAGE_SIZE - offset, n - len); | ||
29 | |||
30 | map = kmap_atomic(page); | ||
31 | memcpy(to, map+offset, size); | ||
32 | kunmap_atomic(map); | ||
33 | put_page(page); | ||
34 | |||
35 | len += size; | ||
36 | to += size; | ||
37 | addr += size; | ||
38 | |||
39 | } while (len < n); | ||
40 | |||
41 | return len; | ||
42 | } | ||
43 | EXPORT_SYMBOL_GPL(copy_from_user_nmi); | ||