mirror of
https://github.com/torvalds/linux.git
synced 2024-12-23 03:11:46 +00:00
1ac2e6ca44
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>
44 lines
815 B
C
44 lines
815 B
C
/*
|
|
* User address space access functions.
|
|
*
|
|
* For licencing details see kernel-base/COPYING
|
|
*/
|
|
|
|
#include <linux/highmem.h>
|
|
#include <linux/module.h>
|
|
|
|
/*
|
|
* best effort, GUP based copy_from_user() that is NMI-safe
|
|
*/
|
|
unsigned long
|
|
copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
|
|
{
|
|
unsigned long offset, addr = (unsigned long)from;
|
|
unsigned long size, len = 0;
|
|
struct page *page;
|
|
void *map;
|
|
int ret;
|
|
|
|
do {
|
|
ret = __get_user_pages_fast(addr, 1, 0, &page);
|
|
if (!ret)
|
|
break;
|
|
|
|
offset = addr & (PAGE_SIZE - 1);
|
|
size = min(PAGE_SIZE - offset, n - len);
|
|
|
|
map = kmap_atomic(page);
|
|
memcpy(to, map+offset, size);
|
|
kunmap_atomic(map);
|
|
put_page(page);
|
|
|
|
len += size;
|
|
to += size;
|
|
addr += size;
|
|
|
|
} while (len < n);
|
|
|
|
return len;
|
|
}
|
|
EXPORT_SYMBOL_GPL(copy_from_user_nmi);
|