Skip to content

Commit

Permalink
jump label: Base patch for jump label
Browse files Browse the repository at this point in the history
base patch to implement 'jump labeling'. Based on a new 'asm goto' inline
assembly gcc mechanism, we can now branch to labels from an 'asm goto'
statment. This allows us to create a 'no-op' fastpath, which can subsequently
be patched with a jump to the slowpath code. This is useful for code which
might be rarely used, but which we'd like to be able to call, if needed.
Tracepoints are the current usecase that these are being implemented for.

Acked-by: David S. Miller <[email protected]>
Signed-off-by: Jason Baron <[email protected]>
LKML-Reference: <ee8b3595967989fdaf84e698dc7447d315ce972a.1284733808.git.jbaron@redhat.com>

[ cleaned up some formating ]

Signed-off-by: Steven Rostedt <[email protected]>
  • Loading branch information
jibaron authored and rostedt committed Sep 22, 2010
1 parent fa6f2cc commit bf5438f
Show file tree
Hide file tree
Showing 12 changed files with 442 additions and 4 deletions.
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,11 @@ KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
# conserve stack if available
KBUILD_CFLAGS += $(call cc-option,-fconserve-stack)

# check for 'asm goto'
ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
endif

# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
# But warn user when we do so
warn-assign = \
Expand Down
3 changes: 3 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,7 @@ config HAVE_PERF_EVENTS_NMI
subsystem. Also has support for calculating CPU cycle events
to determine how many clock cycles in a given period.

config HAVE_ARCH_JUMP_LABEL
bool

source "kernel/gcov/Kconfig"
3 changes: 2 additions & 1 deletion arch/x86/include/asm/alternative.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/stringify.h>
#include <linux/jump_label.h>
#include <asm/asm.h>

/*
Expand Down Expand Up @@ -182,7 +183,7 @@ extern void *text_poke_early(void *addr, const void *opcode, size_t len);
extern void *text_poke(void *addr, const void *opcode, size_t len);
extern void *text_poke_smp(void *addr, const void *opcode, size_t len);

#if defined(CONFIG_DYNAMIC_FTRACE)
#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
#define IDEAL_NOP_SIZE_5 5
extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
extern void arch_init_ideal_nop5(void);
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/alternative.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len)
return addr;
}

#if defined(CONFIG_DYNAMIC_FTRACE)
#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)

unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];

Expand Down
10 changes: 10 additions & 0 deletions include/asm-generic/vmlinux.lds.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@
\
BUG_TABLE \
\
JUMP_TABLE \
\
/* PCI quirks */ \
.pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
Expand Down Expand Up @@ -563,6 +565,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) = .; \
}

#ifdef CONFIG_PM_TRACE
#define TRACEDATA \
. = ALIGN(4); \
Expand Down
58 changes: 58 additions & 0 deletions include/linux/jump_label.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef _LINUX_JUMP_LABEL_H
#define _LINUX_JUMP_LABEL_H

#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_HAVE_ARCH_JUMP_LABEL)
# include <asm/jump_label.h>
# define HAVE_JUMP_LABEL
#endif

enum jump_label_type {
JUMP_LABEL_ENABLE,
JUMP_LABEL_DISABLE
};

struct module;

#ifdef HAVE_JUMP_LABEL

extern struct jump_entry __start___jump_table[];
extern struct jump_entry __stop___jump_table[];

extern void arch_jump_label_transform(struct jump_entry *entry,
enum jump_label_type type);
extern void jump_label_update(unsigned long key, enum jump_label_type type);
extern void jump_label_apply_nops(struct module *mod);
extern void arch_jump_label_text_poke_early(jump_label_t addr);

#define enable_jump_label(key) \
jump_label_update((unsigned long)key, JUMP_LABEL_ENABLE);

#define disable_jump_label(key) \
jump_label_update((unsigned long)key, JUMP_LABEL_DISABLE);

#else

#define JUMP_LABEL(key, label) \
do { \
if (unlikely(*key)) \
goto label; \
} while (0)

#define enable_jump_label(cond_var) \
do { \
*(cond_var) = 1; \
} while (0)

#define disable_jump_label(cond_var) \
do { \
*(cond_var) = 0; \
} while (0)

static inline int jump_label_apply_nops(struct module *mod)
{
return 0;
}

#endif

#endif
5 changes: 4 additions & 1 deletion include/linux/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,10 @@ struct module
struct tracepoint *tracepoints;
unsigned int num_tracepoints;
#endif

#ifdef HAVE_JUMP_LABEL
struct jump_entry *jump_entries;
unsigned int num_jump_entries;
#endif
#ifdef CONFIG_TRACING
const char **trace_bprintk_fmt_start;
unsigned int num_trace_bprintk_fmt;
Expand Down
2 changes: 1 addition & 1 deletion kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \
async.o range.o
async.o range.o jump_label.o
obj-$(CONFIG_HAVE_EARLY_RES) += early_res.o
obj-y += groups.o

Expand Down
Loading

0 comments on commit bf5438f

Please sign in to comment.