tile: get rid of zeroing, switch to RAW_COPY_USER
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
c0ea73f18c
commit
23504bae7f
|
@ -33,6 +33,7 @@ config TILE
|
|||
select USER_STACKTRACE_SUPPORT
|
||||
select USE_PMC if PERF_EVENTS
|
||||
select VIRT_TO_BUS
|
||||
select ARCH_HAS_RAW_COPY_USER
|
||||
|
||||
config MMU
|
||||
def_bool y
|
||||
|
|
|
@ -313,145 +313,16 @@ extern int __put_user_bad(void)
|
|||
((x) = 0, -EFAULT); \
|
||||
})
|
||||
|
||||
/**
|
||||
* __copy_to_user() - copy 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 if pagefaults are
|
||||
* enabled.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* An alternate version - __copy_to_user_inatomic() - is designed
|
||||
* to be called from atomic context, typically bracketed by calls
|
||||
* to pagefault_disable() and pagefault_enable().
|
||||
*/
|
||||
extern unsigned long __must_check __copy_to_user_inatomic(
|
||||
void __user *to, const void *from, unsigned long n);
|
||||
|
||||
static inline unsigned long __must_check
|
||||
__copy_to_user(void __user *to, const void *from, unsigned long n)
|
||||
{
|
||||
might_fault();
|
||||
return __copy_to_user_inatomic(to, from, n);
|
||||
}
|
||||
|
||||
static inline unsigned long __must_check
|
||||
copy_to_user(void __user *to, const void *from, unsigned long n)
|
||||
{
|
||||
if (access_ok(VERIFY_WRITE, to, n))
|
||||
n = __copy_to_user(to, from, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* __copy_from_user() - copy 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 if pagefaults are
|
||||
* enabled.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* An alternate version - __copy_from_user_inatomic() - is designed
|
||||
* to be called from atomic context, typically bracketed by calls
|
||||
* to pagefault_disable() and pagefault_enable(). This version
|
||||
* does *NOT* pad with zeros.
|
||||
*/
|
||||
extern unsigned long __must_check __copy_from_user_inatomic(
|
||||
void *to, const void __user *from, unsigned long n);
|
||||
extern unsigned long __must_check __copy_from_user_zeroing(
|
||||
void *to, const void __user *from, unsigned long n);
|
||||
|
||||
static inline unsigned long __must_check
|
||||
__copy_from_user(void *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
might_fault();
|
||||
return __copy_from_user_zeroing(to, from, n);
|
||||
}
|
||||
|
||||
static inline unsigned long __must_check
|
||||
_copy_from_user(void *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
if (access_ok(VERIFY_READ, from, n))
|
||||
n = __copy_from_user(to, from, n);
|
||||
else
|
||||
memset(to, 0, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
extern void __compiletime_error("usercopy buffer size is too small")
|
||||
__bad_copy_user(void);
|
||||
|
||||
static inline void copy_user_overflow(int size, unsigned long count)
|
||||
{
|
||||
WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count);
|
||||
}
|
||||
|
||||
static inline unsigned long __must_check copy_from_user(void *to,
|
||||
const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
int sz = __compiletime_object_size(to);
|
||||
|
||||
if (likely(sz == -1 || sz >= n))
|
||||
n = _copy_from_user(to, from, n);
|
||||
else if (!__builtin_constant_p(n))
|
||||
copy_user_overflow(sz, n);
|
||||
else
|
||||
__bad_copy_user();
|
||||
|
||||
return n;
|
||||
}
|
||||
extern unsigned long __must_check
|
||||
raw_copy_to_user(void __user *to, const void *from, unsigned long n);
|
||||
extern unsigned long __must_check
|
||||
raw_copy_from_user(void *to, const void __user *from, unsigned long n);
|
||||
#define INLINE_COPY_FROM_USER
|
||||
#define INLINE_COPY_TO_USER
|
||||
|
||||
#ifdef __tilegx__
|
||||
/**
|
||||
* __copy_in_user() - copy data within user space, with less checking.
|
||||
* @to: Destination address, in user space.
|
||||
* @from: Source address, in user space.
|
||||
* @n: Number of bytes to copy.
|
||||
*
|
||||
* Context: User context only. This function may sleep if pagefaults are
|
||||
* enabled.
|
||||
*
|
||||
* Copy data from user space to user space. Caller must check
|
||||
* the specified blocks with access_ok() before calling this function.
|
||||
*
|
||||
* Returns number of bytes that could not be copied.
|
||||
* On success, this will be zero.
|
||||
*/
|
||||
extern unsigned long __copy_in_user_inatomic(
|
||||
extern unsigned long raw_copy_in_user(
|
||||
void __user *to, const void __user *from, unsigned long n);
|
||||
|
||||
static inline unsigned long __must_check
|
||||
__copy_in_user(void __user *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
might_fault();
|
||||
return __copy_in_user_inatomic(to, from, n);
|
||||
}
|
||||
|
||||
static inline unsigned long __must_check
|
||||
copy_in_user(void __user *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n))
|
||||
n = __copy_in_user(to, from, n);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -38,11 +38,10 @@ EXPORT_SYMBOL(__mcount);
|
|||
|
||||
/* arch/tile/lib/, various memcpy files */
|
||||
EXPORT_SYMBOL(memcpy);
|
||||
EXPORT_SYMBOL(__copy_to_user_inatomic);
|
||||
EXPORT_SYMBOL(__copy_from_user_inatomic);
|
||||
EXPORT_SYMBOL(__copy_from_user_zeroing);
|
||||
EXPORT_SYMBOL(raw_copy_to_user);
|
||||
EXPORT_SYMBOL(raw_copy_from_user);
|
||||
#ifdef __tilegx__
|
||||
EXPORT_SYMBOL(__copy_in_user_inatomic);
|
||||
EXPORT_SYMBOL(raw_copy_in_user);
|
||||
#endif
|
||||
|
||||
/* hypervisor glue */
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#define IS_MEMCPY 0
|
||||
#define IS_COPY_FROM_USER 1
|
||||
#define IS_COPY_FROM_USER_ZEROING 2
|
||||
#define IS_COPY_TO_USER -1
|
||||
|
||||
.section .text.memcpy_common, "ax"
|
||||
|
@ -42,40 +41,31 @@
|
|||
9
|
||||
|
||||
|
||||
/* __copy_from_user_inatomic takes the kernel target address in r0,
|
||||
/* raw_copy_from_user takes the kernel target address in r0,
|
||||
* the user source in r1, and the bytes to copy in r2.
|
||||
* It returns the number of uncopiable bytes (hopefully zero) in r0.
|
||||
*/
|
||||
ENTRY(__copy_from_user_inatomic)
|
||||
.type __copy_from_user_inatomic, @function
|
||||
FEEDBACK_ENTER_EXPLICIT(__copy_from_user_inatomic, \
|
||||
ENTRY(raw_copy_from_user)
|
||||
.type raw_copy_from_user, @function
|
||||
FEEDBACK_ENTER_EXPLICIT(raw_copy_from_user, \
|
||||
.text.memcpy_common, \
|
||||
.Lend_memcpy_common - __copy_from_user_inatomic)
|
||||
.Lend_memcpy_common - raw_copy_from_user)
|
||||
{ movei r29, IS_COPY_FROM_USER; j memcpy_common }
|
||||
.size __copy_from_user_inatomic, . - __copy_from_user_inatomic
|
||||
.size raw_copy_from_user, . - raw_copy_from_user
|
||||
|
||||
/* __copy_from_user_zeroing is like __copy_from_user_inatomic, but
|
||||
* any uncopiable bytes are zeroed in the target.
|
||||
*/
|
||||
ENTRY(__copy_from_user_zeroing)
|
||||
.type __copy_from_user_zeroing, @function
|
||||
FEEDBACK_REENTER(__copy_from_user_inatomic)
|
||||
{ movei r29, IS_COPY_FROM_USER_ZEROING; j memcpy_common }
|
||||
.size __copy_from_user_zeroing, . - __copy_from_user_zeroing
|
||||
|
||||
/* __copy_to_user_inatomic takes the user target address in r0,
|
||||
/* raw_copy_to_user takes the user target address in r0,
|
||||
* the kernel source in r1, and the bytes to copy in r2.
|
||||
* It returns the number of uncopiable bytes (hopefully zero) in r0.
|
||||
*/
|
||||
ENTRY(__copy_to_user_inatomic)
|
||||
.type __copy_to_user_inatomic, @function
|
||||
FEEDBACK_REENTER(__copy_from_user_inatomic)
|
||||
ENTRY(raw_copy_to_user)
|
||||
.type raw_copy_to_user, @function
|
||||
FEEDBACK_REENTER(raw_copy_from_user)
|
||||
{ movei r29, IS_COPY_TO_USER; j memcpy_common }
|
||||
.size __copy_to_user_inatomic, . - __copy_to_user_inatomic
|
||||
.size raw_copy_to_user, . - raw_copy_to_user
|
||||
|
||||
ENTRY(memcpy)
|
||||
.type memcpy, @function
|
||||
FEEDBACK_REENTER(__copy_from_user_inatomic)
|
||||
FEEDBACK_REENTER(raw_copy_from_user)
|
||||
{ movei r29, IS_MEMCPY }
|
||||
.size memcpy, . - memcpy
|
||||
/* Fall through */
|
||||
|
@ -520,12 +510,7 @@ copy_from_user_fixup_loop:
|
|||
{ bnzt r2, copy_from_user_fixup_loop }
|
||||
|
||||
.Lcopy_from_user_fixup_zero_remainder:
|
||||
{ bbs r29, 2f } /* low bit set means IS_COPY_FROM_USER */
|
||||
/* byte-at-a-time loop faulted, so zero the rest. */
|
||||
{ move r3, r2; bz r2, 2f /* should be impossible, but handle it. */ }
|
||||
1: { sb r0, zero; addi r0, r0, 1; addi r3, r3, -1 }
|
||||
{ bnzt r3, 1b }
|
||||
2: move lr, r27
|
||||
move lr, r27
|
||||
{ move r0, r2; jrp lr }
|
||||
|
||||
copy_to_user_fixup_loop:
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
__v; \
|
||||
})
|
||||
|
||||
#define USERCOPY_FUNC __copy_to_user_inatomic
|
||||
#define USERCOPY_FUNC raw_copy_to_user
|
||||
#define ST1(p, v) _ST((p), st1, (v))
|
||||
#define ST2(p, v) _ST((p), st2, (v))
|
||||
#define ST4(p, v) _ST((p), st4, (v))
|
||||
|
@ -62,7 +62,7 @@
|
|||
#define LD8 LD
|
||||
#include "memcpy_64.c"
|
||||
|
||||
#define USERCOPY_FUNC __copy_from_user_inatomic
|
||||
#define USERCOPY_FUNC raw_copy_from_user
|
||||
#define ST1 ST
|
||||
#define ST2 ST
|
||||
#define ST4 ST
|
||||
|
@ -73,7 +73,7 @@
|
|||
#define LD8(p) _LD((p), ld)
|
||||
#include "memcpy_64.c"
|
||||
|
||||
#define USERCOPY_FUNC __copy_in_user_inatomic
|
||||
#define USERCOPY_FUNC raw_copy_in_user
|
||||
#define ST1(p, v) _ST((p), st1, (v))
|
||||
#define ST2(p, v) _ST((p), st2, (v))
|
||||
#define ST4(p, v) _ST((p), st4, (v))
|
||||
|
@ -83,12 +83,3 @@
|
|||
#define LD4(p) _LD((p), ld4u)
|
||||
#define LD8(p) _LD((p), ld)
|
||||
#include "memcpy_64.c"
|
||||
|
||||
unsigned long __copy_from_user_zeroing(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
unsigned long rc = __copy_from_user_inatomic(to, from, n);
|
||||
if (unlikely(rc))
|
||||
memset(to + n - rc, 0, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue