uaccess.h
来自「Linux Kernel 2.6.9 for OMAP1710」· C头文件 代码 · 共 506 行 · 第 1/2 页
H
506 行
({ \ long __pu_err; \ __put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \ __pu_err; \})#define __put_user_check(x,ptr,size) \({ \ long __pu_err = -EFAULT; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ might_sleep(); \ if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \ __pu_err; \}) #define __put_user_u64(x, addr, err) \ __asm__ __volatile__( \ "1: movl %%eax,0(%2)\n" \ "2: movl %%edx,4(%2)\n" \ "3:\n" \ ".section .fixup,\"ax\"\n" \ "4: movl %3,%0\n" \ " jmp 3b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ " .long 1b,4b\n" \ " .long 2b,4b\n" \ ".previous" \ : "=r"(err) \ : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))#ifdef CONFIG_X86_WP_WORKS_OK#define __put_user_size(x,ptr,size,retval,errret) \do { \ retval = 0; \ __chk_user_ptr(ptr); \ switch (size) { \ case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break; \ case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \ case 4: __put_user_asm(x,ptr,retval,"l","","ir",errret); break; \ case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\ default: __put_user_bad(); \ } \} while (0)#else#define __put_user_size(x,ptr,size,retval,errret) \do { \ __typeof__(*(ptr)) __pus_tmp = x; \ retval = 0; \ \ if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0)) \ retval = errret; \} while (0)#endifstruct __large_struct { unsigned long buf[100]; };#define __m(x) (*(struct __large_struct *)(x))/* * Tell gcc we read from memory instead of writing: this is because * we do not write to any memory gcc knows about, so there are no * aliasing issues. */#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \ __asm__ __volatile__( \ "1: mov"itype" %"rtype"1,%2\n" \ "2:\n" \ ".section .fixup,\"ax\"\n" \ "3: movl %3,%0\n" \ " jmp 2b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ " .long 1b,3b\n" \ ".previous" \ : "=r"(err) \ : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))#define __get_user_nocheck(x,ptr,size) \({ \ long __gu_err, __gu_val; \ __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\ (x) = (__typeof__(*(ptr)))__gu_val; \ __gu_err; \})extern long __get_user_bad(void);#define __get_user_size(x,ptr,size,retval,errret) \do { \ retval = 0; \ __chk_user_ptr(ptr); \ switch (size) { \ case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break; \ case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break; \ case 4: __get_user_asm(x,ptr,retval,"l","","=r",errret);break; \ default: (x) = __get_user_bad(); \ } \} while (0)#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \ __asm__ __volatile__( \ "1: mov"itype" %2,%"rtype"1\n" \ "2:\n" \ ".section .fixup,\"ax\"\n" \ "3: movl %3,%0\n" \ " xor"itype" %"rtype"1,%"rtype"1\n" \ " jmp 2b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ " .long 1b,3b\n" \ ".previous" \ : "=r"(err), ltype (x) \ : "m"(__m(addr)), "i"(errret), "0"(err))unsigned long __must_check __copy_to_user_ll(void __user *to, const void *from, unsigned long n);unsigned long __must_check __copy_from_user_ll(void *to, const void __user *from, unsigned long n);/* * Here we special-case 1, 2 and 4-byte copy_*_user invocations. On a fault * we return the initial request size (1, 2 or 4), as copy_*_user should do. * If a store crosses a page boundary and gets a fault, the x86 will not write * anything, so this is accurate. *//** * __copy_to_user: - Copy a block of data into user space, with less checking. * @to: Destination address, in user space. * @from: Source address, in kernel space. * @n: Number of bytes to copy. * * Context: User context only. This function may sleep. * * Copy data from kernel space to user space. Caller must check * the specified block with access_ok() before calling this function. * * Returns number of bytes that could not be copied. * On success, this will be zero. */static inline unsigned long __must_check__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n){ if (__builtin_constant_p(n)) { unsigned long ret; switch (n) { case 1: __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1); return ret; case 2: __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2); return ret; case 4: __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4); return ret; } } return __copy_to_user_ll(to, from, n);}static inline unsigned long __must_check__copy_to_user(void __user *to, const void *from, unsigned long n){ might_sleep(); return __copy_to_user_inatomic(to, from, n);}/** * __copy_from_user: - Copy a block of data from user space, with less checking. * @to: Destination address, in kernel space. * @from: Source address, in user space. * @n: Number of bytes to copy. * * Context: User context only. This function may sleep. * * Copy data from user space to kernel space. Caller must check * the specified block with access_ok() before calling this function. * * Returns number of bytes that could not be copied. * On success, this will be zero. * * If some data could not be copied, this function will pad the copied * data to the requested size using zero bytes. */static inline unsigned long__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n){ if (__builtin_constant_p(n)) { unsigned long ret; switch (n) { case 1: __get_user_size(*(u8 *)to, from, 1, ret, 1); return ret; case 2: __get_user_size(*(u16 *)to, from, 2, ret, 2); return ret; case 4: __get_user_size(*(u32 *)to, from, 4, ret, 4); return ret; } } return __copy_from_user_ll(to, from, n);}static inline unsigned long__copy_from_user(void *to, const void __user *from, unsigned long n){ might_sleep(); return __copy_from_user_inatomic(to, from, n);}unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n);unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n);long __must_check strncpy_from_user(char *dst, const char __user *src, long count);long __must_check __strncpy_from_user(char *dst, const char __user *src, long count);/** * strlen_user: - Get the size of a string in user space. * @str: The string to measure. * * Context: User context only. This function may sleep. * * Get the size of a NUL-terminated string in user space. * * Returns the size of the string INCLUDING the terminating NUL. * On exception, returns 0. * * If there is a limit on the length of a valid string, you may wish to * consider using strnlen_user() instead. */#define strlen_user(str) strnlen_user(str, ~0UL >> 1)long strnlen_user(const char __user *str, long n);unsigned long __must_check clear_user(void __user *mem, unsigned long len);unsigned long __must_check __clear_user(void __user *mem, unsigned long len);#endif /* __i386_UACCESS_H */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?