mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: x86@kernel.org
Cc: peterz@infradead.org, linux-kernel@vger.kernel.org,
	rostedt@goodmis.org, mhiramat@kernel.org, bristot@redhat.com,
	jbaron@akamai.com, torvalds@linux-foundation.org,
	tglx@linutronix.de, mingo@kernel.org, namit@vmware.com,
	hpa@zytor.com, luto@kernel.org, ard.biesheuvel@linaro.org,
	jpoimboe@redhat.com
Subject: [RESEND][PATCH v3 16/17] static_call: Allow early init
Date: Tue, 24 Mar 2020 14:56:19 +0100	[thread overview]
Message-ID: <20200324142246.247811691@infradead.org> (raw)
In-Reply-To: <20200324135603.483964896@infradead.org>

In order to use static_call() to wire up x86_pmu, we need to
initialize earlier; copy some of the tricks from jump_label to enable
this.

Primarily we overload key->next to store a sites pointer when there
are no modules, this avoids having to use kmalloc() to initialize the
sites and allows us to run much earlier.

(arguably, this is much much earlier than needed for perf, but it
might allow other uses.)

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 arch/x86/kernel/setup.c       |    2 +
 arch/x86/kernel/static_call.c |    8 +++++-
 include/linux/static_call.h   |   15 ++++++++++--
 kernel/static_call.c          |   52 +++++++++++++++++++++++++++++++++++++++---
 4 files changed, 71 insertions(+), 6 deletions(-)

--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -18,6 +18,7 @@
 #include <linux/sfi.h>
 #include <linux/tboot.h>
 #include <linux/usb/xhci-dbgp.h>
+#include <linux/static_call.h>
 
 #include <uapi/linux/mount.h>
 
@@ -841,6 +842,7 @@ void __init setup_arch(char **cmdline_p)
 	early_cpu_init();
 	arch_init_ideal_nops();
 	jump_label_init();
+	static_call_init();
 	early_ioremap_init();
 
 	setup_olpc_ofw_pgd();
--- a/arch/x86/kernel/static_call.c
+++ b/arch/x86/kernel/static_call.c
@@ -11,7 +11,7 @@ enum insn_type {
 	ret = 3,  /* tramp / site cond-tail-call */
 };
 
-static void __static_call_transform(void *insn, enum insn_type type, void *func)
+static void __ref __static_call_transform(void *insn, enum insn_type type, void *func)
 {
 	int size = CALL_INSN_SIZE;
 	const void *code;
@@ -33,11 +33,17 @@ static void __static_call_transform(void
 		code = text_gen_insn(RET_INSN_OPCODE, insn, func);
 		size = RET_INSN_SIZE;
 		break;
+
+	default: /* GCC is a moron -- it figures @code can be uninitialized below */
+		BUG();
 	}
 
 	if (memcmp(insn, code, size) == 0)
 		return;
 
+	if (unlikely(system_state == SYSTEM_BOOTING))
+		return text_poke_early(insn, code, size);
+
 	text_poke_bp(insn, code, size, NULL);
 }
 
--- a/include/linux/static_call.h
+++ b/include/linux/static_call.h
@@ -84,6 +84,8 @@ extern void arch_static_call_transform(v
 
 #ifdef CONFIG_HAVE_STATIC_CALL_INLINE
 
+extern void __init static_call_init(void);
+
 struct static_call_mod {
 	struct static_call_mod *next;
 	struct module *mod; /* for vmlinux, mod == NULL */
@@ -92,7 +94,12 @@ struct static_call_mod {
 
 struct static_call_key {
 	void *func;
-	struct static_call_mod *next;
+	union {
+		/* bit0 => 0 - next, 1 - sites */
+		unsigned long type;
+		struct static_call_mod *next;
+		struct static_call_site *sites;
+	};
 };
 
 extern void __static_call_update(struct static_call_key *key, void *tramp, void *func);
@@ -103,7 +110,7 @@ extern int static_call_text_reserved(voi
 	DECLARE_STATIC_CALL(name, _func);				\
 	struct static_call_key STATIC_CALL_NAME(name) = {		\
 		.func = _func,						\
-		.next = NULL,						\
+		.type = 1,						\
 	};								\
 	__ADDRESSABLE(STATIC_CALL_NAME(name));				\
 	ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
@@ -121,6 +128,8 @@ extern int static_call_text_reserved(voi
 
 #elif defined(CONFIG_HAVE_STATIC_CALL)
 
+static inline void static_call_init(void) { }
+
 struct static_call_key {
 	void *func;
 };
@@ -154,6 +163,8 @@ static inline int static_call_text_reser
 
 #else /* Generic implementation */
 
+static inline void static_call_init(void) { }
+
 struct static_call_key {
 	void *func;
 };
--- a/kernel/static_call.c
+++ b/kernel/static_call.c
@@ -94,10 +94,31 @@ static inline void static_call_sort_entr
 	     static_call_site_cmp, static_call_site_swap);
 }
 
+static inline bool static_call_key_has_next(struct static_call_key *key)
+{
+	return !(key->type & 1);
+}
+
+static inline struct static_call_mod *static_call_key_next(struct static_call_key *key)
+{
+	if (static_call_key_has_next(key))
+		return key->next->next;
+
+	return NULL;
+}
+
+static inline struct static_call_site *static_call_key_sites(struct static_call_key *key)
+{
+	if (static_call_key_has_next(key))
+		return key->next->sites;
+
+	return (struct static_call_site *)(key->type & ~1);
+}
+
 void __static_call_update(struct static_call_key *key, void *tramp, void *func)
 {
 	struct static_call_site *site, *stop;
-	struct static_call_mod *site_mod;
+	struct static_call_mod *site_mod, first;
 
 	cpus_read_lock();
 	static_call_lock();
@@ -116,7 +137,13 @@ void __static_call_update(struct static_
 	if (WARN_ON_ONCE(!static_call_initialized))
 		goto done;
 
-	for (site_mod = key->next; site_mod; site_mod = site_mod->next) {
+	first = (struct static_call_mod){
+		.next = static_call_key_next(key),
+		.mod = NULL,
+		.sites = static_call_key_sites(key),
+	};
+
+	for (site_mod = &first; site_mod; site_mod = site_mod->next) {
 		if (!site_mod->sites) {
 			/*
 			 * This can happen if the static call key is defined in
@@ -191,16 +218,35 @@ static int __static_call_init(struct mod
 		if (key != prev_key) {
 			prev_key = key;
 
+			if (!mod) {
+				key->sites = site;
+				key->type |= 1;
+				goto do_transform;
+			}
+
 			site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL);
 			if (!site_mod)
 				return -ENOMEM;
 
+			if (!static_call_key_has_next(key)) {
+				site_mod->mod = NULL;
+				site_mod->next = NULL;
+				site_mod->sites = static_call_key_sites(key);
+
+				key->next = site_mod;
+
+				site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL);
+				if (!site_mod)
+					return -ENOMEM;
+			}
+
 			site_mod->mod = mod;
 			site_mod->sites = site;
 			site_mod->next = key->next;
 			key->next = site_mod;
 		}
 
+do_transform:
 		arch_static_call_transform(site_addr, NULL, key->func,
 				static_call_is_tail(site));
 	}
@@ -343,7 +389,7 @@ int static_call_text_reserved(void *star
 	return ret;
 }
 
-static void __init static_call_init(void)
+void __init static_call_init(void)
 {
 	int ret;
 



  parent reply	other threads:[~2020-03-24 14:24 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-24 13:56 [RESEND][PATCH v3 00/17] Add static_call() Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 01/17] notifier: Fix broken error handling pattern Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 02/17] module: Fix up module_notifier return values Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 03/17] module: Properly propagate MODULE_STATE_COMING failure Peter Zijlstra
2020-03-25 17:35   ` Jessica Yu
2020-03-27  4:51     ` Josh Poimboeuf
2020-03-27 12:04     ` Miroslav Benes
2020-03-24 13:56 ` [RESEND][PATCH v3 04/17] jump_label,module: Fix module lifetime for __jump_label_mod_text_reserved Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 05/17] compiler.h: Make __ADDRESSABLE() symbol truly unique Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 06/17] static_call: Add basic static call infrastructure Peter Zijlstra
2020-03-26 16:42   ` Nadav Amit
2020-03-26 17:01     ` Peter Zijlstra
2020-03-26 18:09       ` Nadav Amit
2020-03-26 18:28         ` Peter Zijlstra
2020-03-26 19:02           ` Nadav Amit
2020-03-26 19:13             ` Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 07/17] static_call: Add inline " Peter Zijlstra
2020-03-26 15:54   ` Borislav Petkov
2020-03-24 13:56 ` [RESEND][PATCH v3 08/17] static_call: Avoid kprobes on inline static_call()s Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 09/17] x86/static_call: Add out-of-line static call implementation Peter Zijlstra
2020-03-26 14:57   ` Borislav Petkov
2020-04-06  1:08   ` Fangrui Song
2020-04-06 11:04     ` Peter Zijlstra
2020-04-06 18:29       ` Nick Desaulniers
2020-03-24 13:56 ` [RESEND][PATCH v3 10/17] x86/static_call: Add inline static call implementation for x86-64 Peter Zijlstra
2020-03-26 15:17   ` Borislav Petkov
2020-03-26 16:06   ` Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 11/17] static_call: Simple self-test Peter Zijlstra
2020-03-26 15:44   ` Borislav Petkov
2020-03-26 17:08     ` Peter Zijlstra
2020-03-26 17:33       ` Borislav Petkov
2020-03-24 13:56 ` [RESEND][PATCH v3 12/17] tracepoint: Optimize using static_call() Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 13/17] x86/alternatives: Teach text_poke_bp() to emulate RET Peter Zijlstra
2020-03-24 13:56 ` [RESEND][PATCH v3 14/17] static_call: Add static_cond_call() Peter Zijlstra
2020-03-24 16:14   ` Linus Torvalds
2020-03-24 16:22     ` Andy Lutomirski
2020-03-24 16:33       ` Linus Torvalds
2020-03-24 17:03         ` Peter Zijlstra
2020-03-25 18:13           ` Peter Zijlstra
2020-03-25 18:26             ` Linus Torvalds
2020-03-25 19:34         ` hpa
2020-03-25 20:52           ` Linus Torvalds
2020-03-25 22:07             ` Peter Zijlstra
2020-03-24 16:54     ` Peter Zijlstra
2020-03-26 23:37   ` Rasmus Villemoes
2020-03-27 10:08     ` Peter Zijlstra
2020-03-27 13:25       ` Rasmus Villemoes
2020-03-24 13:56 ` [RESEND][PATCH v3 15/17] static_call: Handle tail-calls Peter Zijlstra
2020-03-24 13:56 ` Peter Zijlstra [this message]
2020-03-24 13:56 ` [RESEND][PATCH v3 17/17] x86/perf, static_call: Optimize x86_pmu methods Peter Zijlstra
2020-03-25 17:49 ` [RESEND][PATCH v3 00/17] Add static_call() Peter Zijlstra

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=20200324142246.247811691@infradead.org \
    --to=peterz@infradead.org \
    --cc=ard.biesheuvel@linaro.org \
    --cc=bristot@redhat.com \
    --cc=hpa@zytor.com \
    --cc=jbaron@akamai.com \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@kernel.org \
    --cc=namit@vmware.com \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=x86@kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome