linux/arch/sh/include/asm/uaccess_32.h
Paul Mundt 0e100e11bd sh: switch to generic strncpy_from_user().
This kills off the special sh32/64 versions and adopts the generic
version. It should be possible to optimize this for SH-4A unaligned
loads, but this is a corner case that can be supported incrementally.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
2012-06-13 10:28:16 +09:00

209 lines
4.4 KiB
C

/*
* User space memory access functions
*
* Copyright (C) 1999, 2002 Niibe Yutaka
* Copyright (C) 2003 - 2008 Paul Mundt
*
* Based on:
* MIPS implementation version 1.15 by
* Copyright (C) 1996, 1997, 1998 by Ralf Baechle
* and i386 version.
*/
#ifndef __ASM_SH_UACCESS_32_H
#define __ASM_SH_UACCESS_32_H
#define __get_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
switch (size) { \
case 1: \
__get_user_asm(x, ptr, retval, "b"); \
break; \
case 2: \
__get_user_asm(x, ptr, retval, "w"); \
break; \
case 4: \
__get_user_asm(x, ptr, retval, "l"); \
break; \
default: \
__get_user_unknown(); \
break; \
} \
} while (0)
#ifdef CONFIG_MMU
#define __get_user_asm(x, addr, err, insn) \
({ \
__asm__ __volatile__( \
"1:\n\t" \
"mov." insn " %2, %1\n\t" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3:\n\t" \
"mov #0, %1\n\t" \
"mov.l 4f, %0\n\t" \
"jmp @%0\n\t" \
" mov %3, %0\n\t" \
".balign 4\n" \
"4: .long 2b\n\t" \
".previous\n" \
".section __ex_table,\"a\"\n\t" \
".long 1b, 3b\n\t" \
".previous" \
:"=&r" (err), "=&r" (x) \
:"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
#else
#define __get_user_asm(x, addr, err, insn) \
do { \
__asm__ __volatile__ ( \
"mov." insn " %1, %0\n\t" \
: "=&r" (x) \
: "m" (__m(addr)) \
); \
} while (0)
#endif /* CONFIG_MMU */
extern void __get_user_unknown(void);
#define __put_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
switch (size) { \
case 1: \
__put_user_asm(x, ptr, retval, "b"); \
break; \
case 2: \
__put_user_asm(x, ptr, retval, "w"); \
break; \
case 4: \
__put_user_asm(x, ptr, retval, "l"); \
break; \
case 8: \
__put_user_u64(x, ptr, retval); \
break; \
default: \
__put_user_unknown(); \
} \
} while (0)
#ifdef CONFIG_MMU
#define __put_user_asm(x, addr, err, insn) \
do { \
__asm__ __volatile__ ( \
"1:\n\t" \
"mov." insn " %1, %2\n\t" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3:\n\t" \
"mov.l 4f, %0\n\t" \
"jmp @%0\n\t" \
" mov %3, %0\n\t" \
".balign 4\n" \
"4: .long 2b\n\t" \
".previous\n" \
".section __ex_table,\"a\"\n\t" \
".long 1b, 3b\n\t" \
".previous" \
: "=&r" (err) \
: "r" (x), "m" (__m(addr)), "i" (-EFAULT), \
"0" (err) \
: "memory" \
); \
} while (0)
#else
#define __put_user_asm(x, addr, err, insn) \
do { \
__asm__ __volatile__ ( \
"mov." insn " %0, %1\n\t" \
: /* no outputs */ \
: "r" (x), "m" (__m(addr)) \
: "memory" \
); \
} while (0)
#endif /* CONFIG_MMU */
#if defined(CONFIG_CPU_LITTLE_ENDIAN)
#define __put_user_u64(val,addr,retval) \
({ \
__asm__ __volatile__( \
"1:\n\t" \
"mov.l %R1,%2\n\t" \
"mov.l %S1,%T2\n\t" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3:\n\t" \
"mov.l 4f,%0\n\t" \
"jmp @%0\n\t" \
" mov %3,%0\n\t" \
".balign 4\n" \
"4: .long 2b\n\t" \
".previous\n" \
".section __ex_table,\"a\"\n\t" \
".long 1b, 3b\n\t" \
".previous" \
: "=r" (retval) \
: "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
: "memory"); })
#else
#define __put_user_u64(val,addr,retval) \
({ \
__asm__ __volatile__( \
"1:\n\t" \
"mov.l %S1,%2\n\t" \
"mov.l %R1,%T2\n\t" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3:\n\t" \
"mov.l 4f,%0\n\t" \
"jmp @%0\n\t" \
" mov %3,%0\n\t" \
".balign 4\n" \
"4: .long 2b\n\t" \
".previous\n" \
".section __ex_table,\"a\"\n\t" \
".long 1b, 3b\n\t" \
".previous" \
: "=r" (retval) \
: "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
: "memory"); })
#endif
extern void __put_user_unknown(void);
/*
* Return the size of a string (including the ending 0 even when we have
* exceeded the maximum string length).
*/
static inline long __strnlen_user(const char __user *__s, long __n)
{
unsigned long res;
unsigned long __dummy;
__asm__ __volatile__(
"1:\t"
"mov.b @(%0,%3), %1\n\t"
"cmp/eq %4, %0\n\t"
"bt/s 2f\n\t"
" add #1, %0\n\t"
"tst %1, %1\n\t"
"bf 1b\n\t"
"2:\n"
".section .fixup,\"ax\"\n"
"3:\n\t"
"mov.l 4f, %1\n\t"
"jmp @%1\n\t"
" mov #0, %0\n"
".balign 4\n"
"4: .long 2b\n"
".previous\n"
".section __ex_table,\"a\"\n"
" .balign 4\n"
" .long 1b,3b\n"
".previous"
: "=z" (res), "=&r" (__dummy)
: "0" (0), "r" (__s), "r" (__n)
: "t");
return res;
}
#endif /* __ASM_SH_UACCESS_32_H */