162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_IA64_UACCESS_H 362306a36Sopenharmony_ci#define _ASM_IA64_UACCESS_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci/* 662306a36Sopenharmony_ci * This file defines various macros to transfer memory areas across 762306a36Sopenharmony_ci * the user/kernel boundary. This needs to be done carefully because 862306a36Sopenharmony_ci * this code is executed in kernel mode and uses user-specified 962306a36Sopenharmony_ci * addresses. Thus, we need to be careful not to let the user to 1062306a36Sopenharmony_ci * trick us into accessing kernel memory that would normally be 1162306a36Sopenharmony_ci * inaccessible. This code is also fairly performance sensitive, 1262306a36Sopenharmony_ci * so we want to spend as little time doing safety checks as 1362306a36Sopenharmony_ci * possible. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * To make matters a bit more interesting, these macros sometimes also 1662306a36Sopenharmony_ci * called from within the kernel itself, in which case the address 1762306a36Sopenharmony_ci * validity check must be skipped. The get_fs() macro tells us what 1862306a36Sopenharmony_ci * to do: if get_fs()==USER_DS, checking is performed, if 1962306a36Sopenharmony_ci * get_fs()==KERNEL_DS, checking is bypassed. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Note that even if the memory area specified by the user is in a 2262306a36Sopenharmony_ci * valid address range, it is still possible that we'll get a page 2362306a36Sopenharmony_ci * fault while accessing it. This is handled by filling out an 2462306a36Sopenharmony_ci * exception handler fixup entry for each instruction that has the 2562306a36Sopenharmony_ci * potential to fault. When such a fault occurs, the page fault 2662306a36Sopenharmony_ci * handler checks to see whether the faulting instruction has a fixup 2762306a36Sopenharmony_ci * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and 2862306a36Sopenharmony_ci * then resumes execution at the continuation point. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * Based on <asm-alpha/uaccess.h>. 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * Copyright (C) 1998, 1999, 2001-2004 Hewlett-Packard Co 3362306a36Sopenharmony_ci * David Mosberger-Tang <davidm@hpl.hp.com> 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <linux/compiler.h> 3762306a36Sopenharmony_ci#include <linux/page-flags.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#include <asm/intrinsics.h> 4062306a36Sopenharmony_ci#include <linux/pgtable.h> 4162306a36Sopenharmony_ci#include <asm/io.h> 4262306a36Sopenharmony_ci#include <asm/extable.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* 4562306a36Sopenharmony_ci * When accessing user memory, we need to make sure the entire area really is 4662306a36Sopenharmony_ci * in user-level space. We also need to make sure that the address doesn't 4762306a36Sopenharmony_ci * point inside the virtually mapped linear page table. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_cistatic inline int __access_ok(const void __user *p, unsigned long size) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci unsigned long limit = TASK_SIZE; 5262306a36Sopenharmony_ci unsigned long addr = (unsigned long)p; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return likely((size <= limit) && (addr <= (limit - size)) && 5562306a36Sopenharmony_ci likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT)); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci#define __access_ok __access_ok 5862306a36Sopenharmony_ci#include <asm-generic/access_ok.h> 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * These are the main single-value transfer routines. They automatically 6262306a36Sopenharmony_ci * use the right size if we just have the right pointer type. 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci * Careful to not 6562306a36Sopenharmony_ci * (a) re-use the arguments for side effects (sizeof/typeof is ok) 6662306a36Sopenharmony_ci * (b) require any knowledge of processes at this stage 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ci#define put_user(x, ptr) __put_user_check((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr))) 6962306a36Sopenharmony_ci#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr))) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* 7262306a36Sopenharmony_ci * The "__xxx" versions do not do address space checking, useful when 7362306a36Sopenharmony_ci * doing multiple accesses to the same area (the programmer has to do the 7462306a36Sopenharmony_ci * checks by hand with "access_ok()") 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci#define __put_user(x, ptr) __put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr))) 7762306a36Sopenharmony_ci#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr))) 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#ifdef ASM_SUPPORTED 8062306a36Sopenharmony_ci struct __large_struct { unsigned long buf[100]; }; 8162306a36Sopenharmony_ci# define __m(x) (*(struct __large_struct __user *)(x)) 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* We need to declare the __ex_table section before we can use it in .xdata. */ 8462306a36Sopenharmony_ciasm (".section \"__ex_table\", \"a\"\n\t.previous"); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci# define __get_user_size(val, addr, n, err) \ 8762306a36Sopenharmony_cido { \ 8862306a36Sopenharmony_ci register long __gu_r8 asm ("r8") = 0; \ 8962306a36Sopenharmony_ci register long __gu_r9 asm ("r9"); \ 9062306a36Sopenharmony_ci asm ("\n[1:]\tld"#n" %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ 9162306a36Sopenharmony_ci "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n" \ 9262306a36Sopenharmony_ci "[1:]" \ 9362306a36Sopenharmony_ci : "=r"(__gu_r9), "=r"(__gu_r8) : "m"(__m(addr)), "1"(__gu_r8)); \ 9462306a36Sopenharmony_ci (err) = __gu_r8; \ 9562306a36Sopenharmony_ci (val) = __gu_r9; \ 9662306a36Sopenharmony_ci} while (0) 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* 9962306a36Sopenharmony_ci * The "__put_user_size()" macro tells gcc it reads from memory instead of writing it. This 10062306a36Sopenharmony_ci * is because they do not write to any memory gcc knows about, so there are no aliasing 10162306a36Sopenharmony_ci * issues. 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_ci# define __put_user_size(val, addr, n, err) \ 10462306a36Sopenharmony_cido { \ 10562306a36Sopenharmony_ci register long __pu_r8 asm ("r8") = 0; \ 10662306a36Sopenharmony_ci asm volatile ("\n[1:]\tst"#n" %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ 10762306a36Sopenharmony_ci "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \ 10862306a36Sopenharmony_ci "[1:]" \ 10962306a36Sopenharmony_ci : "=r"(__pu_r8) : "m"(__m(addr)), "rO"(val), "0"(__pu_r8)); \ 11062306a36Sopenharmony_ci (err) = __pu_r8; \ 11162306a36Sopenharmony_ci} while (0) 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#else /* !ASM_SUPPORTED */ 11462306a36Sopenharmony_ci# define RELOC_TYPE 2 /* ip-rel */ 11562306a36Sopenharmony_ci# define __get_user_size(val, addr, n, err) \ 11662306a36Sopenharmony_cido { \ 11762306a36Sopenharmony_ci __ld_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE); \ 11862306a36Sopenharmony_ci (err) = ia64_getreg(_IA64_REG_R8); \ 11962306a36Sopenharmony_ci (val) = ia64_getreg(_IA64_REG_R9); \ 12062306a36Sopenharmony_ci} while (0) 12162306a36Sopenharmony_ci# define __put_user_size(val, addr, n, err) \ 12262306a36Sopenharmony_cido { \ 12362306a36Sopenharmony_ci __st_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE, \ 12462306a36Sopenharmony_ci (__force unsigned long) (val)); \ 12562306a36Sopenharmony_ci (err) = ia64_getreg(_IA64_REG_R8); \ 12662306a36Sopenharmony_ci} while (0) 12762306a36Sopenharmony_ci#endif /* !ASM_SUPPORTED */ 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciextern void __get_user_unknown (void); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* 13262306a36Sopenharmony_ci * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which 13362306a36Sopenharmony_ci * could clobber r8 and r9 (among others). Thus, be careful not to evaluate it while 13462306a36Sopenharmony_ci * using r8/r9. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_ci#define __do_get_user(check, x, ptr, size) \ 13762306a36Sopenharmony_ci({ \ 13862306a36Sopenharmony_ci const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ 13962306a36Sopenharmony_ci __typeof__ (size) __gu_size = (size); \ 14062306a36Sopenharmony_ci long __gu_err = -EFAULT; \ 14162306a36Sopenharmony_ci unsigned long __gu_val = 0; \ 14262306a36Sopenharmony_ci if (!check || __access_ok(__gu_ptr, size)) \ 14362306a36Sopenharmony_ci switch (__gu_size) { \ 14462306a36Sopenharmony_ci case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break; \ 14562306a36Sopenharmony_ci case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break; \ 14662306a36Sopenharmony_ci case 4: __get_user_size(__gu_val, __gu_ptr, 4, __gu_err); break; \ 14762306a36Sopenharmony_ci case 8: __get_user_size(__gu_val, __gu_ptr, 8, __gu_err); break; \ 14862306a36Sopenharmony_ci default: __get_user_unknown(); break; \ 14962306a36Sopenharmony_ci } \ 15062306a36Sopenharmony_ci (x) = (__force __typeof__(*(__gu_ptr))) __gu_val; \ 15162306a36Sopenharmony_ci __gu_err; \ 15262306a36Sopenharmony_ci}) 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci#define __get_user_nocheck(x, ptr, size) __do_get_user(0, x, ptr, size) 15562306a36Sopenharmony_ci#define __get_user_check(x, ptr, size) __do_get_user(1, x, ptr, size) 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciextern void __put_user_unknown (void); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* 16062306a36Sopenharmony_ci * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which 16162306a36Sopenharmony_ci * could clobber r8 (among others). Thus, be careful not to evaluate them while using r8. 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci#define __do_put_user(check, x, ptr, size) \ 16462306a36Sopenharmony_ci({ \ 16562306a36Sopenharmony_ci __typeof__ (x) __pu_x = (x); \ 16662306a36Sopenharmony_ci __typeof__ (*(ptr)) __user *__pu_ptr = (ptr); \ 16762306a36Sopenharmony_ci __typeof__ (size) __pu_size = (size); \ 16862306a36Sopenharmony_ci long __pu_err = -EFAULT; \ 16962306a36Sopenharmony_ci \ 17062306a36Sopenharmony_ci if (!check || __access_ok(__pu_ptr, __pu_size)) \ 17162306a36Sopenharmony_ci switch (__pu_size) { \ 17262306a36Sopenharmony_ci case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break; \ 17362306a36Sopenharmony_ci case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break; \ 17462306a36Sopenharmony_ci case 4: __put_user_size(__pu_x, __pu_ptr, 4, __pu_err); break; \ 17562306a36Sopenharmony_ci case 8: __put_user_size(__pu_x, __pu_ptr, 8, __pu_err); break; \ 17662306a36Sopenharmony_ci default: __put_user_unknown(); break; \ 17762306a36Sopenharmony_ci } \ 17862306a36Sopenharmony_ci __pu_err; \ 17962306a36Sopenharmony_ci}) 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci#define __put_user_nocheck(x, ptr, size) __do_put_user(0, x, ptr, size) 18262306a36Sopenharmony_ci#define __put_user_check(x, ptr, size) __do_put_user(1, x, ptr, size) 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/* 18562306a36Sopenharmony_ci * Complex access routines 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_ciextern unsigned long __must_check __copy_user (void __user *to, const void __user *from, 18862306a36Sopenharmony_ci unsigned long count); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic inline unsigned long 19162306a36Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long count) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci return __copy_user(to, (__force void __user *) from, count); 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic inline unsigned long 19762306a36Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long count) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci return __copy_user((__force void __user *) to, from, count); 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci#define INLINE_COPY_FROM_USER 20362306a36Sopenharmony_ci#define INLINE_COPY_TO_USER 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ciextern unsigned long __do_clear_user (void __user *, unsigned long); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#define __clear_user(to, n) __do_clear_user(to, n) 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#define clear_user(to, n) \ 21062306a36Sopenharmony_ci({ \ 21162306a36Sopenharmony_ci unsigned long __cu_len = (n); \ 21262306a36Sopenharmony_ci if (__access_ok(to, __cu_len)) \ 21362306a36Sopenharmony_ci __cu_len = __do_clear_user(to, __cu_len); \ 21462306a36Sopenharmony_ci __cu_len; \ 21562306a36Sopenharmony_ci}) 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/* 21962306a36Sopenharmony_ci * Returns: -EFAULT if exception before terminator, N if the entire buffer filled, else 22062306a36Sopenharmony_ci * strlen. 22162306a36Sopenharmony_ci */ 22262306a36Sopenharmony_ciextern long __must_check __strncpy_from_user (char *to, const char __user *from, long to_len); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci#define strncpy_from_user(to, from, n) \ 22562306a36Sopenharmony_ci({ \ 22662306a36Sopenharmony_ci const char __user * __sfu_from = (from); \ 22762306a36Sopenharmony_ci long __sfu_ret = -EFAULT; \ 22862306a36Sopenharmony_ci if (__access_ok(__sfu_from, 0)) \ 22962306a36Sopenharmony_ci __sfu_ret = __strncpy_from_user((to), __sfu_from, (n)); \ 23062306a36Sopenharmony_ci __sfu_ret; \ 23162306a36Sopenharmony_ci}) 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/* 23462306a36Sopenharmony_ci * Returns: 0 if exception before NUL or reaching the supplied limit 23562306a36Sopenharmony_ci * (N), a value greater than N if the limit would be exceeded, else 23662306a36Sopenharmony_ci * strlen. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ciextern unsigned long __strnlen_user (const char __user *, long); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci#define strnlen_user(str, len) \ 24162306a36Sopenharmony_ci({ \ 24262306a36Sopenharmony_ci const char __user *__su_str = (str); \ 24362306a36Sopenharmony_ci unsigned long __su_ret = 0; \ 24462306a36Sopenharmony_ci if (__access_ok(__su_str, 0)) \ 24562306a36Sopenharmony_ci __su_ret = __strnlen_user(__su_str, len); \ 24662306a36Sopenharmony_ci __su_ret; \ 24762306a36Sopenharmony_ci}) 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci#define ARCH_HAS_TRANSLATE_MEM_PTR 1 25062306a36Sopenharmony_cistatic __inline__ void * 25162306a36Sopenharmony_cixlate_dev_mem_ptr(phys_addr_t p) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci struct page *page; 25462306a36Sopenharmony_ci void *ptr; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci page = pfn_to_page(p >> PAGE_SHIFT); 25762306a36Sopenharmony_ci if (PageUncached(page)) 25862306a36Sopenharmony_ci ptr = (void *)p + __IA64_UNCACHED_OFFSET; 25962306a36Sopenharmony_ci else 26062306a36Sopenharmony_ci ptr = __va(p); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci return ptr; 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci#endif /* _ASM_IA64_UACCESS_H */ 266