18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_UACCESS_64_H 38c2ecf20Sopenharmony_ci#define _ASM_X86_UACCESS_64_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci/* 68c2ecf20Sopenharmony_ci * User space memory access functions 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/compiler.h> 98c2ecf20Sopenharmony_ci#include <linux/lockdep.h> 108c2ecf20Sopenharmony_ci#include <linux/kasan-checks.h> 118c2ecf20Sopenharmony_ci#include <asm/alternative.h> 128c2ecf20Sopenharmony_ci#include <asm/cpufeatures.h> 138c2ecf20Sopenharmony_ci#include <asm/page.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* 168c2ecf20Sopenharmony_ci * Copy To/From Userspace 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* Handles exceptions in both to and from, but doesn't do access_ok */ 208c2ecf20Sopenharmony_ci__must_check unsigned long 218c2ecf20Sopenharmony_cicopy_user_enhanced_fast_string(void *to, const void *from, unsigned len); 228c2ecf20Sopenharmony_ci__must_check unsigned long 238c2ecf20Sopenharmony_cicopy_user_generic_string(void *to, const void *from, unsigned len); 248c2ecf20Sopenharmony_ci__must_check unsigned long 258c2ecf20Sopenharmony_cicopy_user_generic_unrolled(void *to, const void *from, unsigned len); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic __always_inline __must_check unsigned long 288c2ecf20Sopenharmony_cicopy_user_generic(void *to, const void *from, unsigned len) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci unsigned ret; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci /* 338c2ecf20Sopenharmony_ci * If CPU has ERMS feature, use copy_user_enhanced_fast_string. 348c2ecf20Sopenharmony_ci * Otherwise, if CPU has rep_good feature, use copy_user_generic_string. 358c2ecf20Sopenharmony_ci * Otherwise, use copy_user_generic_unrolled. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci alternative_call_2(copy_user_generic_unrolled, 388c2ecf20Sopenharmony_ci copy_user_generic_string, 398c2ecf20Sopenharmony_ci X86_FEATURE_REP_GOOD, 408c2ecf20Sopenharmony_ci copy_user_enhanced_fast_string, 418c2ecf20Sopenharmony_ci X86_FEATURE_ERMS, 428c2ecf20Sopenharmony_ci ASM_OUTPUT2("=a" (ret), "=D" (to), "=S" (from), 438c2ecf20Sopenharmony_ci "=d" (len)), 448c2ecf20Sopenharmony_ci "1" (to), "2" (from), "3" (len) 458c2ecf20Sopenharmony_ci : "memory", "rcx", "r8", "r9", "r10", "r11"); 468c2ecf20Sopenharmony_ci return ret; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic __always_inline __must_check unsigned long 508c2ecf20Sopenharmony_ciraw_copy_from_user(void *dst, const void __user *src, unsigned long size) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci return copy_user_generic(dst, (__force void *)src, size); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic __always_inline __must_check unsigned long 568c2ecf20Sopenharmony_ciraw_copy_to_user(void __user *dst, const void *src, unsigned long size) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci return copy_user_generic((__force void *)dst, src, size); 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic __always_inline __must_check 628c2ecf20Sopenharmony_ciunsigned long raw_copy_in_user(void __user *dst, const void __user *src, unsigned long size) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci return copy_user_generic((__force void *)dst, 658c2ecf20Sopenharmony_ci (__force void *)src, size); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ciextern long __copy_user_nocache(void *dst, const void __user *src, 698c2ecf20Sopenharmony_ci unsigned size, int zerorest); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciextern long __copy_user_flushcache(void *dst, const void __user *src, unsigned size); 728c2ecf20Sopenharmony_ciextern void memcpy_page_flushcache(char *to, struct page *page, size_t offset, 738c2ecf20Sopenharmony_ci size_t len); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic inline int 768c2ecf20Sopenharmony_ci__copy_from_user_inatomic_nocache(void *dst, const void __user *src, 778c2ecf20Sopenharmony_ci unsigned size) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci kasan_check_write(dst, size); 808c2ecf20Sopenharmony_ci return __copy_user_nocache(dst, src, size, 0); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline int 848c2ecf20Sopenharmony_ci__copy_from_user_flushcache(void *dst, const void __user *src, unsigned size) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci kasan_check_write(dst, size); 878c2ecf20Sopenharmony_ci return __copy_user_flushcache(dst, src, size); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci#endif /* _ASM_X86_UACCESS_64_H */ 90