Commit a1a386ef authored by Hirokazu Takata's avatar Hirokazu Takata Committed by Linus Torvalds

[PATCH] m32r: update uaccess.h

  This patch updates asm-m32r/uaccess.h.

	* include/asm-m32r/uaccess.h:
	(__copy_to_user_inatomic): Added.
	(__copy_from_user_inatomic): Added.
	Update comments.
Signed-off-by: default avatarHirokazu Takata <takata@linux-m32r.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f896c1c5
#ifndef _ASM_M32R_UACCESS_H
#define _ASM_M32R_UACCESS_H
/* $Id$ */
/*
* linux/include/asm-m32r/uaccess.h
*
* M32R version.
* Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
*/
#undef UACCESS_DEBUG
......@@ -61,7 +66,13 @@ static inline void set_fs(mm_segment_t s)
((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
/*
* Uhhuh, this needs 33-bit arithmetic. We have a carry..
* Test whether a block of memory is a valid user space address.
* Returns 0 if the range is valid, nonzero otherwise.
*
* This is equivalent to the following test:
* (u33)addr + (u33)size >= (u33)current->addr_limit.seg
*
* This needs 33-bit arithmetic. We have a carry...
*/
#define __range_ok(addr,size) ({ \
unsigned long flag, sum; \
......@@ -78,8 +89,27 @@ static inline void set_fs(mm_segment_t s)
: "cbit" ); \
flag; })
/**
* access_ok: - Checks if a user space pointer is valid
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
* %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
* to write to a block, it is always safe to read from it.
* @addr: User space pointer to start of block to check
* @size: Size of block to check
*
* Context: User context only. This function may sleep.
*
* Checks if a pointer to a block of memory in user space is valid.
*
* Returns true (nonzero) if the memory block may be valid, false (zero)
* if it is definitely invalid.
*
* Note that, depending on architecture, this function probably just
* checks that the pointer is in the user space range - after calling
* this function, memory access functions may still return -EFAULT.
*/
#ifdef CONFIG_MMU
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
#else
static inline int access_ok(int type, const void *addr, unsigned long size)
{
......@@ -90,7 +120,24 @@ static inline int access_ok(int type, const void *addr, unsigned long size)
}
#endif /* CONFIG_MMU */
static __inline__ int verify_area(int type, const void __user *addr,
/**
* verify_area: - Obsolete, use access_ok()
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
* @addr: User space pointer to start of block to check
* @size: Size of block to check
*
* Context: User context only. This function may sleep.
*
* This function has been replaced by access_ok().
*
* Checks if a pointer to a block of memory in user space is valid.
*
* Returns zero if the memory block may be valid, -EFAULT
* if it is definitely invalid.
*
* See access_ok() for more details.
*/
static inline int verify_area(int type, const void __user *addr,
unsigned long size)
{
return access_ok(type, addr, size) ? 0 : -EFAULT;
......@@ -167,6 +214,23 @@ extern void __get_user_4(void);
/* Careful: we have to cast the result to the type of the pointer for sign
reasons */
/**
* get_user: - Get a simple variable from user space.
* @x: Variable to store result.
* @ptr: Source address, in user space.
*
* Context: User context only. This function may sleep.
*
* This macro copies a single simple variable from user space to kernel
* space. It supports simple types like char and int, but not larger
* data types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and the result of
* dereferencing @ptr must be assignable to @x without a cast.
*
* Returns zero on success, or -EFAULT on error.
* On error, the variable @x is set to zero.
*/
#define get_user(x,ptr) \
({ int __ret_gu,__val_gu; \
__chk_user_ptr(ptr); \
......@@ -182,11 +246,69 @@ extern void __get_user_4(void);
extern void __put_user_bad(void);
/**
* put_user: - Write a simple value into user space.
* @x: Value to copy to user space.
* @ptr: Destination address, in user space.
*
* Context: User context only. This function may sleep.
*
* This macro copies a single simple value from kernel space to user
* space. It supports simple types like char and int, but not larger
* data types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and @x must be assignable
* to the result of dereferencing @ptr.
*
* Returns zero on success, or -EFAULT on error.
*/
#define put_user(x,ptr) \
__put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
/**
* __get_user: - Get a simple variable from user space, with less checking.
* @x: Variable to store result.
* @ptr: Source address, in user space.
*
* Context: User context only. This function may sleep.
*
* This macro copies a single simple variable from user space to kernel
* space. It supports simple types like char and int, but not larger
* data types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and the result of
* dereferencing @ptr must be assignable to @x without a cast.
*
* Caller must check the pointer with access_ok() before calling this
* function.
*
* Returns zero on success, or -EFAULT on error.
* On error, the variable @x is set to zero.
*/
#define __get_user(x,ptr) \
__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
/**
* __put_user: - Write a simple value into user space, with less checking.
* @x: Value to copy to user space.
* @ptr: Destination address, in user space.
*
* Context: User context only. This function may sleep.
*
* This macro copies a single simple value from kernel space to user
* space. It supports simple types like char and int, but not larger
* data types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and @x must be assignable
* to the result of dereferencing @ptr.
*
* Caller must check the pointer with access_ok() before calling this
* function.
*
* Returns zero on success, or -EFAULT on error.
*/
#define __put_user(x,ptr) \
__put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
......@@ -208,48 +330,6 @@ extern void __put_user_bad(void);
__pu_err; \
})
#define __put_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
__chk_user_ptr(ptr); \
switch (size) { \
case 1: __put_user_asm(x,ptr,retval,"b"); break; \
case 2: __put_user_asm(x,ptr,retval,"h"); break; \
case 4: __put_user_asm(x,ptr,retval,""); break; \
case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
default: __put_user_bad(); \
} \
} while (0)
struct __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) \
__asm__ __volatile__( \
" .fillinsn\n" \
"1: st"itype" %1,@%2\n" \
" .fillinsn\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
" .balign 4\n" \
"3: ldi %0,%3\n" \
" seth r14,#high(2b)\n" \
" or3 r14,r14,#low(2b)\n" \
" jmp r14\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .balign 4\n" \
" .long 1b,3b\n" \
".previous" \
: "=r"(err) \
: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err) \
: "r14", "memory")
#if defined(__LITTLE_ENDIAN__)
#define __put_user_u64(x, addr, err) \
__asm__ __volatile__( \
......@@ -307,6 +387,48 @@ struct __large_struct { unsigned long buf[100]; };
#error no endian defined
#endif
#define __put_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
__chk_user_ptr(ptr); \
switch (size) { \
case 1: __put_user_asm(x,ptr,retval,"b"); break; \
case 2: __put_user_asm(x,ptr,retval,"h"); break; \
case 4: __put_user_asm(x,ptr,retval,""); break; \
case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
default: __put_user_bad(); \
} \
} while (0)
struct __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) \
__asm__ __volatile__( \
" .fillinsn\n" \
"1: st"itype" %1,@%2\n" \
" .fillinsn\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
" .balign 4\n" \
"3: ldi %0,%3\n" \
" seth r14,#high(2b)\n" \
" or3 r14,r14,#low(2b)\n" \
" jmp r14\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .balign 4\n" \
" .long 1b,3b\n" \
".previous" \
: "=r"(err) \
: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err) \
: "r14", "memory")
#define __get_user_nocheck(x,ptr,size) \
({ \
long __gu_err, __gu_val; \
......@@ -350,6 +472,13 @@ do { \
: "r"(addr), "i"(-EFAULT), "0"(err) \
: "r14", "memory")
/*
* 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 m32r will not write
* anything, so this is accurate.
*/
/*
* Copy To/From Userspace
......@@ -479,14 +608,14 @@ do { \
/* We let the __ versions of copy_from/to_user inline, because they're often
* used in fast paths and have only a small space overhead.
*/
static __inline__ unsigned long __generic_copy_from_user_nocheck(void *to,
static inline unsigned long __generic_copy_from_user_nocheck(void *to,
const void __user *from, unsigned long n)
{
__copy_user_zeroing(to,from,n);
return n;
}
static __inline__ unsigned long __generic_copy_to_user_nocheck(void __user *to,
static inline unsigned long __generic_copy_to_user_nocheck(void __user *to,
const void *from, unsigned long n)
{
__copy_user(to,from,n);
......@@ -496,30 +625,132 @@ static __inline__ unsigned long __generic_copy_to_user_nocheck(void __user *to,
unsigned long __generic_copy_to_user(void *, const void *, unsigned long);
unsigned long __generic_copy_from_user(void *, const void *, unsigned long);
/**
* __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.
*/
#define __copy_to_user(to,from,n) \
__generic_copy_to_user_nocheck((to),(from),(n))
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user
/**
* copy_to_user: - Copy a block of data into user space.
* @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.
*
* Returns number of bytes that could not be copied.
* On success, this will be zero.
*/
#define copy_to_user(to,from,n) \
({ \
might_sleep(); \
__generic_copy_to_user((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.
*/
#define __copy_from_user(to,from,n) \
__generic_copy_from_user_nocheck((to),(from),(n))
/**
* copy_from_user: - Copy a block of data from user space.
* @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.
*
* 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.
*/
#define copy_from_user(to,from,n) \
({ \
might_sleep(); \
__generic_copy_from_user((to),(from),(n)); \
__generic_copy_from_user((to),(from),(n)); \
})
#define __copy_to_user(to,from,n) \
__generic_copy_to_user_nocheck((to),(from),(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);
#define __copy_from_user(to,from,n) \
__generic_copy_from_user_nocheck((to),(from),(n))
/**
* __clear_user: - Zero a block of memory in user space, with less checking.
* @to: Destination address, in user space.
* @n: Number of bytes to zero.
*
* Zero a block of memory in user space. Caller must check
* the specified block with access_ok() before calling this function.
*
* Returns number of bytes that could not be cleared.
* On success, this will be zero.
*/
unsigned long __clear_user(void __user *mem, unsigned long len);
long strncpy_from_user(char *dst, const char __user *src, long count);
long __strncpy_from_user(char *dst, const char __user *src, long count);
/**
* clear_user: - Zero a block of memory in user space.
* @to: Destination address, in user space.
* @n: Number of bytes to zero.
*
* Zero a block of memory in user space. Caller must check
* the specified block with access_ok() before calling this function.
*
* Returns number of bytes that could not be cleared.
* On success, this will be zero.
*/
unsigned long clear_user(void __user *mem, unsigned long len);
/**
* 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 clear_user(void __user *mem, unsigned long len);
unsigned long __clear_user(void __user *mem, unsigned long len);
#endif /* _ASM_M32R_UACCESS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment