Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9f5ab7b authored by Jason Baron's avatar Jason Baron Committed by Steven Rostedt
Browse files

jump label: x86 support



add x86 support for jump label. I'm keeping this patch separate so its clear
to arch maintainers what was required for x86 support this new feature.
Hopefully, it wouldn't be too painful for other archs.

Signed-off-by: default avatarJason Baron <jbaron@redhat.com>
LKML-Reference: <f838f49f40fbea0254036194be66dc48b598dcea.1284733808.git.jbaron@redhat.com>

[ cleaned up some formatting ]

Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 52159d98
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,7 @@ config X86
	select ANON_INODES
	select ANON_INODES
	select HAVE_ARCH_KMEMCHECK
	select HAVE_ARCH_KMEMCHECK
	select HAVE_USER_RETURN_NOTIFIER
	select HAVE_USER_RETURN_NOTIFIER
	select HAVE_ARCH_JUMP_LABEL if !CC_OPTIMIZE_FOR_SIZE


config INSTRUCTION_DECODER
config INSTRUCTION_DECODER
	def_bool (KPROBES || PERF_EVENTS)
	def_bool (KPROBES || PERF_EVENTS)
+47 −0
Original line number Original line Diff line number Diff line
#ifndef _ASM_X86_JUMP_LABEL_H
#define _ASM_X86_JUMP_LABEL_H

#ifdef __KERNEL__

#include <linux/types.h>
#include <asm/nops.h>

#define JUMP_LABEL_NOP_SIZE 5

# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"

# define JUMP_LABEL(key, label)					\
	do {							\
		asm goto("1:"					\
			JUMP_LABEL_INITIAL_NOP			\
			".pushsection __jump_table,  \"a\" \n\t"\
			_ASM_PTR "1b, %l[" #label "], %c0 \n\t" \
			".popsection \n\t"			\
			: :  "i" (key) :  : label);		\
	} while (0)

#endif /* __KERNEL__ */

#ifdef CONFIG_X86_64

typedef u64 jump_label_t;

struct jump_entry {
	jump_label_t code;
	jump_label_t target;
	jump_label_t key;
};

#else

typedef u32 jump_label_t;

struct jump_entry {
	jump_label_t code;
	jump_label_t target;
	jump_label_t key;
};

#endif

#endif
+1 −1
Original line number Original line Diff line number Diff line
@@ -32,7 +32,7 @@ GCOV_PROFILE_paravirt.o := n
obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(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			+= 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_VISWS)	+= visws_quirks.o
obj-$(CONFIG_X86_32)	+= probe_roms_32.o
obj-$(CONFIG_X86_32)	+= probe_roms_32.o
obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
+50 −0
Original line number Original line Diff line number Diff line
/*
 * jump label x86 support
 *
 * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
 *
 */
#include <linux/jump_label.h>
#include <linux/memory.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/jhash.h>
#include <linux/cpu.h>
#include <asm/kprobes.h>
#include <asm/alternative.h>

#ifdef HAVE_JUMP_LABEL

union jump_code_union {
	char code[JUMP_LABEL_NOP_SIZE];
	struct {
		char jump;
		int offset;
	} __attribute__((packed));
};

void arch_jump_label_transform(struct jump_entry *entry,
			       enum jump_label_type type)
{
	union jump_code_union code;

	if (type == JUMP_LABEL_ENABLE) {
		code.jump = 0xe9;
		code.offset = entry->target -
				(entry->code + JUMP_LABEL_NOP_SIZE);
	} else
		memcpy(&code, ideal_nop5, JUMP_LABEL_NOP_SIZE);
	get_online_cpus();
	mutex_lock(&text_mutex);
	text_poke_smp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
	mutex_unlock(&text_mutex);
	put_online_cpus();
}

void arch_jump_label_text_poke_early(jump_label_t addr)
{
	text_poke_early((void *)addr, ideal_nop5, JUMP_LABEL_NOP_SIZE);
}

#endif
+3 −0
Original line number Original line Diff line number Diff line
@@ -239,6 +239,9 @@ int module_finalize(const Elf_Ehdr *hdr,
		apply_paravirt(pseg, pseg + para->sh_size);
		apply_paravirt(pseg, pseg + para->sh_size);
	}
	}


	/* make jump label nops */
	jump_label_apply_nops(me);

	return module_bug_finalize(hdr, sechdrs, me);
	return module_bug_finalize(hdr, sechdrs, me);
}
}