Commit 5de7bcaa authored by Linus Torvalds's avatar Linus Torvalds
Browse files

x86: rename and clean up __copy_from_user_inatomic_nocache()



Similarly to the previous commit, this renames the somewhat confusingly
named function.  But in this case, it was at least less confusing: the
__copy_from_user_inatomic_nocache is indeed copying from user memory,
and it is indeed ok to be used in an atomic context, so it will not warn
about it.

But the previous commit also removed the NTB mis-use of the
__copy_from_user_inatomic_nocache() function, and as a result every
call-site is now _actually_ doing a real user copy.  That means that we
can now do the proper user pointer verification too.

End result: add proper address checking, remove the double underscores,
and change the "nocache" to "nontemporal" to more accurately describe
what this x86-only function actually does.  It might be worth noting
that only the target is non-temporal: the actual user accesses are
normal memory accesses.

Also worth noting is that non-x86 targets (and on older 32-bit x86 CPU's
before XMM2 in the Pentium III) we end up just falling back on a regular
user copy, so nothing can actually depend on the non-temporal semantics,
but that has always been true.

Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d187a86d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -507,7 +507,7 @@ extern struct movsl_mask {
} ____cacheline_aligned_in_smp movsl_mask;
#endif

#define ARCH_HAS_NOCACHE_UACCESS 1
#define ARCH_HAS_NONTEMPORAL_UACCESS 1

/*
 * The "unsafe" user accesses aren't really "unsafe", but the naming
+1 −7
Original line number Diff line number Diff line
@@ -26,13 +26,7 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long n)
	return __copy_user_ll(to, (__force const void *)from, n);
}

static __always_inline unsigned long
__copy_from_user_inatomic_nocache(void *to, const void __user *from,
				  unsigned long n)
{
       return __copy_from_user_ll_nocache_nozero(to, from, n);
}

unsigned long __must_check copy_from_user_inatomic_nontemporal(void *, const void __user *, unsigned long n);
unsigned long __must_check clear_user(void __user *mem, unsigned long len);
unsigned long __must_check __clear_user(void __user *mem, unsigned long len);

+2 −1
Original line number Diff line number Diff line
@@ -152,11 +152,12 @@ extern size_t copy_to_nontemporal(void *dst, const void *src, size_t size);
extern long __copy_user_flushcache(void *dst, const void __user *src, unsigned size);

static inline int
__copy_from_user_inatomic_nocache(void *dst, const void __user *src,
copy_from_user_inatomic_nontemporal(void *dst, const void __user *src,
				  unsigned size)
{
	long ret;
	kasan_check_write(dst, size);
	src = mask_user_address(src);
	stac();
	ret = copy_to_nontemporal(dst, (__force const void *)src, size);
	clac();
+5 −4
Original line number Diff line number Diff line
@@ -322,10 +322,11 @@ unsigned long __copy_user_ll(void *to, const void *from, unsigned long n)
}
EXPORT_SYMBOL(__copy_user_ll);

unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
unsigned long copy_from_user_inatomic_nontemporal(void *to, const void __user *from,
					unsigned long n)
{
	__uaccess_begin_nospec();
	if (!user_access_begin(from, n))
		return n;
#ifdef CONFIG_X86_INTEL_USERCOPY
	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
		n = __copy_user_intel_nocache(to, from, n);
@@ -334,7 +335,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
#else
	__copy_user(to, from, n);
#endif
	__uaccess_end();
	user_access_end();
	return n;
}
EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
EXPORT_SYMBOL(copy_from_user_inatomic_nontemporal);
+1 −1
Original line number Diff line number Diff line
@@ -520,7 +520,7 @@ ggtt_write(struct io_mapping *mapping,

	/* We can use the cpu mem copy function because this is X86. */
	vaddr = io_mapping_map_atomic_wc(mapping, base);
	unwritten = __copy_from_user_inatomic_nocache((void __force *)vaddr + offset,
	unwritten = copy_from_user_inatomic_nontemporal((void __force *)vaddr + offset,
						      user_data, length);
	io_mapping_unmap_atomic(vaddr);
	if (unwritten) {
Loading