mirror of https://gitee.com/openkylin/linux.git
powerpc/uaccess: Implement unsafe_copy_to_user() as a simple loop
At the time being, unsafe_copy_to_user() is based on raw_copy_to_user() which calls __copy_tofrom_user(). __copy_tofrom_user() is a big optimised function to copy big amount of data. It aligns destinations to cache line in order to use dcbz instruction. Today unsafe_copy_to_user() is called only from filldir(). It is used to mainly copy small amount of data like filenames, so __copy_tofrom_user() is not fit. Also, unsafe_copy_to_user() is used within user_access_begin/end sections. In those section, it is preferable to not call functions. Rewrite unsafe_copy_to_user() as a macro that uses __put_user_goto(). We first perform a loop of long, then we finish with necessary complements. unsafe_copy_to_user() might be used in the near future to copy fixed-size data, like pt_regs structs during signal processing. Having it as a macro allows GCC to optimise it for instead when it knows the size in advance, it can unloop loops, drop complements when the size is a multiple of longs, etc ... Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/fe952112c29bf6a0a2778c9e6bbb4f4afd2c4258.1587143308.git.christophe.leroy@c-s.fr
This commit is contained in:
parent
334710b149
commit
17bc43367f
|
@ -535,7 +535,26 @@ static __must_check inline bool user_access_begin(const void __user *ptr, size_t
|
|||
#define unsafe_op_wrap(op, err) do { if (unlikely(op)) goto err; } while (0)
|
||||
#define unsafe_get_user(x, p, e) unsafe_op_wrap(__get_user_allowed(x, p), e)
|
||||
#define unsafe_put_user(x, p, e) __put_user_goto(x, p, e)
|
||||
|
||||
#define unsafe_copy_to_user(d, s, l, e) \
|
||||
unsafe_op_wrap(raw_copy_to_user_allowed(d, s, l), e)
|
||||
do { \
|
||||
u8 __user *_dst = (u8 __user *)(d); \
|
||||
const u8 *_src = (const u8 *)(s); \
|
||||
size_t _len = (l); \
|
||||
int _i; \
|
||||
\
|
||||
for (_i = 0; _i < (_len & ~(sizeof(long) - 1)); _i += sizeof(long)) \
|
||||
__put_user_goto(*(long*)(_src + _i), (long __user *)(_dst + _i), e);\
|
||||
if (IS_ENABLED(CONFIG_PPC64) && (_len & 4)) { \
|
||||
__put_user_goto(*(u32*)(_src + _i), (u32 __user *)(_dst + _i), e); \
|
||||
_i += 4; \
|
||||
} \
|
||||
if (_len & 2) { \
|
||||
__put_user_goto(*(u16*)(_src + _i), (u16 __user *)(_dst + _i), e); \
|
||||
_i += 2; \
|
||||
} \
|
||||
if (_len & 1) \
|
||||
__put_user_goto(*(u8*)(_src + _i), (u8 __user *)(_dst + _i), e);\
|
||||
} while (0)
|
||||
|
||||
#endif /* _ARCH_POWERPC_UACCESS_H */
|
||||
|
|
Loading…
Reference in New Issue