162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * include/asm-xtensa/uaccess.h
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * User space memory access functions
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * These routines provide basic accessing functions to the user memory
762306a36Sopenharmony_ci * space for the kernel. This header file provides functions such as:
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
1062306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
1162306a36Sopenharmony_ci * for more details.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * Copyright (C) 2001 - 2005 Tensilica Inc.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#ifndef _XTENSA_UACCESS_H
1762306a36Sopenharmony_ci#define _XTENSA_UACCESS_H
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <linux/prefetch.h>
2062306a36Sopenharmony_ci#include <asm/types.h>
2162306a36Sopenharmony_ci#include <asm/extable.h>
2262306a36Sopenharmony_ci#include <asm-generic/access_ok.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/*
2562306a36Sopenharmony_ci * These are the main single-value transfer routines.  They
2662306a36Sopenharmony_ci * automatically use the right size if we just have the right pointer
2762306a36Sopenharmony_ci * type.
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * This gets kind of ugly. We want to return _two_ values in
3062306a36Sopenharmony_ci * "get_user()" and yet we don't want to do any pointers, because that
3162306a36Sopenharmony_ci * is too much of a performance impact. Thus we have a few rather ugly
3262306a36Sopenharmony_ci * macros here, and hide all the uglyness from the user.
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * Careful to not
3562306a36Sopenharmony_ci * (a) re-use the arguments for side effects (sizeof is ok)
3662306a36Sopenharmony_ci * (b) require any knowledge of processes at this stage
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci#define put_user(x, ptr)	__put_user_check((x), (ptr), sizeof(*(ptr)))
3962306a36Sopenharmony_ci#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr)))
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*
4262306a36Sopenharmony_ci * The "__xxx" versions of the user access functions are versions that
4362306a36Sopenharmony_ci * do not verify the address space, that must have been done previously
4462306a36Sopenharmony_ci * with a separate "access_ok()" call (this is used when we do multiple
4562306a36Sopenharmony_ci * accesses to the same area of user memory).
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_ci#define __put_user(x, ptr) __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
4862306a36Sopenharmony_ci#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ciextern long __put_user_bad(void);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define __put_user_nocheck(x, ptr, size)		\
5462306a36Sopenharmony_ci({							\
5562306a36Sopenharmony_ci	long __pu_err;					\
5662306a36Sopenharmony_ci	__put_user_size((x), (ptr), (size), __pu_err);	\
5762306a36Sopenharmony_ci	__pu_err;					\
5862306a36Sopenharmony_ci})
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define __put_user_check(x, ptr, size)					\
6162306a36Sopenharmony_ci({									\
6262306a36Sopenharmony_ci	long __pu_err = -EFAULT;					\
6362306a36Sopenharmony_ci	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
6462306a36Sopenharmony_ci	if (access_ok(__pu_addr, size))			\
6562306a36Sopenharmony_ci		__put_user_size((x), __pu_addr, (size), __pu_err);	\
6662306a36Sopenharmony_ci	__pu_err;							\
6762306a36Sopenharmony_ci})
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define __put_user_size(x, ptr, size, retval)				\
7062306a36Sopenharmony_cido {									\
7162306a36Sopenharmony_ci	int __cb;							\
7262306a36Sopenharmony_ci	retval = 0;							\
7362306a36Sopenharmony_ci	switch (size) {							\
7462306a36Sopenharmony_ci	case 1: __put_user_asm(x, ptr, retval, 1, "s8i", __cb);  break;	\
7562306a36Sopenharmony_ci	case 2: __put_user_asm(x, ptr, retval, 2, "s16i", __cb); break;	\
7662306a36Sopenharmony_ci	case 4: __put_user_asm(x, ptr, retval, 4, "s32i", __cb); break;	\
7762306a36Sopenharmony_ci	case 8: {							\
7862306a36Sopenharmony_ci		     __typeof__(*ptr) __v64 = x;			\
7962306a36Sopenharmony_ci		     retval = __copy_to_user(ptr, &__v64, 8) ? -EFAULT : 0;	\
8062306a36Sopenharmony_ci		     break;						\
8162306a36Sopenharmony_ci	        }							\
8262306a36Sopenharmony_ci	default: __put_user_bad();					\
8362306a36Sopenharmony_ci	}								\
8462306a36Sopenharmony_ci} while (0)
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/*
8862306a36Sopenharmony_ci * Consider a case of a user single load/store would cause both an
8962306a36Sopenharmony_ci * unaligned exception and an MMU-related exception (unaligned
9062306a36Sopenharmony_ci * exceptions happen first):
9162306a36Sopenharmony_ci *
9262306a36Sopenharmony_ci * User code passes a bad variable ptr to a system call.
9362306a36Sopenharmony_ci * Kernel tries to access the variable.
9462306a36Sopenharmony_ci * Unaligned exception occurs.
9562306a36Sopenharmony_ci * Unaligned exception handler tries to make aligned accesses.
9662306a36Sopenharmony_ci * Double exception occurs for MMU-related cause (e.g., page not mapped).
9762306a36Sopenharmony_ci * do_page_fault() thinks the fault address belongs to the kernel, not the
9862306a36Sopenharmony_ci * user, and panics.
9962306a36Sopenharmony_ci *
10062306a36Sopenharmony_ci * The kernel currently prohibits user unaligned accesses.  We use the
10162306a36Sopenharmony_ci * __check_align_* macros to check for unaligned addresses before
10262306a36Sopenharmony_ci * accessing user space so we don't crash the kernel.  Both
10362306a36Sopenharmony_ci * __put_user_asm and __get_user_asm use these alignment macros, so
10462306a36Sopenharmony_ci * macro-specific labels such as 0f, 1f, %0, %2, and %3 must stay in
10562306a36Sopenharmony_ci * sync.
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci#define __check_align_1  ""
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#define __check_align_2				\
11162306a36Sopenharmony_ci	"   _bbci.l %[mem] * 0, 1f	\n"	\
11262306a36Sopenharmony_ci	"   movi    %[err], %[efault]	\n"	\
11362306a36Sopenharmony_ci	"   _j      2f			\n"
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#define __check_align_4				\
11662306a36Sopenharmony_ci	"   _bbsi.l %[mem] * 0, 0f	\n"	\
11762306a36Sopenharmony_ci	"   _bbci.l %[mem] * 0 + 1, 1f	\n"	\
11862306a36Sopenharmony_ci	"0: movi    %[err], %[efault]	\n"	\
11962306a36Sopenharmony_ci	"   _j      2f			\n"
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/*
12362306a36Sopenharmony_ci * We don't tell gcc that we are accessing memory, but this is OK
12462306a36Sopenharmony_ci * because we do not write to any memory gcc knows about, so there
12562306a36Sopenharmony_ci * are no aliasing issues.
12662306a36Sopenharmony_ci *
12762306a36Sopenharmony_ci * WARNING: If you modify this macro at all, verify that the
12862306a36Sopenharmony_ci * __check_align_* macros still work.
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_ci#define __put_user_asm(x_, addr_, err_, align, insn, cb)\
13162306a36Sopenharmony_ci__asm__ __volatile__(					\
13262306a36Sopenharmony_ci	__check_align_##align				\
13362306a36Sopenharmony_ci	"1: "insn"  %[x], %[mem]	\n"		\
13462306a36Sopenharmony_ci	"2:				\n"		\
13562306a36Sopenharmony_ci	"   .section  .fixup,\"ax\"	\n"		\
13662306a36Sopenharmony_ci	"   .align 4			\n"		\
13762306a36Sopenharmony_ci	"   .literal_position		\n"		\
13862306a36Sopenharmony_ci	"5:				\n"		\
13962306a36Sopenharmony_ci	"   movi   %[tmp], 2b		\n"		\
14062306a36Sopenharmony_ci	"   movi   %[err], %[efault]	\n"		\
14162306a36Sopenharmony_ci	"   jx     %[tmp]		\n"		\
14262306a36Sopenharmony_ci	"   .previous			\n"		\
14362306a36Sopenharmony_ci	"   .section  __ex_table,\"a\"	\n"		\
14462306a36Sopenharmony_ci	"   .long	1b, 5b		\n"		\
14562306a36Sopenharmony_ci	"   .previous"					\
14662306a36Sopenharmony_ci	:[err] "+r"(err_), [tmp] "=r"(cb), [mem] "=m"(*(addr_))		\
14762306a36Sopenharmony_ci	:[x] "r"(x_), [efault] "i"(-EFAULT))
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci#define __get_user_nocheck(x, ptr, size)			\
15062306a36Sopenharmony_ci({								\
15162306a36Sopenharmony_ci	long __gu_err;						\
15262306a36Sopenharmony_ci	__get_user_size((x), (ptr), (size), __gu_err);		\
15362306a36Sopenharmony_ci	__gu_err;						\
15462306a36Sopenharmony_ci})
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci#define __get_user_check(x, ptr, size)					\
15762306a36Sopenharmony_ci({									\
15862306a36Sopenharmony_ci	long __gu_err = -EFAULT;					\
15962306a36Sopenharmony_ci	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);		\
16062306a36Sopenharmony_ci	if (access_ok(__gu_addr, size))					\
16162306a36Sopenharmony_ci		__get_user_size((x), __gu_addr, (size), __gu_err);	\
16262306a36Sopenharmony_ci	else								\
16362306a36Sopenharmony_ci		(x) = (__typeof__(*(ptr)))0;				\
16462306a36Sopenharmony_ci	__gu_err;							\
16562306a36Sopenharmony_ci})
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ciextern long __get_user_bad(void);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci#define __get_user_size(x, ptr, size, retval)				\
17062306a36Sopenharmony_cido {									\
17162306a36Sopenharmony_ci	int __cb;							\
17262306a36Sopenharmony_ci	retval = 0;							\
17362306a36Sopenharmony_ci	switch (size) {							\
17462306a36Sopenharmony_ci	case 1: __get_user_asm(x, ptr, retval, 1, "l8ui", __cb);  break;\
17562306a36Sopenharmony_ci	case 2: __get_user_asm(x, ptr, retval, 2, "l16ui", __cb); break;\
17662306a36Sopenharmony_ci	case 4: __get_user_asm(x, ptr, retval, 4, "l32i", __cb);  break;\
17762306a36Sopenharmony_ci	case 8: {							\
17862306a36Sopenharmony_ci		u64 __x;						\
17962306a36Sopenharmony_ci		if (unlikely(__copy_from_user(&__x, ptr, 8))) {		\
18062306a36Sopenharmony_ci			retval = -EFAULT;				\
18162306a36Sopenharmony_ci			(x) = (__typeof__(*(ptr)))0;			\
18262306a36Sopenharmony_ci		} else {						\
18362306a36Sopenharmony_ci			(x) = *(__force __typeof__(*(ptr)) *)&__x;	\
18462306a36Sopenharmony_ci		}							\
18562306a36Sopenharmony_ci		break;							\
18662306a36Sopenharmony_ci	}								\
18762306a36Sopenharmony_ci	default:							\
18862306a36Sopenharmony_ci		(x) = (__typeof__(*(ptr)))0;				\
18962306a36Sopenharmony_ci		__get_user_bad();					\
19062306a36Sopenharmony_ci	}								\
19162306a36Sopenharmony_ci} while (0)
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci/*
19562306a36Sopenharmony_ci * WARNING: If you modify this macro at all, verify that the
19662306a36Sopenharmony_ci * __check_align_* macros still work.
19762306a36Sopenharmony_ci */
19862306a36Sopenharmony_ci#define __get_user_asm(x_, addr_, err_, align, insn, cb) \
19962306a36Sopenharmony_cido {							\
20062306a36Sopenharmony_ci	u32 __x = 0;					\
20162306a36Sopenharmony_ci	__asm__ __volatile__(				\
20262306a36Sopenharmony_ci		__check_align_##align			\
20362306a36Sopenharmony_ci		"1: "insn"  %[x], %[mem]	\n"	\
20462306a36Sopenharmony_ci		"2:				\n"	\
20562306a36Sopenharmony_ci		"   .section  .fixup,\"ax\"	\n"	\
20662306a36Sopenharmony_ci		"   .align 4			\n"	\
20762306a36Sopenharmony_ci		"   .literal_position		\n"	\
20862306a36Sopenharmony_ci		"5:				\n"	\
20962306a36Sopenharmony_ci		"   movi   %[tmp], 2b		\n"	\
21062306a36Sopenharmony_ci		"   movi   %[err], %[efault]	\n"	\
21162306a36Sopenharmony_ci		"   jx     %[tmp]		\n"	\
21262306a36Sopenharmony_ci		"   .previous			\n"	\
21362306a36Sopenharmony_ci		"   .section  __ex_table,\"a\"	\n"	\
21462306a36Sopenharmony_ci		"   .long	1b, 5b		\n"	\
21562306a36Sopenharmony_ci		"   .previous"				\
21662306a36Sopenharmony_ci		:[err] "+r"(err_), [tmp] "=r"(cb), [x] "+r"(__x) \
21762306a36Sopenharmony_ci		:[mem] "m"(*(addr_)), [efault] "i"(-EFAULT)); \
21862306a36Sopenharmony_ci	(x_) = (__force __typeof__(*(addr_)))__x;	\
21962306a36Sopenharmony_ci} while (0)
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci/*
22362306a36Sopenharmony_ci * Copy to/from user space
22462306a36Sopenharmony_ci */
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ciextern unsigned __xtensa_copy_user(void *to, const void *from, unsigned n);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic inline unsigned long
22962306a36Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long n)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	prefetchw(to);
23262306a36Sopenharmony_ci	return __xtensa_copy_user(to, (__force const void *)from, n);
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_cistatic inline unsigned long
23562306a36Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	prefetch(from);
23862306a36Sopenharmony_ci	return __xtensa_copy_user((__force void *)to, from, n);
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci#define INLINE_COPY_FROM_USER
24162306a36Sopenharmony_ci#define INLINE_COPY_TO_USER
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci/*
24462306a36Sopenharmony_ci * We need to return the number of bytes not cleared.  Our memset()
24562306a36Sopenharmony_ci * returns zero if a problem occurs while accessing user-space memory.
24662306a36Sopenharmony_ci * In that event, return no memory cleared.  Otherwise, zero for
24762306a36Sopenharmony_ci * success.
24862306a36Sopenharmony_ci */
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cistatic inline unsigned long
25162306a36Sopenharmony_ci__xtensa_clear_user(void __user *addr, unsigned long size)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	if (!__memset((void __force *)addr, 0, size))
25462306a36Sopenharmony_ci		return size;
25562306a36Sopenharmony_ci	return 0;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic inline unsigned long
25962306a36Sopenharmony_ciclear_user(void __user *addr, unsigned long size)
26062306a36Sopenharmony_ci{
26162306a36Sopenharmony_ci	if (access_ok(addr, size))
26262306a36Sopenharmony_ci		return __xtensa_clear_user(addr, size);
26362306a36Sopenharmony_ci	return size ? -EFAULT : 0;
26462306a36Sopenharmony_ci}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci#define __clear_user  __xtensa_clear_user
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci#ifdef CONFIG_ARCH_HAS_STRNCPY_FROM_USER
27062306a36Sopenharmony_ciextern long __strncpy_user(char *dst, const char __user *src, long count);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistatic inline long
27362306a36Sopenharmony_cistrncpy_from_user(char *dst, const char __user *src, long count)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	if (access_ok(src, 1))
27662306a36Sopenharmony_ci		return __strncpy_user(dst, src, count);
27762306a36Sopenharmony_ci	return -EFAULT;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci#else
28062306a36Sopenharmony_cilong strncpy_from_user(char *dst, const char __user *src, long count);
28162306a36Sopenharmony_ci#endif
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci/*
28462306a36Sopenharmony_ci * Return the size of a string (including the ending 0!)
28562306a36Sopenharmony_ci */
28662306a36Sopenharmony_ciextern long __strnlen_user(const char __user *str, long len);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cistatic inline long strnlen_user(const char __user *str, long len)
28962306a36Sopenharmony_ci{
29062306a36Sopenharmony_ci	if (!access_ok(str, 1))
29162306a36Sopenharmony_ci		return 0;
29262306a36Sopenharmony_ci	return __strnlen_user(str, len);
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci#endif	/* _XTENSA_UACCESS_H */
296