|  | @@ -0,0 +1,198 @@
 | 
	
		
			
				|  |  | +#ifndef __M68K_UACCESS_H
 | 
	
		
			
				|  |  | +#define __M68K_UACCESS_H
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * User space memory access functions
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +#include <linux/compiler.h>
 | 
	
		
			
				|  |  | +#include <linux/errno.h>
 | 
	
		
			
				|  |  | +#include <linux/types.h>
 | 
	
		
			
				|  |  | +#include <linux/sched.h>
 | 
	
		
			
				|  |  | +#include <asm/segment.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define VERIFY_READ	0
 | 
	
		
			
				|  |  | +#define VERIFY_WRITE	1
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* We let the MMU do all checking */
 | 
	
		
			
				|  |  | +static inline int access_ok(int type, const void __user *addr,
 | 
	
		
			
				|  |  | +			    unsigned long size)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return 1;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Not all varients of the 68k family support the notion of address spaces.
 | 
	
		
			
				|  |  | + * The traditional 680x0 parts do, and they use the sfc/dfc registers and
 | 
	
		
			
				|  |  | + * the "moves" instruction to access user space from kernel space. Other
 | 
	
		
			
				|  |  | + * family members like ColdFire don't support this, and only have a single
 | 
	
		
			
				|  |  | + * address space, and use the usual "move" instruction for user space access.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Outside of this difference the user space access functions are the same.
 | 
	
		
			
				|  |  | + * So lets keep the code simple and just define in what we need to use.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +#ifdef CONFIG_CPU_HAS_ADDRESS_SPACES
 | 
	
		
			
				|  |  | +#define	MOVES	"moves"
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +#define	MOVES	"move"
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * The exception table consists of pairs of addresses: the first is the
 | 
	
		
			
				|  |  | + * address of an instruction that is allowed to fault, and the second is
 | 
	
		
			
				|  |  | + * the address at which the program should continue.  No registers are
 | 
	
		
			
				|  |  | + * modified, so it is entirely up to the continuation code to figure out
 | 
	
		
			
				|  |  | + * what to do.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * All the routines below use bits of fixup code that are out of line
 | 
	
		
			
				|  |  | + * with the main instruction path.  This means when everything is well,
 | 
	
		
			
				|  |  | + * we don't even have to jump over them.  Further, they do not intrude
 | 
	
		
			
				|  |  | + * on our cache or tlb entries.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct exception_table_entry
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	unsigned long insn, fixup;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +extern int __put_user_bad(void);
 | 
	
		
			
				|  |  | +extern int __get_user_bad(void);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __put_user_asm(res, x, ptr, bwl, reg, err)	\
 | 
	
		
			
				|  |  | +asm volatile ("\n"					\
 | 
	
		
			
				|  |  | +	"1:	"MOVES"."#bwl"	%2,%1\n"		\
 | 
	
		
			
				|  |  | +	"2:\n"						\
 | 
	
		
			
				|  |  | +	"	.section .fixup,\"ax\"\n"		\
 | 
	
		
			
				|  |  | +	"	.even\n"				\
 | 
	
		
			
				|  |  | +	"10:	moveq.l	%3,%0\n"			\
 | 
	
		
			
				|  |  | +	"	jra 2b\n"				\
 | 
	
		
			
				|  |  | +	"	.previous\n"				\
 | 
	
		
			
				|  |  | +	"\n"						\
 | 
	
		
			
				|  |  | +	"	.section __ex_table,\"a\"\n"		\
 | 
	
		
			
				|  |  | +	"	.align	4\n"				\
 | 
	
		
			
				|  |  | +	"	.long	1b,10b\n"			\
 | 
	
		
			
				|  |  | +	"	.long	2b,10b\n"			\
 | 
	
		
			
				|  |  | +	"	.previous"				\
 | 
	
		
			
				|  |  | +	: "+d" (res), "=m" (*(ptr))			\
 | 
	
		
			
				|  |  | +	: #reg (x), "i" (err))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * These are the main single-value transfer routines.  They automatically
 | 
	
		
			
				|  |  | + * use the right size if we just have the right pointer type.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __put_user(x, ptr)						\
 | 
	
		
			
				|  |  | +({									\
 | 
	
		
			
				|  |  | +	typeof(*(ptr)) __pu_val = (x);					\
 | 
	
		
			
				|  |  | +	int __pu_err = 0;						\
 | 
	
		
			
				|  |  | +	__chk_user_ptr(ptr);						\
 | 
	
		
			
				|  |  | +	switch (sizeof (*(ptr))) {					\
 | 
	
		
			
				|  |  | +	case 1:								\
 | 
	
		
			
				|  |  | +		__put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT);	\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	case 2:								\
 | 
	
		
			
				|  |  | +		__put_user_asm(__pu_err, __pu_val, ptr, w, d, -EFAULT);	\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	case 4:								\
 | 
	
		
			
				|  |  | +		__put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT);	\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	case 8:								\
 | 
	
		
			
				|  |  | + 	    {								\
 | 
	
		
			
				|  |  | + 		const void __user *__pu_ptr = (ptr);			\
 | 
	
		
			
				|  |  | +		asm volatile ("\n"					\
 | 
	
		
			
				|  |  | +			"1:	"MOVES".l	%2,(%1)+\n"		\
 | 
	
		
			
				|  |  | +			"2:	"MOVES".l	%R2,(%1)\n"		\
 | 
	
		
			
				|  |  | +			"3:\n"						\
 | 
	
		
			
				|  |  | +			"	.section .fixup,\"ax\"\n"		\
 | 
	
		
			
				|  |  | +			"	.even\n"				\
 | 
	
		
			
				|  |  | +			"10:	movel %3,%0\n"				\
 | 
	
		
			
				|  |  | +			"	jra 3b\n"				\
 | 
	
		
			
				|  |  | +			"	.previous\n"				\
 | 
	
		
			
				|  |  | +			"\n"						\
 | 
	
		
			
				|  |  | +			"	.section __ex_table,\"a\"\n"		\
 | 
	
		
			
				|  |  | +			"	.align 4\n"				\
 | 
	
		
			
				|  |  | +			"	.long 1b,10b\n"				\
 | 
	
		
			
				|  |  | +			"	.long 2b,10b\n"				\
 | 
	
		
			
				|  |  | +			"	.long 3b,10b\n"				\
 | 
	
		
			
				|  |  | +			"	.previous"				\
 | 
	
		
			
				|  |  | +			: "+d" (__pu_err), "+a" (__pu_ptr)		\
 | 
	
		
			
				|  |  | +			: "r" (__pu_val), "i" (-EFAULT)			\
 | 
	
		
			
				|  |  | +			: "memory");					\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	    }								\
 | 
	
		
			
				|  |  | +	default:							\
 | 
	
		
			
				|  |  | +		__pu_err = __put_user_bad();				\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	}								\
 | 
	
		
			
				|  |  | +	__pu_err;							\
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +#define put_user(x, ptr)	__put_user(x, ptr)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({	\
 | 
	
		
			
				|  |  | +	type __gu_val;						\
 | 
	
		
			
				|  |  | +	asm volatile ("\n"					\
 | 
	
		
			
				|  |  | +		"1:	"MOVES"."#bwl"	%2,%1\n"		\
 | 
	
		
			
				|  |  | +		"2:\n"						\
 | 
	
		
			
				|  |  | +		"	.section .fixup,\"ax\"\n"		\
 | 
	
		
			
				|  |  | +		"	.even\n"				\
 | 
	
		
			
				|  |  | +		"10:	move.l	%3,%0\n"			\
 | 
	
		
			
				|  |  | +		"	sub.l	%1,%1\n"			\
 | 
	
		
			
				|  |  | +		"	jra	2b\n"				\
 | 
	
		
			
				|  |  | +		"	.previous\n"				\
 | 
	
		
			
				|  |  | +		"\n"						\
 | 
	
		
			
				|  |  | +		"	.section __ex_table,\"a\"\n"		\
 | 
	
		
			
				|  |  | +		"	.align	4\n"				\
 | 
	
		
			
				|  |  | +		"	.long	1b,10b\n"			\
 | 
	
		
			
				|  |  | +		"	.previous"				\
 | 
	
		
			
				|  |  | +		: "+d" (res), "=&" #reg (__gu_val)		\
 | 
	
		
			
				|  |  | +		: "m" (*(ptr)), "i" (err));			\
 | 
	
		
			
				|  |  | +	(x) = (typeof(*(ptr)))(unsigned long)__gu_val;		\
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __get_user(x, ptr)						\
 | 
	
		
			
				|  |  | +({									\
 | 
	
		
			
				|  |  | +	int __gu_err = 0;						\
 | 
	
		
			
				|  |  | +	__chk_user_ptr(ptr);						\
 | 
	
		
			
				|  |  | +	switch (sizeof(*(ptr))) {					\
 | 
	
		
			
				|  |  | +	case 1:								\
 | 
	
		
			
				|  |  | +		__get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT);	\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	case 2:								\
 | 
	
		
			
				|  |  | +		__get_user_asm(__gu_err, x, ptr, u16, w, d, -EFAULT);	\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	case 4:								\
 | 
	
		
			
				|  |  | +		__get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT);	\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +/*	case 8:	disabled because gcc-4.1 has a broken typeof		\
 | 
	
		
			
				|  |  | + 	    {								\
 | 
	
		
			
				|  |  | + 		const void *__gu_ptr = (ptr);				\
 | 
	
		
			
				|  |  | + 		u64 __gu_val;						\
 | 
	
		
			
				|  |  | +		asm volatile ("\n"					\
 | 
	
		
			
				|  |  | +			"1:	"MOVES".l	(%2)+,%1\n"		\
 | 
	
		
			
				|  |  | +			"2:	"MOVES".l	(%2),%R1\n"		\
 | 
	
		
			
				|  |  | +			"3:\n"						\
 | 
	
		
			
				|  |  | +			"	.section .fixup,\"ax\"\n"		\
 | 
	
		
			
				|  |  | +			"	.even\n"				\
 | 
	
		
			
				|  |  | +			"10:	move.l	%3,%0\n"			\
 | 
	
		
			
				|  |  | +			"	sub.l	%1,%1\n"			\
 | 
	
		
			
				|  |  | +			"	sub.l	%R1,%R1\n"			\
 | 
	
		
			
				|  |  | +			"	jra	3b\n"				\
 | 
	
		
			
				|  |  | +			"	.previous\n"				\
 | 
	
		
			
				|  |  | +			"\n"						\
 | 
	
		
			
				|  |  | +			"	.section __ex_table,\"a\"\n"		\
 | 
	
		
			
				|  |  | +			"	.align	4\n"				\
 | 
	
		
			
				|  |  | +			"	.long	1b,10b\n"			\
 | 
	
		
			
				|  |  | +			"	.long	2b,10b\n"			\
 | 
	
		
			
				|  |  | +			"	.previous"				\
 | 
	
		
			
				|  |  | +			: "+d" (__gu_err), "=&r" (__gu_val),		\
 | 
	
		
			
				|  |  | +			  "+a" (__gu_ptr)				\
 | 
	
		
			
				|  |  | +			: "i" (-EFAULT)					\
 | 
	
		
			
				|  |  | +			: "memory");					\
 | 
	
		
			
				|  |  | +		(x) = (typeof(*(ptr)))__gu_val;				\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	    }	*/							\
 | 
	
		
			
				|  |  | +	default:							\
 | 
	
		
			
				|  |  | +		__gu_err = __get_user_bad();				\
 | 
	
		
			
				|  |  | +		break;							\
 | 
	
		
			
				|  |  | +	}								\
 | 
	
		
			
				|  |  | +	__gu_err;							\
 |