aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2010-12-28 16:26:23 -0500
committerRalf Baechle <ralf@linux-mips.org>2011-01-18 13:30:24 -0500
commit94bb0c1ab293c298a8852e4f10c4215bad6daa9b (patch)
treee4e7dfa18bf2ffd832a97d7ab67863b1b363c6fe /arch/mips/kernel
parent8d662c8d34a05e8e47deaa9e22fe770dc557c2d3 (diff)
MIPS: jump label: Add MIPS support.
In order not to be left behind, we add jump label support for MIPS. Tested on 64-bit big endian (Octeon), and 32-bit little endian (malta/qemu). Signed-off-by: David Daney <ddaney@caviumnetworks.com> To: linux-mips@linux-mips.org Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Jason Baron <jbaron@redhat.com> Patchwork: https://patchwork.linux-mips.org/patch/1923/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/jump_label.c54
-rw-r--r--arch/mips/kernel/module.c5
3 files changed, 61 insertions, 0 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 39773979ca6d..cedee2bcbd18 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -107,4 +107,6 @@ obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/
107 107
108obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o 108obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
109 109
110obj-$(CONFIG_JUMP_LABEL) += jump_label.o
111
110CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS) 112CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
diff --git a/arch/mips/kernel/jump_label.c b/arch/mips/kernel/jump_label.c
new file mode 100644
index 000000000000..6001610cfe55
--- /dev/null
+++ b/arch/mips/kernel/jump_label.c
@@ -0,0 +1,54 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (c) 2010 Cavium Networks, Inc.
7 */
8
9#include <linux/jump_label.h>
10#include <linux/kernel.h>
11#include <linux/memory.h>
12#include <linux/mutex.h>
13#include <linux/types.h>
14#include <linux/cpu.h>
15
16#include <asm/cacheflush.h>
17#include <asm/inst.h>
18
19#ifdef HAVE_JUMP_LABEL
20
21#define J_RANGE_MASK ((1ul << 28) - 1)
22
23void arch_jump_label_transform(struct jump_entry *e,
24 enum jump_label_type type)
25{
26 union mips_instruction insn;
27 union mips_instruction *insn_p =
28 (union mips_instruction *)(unsigned long)e->code;
29
30 /* Jump only works within a 256MB aligned region. */
31 BUG_ON((e->target & ~J_RANGE_MASK) != (e->code & ~J_RANGE_MASK));
32
33 /* Target must have 4 byte alignment. */
34 BUG_ON((e->target & 3) != 0);
35
36 if (type == JUMP_LABEL_ENABLE) {
37 insn.j_format.opcode = j_op;
38 insn.j_format.target = (e->target & J_RANGE_MASK) >> 2;
39 } else {
40 insn.word = 0; /* nop */
41 }
42
43 get_online_cpus();
44 mutex_lock(&text_mutex);
45 *insn_p = insn;
46
47 flush_icache_range((unsigned long)insn_p,
48 (unsigned long)insn_p + sizeof(*insn_p));
49
50 mutex_unlock(&text_mutex);
51 put_online_cpus();
52}
53
54#endif /* HAVE_JUMP_LABEL */
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index d87a72e9fac7..dd940b701963 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -30,6 +30,8 @@
30#include <linux/kernel.h> 30#include <linux/kernel.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <linux/jump_label.h>
34
33#include <asm/pgtable.h> /* MODULE_START */ 35#include <asm/pgtable.h> /* MODULE_START */
34 36
35struct mips_hi16 { 37struct mips_hi16 {
@@ -382,6 +384,9 @@ int module_finalize(const Elf_Ehdr *hdr,
382 const Elf_Shdr *s; 384 const Elf_Shdr *s;
383 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 385 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
384 386
387 /* Make jump label nops. */
388 jump_label_apply_nops(me);
389
385 INIT_LIST_HEAD(&me->arch.dbe_list); 390 INIT_LIST_HEAD(&me->arch.dbe_list);
386 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 391 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
387 if (strcmp("__dbe_table", secstrings + s->sh_name) != 0) 392 if (strcmp("__dbe_table", secstrings + s->sh_name) != 0)