1 /* user_fixup.c: Fix up user copy faults.
3 * Copyright (C) 2004 David S. Miller <davem@redhat.com>
6 #include <linux/compiler.h>
7 #include <linux/kernel.h>
8 #include <linux/string.h>
9 #include <linux/errno.h>
10 #include <asm/uaccess.h>
12 /* Calculating the exact fault address when using
13 * block loads and stores can be very complicated.
15 * Instead of trying to be clever and handling all
16 * of the cases, just fix things up simply here.
19 static unsigned long compute_size(unsigned long start
, unsigned long size
, unsigned long *offset
)
21 unsigned long fault_addr
= current_thread_info()->fault_address
;
22 unsigned long end
= start
+ size
;
24 if (fault_addr
< start
|| fault_addr
>= end
) {
27 *offset
= start
- fault_addr
;
28 size
= end
- fault_addr
;
33 unsigned long copy_from_user_fixup(void *to
, const void __user
*from
, unsigned long size
)
37 size
= compute_size((unsigned long) from
, size
, &offset
);
39 memset(to
+ offset
, 0, size
);
44 unsigned long copy_to_user_fixup(void __user
*to
, const void *from
, unsigned long size
)
48 return compute_size((unsigned long) to
, size
, &offset
);
51 unsigned long copy_in_user_fixup(void __user
*to
, void __user
*from
, unsigned long size
)
53 unsigned long fault_addr
= current_thread_info()->fault_address
;
54 unsigned long start
= (unsigned long) to
;
55 unsigned long end
= start
+ size
;
57 if (fault_addr
>= start
&& fault_addr
< end
)
58 return end
- fault_addr
;
60 start
= (unsigned long) from
;
62 if (fault_addr
>= start
&& fault_addr
< end
)
63 return end
- fault_addr
;