162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __M68K_UACCESS_H 362306a36Sopenharmony_ci#define __M68K_UACCESS_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#ifdef CONFIG_MMU 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/* 862306a36Sopenharmony_ci * User space memory access functions 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#include <linux/compiler.h> 1162306a36Sopenharmony_ci#include <linux/types.h> 1262306a36Sopenharmony_ci#include <asm/extable.h> 1362306a36Sopenharmony_ci#include <asm-generic/access_ok.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* 1662306a36Sopenharmony_ci * Not all varients of the 68k family support the notion of address spaces. 1762306a36Sopenharmony_ci * The traditional 680x0 parts do, and they use the sfc/dfc registers and 1862306a36Sopenharmony_ci * the "moves" instruction to access user space from kernel space. Other 1962306a36Sopenharmony_ci * family members like ColdFire don't support this, and only have a single 2062306a36Sopenharmony_ci * address space, and use the usual "move" instruction for user space access. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Outside of this difference the user space access functions are the same. 2362306a36Sopenharmony_ci * So lets keep the code simple and just define in what we need to use. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_ADDRESS_SPACES 2662306a36Sopenharmony_ci#define MOVES "moves" 2762306a36Sopenharmony_ci#else 2862306a36Sopenharmony_ci#define MOVES "move" 2962306a36Sopenharmony_ci#endif 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define __put_user_asm(inst, res, x, ptr, bwl, reg, err) \ 3262306a36Sopenharmony_ciasm volatile ("\n" \ 3362306a36Sopenharmony_ci "1: "inst"."#bwl" %2,%1\n" \ 3462306a36Sopenharmony_ci "2:\n" \ 3562306a36Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 3662306a36Sopenharmony_ci " .even\n" \ 3762306a36Sopenharmony_ci "10: moveq.l %3,%0\n" \ 3862306a36Sopenharmony_ci " jra 2b\n" \ 3962306a36Sopenharmony_ci " .previous\n" \ 4062306a36Sopenharmony_ci "\n" \ 4162306a36Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 4262306a36Sopenharmony_ci " .align 4\n" \ 4362306a36Sopenharmony_ci " .long 1b,10b\n" \ 4462306a36Sopenharmony_ci " .long 2b,10b\n" \ 4562306a36Sopenharmony_ci " .previous" \ 4662306a36Sopenharmony_ci : "+d" (res), "=m" (*(ptr)) \ 4762306a36Sopenharmony_ci : #reg (x), "i" (err)) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define __put_user_asm8(inst, res, x, ptr) \ 5062306a36Sopenharmony_cido { \ 5162306a36Sopenharmony_ci const void *__pu_ptr = (const void __force *)(ptr); \ 5262306a36Sopenharmony_ci \ 5362306a36Sopenharmony_ci asm volatile ("\n" \ 5462306a36Sopenharmony_ci "1: "inst".l %2,(%1)+\n" \ 5562306a36Sopenharmony_ci "2: "inst".l %R2,(%1)\n" \ 5662306a36Sopenharmony_ci "3:\n" \ 5762306a36Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 5862306a36Sopenharmony_ci " .even\n" \ 5962306a36Sopenharmony_ci "10: movel %3,%0\n" \ 6062306a36Sopenharmony_ci " jra 3b\n" \ 6162306a36Sopenharmony_ci " .previous\n" \ 6262306a36Sopenharmony_ci "\n" \ 6362306a36Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 6462306a36Sopenharmony_ci " .align 4\n" \ 6562306a36Sopenharmony_ci " .long 1b,10b\n" \ 6662306a36Sopenharmony_ci " .long 2b,10b\n" \ 6762306a36Sopenharmony_ci " .long 3b,10b\n" \ 6862306a36Sopenharmony_ci " .previous" \ 6962306a36Sopenharmony_ci : "+d" (res), "+a" (__pu_ptr) \ 7062306a36Sopenharmony_ci : "r" (x), "i" (-EFAULT) \ 7162306a36Sopenharmony_ci : "memory"); \ 7262306a36Sopenharmony_ci} while (0) 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* 7562306a36Sopenharmony_ci * These are the main single-value transfer routines. They automatically 7662306a36Sopenharmony_ci * use the right size if we just have the right pointer type. 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#define __put_user(x, ptr) \ 8062306a36Sopenharmony_ci({ \ 8162306a36Sopenharmony_ci typeof(*(ptr)) __pu_val = (x); \ 8262306a36Sopenharmony_ci int __pu_err = 0; \ 8362306a36Sopenharmony_ci __chk_user_ptr(ptr); \ 8462306a36Sopenharmony_ci switch (sizeof (*(ptr))) { \ 8562306a36Sopenharmony_ci case 1: \ 8662306a36Sopenharmony_ci __put_user_asm(MOVES, __pu_err, __pu_val, ptr, b, d, -EFAULT); \ 8762306a36Sopenharmony_ci break; \ 8862306a36Sopenharmony_ci case 2: \ 8962306a36Sopenharmony_ci __put_user_asm(MOVES, __pu_err, __pu_val, ptr, w, r, -EFAULT); \ 9062306a36Sopenharmony_ci break; \ 9162306a36Sopenharmony_ci case 4: \ 9262306a36Sopenharmony_ci __put_user_asm(MOVES, __pu_err, __pu_val, ptr, l, r, -EFAULT); \ 9362306a36Sopenharmony_ci break; \ 9462306a36Sopenharmony_ci case 8: \ 9562306a36Sopenharmony_ci __put_user_asm8(MOVES, __pu_err, __pu_val, ptr); \ 9662306a36Sopenharmony_ci break; \ 9762306a36Sopenharmony_ci default: \ 9862306a36Sopenharmony_ci BUILD_BUG(); \ 9962306a36Sopenharmony_ci } \ 10062306a36Sopenharmony_ci __pu_err; \ 10162306a36Sopenharmony_ci}) 10262306a36Sopenharmony_ci#define put_user(x, ptr) __put_user(x, ptr) 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci#define __get_user_asm(inst, res, x, ptr, type, bwl, reg, err) ({ \ 10662306a36Sopenharmony_ci type __gu_val; \ 10762306a36Sopenharmony_ci asm volatile ("\n" \ 10862306a36Sopenharmony_ci "1: "inst"."#bwl" %2,%1\n" \ 10962306a36Sopenharmony_ci "2:\n" \ 11062306a36Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 11162306a36Sopenharmony_ci " .even\n" \ 11262306a36Sopenharmony_ci "10: move.l %3,%0\n" \ 11362306a36Sopenharmony_ci " sub.l %1,%1\n" \ 11462306a36Sopenharmony_ci " jra 2b\n" \ 11562306a36Sopenharmony_ci " .previous\n" \ 11662306a36Sopenharmony_ci "\n" \ 11762306a36Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 11862306a36Sopenharmony_ci " .align 4\n" \ 11962306a36Sopenharmony_ci " .long 1b,10b\n" \ 12062306a36Sopenharmony_ci " .previous" \ 12162306a36Sopenharmony_ci : "+d" (res), "=&" #reg (__gu_val) \ 12262306a36Sopenharmony_ci : "m" (*(ptr)), "i" (err)); \ 12362306a36Sopenharmony_ci (x) = (__force typeof(*(ptr)))(__force unsigned long)__gu_val; \ 12462306a36Sopenharmony_ci}) 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci#define __get_user_asm8(inst, res, x, ptr) \ 12762306a36Sopenharmony_cido { \ 12862306a36Sopenharmony_ci const void *__gu_ptr = (const void __force *)(ptr); \ 12962306a36Sopenharmony_ci union { \ 13062306a36Sopenharmony_ci u64 l; \ 13162306a36Sopenharmony_ci __typeof__(*(ptr)) t; \ 13262306a36Sopenharmony_ci } __gu_val; \ 13362306a36Sopenharmony_ci \ 13462306a36Sopenharmony_ci asm volatile ("\n" \ 13562306a36Sopenharmony_ci "1: "inst".l (%2)+,%1\n" \ 13662306a36Sopenharmony_ci "2: "inst".l (%2),%R1\n" \ 13762306a36Sopenharmony_ci "3:\n" \ 13862306a36Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 13962306a36Sopenharmony_ci " .even\n" \ 14062306a36Sopenharmony_ci "10: move.l %3,%0\n" \ 14162306a36Sopenharmony_ci " sub.l %1,%1\n" \ 14262306a36Sopenharmony_ci " sub.l %R1,%R1\n" \ 14362306a36Sopenharmony_ci " jra 3b\n" \ 14462306a36Sopenharmony_ci " .previous\n" \ 14562306a36Sopenharmony_ci "\n" \ 14662306a36Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 14762306a36Sopenharmony_ci " .align 4\n" \ 14862306a36Sopenharmony_ci " .long 1b,10b\n" \ 14962306a36Sopenharmony_ci " .long 2b,10b\n" \ 15062306a36Sopenharmony_ci " .previous" \ 15162306a36Sopenharmony_ci : "+d" (res), "=&r" (__gu_val.l), \ 15262306a36Sopenharmony_ci "+a" (__gu_ptr) \ 15362306a36Sopenharmony_ci : "i" (-EFAULT) \ 15462306a36Sopenharmony_ci : "memory"); \ 15562306a36Sopenharmony_ci (x) = __gu_val.t; \ 15662306a36Sopenharmony_ci} while (0) 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci#define __get_user(x, ptr) \ 15962306a36Sopenharmony_ci({ \ 16062306a36Sopenharmony_ci int __gu_err = 0; \ 16162306a36Sopenharmony_ci __chk_user_ptr(ptr); \ 16262306a36Sopenharmony_ci switch (sizeof(*(ptr))) { \ 16362306a36Sopenharmony_ci case 1: \ 16462306a36Sopenharmony_ci __get_user_asm(MOVES, __gu_err, x, ptr, u8, b, d, -EFAULT); \ 16562306a36Sopenharmony_ci break; \ 16662306a36Sopenharmony_ci case 2: \ 16762306a36Sopenharmony_ci __get_user_asm(MOVES, __gu_err, x, ptr, u16, w, r, -EFAULT); \ 16862306a36Sopenharmony_ci break; \ 16962306a36Sopenharmony_ci case 4: \ 17062306a36Sopenharmony_ci __get_user_asm(MOVES, __gu_err, x, ptr, u32, l, r, -EFAULT); \ 17162306a36Sopenharmony_ci break; \ 17262306a36Sopenharmony_ci case 8: \ 17362306a36Sopenharmony_ci __get_user_asm8(MOVES, __gu_err, x, ptr); \ 17462306a36Sopenharmony_ci break; \ 17562306a36Sopenharmony_ci default: \ 17662306a36Sopenharmony_ci BUILD_BUG(); \ 17762306a36Sopenharmony_ci } \ 17862306a36Sopenharmony_ci __gu_err; \ 17962306a36Sopenharmony_ci}) 18062306a36Sopenharmony_ci#define get_user(x, ptr) __get_user(x, ptr) 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ciunsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n); 18362306a36Sopenharmony_ciunsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#define __suffix0 18662306a36Sopenharmony_ci#define __suffix1 b 18762306a36Sopenharmony_ci#define __suffix2 w 18862306a36Sopenharmony_ci#define __suffix4 l 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci#define ____constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)\ 19162306a36Sopenharmony_ci asm volatile ("\n" \ 19262306a36Sopenharmony_ci "1: "MOVES"."#s1" (%2)+,%3\n" \ 19362306a36Sopenharmony_ci " move."#s1" %3,(%1)+\n" \ 19462306a36Sopenharmony_ci " .ifnc \""#s2"\",\"\"\n" \ 19562306a36Sopenharmony_ci "2: "MOVES"."#s2" (%2)+,%3\n" \ 19662306a36Sopenharmony_ci " move."#s2" %3,(%1)+\n" \ 19762306a36Sopenharmony_ci " .ifnc \""#s3"\",\"\"\n" \ 19862306a36Sopenharmony_ci "3: "MOVES"."#s3" (%2)+,%3\n" \ 19962306a36Sopenharmony_ci " move."#s3" %3,(%1)+\n" \ 20062306a36Sopenharmony_ci " .endif\n" \ 20162306a36Sopenharmony_ci " .endif\n" \ 20262306a36Sopenharmony_ci "4:\n" \ 20362306a36Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 20462306a36Sopenharmony_ci " .align 4\n" \ 20562306a36Sopenharmony_ci " .long 1b,10f\n" \ 20662306a36Sopenharmony_ci " .ifnc \""#s2"\",\"\"\n" \ 20762306a36Sopenharmony_ci " .long 2b,20f\n" \ 20862306a36Sopenharmony_ci " .ifnc \""#s3"\",\"\"\n" \ 20962306a36Sopenharmony_ci " .long 3b,30f\n" \ 21062306a36Sopenharmony_ci " .endif\n" \ 21162306a36Sopenharmony_ci " .endif\n" \ 21262306a36Sopenharmony_ci " .previous\n" \ 21362306a36Sopenharmony_ci "\n" \ 21462306a36Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 21562306a36Sopenharmony_ci " .even\n" \ 21662306a36Sopenharmony_ci "10: addq.l #"#n1",%0\n" \ 21762306a36Sopenharmony_ci " .ifnc \""#s2"\",\"\"\n" \ 21862306a36Sopenharmony_ci "20: addq.l #"#n2",%0\n" \ 21962306a36Sopenharmony_ci " .ifnc \""#s3"\",\"\"\n" \ 22062306a36Sopenharmony_ci "30: addq.l #"#n3",%0\n" \ 22162306a36Sopenharmony_ci " .endif\n" \ 22262306a36Sopenharmony_ci " .endif\n" \ 22362306a36Sopenharmony_ci " jra 4b\n" \ 22462306a36Sopenharmony_ci " .previous\n" \ 22562306a36Sopenharmony_ci : "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp) \ 22662306a36Sopenharmony_ci : : "memory") 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci#define ___constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)\ 22962306a36Sopenharmony_ci ____constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3) 23062306a36Sopenharmony_ci#define __constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3) \ 23162306a36Sopenharmony_ci ___constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, \ 23262306a36Sopenharmony_ci __suffix##n1, __suffix##n2, __suffix##n3) 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic __always_inline unsigned long 23562306a36Sopenharmony_ci__constant_copy_from_user(void *to, const void __user *from, unsigned long n) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci unsigned long res = 0, tmp; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci switch (n) { 24062306a36Sopenharmony_ci case 1: 24162306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 1, 0, 0); 24262306a36Sopenharmony_ci break; 24362306a36Sopenharmony_ci case 2: 24462306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 2, 0, 0); 24562306a36Sopenharmony_ci break; 24662306a36Sopenharmony_ci case 3: 24762306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 2, 1, 0); 24862306a36Sopenharmony_ci break; 24962306a36Sopenharmony_ci case 4: 25062306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 4, 0, 0); 25162306a36Sopenharmony_ci break; 25262306a36Sopenharmony_ci case 5: 25362306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 4, 1, 0); 25462306a36Sopenharmony_ci break; 25562306a36Sopenharmony_ci case 6: 25662306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 4, 2, 0); 25762306a36Sopenharmony_ci break; 25862306a36Sopenharmony_ci case 7: 25962306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 4, 2, 1); 26062306a36Sopenharmony_ci break; 26162306a36Sopenharmony_ci case 8: 26262306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 0); 26362306a36Sopenharmony_ci break; 26462306a36Sopenharmony_ci case 9: 26562306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 1); 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci case 10: 26862306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 2); 26962306a36Sopenharmony_ci break; 27062306a36Sopenharmony_ci case 12: 27162306a36Sopenharmony_ci __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 4); 27262306a36Sopenharmony_ci break; 27362306a36Sopenharmony_ci default: 27462306a36Sopenharmony_ci /* we limit the inlined version to 3 moves */ 27562306a36Sopenharmony_ci return __generic_copy_from_user(to, from, n); 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci return res; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3) \ 28262306a36Sopenharmony_ci asm volatile ("\n" \ 28362306a36Sopenharmony_ci " move."#s1" (%2)+,%3\n" \ 28462306a36Sopenharmony_ci "11: "MOVES"."#s1" %3,(%1)+\n" \ 28562306a36Sopenharmony_ci "12: move."#s2" (%2)+,%3\n" \ 28662306a36Sopenharmony_ci "21: "MOVES"."#s2" %3,(%1)+\n" \ 28762306a36Sopenharmony_ci "22:\n" \ 28862306a36Sopenharmony_ci " .ifnc \""#s3"\",\"\"\n" \ 28962306a36Sopenharmony_ci " move."#s3" (%2)+,%3\n" \ 29062306a36Sopenharmony_ci "31: "MOVES"."#s3" %3,(%1)+\n" \ 29162306a36Sopenharmony_ci "32:\n" \ 29262306a36Sopenharmony_ci " .endif\n" \ 29362306a36Sopenharmony_ci "4:\n" \ 29462306a36Sopenharmony_ci "\n" \ 29562306a36Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 29662306a36Sopenharmony_ci " .align 4\n" \ 29762306a36Sopenharmony_ci " .long 11b,5f\n" \ 29862306a36Sopenharmony_ci " .long 12b,5f\n" \ 29962306a36Sopenharmony_ci " .long 21b,5f\n" \ 30062306a36Sopenharmony_ci " .long 22b,5f\n" \ 30162306a36Sopenharmony_ci " .ifnc \""#s3"\",\"\"\n" \ 30262306a36Sopenharmony_ci " .long 31b,5f\n" \ 30362306a36Sopenharmony_ci " .long 32b,5f\n" \ 30462306a36Sopenharmony_ci " .endif\n" \ 30562306a36Sopenharmony_ci " .previous\n" \ 30662306a36Sopenharmony_ci "\n" \ 30762306a36Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 30862306a36Sopenharmony_ci " .even\n" \ 30962306a36Sopenharmony_ci "5: moveq.l #"#n",%0\n" \ 31062306a36Sopenharmony_ci " jra 4b\n" \ 31162306a36Sopenharmony_ci " .previous\n" \ 31262306a36Sopenharmony_ci : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp) \ 31362306a36Sopenharmony_ci : : "memory") 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic __always_inline unsigned long 31662306a36Sopenharmony_ci__constant_copy_to_user(void __user *to, const void *from, unsigned long n) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci unsigned long res = 0, tmp; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci switch (n) { 32162306a36Sopenharmony_ci case 1: 32262306a36Sopenharmony_ci __put_user_asm(MOVES, res, *(u8 *)from, (u8 __user *)to, 32362306a36Sopenharmony_ci b, d, 1); 32462306a36Sopenharmony_ci break; 32562306a36Sopenharmony_ci case 2: 32662306a36Sopenharmony_ci __put_user_asm(MOVES, res, *(u16 *)from, (u16 __user *)to, 32762306a36Sopenharmony_ci w, r, 2); 32862306a36Sopenharmony_ci break; 32962306a36Sopenharmony_ci case 3: 33062306a36Sopenharmony_ci __constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,); 33162306a36Sopenharmony_ci break; 33262306a36Sopenharmony_ci case 4: 33362306a36Sopenharmony_ci __put_user_asm(MOVES, res, *(u32 *)from, (u32 __user *)to, 33462306a36Sopenharmony_ci l, r, 4); 33562306a36Sopenharmony_ci break; 33662306a36Sopenharmony_ci case 5: 33762306a36Sopenharmony_ci __constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,); 33862306a36Sopenharmony_ci break; 33962306a36Sopenharmony_ci case 6: 34062306a36Sopenharmony_ci __constant_copy_to_user_asm(res, to, from, tmp, 6, l, w,); 34162306a36Sopenharmony_ci break; 34262306a36Sopenharmony_ci case 7: 34362306a36Sopenharmony_ci __constant_copy_to_user_asm(res, to, from, tmp, 7, l, w, b); 34462306a36Sopenharmony_ci break; 34562306a36Sopenharmony_ci case 8: 34662306a36Sopenharmony_ci __constant_copy_to_user_asm(res, to, from, tmp, 8, l, l,); 34762306a36Sopenharmony_ci break; 34862306a36Sopenharmony_ci case 9: 34962306a36Sopenharmony_ci __constant_copy_to_user_asm(res, to, from, tmp, 9, l, l, b); 35062306a36Sopenharmony_ci break; 35162306a36Sopenharmony_ci case 10: 35262306a36Sopenharmony_ci __constant_copy_to_user_asm(res, to, from, tmp, 10, l, l, w); 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci case 12: 35562306a36Sopenharmony_ci __constant_copy_to_user_asm(res, to, from, tmp, 12, l, l, l); 35662306a36Sopenharmony_ci break; 35762306a36Sopenharmony_ci default: 35862306a36Sopenharmony_ci /* limit the inlined version to 3 moves */ 35962306a36Sopenharmony_ci return __generic_copy_to_user(to, from, n); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci return res; 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic inline unsigned long 36662306a36Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long n) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci if (__builtin_constant_p(n)) 36962306a36Sopenharmony_ci return __constant_copy_from_user(to, from, n); 37062306a36Sopenharmony_ci return __generic_copy_from_user(to, from, n); 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic inline unsigned long 37462306a36Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci if (__builtin_constant_p(n)) 37762306a36Sopenharmony_ci return __constant_copy_to_user(to, from, n); 37862306a36Sopenharmony_ci return __generic_copy_to_user(to, from, n); 37962306a36Sopenharmony_ci} 38062306a36Sopenharmony_ci#define INLINE_COPY_FROM_USER 38162306a36Sopenharmony_ci#define INLINE_COPY_TO_USER 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci#define __get_kernel_nofault(dst, src, type, err_label) \ 38462306a36Sopenharmony_cido { \ 38562306a36Sopenharmony_ci type *__gk_dst = (type *)(dst); \ 38662306a36Sopenharmony_ci type *__gk_src = (type *)(src); \ 38762306a36Sopenharmony_ci int __gk_err = 0; \ 38862306a36Sopenharmony_ci \ 38962306a36Sopenharmony_ci switch (sizeof(type)) { \ 39062306a36Sopenharmony_ci case 1: \ 39162306a36Sopenharmony_ci __get_user_asm("move", __gk_err, *__gk_dst, __gk_src, \ 39262306a36Sopenharmony_ci u8, b, d, -EFAULT); \ 39362306a36Sopenharmony_ci break; \ 39462306a36Sopenharmony_ci case 2: \ 39562306a36Sopenharmony_ci __get_user_asm("move", __gk_err, *__gk_dst, __gk_src, \ 39662306a36Sopenharmony_ci u16, w, r, -EFAULT); \ 39762306a36Sopenharmony_ci break; \ 39862306a36Sopenharmony_ci case 4: \ 39962306a36Sopenharmony_ci __get_user_asm("move", __gk_err, *__gk_dst, __gk_src, \ 40062306a36Sopenharmony_ci u32, l, r, -EFAULT); \ 40162306a36Sopenharmony_ci break; \ 40262306a36Sopenharmony_ci case 8: \ 40362306a36Sopenharmony_ci __get_user_asm8("move", __gk_err, *__gk_dst, __gk_src); \ 40462306a36Sopenharmony_ci break; \ 40562306a36Sopenharmony_ci default: \ 40662306a36Sopenharmony_ci BUILD_BUG(); \ 40762306a36Sopenharmony_ci } \ 40862306a36Sopenharmony_ci if (unlikely(__gk_err)) \ 40962306a36Sopenharmony_ci goto err_label; \ 41062306a36Sopenharmony_ci} while (0) 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci#define __put_kernel_nofault(dst, src, type, err_label) \ 41362306a36Sopenharmony_cido { \ 41462306a36Sopenharmony_ci type __pk_src = *(type *)(src); \ 41562306a36Sopenharmony_ci type *__pk_dst = (type *)(dst); \ 41662306a36Sopenharmony_ci int __pk_err = 0; \ 41762306a36Sopenharmony_ci \ 41862306a36Sopenharmony_ci switch (sizeof(type)) { \ 41962306a36Sopenharmony_ci case 1: \ 42062306a36Sopenharmony_ci __put_user_asm("move", __pk_err, __pk_src, __pk_dst, \ 42162306a36Sopenharmony_ci b, d, -EFAULT); \ 42262306a36Sopenharmony_ci break; \ 42362306a36Sopenharmony_ci case 2: \ 42462306a36Sopenharmony_ci __put_user_asm("move", __pk_err, __pk_src, __pk_dst, \ 42562306a36Sopenharmony_ci w, r, -EFAULT); \ 42662306a36Sopenharmony_ci break; \ 42762306a36Sopenharmony_ci case 4: \ 42862306a36Sopenharmony_ci __put_user_asm("move", __pk_err, __pk_src, __pk_dst, \ 42962306a36Sopenharmony_ci l, r, -EFAULT); \ 43062306a36Sopenharmony_ci break; \ 43162306a36Sopenharmony_ci case 8: \ 43262306a36Sopenharmony_ci __put_user_asm8("move", __pk_err, __pk_src, __pk_dst); \ 43362306a36Sopenharmony_ci break; \ 43462306a36Sopenharmony_ci default: \ 43562306a36Sopenharmony_ci BUILD_BUG(); \ 43662306a36Sopenharmony_ci } \ 43762306a36Sopenharmony_ci if (unlikely(__pk_err)) \ 43862306a36Sopenharmony_ci goto err_label; \ 43962306a36Sopenharmony_ci} while (0) 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ciextern long strncpy_from_user(char *dst, const char __user *src, long count); 44262306a36Sopenharmony_ciextern __must_check long strnlen_user(const char __user *str, long n); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ciunsigned long __clear_user(void __user *to, unsigned long n); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci#define clear_user __clear_user 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci#else /* !CONFIG_MMU */ 44962306a36Sopenharmony_ci#include <asm-generic/uaccess.h> 45062306a36Sopenharmony_ci#endif 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci#endif /* _M68K_UACCESS_H */ 453