X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=include%2Flinux%2Fuaccess.h;h=975c963e57898aee95fed95e129bd91a1578a414;hb=721e2629fa2167c0e5a9f10d704b1fee1621a8cb;hp=a48d7f11c7be06772327604dc40c3f91b0b57145;hpb=ebdea46fecae40c4d7effcd33f40918a37a1df4b;p=cascardo%2Flinux.git diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index a48d7f11c7be..975c963e5789 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -1,8 +1,43 @@ #ifndef __LINUX_UACCESS_H__ #define __LINUX_UACCESS_H__ +#include #include +/* + * These routines enable/disable the pagefault handler in that + * it will not take any locks and go straight to the fixup table. + * + * They have great resemblance to the preempt_disable/enable calls + * and in fact they are identical; this is because currently there is + * no other way to make the pagefault handlers do this. So we do + * disable preemption but we don't necessarily care about that. + */ +static inline void pagefault_disable(void) +{ + inc_preempt_count(); + /* + * make sure to have issued the store before a pagefault + * can hit. + */ + barrier(); +} + +static inline void pagefault_enable(void) +{ + /* + * make sure to issue those last loads/stores before enabling + * the pagefault handler again. + */ + barrier(); + dec_preempt_count(); + /* + * make sure we do.. + */ + barrier(); + preempt_check_resched(); +} + #ifndef ARCH_HAS_NOCACHE_UACCESS static inline unsigned long __copy_from_user_inatomic_nocache(void *to, @@ -30,14 +65,22 @@ static inline unsigned long __copy_from_user_nocache(void *to, * do_page_fault() doesn't attempt to take mmap_sem. This makes * probe_kernel_address() suitable for use within regions where the caller * already holds mmap_sem, or other locks which nest inside mmap_sem. + * This must be a macro because __get_user() needs to know the types of the + * args. + * + * We don't include enough header files to be able to do the set_fs(). We + * require that the probe_kernel_address() caller will do that. */ #define probe_kernel_address(addr, retval) \ ({ \ long ret; \ + mm_segment_t old_fs = get_fs(); \ \ - inc_preempt_count(); \ - ret = __get_user(retval, addr); \ - dec_preempt_count(); \ + set_fs(KERNEL_DS); \ + pagefault_disable(); \ + ret = __get_user(retval, (__force typeof(retval) __user *)(addr)); \ + pagefault_enable(); \ + set_fs(old_fs); \ ret; \ })