| /* SPDX-License-Identifier: GPL-2.0 */ | |
| /* | |
| * 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); | |
| #endif /* __ASM_SH_UACCESS_32_H */ |