12 #include <linux/kernel.h>
13 #include <linux/ctype.h>
17 #include <linux/sched.h>
21 #include <asm/current.h>
25 pin_page_for_write(
const void __user *_addr,
pte_t **ptep,
spinlock_t **ptlp)
27 unsigned long addr = (
unsigned long)_addr;
46 pte = pte_offset_map_lock(
current->mm, pmd, addr, &ptl);
49 pte_unmap_unlock(pte, ptl);
60 __copy_to_user_memcpy(
void __user *to,
const void *
from,
unsigned long n)
65 memcpy((
void *)to, from, n);
79 while (!pin_page_for_write(to, &pte, &ptl)) {
92 memcpy((
void *)to, from, tocopy);
97 pte_unmap_unlock(pte, ptl);
117 return __copy_to_user_std(to, from, n);
118 return __copy_to_user_memcpy(to, from, n);
122 __clear_user_memset(
void __user *addr,
unsigned long n)
125 memset((
void *)addr, 0, n);
135 while (!pin_page_for_write(addr, &pte, &ptl)) {
146 memset((
void *)addr, 0, tocopy);
150 pte_unmap_unlock(pte, ptl);
162 return __clear_user_std(addr, n);
163 return __clear_user_memset(addr, n);
181 static int __init test_size_treshold(
void)
183 struct page *src_page, *dst_page;
184 void *user_ptr, *kernel_ptr;
185 unsigned long long t0,
t1,
t2;
201 ret = __copy_to_user_memcpy(user_ptr, kernel_ptr,
PAGE_SIZE);
203 for (size =
PAGE_SIZE; size >= 4; size /= 2) {
205 ret |= __copy_to_user_memcpy(user_ptr, kernel_ptr, size);
207 ret |= __copy_to_user_std(user_ptr, kernel_ptr, size);
209 printk(
"copy_to_user: %d %llu %llu\n", size, t1 - t0, t2 - t1);
212 for (size =
PAGE_SIZE; size >= 4; size /= 2) {
214 ret |= __clear_user_memset(user_ptr, size);
216 ret |= __clear_user_std(user_ptr, size);
218 printk(
"clear_user: %d %llu %llu\n", size, t1 - t0, t2 - t1);