From: Ingo Molnar <mingo@elte.hu>
To: Jason Baron <jbaron@redhat.com>
Cc: linux-kernel@vger.kernel.org, mathieu.desnoyers@polymtl.ca,
tglx@linutronix.de, rostedt@goodmis.org, ak@suse.de,
roland@redhat.com, rth@redhat.com, mhiramat@redhat.com
Subject: Re: [PATCH 2/4] jump label - base patch
Date: Thu, 1 Oct 2009 13:36:08 +0200 [thread overview]
Message-ID: <20091001113608.GB2962@elte.hu> (raw)
In-Reply-To: <98c4c0b11300ac3b7de3acb2096f8f34184b1457.1253831946.git.jbaron@redhat.com>
* Jason Baron <jbaron@redhat.com> wrote:
> Base jump label patch which creates macros for jump patching. This
> feature is dependent on gcc version >= 4.5
>
> Signed-off-by: Jason Baron <jbaron@redhat.com>
> ---
> arch/x86/include/asm/jump_label.h | 27 +++++++++++
> arch/x86/kernel/Makefile | 2 +-
> arch/x86/kernel/jump_label.c | 92 +++++++++++++++++++++++++++++++++++++
> include/asm-generic/vmlinux.lds.h | 11 ++++
> include/linux/jump_label.h | 53 +++++++++++++++++++++
> 5 files changed, 184 insertions(+), 1 deletions(-)
> create mode 100644 arch/x86/include/asm/jump_label.h
> create mode 100644 arch/x86/kernel/jump_label.c
> create mode 100644 include/linux/jump_label.h
>
> diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
> new file mode 100644
> index 0000000..21a7b79
> --- /dev/null
> +++ b/arch/x86/include/asm/jump_label.h
> @@ -0,0 +1,27 @@
> +#ifndef _ASM_X86_JUMP_LABEL_H
> +#define _ASM_X86_JUMP_LABEL_H
> +
> +#include <asm/nops.h>
> +
> +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
> +#define __HAVE_ARCH_JUMP_LABEL
> +#endif
that should be:
> +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
Also, please use:
#if ...
# define
#endif
whitespace constructs to keep them more readable.
> +
> +#ifdef __HAVE_ARCH_JUMP_LABEL
> +
> +#define JUMP_LABEL(tag, label, cond) \
(these spaces should be tabs)
> + do { \
> + static const char __jlstrtab_##tag[] \
> + __used __attribute__((section("__jump_strings"))) = #tag; \
> + asm goto ("1:" \
> + "jmp %l[" #label "] \n\t" \
> + ".pushsection __jump_table, \"a\" \n\t" \
> + _ASM_PTR "1b, %l[" #label "], %c0, 0 \n\t" \
> + ".popsection \n\t" \
> + : : "i" (__jlstrtab_##tag) : : label); \
> + } while (0)
> +
> +#endif
> +
> +#endif
> +
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index 91d4189..b6b3e42 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -32,7 +32,7 @@ GCOV_PROFILE_paravirt.o := n
> obj-y := process_$(BITS).o signal.o entry_$(BITS).o
> obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
> obj-y += time.o ioport.o ldt.o dumpstack.o
> -obj-y += setup.o x86_init.o i8259.o irqinit.o
> +obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o
> obj-$(CONFIG_X86_VISWS) += visws_quirks.o
> obj-$(CONFIG_X86_32) += probe_roms_32.o
> obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
> diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
> new file mode 100644
> index 0000000..207947d
> --- /dev/null
> +++ b/arch/x86/kernel/jump_label.c
> @@ -0,0 +1,92 @@
> +#include <linux/jump_label.h>
> +#include <linux/memory.h>
> +#include <linux/kprobes.h>
> +#include <linux/uaccess.h>
> +
> +#ifdef __HAVE_ARCH_JUMP_LABEL
> +
> +extern struct jump_entry __start___jump_table[];
> +extern struct jump_entry __stop___jump_table[];
externs should go into .h's.
> +
> +DEFINE_MUTEX(jump_label_mutex);
Shouldnt this code rely on text_mutex, which is our generic 'patch
kernel text' exclusion primitive?
> +
> +union jump_code_union {
> + char code[RELATIVEJUMP_SIZE];
> + struct {
> + char jump;
> + int offset;
> + } __attribute__((packed));
> +};
> +
> +void jump_label_transform(struct jump_entry *entry, enum jump_label_type type)
> +{
> + union jump_code_union code;
> + long jump_length;
> + unsigned char opcode;
> + size_t opcode_length;
> +
> + if (entry->type == UNKOWN_JUMP) {
> + if (probe_kernel_read(&opcode, (void *)entry->code, 1))
> + BUG();
a BUG() is not nice. It results fewer decodable bug reports than a
WARN_ON_ONCE().
> +
> + if (opcode == 0xe9)
> + entry->type = LONG_JUMP;
> + else if (opcode == 0xeb)
> + entry->type = SHORT_JUMP;
> + else
> + BUG();
ditto.
> + }
> +
> + if (entry->type == LONG_JUMP)
> + opcode_length = 5;
> + else
> + opcode_length = 2;
> +
> + if (type == JUMP_LABEL_ENABLE) {
> + if (entry->type == SHORT_JUMP) {
> + code.code[0] = 0xeb;
> + code.code[1] = 0;
> + } else {
> + code.code[0] = 0xe9;
> + code.offset = 0;
> + }
> + } else {
> + jump_length = entry->target - (entry->code + opcode_length);
> + if (entry->type == SHORT_JUMP) {
> + if ((jump_length > 127 || jump_length < -128)) {
> + BUG();
> + }
WARN_ON_ONCE() again.
> + code.code[0] = 0xeb;
> + code.code[1] = (char)jump_length;
> + } else {
> + if ((jump_length > INT_MAX || jump_length < INT_MIN)) {
> + BUG();
> + }
ditto.
> + code.code[0] = 0xe9;
> + code.offset = jump_length;
> + }
> + }
> +
> + mutex_lock(&text_mutex);
> + text_poke_fixup((void *)entry->code, &code,
> + opcode_length, (void *)entry->code + opcode_length);
> + mutex_unlock(&text_mutex);
Note that here we take the text_mutex anyway. Can drop jump_label_mutex
and take the text_mutex wider?
> +}
> +
> +int jump_label_update(const char *name, enum jump_label_type type)
> +{
> + struct jump_entry *iter;
> +
> + mutex_lock(&jump_label_mutex);
> + for (iter = __start___jump_table; iter < __stop___jump_table; iter++) {
how big can this table become, realistically, long term?
> + if (!strcmp(name, iter->name)) {
> + if (!(system_state == SYSTEM_RUNNING &&
> + (init_kernel_text(iter->code))))
> + jump_label_transform(iter, type);
> + }
> + }
> + mutex_unlock(&jump_label_mutex);
> + return 0;
> +}
We always seem to return 0 - should be void?
> +
> +#endif
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index e7eae37..d2f38e2 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -213,6 +213,7 @@
> *(__vermagic) /* Kernel version magic */ \
> *(__markers_strings) /* Markers: strings */ \
> *(__tracepoints_strings)/* Tracepoints: strings */ \
> + *(__jump_strings)/* Jump: strings */ \
> } \
inserted line does not follow existing style carefully enough.
> \
> .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
> @@ -220,6 +221,8 @@
> } \
> \
> BUG_TABLE \
> + JUMP_TABLE \
> + \
> \
> /* PCI quirks */ \
> .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
> @@ -564,6 +567,14 @@
> #define BUG_TABLE
> #endif
>
> +#define JUMP_TABLE \
> + . = ALIGN(8); \
> + __jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) { \
> + VMLINUX_SYMBOL(__start___jump_table) = .; \
> + *(__jump_table) \
> + VMLINUX_SYMBOL(__stop___jump_table) = .; \
> + }
ditto.
> +
> #ifdef CONFIG_PM_TRACE
> #define TRACEDATA \
> . = ALIGN(4); \
> diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
> new file mode 100644
> index 0000000..eb0a4ef
> --- /dev/null
> +++ b/include/linux/jump_label.h
> @@ -0,0 +1,53 @@
> +#ifndef _LINUX_JUMP_LABEL_H
> +#define _LINUX_JUMP_LABEL_H
> +
> +#include <asm/jump_label.h>
> +
> +struct jump_entry {
> + unsigned long code;
> + unsigned long target;
> + char *name;
> + unsigned long type;
> +};
please use new structure definition alignments like in
include/linux/perf_event.h.
> +
> +enum jump_label_type {
> + JUMP_LABEL_ENABLE,
> + JUMP_LABEL_DISABLE
> +};
so 0 is enable and 1 is disable?
> +
> +enum jump_label_instruction {
> + UNKOWN_JUMP,
> + SHORT_JUMP,
> + LONG_JUMP
> +};
> +
> +#ifdef __HAVE_ARCH_JUMP_LABEL
> +
> +extern int jump_label_update(const char *name, enum jump_label_type type);
> +
> +#define enable_jump_label(name) \
> + jump_label_update(name, JUMP_LABEL_ENABLE);
> +
> +#define disable_jump_label(name) \
> + jump_label_update(name, JUMP_LABEL_DISABLE);
> +
> +#else
> +
> +#define JUMP_LABEL(tag, label, cond) \
> + if (likely(!cond)) \
> + goto label;
> +
> +static inline int enable_jump_label(const char *name, enum jump_label_type type)
> +{
> + return 0;
> +}
> +
> +static inline int disable_jump_label(const char *name,
> + enum jump_label_type type)
just keep the prototype in a single line. (and ignore checkpatch for
that one)
> +{
> + return 0;
> +}
> +
> +#endif
> +
> +#endif
> --
> 1.6.2.5
Ingo
next prev parent reply other threads:[~2009-10-01 11:36 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-09-24 23:17 [PATCH 0/4] jump label patches Jason Baron
2009-09-24 23:17 ` [PATCH 1/4] jump label - make init_kernel_text() global Jason Baron
2009-10-01 11:20 ` Ingo Molnar
2009-10-01 12:58 ` Mathieu Desnoyers
2009-10-01 20:39 ` Jason Baron
2009-10-03 10:43 ` Ingo Molnar
2009-10-03 12:39 ` Mathieu Desnoyers
2009-10-07 1:54 ` Steven Rostedt
2009-10-07 2:32 ` Mathieu Desnoyers
2009-10-07 3:10 ` Masami Hiramatsu
2009-10-07 3:23 ` Mathieu Desnoyers
2009-10-07 3:29 ` Mathieu Desnoyers
2009-10-07 12:56 ` Steven Rostedt
2009-10-07 13:35 ` Mathieu Desnoyers
2009-09-24 23:17 ` [PATCH 2/4] jump label - base patch Jason Baron
2009-09-25 0:49 ` Roland McGrath
2009-09-26 10:21 ` Steven Rostedt
2009-10-01 11:36 ` Ingo Molnar [this message]
2009-09-24 23:17 ` [PATCH 3/4] jump label - add module support Jason Baron
2009-09-24 23:18 ` [PATCH 4/4] jump label - tracepoint implementation Jason Baron
2009-10-06 5:39 ` [PATCH 0/4] jump label patches Roland McGrath
2009-10-06 14:07 ` Jason Baron
2009-10-06 23:24 ` Richard Henderson
2009-10-07 0:14 ` Roland McGrath
2009-10-07 15:35 ` Richard Henderson
2009-10-06 6:04 ` Roland McGrath
2009-10-06 14:09 ` Steven Rostedt
2009-10-06 14:13 ` Masami Hiramatsu
2009-10-06 14:30 ` Mathieu Desnoyers
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=20091001113608.GB2962@elte.hu \
--to=mingo@elte.hu \
--cc=ak@suse.de \
--cc=jbaron@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@polymtl.ca \
--cc=mhiramat@redhat.com \
--cc=roland@redhat.com \
--cc=rostedt@goodmis.org \
--cc=rth@redhat.com \
--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 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).