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