linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiri Olsa <jolsa@redhat.com>
To: jbaron@redhat.com, rostedt@goodmis.org, mingo@elte.hu
Cc: linux-kernel@vger.kernel.org, Jiri Olsa <jolsa@redhat.com>
Subject: [PATCHv2 1/2] jump_label,x86: use text_poke_smp_batch for entries update
Date: Wed,  4 May 2011 11:41:42 +0200	[thread overview]
Message-ID: <1304502103-3228-2-git-send-email-jolsa@redhat.com> (raw)
In-Reply-To: <1304502103-3228-1-git-send-email-jolsa@redhat.com>

Changing the jump label update code to use batch processing
for x86 architectures. 

Currently each jump label update calls text_poke_smp for each
jump label key entry. Thus one key update ends up calling stop
machine multiple times.

This patch is using text_poke_smp_batch, which is called for
all the key's entries. Thus ensuring the stop machine is called
only once per jump_label key.

Added jump_label_update_end function which is paired with
the key's entries update.

The jump_label_update_end calls arch_jump_label_update_end
(with generic weak definition) which is overloaded by x86
arch and makes the batch update of all the entries queued
by arch_jump_label_transform function.

Added dynamic array/handling for queueing jump_label entries
with the same key.

Tested this on x86 and s390 archs.


Signed-off-by: Jiri Olsa <jolsa@redhat.com>
---
 arch/x86/kernel/jump_label.c |  128 +++++++++++++++++++++++++++++++++++++++---
 include/linux/jump_label.h   |    1 +
 kernel/jump_label.c          |   16 +++++-
 3 files changed, 134 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
index 3fee346..7a4dd32 100644
--- a/arch/x86/kernel/jump_label.c
+++ b/arch/x86/kernel/jump_label.c
@@ -11,6 +11,7 @@
 #include <linux/list.h>
 #include <linux/jhash.h>
 #include <linux/cpu.h>
+#include <linux/slab.h>
 #include <asm/kprobes.h>
 #include <asm/alternative.h>
 
@@ -24,24 +25,133 @@ union jump_code_union {
 	} __attribute__((packed));
 };
 
-void arch_jump_label_transform(struct jump_entry *entry,
-			       enum jump_label_type type)
+struct text_poke_buffer {
+	u8 code[JUMP_LABEL_NOP_SIZE];
+};
+
+#define POKE_ALLOC_CNT 30
+
+static struct text_poke_param  *poke_pars;
+static struct text_poke_buffer *poke_bufs;
+static int poke_cnt, poke_size;
+
+static void poke_setup(struct text_poke_param *param, u8 *buf,
+		       int enable,
+		       struct jump_entry *entry)
 {
-	union jump_code_union code;
+	union jump_code_union *code = (union jump_code_union *) buf;
 
-	if (type == JUMP_LABEL_ENABLE) {
-		code.jump = 0xe9;
-		code.offset = entry->target -
-				(entry->code + JUMP_LABEL_NOP_SIZE);
+	if (enable == JUMP_LABEL_ENABLE) {
+		code->jump = 0xe9;
+		code->offset = entry->target -
+			       (entry->code + JUMP_LABEL_NOP_SIZE);
 	} else
-		memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
+		memcpy(code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
+
+	param->addr = (void *) entry->code;
+	param->opcode = code;
+	param->len = JUMP_LABEL_NOP_SIZE;
+}
+
+static int poke_alloc(void)
+{
+	struct text_poke_param  *pars;
+	struct text_poke_buffer *bufs;
+
+	if (poke_cnt % POKE_ALLOC_CNT)
+		return 0;
+
+	poke_size += POKE_ALLOC_CNT;
+
+	pars = krealloc(poke_pars, poke_size * sizeof(*pars),
+			GFP_KERNEL);
+	if (!pars)
+		return -ENOMEM;
+
+	bufs = krealloc(poke_bufs, poke_size * sizeof(*bufs),
+			GFP_KERNEL);
+	if (!bufs) {
+		kfree(pars);
+		return -ENOMEM;
+	}
+
+	poke_pars = pars;
+	poke_bufs = bufs;
+	return 0;
+}
+
+static void poke_free(void)
+{
+	kfree(poke_pars);
+	kfree(poke_bufs);
+
+	poke_cnt = poke_size = 0;
+	poke_pars = NULL;
+	poke_bufs = NULL;
+}
+
+static void poke_process(struct text_poke_param *par, int cnt)
+{
 	get_online_cpus();
 	mutex_lock(&text_mutex);
-	text_poke_smp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+	text_poke_smp_batch(par, cnt);
 	mutex_unlock(&text_mutex);
 	put_online_cpus();
 }
 
+static void poke_end(void)
+{
+	if (!poke_cnt)
+		return;
+
+	poke_process(poke_pars, poke_cnt);
+	poke_free();
+}
+
+static void process_entry(struct jump_entry *entry,
+			     enum jump_label_type enable)
+{
+	struct text_poke_param  par;
+	struct text_poke_buffer buf;
+
+	poke_setup(&par, buf.code, enable, entry);
+	poke_process(&par, 1);
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+			       enum jump_label_type enable)
+{
+	struct text_poke_param  *par;
+	struct text_poke_buffer *buf;
+
+	if (poke_alloc()) {
+		/*
+		 * Allocation failed, let's finish what we
+		 * gather so far and process this entry
+		 * separatelly. Next call we try the allocation
+		 * again.
+		 */
+		poke_end();
+		process_entry(entry, enable);
+		return;
+	}
+
+	par = &poke_pars[poke_cnt];
+	buf = &poke_bufs[poke_cnt];
+
+	poke_setup(par, buf->code, enable, entry);
+	poke_cnt++;
+}
+
+/*
+ * Called after arch_jump_label_transform is called for
+ * all entries of a single key.
+ */
+void arch_jump_label_update_end(void)
+{
+	poke_end();
+}
+
 void arch_jump_label_text_poke_early(jump_label_t addr)
 {
 	text_poke_early((void *)addr, ideal_nops[NOP_ATOMIC5],
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 83e745f..e7a8fa3 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -46,6 +46,7 @@ extern void jump_label_unlock(void);
 extern void arch_jump_label_transform(struct jump_entry *entry,
 				 enum jump_label_type type);
 extern void arch_jump_label_text_poke_early(jump_label_t addr);
+extern void arch_jump_label_update_end(void);
 extern int jump_label_text_reserved(void *start, void *end);
 extern void jump_label_inc(struct jump_label_key *key);
 extern void jump_label_dec(struct jump_label_key *key);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 74d1c09..6657a37 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -125,6 +125,15 @@ void __weak arch_jump_label_text_poke_early(jump_label_t addr)
 {
 }
 
+void __weak arch_jump_label_update_end(void)
+{
+}
+
+void jump_label_update_end(void)
+{
+	arch_jump_label_update_end();
+}
+
 static __init int jump_label_init(void)
 {
 	struct jump_entry *iter_start = __start___jump_table;
@@ -244,10 +253,11 @@ static int jump_label_add_module(struct module *mod)
 		jlm->next = key->next;
 		key->next = jlm;
 
-		if (jump_label_enabled(key))
+		if (jump_label_enabled(key)) {
 			__jump_label_update(key, iter, JUMP_LABEL_ENABLE);
+			jump_label_update_end();
+		}
 	}
-
 	return 0;
 }
 
@@ -376,6 +386,8 @@ static void jump_label_update(struct jump_label_key *key, int enable)
 #ifdef CONFIG_MODULES
 	__jump_label_mod_update(key, enable);
 #endif
+
+	jump_label_update_end();
 }
 
 #endif
-- 
1.7.1


  reply	other threads:[~2011-05-04  9:41 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-28 20:52 [PATCH] jump_label,x86: use text_poke_smp_batch for entries update Jiri Olsa
2011-04-29 15:15 ` Jason Baron
2011-04-29 15:37   ` Jiri Olsa
2011-05-04  9:41 ` [PATCHv2 0/2] jump_label,x86: make batch update of jump_label entries Jiri Olsa
2011-05-04  9:41   ` Jiri Olsa [this message]
2011-05-04  9:41   ` [PATCHv2 2/2] jump_label,x86: using static arrays before dynamic allocation is needed Jiri Olsa
2011-05-09 18:38   ` [PATCHv3] jump_label,x86: make batch update of jump_label entries Jiri Olsa
2011-05-09 19:27     ` Jason Baron
2011-05-23 16:45       ` Jiri Olsa
2011-05-23 20:53         ` Steven Rostedt

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=1304502103-3228-2-git-send-email-jolsa@redhat.com \
    --to=jolsa@redhat.com \
    --cc=jbaron@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=rostedt@goodmis.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;
as well as URLs for NNTP newsgroup(s).