xref: /openbmc/linux/arch/x86/lib/usercopy.c (revision 81d67439)
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);
44