Merge branch 'for-3.5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj...
[firefly-linux-kernel-4.4.55.git] / arch / x86 / lib / usercopy.c
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 #include <asm/word-at-a-time.h>
11
12 /*
13  * best effort, GUP based copy_from_user() that is NMI-safe
14  */
15 unsigned long
16 copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
17 {
18         unsigned long offset, addr = (unsigned long)from;
19         unsigned long size, len = 0;
20         struct page *page;
21         void *map;
22         int ret;
23
24         do {
25                 ret = __get_user_pages_fast(addr, 1, 0, &page);
26                 if (!ret)
27                         break;
28
29                 offset = addr & (PAGE_SIZE - 1);
30                 size = min(PAGE_SIZE - offset, n - len);
31
32                 map = kmap_atomic(page);
33                 memcpy(to, map+offset, size);
34                 kunmap_atomic(map);
35                 put_page(page);
36
37                 len  += size;
38                 to   += size;
39                 addr += size;
40
41         } while (len < n);
42
43         return len;
44 }
45 EXPORT_SYMBOL_GPL(copy_from_user_nmi);