arch/m68k/include/asm/uaccess.h

Source file repositories/reference/linux-study-clean/arch/m68k/include/asm/uaccess.h

File Facts

System
Linux kernel
Corpus path
arch/m68k/include/asm/uaccess.h
Extension
.h
Size
12188 bytes
Lines
452
Domain
Architecture Layer
Bucket
arch/m68k
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

#ifndef __M68K_UACCESS_H
#define __M68K_UACCESS_H

#ifdef CONFIG_MMU

/*
 * User space memory access functions
 */
#include <linux/compiler.h>
#include <linux/types.h>
#include <asm/extable.h>
#include <asm-generic/access_ok.h>

/*
 * 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

#define __put_user_asm(inst, res, x, ptr, bwl, reg, err) \
asm volatile ("\n"					\
	"1:	"inst"."#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))

#define __put_user_asm8(inst, res, x, ptr)			\
do {								\
	const void *__pu_ptr = (const void __force *)(ptr);	\
								\
	asm volatile ("\n"					\
		"1:	"inst".l %2,(%1)+\n"			\
		"2:	"inst".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" (res), "+a" (__pu_ptr)			\
		: "r" (x), "i" (-EFAULT)			\
		: "memory");					\
} while (0)

/*
 * 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(MOVES, __pu_err, __pu_val, ptr, b, d, -EFAULT); \
		break;							\
	case 2:								\
		__put_user_asm(MOVES, __pu_err, __pu_val, ptr, w, r, -EFAULT); \
		break;							\
	case 4:								\

Annotation

Implementation Notes