/* * User address space access functions. * * For licencing details see kernel-base/COPYING */ #include <linux/highmem.h> #include <linux/module.h> #include <asm/word-at-a-time.h> #include <linux/sched.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; if (__range_not_ok(from, n, TASK_SIZE)) return len; 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);