From: Frederic Weisbecker <frederic@kernel.org>
To: Peter Zijlstra <peterz@infradead.org>
Cc: LKML <linux-kernel@vger.kernel.org>, Mel Gorman <mgorman@suse.de>,
Michal Hocko <mhocko@kernel.org>,
Frederic Weisbecker <frederic@kernel.org>,
Thomas Gleixner <tglx@linutronix.de>,
"Paul E . McKenney" <paulmck@kernel.org>,
Ingo Molnar <mingo@redhat.com>, Michal Hocko <mhocko@suse.com>
Subject: [RFC PATCH 1/7] static_call/x86: Add __static_call_returnl0()
Date: Tue, 10 Nov 2020 01:56:03 +0100 [thread overview]
Message-ID: <20201110005609.40989-2-frederic@kernel.org> (raw)
In-Reply-To: <20201110005609.40989-1-frederic@kernel.org>
From: Peter Zijlstra <peterz@infradead.org>
Provide a stub function that return 0 and wire up the static call site
patching to replace the CALL with a single 5 byte instruction that
clears %RAX, the return value register.
The function can be cast to any function pointer type that has a
single %RAX return (including pointers). Also provide a version that
returns an int for convenience. We are clearing the entire %RAX register
in any case, whether the return value is 32 or 64 bits, since %RAX is
always a scratch register anyway.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Paul E. McKenney <paulmck@kernel.org>
[fweisbec: s/disp16/data16, integrate into text_get_insn(), elaborate
comment on the resulting insn, emulate on int3 trap, provide validation,
uninline __static_call_return0() for HAVE_STATIC_CALL]
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
---
arch/x86/include/asm/text-patching.h | 26 +++++++++++++++++++++++++-
arch/x86/kernel/alternative.c | 5 +++++
arch/x86/kernel/static_call.c | 10 ++++++++--
include/linux/static_call.h | 9 +++++++++
kernel/static_call.c | 10 ++++++++++
5 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
index b7421780e4e9..1250f440d1be 100644
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -65,6 +65,9 @@ extern void text_poke_finish(void);
#define JMP8_INSN_SIZE 2
#define JMP8_INSN_OPCODE 0xEB
+#define XOR5RAX_INSN_SIZE 5
+#define XOR5RAX_INSN_OPCODE 0x31
+
#define DISP32_SIZE 4
static __always_inline int text_opcode_size(u8 opcode)
@@ -80,6 +83,7 @@ static __always_inline int text_opcode_size(u8 opcode)
__CASE(CALL);
__CASE(JMP32);
__CASE(JMP8);
+ __CASE(XOR5RAX);
}
#undef __CASE
@@ -99,8 +103,21 @@ static __always_inline
void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
{
static union text_poke_insn insn; /* per instance */
- int size = text_opcode_size(opcode);
+ int size;
+ if (opcode == XOR5RAX_INSN_OPCODE) {
+ /*
+ * data16 data16 xorq %rax, %rax - a single 5 byte instruction that clears %rax
+ * The REX.W cancels the effect of any data16.
+ */
+ static union text_poke_insn xor5rax = {
+ .text = { 0x66, 0x66, 0x48, 0x31, 0xc0 },
+ };
+
+ return &xor5rax.text;
+ }
+
+ size = text_opcode_size(opcode);
insn.opcode = opcode;
if (size > 1) {
@@ -165,6 +182,13 @@ void int3_emulate_ret(struct pt_regs *regs)
unsigned long ip = int3_emulate_pop(regs);
int3_emulate_jmp(regs, ip);
}
+
+static __always_inline
+void int3_emulate_xor5rax(struct pt_regs *regs)
+{
+ regs->ax = 0;
+}
+
#endif /* !CONFIG_UML_X86 */
#endif /* _ASM_X86_TEXT_PATCHING_H */
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 2400ad62f330..37592f576a10 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -1125,6 +1125,10 @@ noinstr int poke_int3_handler(struct pt_regs *regs)
int3_emulate_jmp(regs, (long)ip + tp->rel32);
break;
+ case XOR5RAX_INSN_OPCODE:
+ int3_emulate_xor5rax(regs);
+ break;
+
default:
BUG();
}
@@ -1291,6 +1295,7 @@ static void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
switch (tp->opcode) {
case INT3_INSN_OPCODE:
case RET_INSN_OPCODE:
+ case XOR5RAX_INSN_OPCODE:
break;
case CALL_INSN_OPCODE:
diff --git a/arch/x86/kernel/static_call.c b/arch/x86/kernel/static_call.c
index ca9a380d9c0b..3a36eaf3dd1f 100644
--- a/arch/x86/kernel/static_call.c
+++ b/arch/x86/kernel/static_call.c
@@ -18,7 +18,11 @@ static void __ref __static_call_transform(void *insn, enum insn_type type, void
switch (type) {
case CALL:
- code = text_gen_insn(CALL_INSN_OPCODE, insn, func);
+ if (func == &__static_call_return0 ||
+ func == &__static_call_returnl0)
+ code = text_gen_insn(XOR5RAX_INSN_OPCODE, insn, func);
+ else
+ code = text_gen_insn(CALL_INSN_OPCODE, insn, func);
break;
case NOP:
@@ -54,7 +58,9 @@ static void __static_call_validate(void *insn, bool tail)
return;
} else {
if (opcode == CALL_INSN_OPCODE ||
- !memcmp(insn, ideal_nops[NOP_ATOMIC5], 5))
+ !memcmp(insn, ideal_nops[NOP_ATOMIC5], 5) ||
+ !memcmp(insn, text_gen_insn(XOR5RAX_INSN_OPCODE, NULL, NULL),
+ XOR5RAX_INSN_SIZE))
return;
}
diff --git a/include/linux/static_call.h b/include/linux/static_call.h
index 695da4c9b338..055544793430 100644
--- a/include/linux/static_call.h
+++ b/include/linux/static_call.h
@@ -136,6 +136,9 @@ extern void arch_static_call_transform(void *site, void *tramp, void *func, bool
#ifdef CONFIG_HAVE_STATIC_CALL_INLINE
+extern int __static_call_return0(void);
+extern long __static_call_returnl0(void);
+
extern int __init static_call_init(void);
struct static_call_mod {
@@ -187,6 +190,9 @@ extern int static_call_text_reserved(void *start, void *end);
#elif defined(CONFIG_HAVE_STATIC_CALL)
+extern int __static_call_return0(void);
+extern long __static_call_returnl0(void);
+
static inline int static_call_init(void) { return 0; }
struct static_call_key {
@@ -234,6 +240,9 @@ static inline int static_call_text_reserved(void *start, void *end)
#else /* Generic implementation */
+static inline int __static_call_return0(void) { return 0; }
+static inline long __static_call_returnl0(void) { return 0; }
+
static inline int static_call_init(void) { return 0; }
struct static_call_key {
diff --git a/kernel/static_call.c b/kernel/static_call.c
index 84565c2a41b8..3cb371e71be6 100644
--- a/kernel/static_call.c
+++ b/kernel/static_call.c
@@ -438,6 +438,16 @@ int __init static_call_init(void)
}
early_initcall(static_call_init);
+int __static_call_return0(void)
+{
+ return 0;
+}
+
+long __static_call_returnl0(void)
+{
+ return 0;
+}
+
#ifdef CONFIG_STATIC_CALL_SELFTEST
static int func_a(int x)
--
2.25.1
next prev parent reply other threads:[~2020-11-10 0:56 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-10 0:56 [RFC PATCH 0/7] preempt: Tune preemption flavour on boot v3 Frederic Weisbecker
2020-11-10 0:56 ` Frederic Weisbecker [this message]
2020-11-10 9:55 ` [RFC PATCH 1/7] static_call/x86: Add __static_call_returnl0() Peter Zijlstra
2020-11-10 10:13 ` Peter Zijlstra
2020-11-10 13:42 ` Frederic Weisbecker
2020-11-10 13:53 ` Peter Zijlstra
2020-11-10 13:24 ` Frederic Weisbecker
2020-11-10 10:06 ` Peter Zijlstra
2020-11-10 0:56 ` [RFC PATCH 2/7] static_call: Pull some static_call declarations to the type headers Frederic Weisbecker
2020-11-10 0:56 ` [RFC PATCH 3/7] preempt: Introduce CONFIG_PREEMPT_DYNAMIC Frederic Weisbecker
2020-11-10 0:56 ` [RFC PATCH 4/7] preempt/dynamic: Provide cond_resched() and might_resched() static calls Frederic Weisbecker
2020-11-10 10:39 ` Peter Zijlstra
2020-11-10 10:48 ` Peter Zijlstra
2021-01-18 13:58 ` Frederic Weisbecker
2020-11-10 0:56 ` [RFC PATCH 5/7] preempt/dynamic: Provide preempt_schedule[_notrace]() " Frederic Weisbecker
2020-11-10 0:56 ` [RFC PATCH 6/7] preempt/dynamic: Provide irqentry_exit_cond_resched() static call Frederic Weisbecker
2020-11-10 10:32 ` Peter Zijlstra
2020-11-10 13:45 ` Frederic Weisbecker
2020-11-10 0:56 ` [RFC PATCH 7/7] preempt/dynamic: Support dynamic preempt with preempt= boot option Frederic Weisbecker
2020-11-11 1:25 ` kernel test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201110005609.40989-2-frederic@kernel.org \
--to=frederic@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mhocko@kernel.org \
--cc=mhocko@suse.com \
--cc=mingo@redhat.com \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.