x86-64: Modify copy_user_generic() alternatives mechanism
In order to avoid unnecessary chains of branches, rather than implementing copy_user_generic() as a function consisting of just a single (possibly patched) branch, instead properly deal with patching call instructions in the alternative instructions framework, and move the patching into the callers. As a follow-on, one could also introduce something like __EXPORT_SYMBOL_ALT() to avoid patching call sites in modules. Signed-off-by: Jan Beulich <jbeulich@novell.com> Cc: Nick Piggin <npiggin@suse.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> LKML-Reference: <4B2BB8180200007800026AE7@vpn.id2.novell.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
/*
|
||||
@@ -16,7 +18,24 @@
|
||||
|
||||
/* Handles exceptions in both to and from, but doesn't do access_ok */
|
||||
__must_check unsigned long
|
||||
copy_user_generic(void *to, const void *from, unsigned len);
|
||||
copy_user_generic_string(void *to, const void *from, unsigned len);
|
||||
__must_check unsigned long
|
||||
copy_user_generic_unrolled(void *to, const void *from, unsigned len);
|
||||
|
||||
static __always_inline __must_check unsigned long
|
||||
copy_user_generic(void *to, const void *from, unsigned len)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
alternative_call(copy_user_generic_unrolled,
|
||||
copy_user_generic_string,
|
||||
X86_FEATURE_REP_GOOD,
|
||||
ASM_OUTPUT2("=a" (ret), "=D" (to), "=S" (from),
|
||||
"=d" (len)),
|
||||
"1" (to), "2" (from), "3" (len)
|
||||
: "memory", "rcx", "r8", "r9", "r10", "r11");
|
||||
return ret;
|
||||
}
|
||||
|
||||
__must_check unsigned long
|
||||
_copy_to_user(void __user *to, const void *from, unsigned len);
|
||||
|
Reference in New Issue
Block a user