diff options
-rw-r--r-- | arch/tile/Kconfig | 1 | ||||
-rw-r--r-- | arch/tile/include/asm/insn.h | 59 | ||||
-rw-r--r-- | arch/tile/include/asm/jump_label.h | 58 | ||||
-rw-r--r-- | arch/tile/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/tile/kernel/ftrace.c | 11 | ||||
-rw-r--r-- | arch/tile/kernel/jump_label.c | 64 |
6 files changed, 184 insertions, 10 deletions
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 106c21bd7f44..49be476f9feb 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
@@ -143,6 +143,7 @@ config TILEGX | |||
143 | select HAVE_KRETPROBES | 143 | select HAVE_KRETPROBES |
144 | select HAVE_ARCH_KGDB | 144 | select HAVE_ARCH_KGDB |
145 | select ARCH_SUPPORTS_ATOMIC_RMW | 145 | select ARCH_SUPPORTS_ATOMIC_RMW |
146 | select HAVE_ARCH_JUMP_LABEL | ||
146 | 147 | ||
147 | config TILEPRO | 148 | config TILEPRO |
148 | def_bool !TILEGX | 149 | def_bool !TILEGX |
diff --git a/arch/tile/include/asm/insn.h b/arch/tile/include/asm/insn.h new file mode 100644 index 000000000000..f78ba5c16722 --- /dev/null +++ b/arch/tile/include/asm/insn.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | #ifndef __ASM_TILE_INSN_H | ||
15 | #define __ASM_TILE_INSN_H | ||
16 | |||
17 | #include <arch/opcode.h> | ||
18 | |||
19 | static inline tilegx_bundle_bits NOP(void) | ||
20 | { | ||
21 | return create_UnaryOpcodeExtension_X0(FNOP_UNARY_OPCODE_X0) | | ||
22 | create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | | ||
23 | create_Opcode_X0(RRR_0_OPCODE_X0) | | ||
24 | create_UnaryOpcodeExtension_X1(NOP_UNARY_OPCODE_X1) | | ||
25 | create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | | ||
26 | create_Opcode_X1(RRR_0_OPCODE_X1); | ||
27 | } | ||
28 | |||
29 | static inline tilegx_bundle_bits tilegx_gen_branch(unsigned long pc, | ||
30 | unsigned long addr, | ||
31 | bool link) | ||
32 | { | ||
33 | tilegx_bundle_bits opcode_x0, opcode_x1; | ||
34 | long pcrel_by_instr = (addr - pc) >> TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES; | ||
35 | |||
36 | if (link) { | ||
37 | /* opcode: jal addr */ | ||
38 | opcode_x1 = | ||
39 | create_Opcode_X1(JUMP_OPCODE_X1) | | ||
40 | create_JumpOpcodeExtension_X1(JAL_JUMP_OPCODE_X1) | | ||
41 | create_JumpOff_X1(pcrel_by_instr); | ||
42 | } else { | ||
43 | /* opcode: j addr */ | ||
44 | opcode_x1 = | ||
45 | create_Opcode_X1(JUMP_OPCODE_X1) | | ||
46 | create_JumpOpcodeExtension_X1(J_JUMP_OPCODE_X1) | | ||
47 | create_JumpOff_X1(pcrel_by_instr); | ||
48 | } | ||
49 | |||
50 | /* opcode: fnop */ | ||
51 | opcode_x0 = | ||
52 | create_UnaryOpcodeExtension_X0(FNOP_UNARY_OPCODE_X0) | | ||
53 | create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | | ||
54 | create_Opcode_X0(RRR_0_OPCODE_X0); | ||
55 | |||
56 | return opcode_x1 | opcode_x0; | ||
57 | } | ||
58 | |||
59 | #endif /* __ASM_TILE_INSN_H */ | ||
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h new file mode 100644 index 000000000000..cde7573f397b --- /dev/null +++ b/arch/tile/include/asm/jump_label.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef _ASM_TILE_JUMP_LABEL_H | ||
16 | #define _ASM_TILE_JUMP_LABEL_H | ||
17 | |||
18 | #include <arch/opcode.h> | ||
19 | |||
20 | #define JUMP_LABEL_NOP_SIZE TILE_BUNDLE_SIZE_IN_BYTES | ||
21 | |||
22 | static __always_inline bool arch_static_branch(struct static_key *key, | ||
23 | bool branch) | ||
24 | { | ||
25 | asm_volatile_goto("1:\n\t" | ||
26 | "nop" "\n\t" | ||
27 | ".pushsection __jump_table, \"aw\"\n\t" | ||
28 | ".quad 1b, %l[l_yes], %0 + %1 \n\t" | ||
29 | ".popsection\n\t" | ||
30 | : : "i" (key), "i" (branch) : : l_yes); | ||
31 | return false; | ||
32 | l_yes: | ||
33 | return true; | ||
34 | } | ||
35 | |||
36 | static __always_inline bool arch_static_branch_jump(struct static_key *key, | ||
37 | bool branch) | ||
38 | { | ||
39 | asm_volatile_goto("1:\n\t" | ||
40 | "j %l[l_yes]" "\n\t" | ||
41 | ".pushsection __jump_table, \"aw\"\n\t" | ||
42 | ".quad 1b, %l[l_yes], %0 + %1 \n\t" | ||
43 | ".popsection\n\t" | ||
44 | : : "i" (key), "i" (branch) : : l_yes); | ||
45 | return false; | ||
46 | l_yes: | ||
47 | return true; | ||
48 | } | ||
49 | |||
50 | typedef u64 jump_label_t; | ||
51 | |||
52 | struct jump_entry { | ||
53 | jump_label_t code; | ||
54 | jump_label_t target; | ||
55 | jump_label_t key; | ||
56 | }; | ||
57 | |||
58 | #endif /* _ASM_TILE_JUMP_LABEL_H */ | ||
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile index 21f77bf68c69..09936d0bcb42 100644 --- a/arch/tile/kernel/Makefile +++ b/arch/tile/kernel/Makefile | |||
@@ -32,5 +32,6 @@ obj-$(CONFIG_TILE_HVGLUE_TRACE) += hvglue_trace.o | |||
32 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount_64.o | 32 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount_64.o |
33 | obj-$(CONFIG_KPROBES) += kprobes.o | 33 | obj-$(CONFIG_KPROBES) += kprobes.o |
34 | obj-$(CONFIG_KGDB) += kgdb.o | 34 | obj-$(CONFIG_KGDB) += kgdb.o |
35 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o | ||
35 | 36 | ||
36 | obj-y += vdso/ | 37 | obj-y += vdso/ |
diff --git a/arch/tile/kernel/ftrace.c b/arch/tile/kernel/ftrace.c index 4180ccdf9cd0..4a572088b270 100644 --- a/arch/tile/kernel/ftrace.c +++ b/arch/tile/kernel/ftrace.c | |||
@@ -20,21 +20,12 @@ | |||
20 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
21 | #include <asm/ftrace.h> | 21 | #include <asm/ftrace.h> |
22 | #include <asm/sections.h> | 22 | #include <asm/sections.h> |
23 | #include <asm/insn.h> | ||
23 | 24 | ||
24 | #include <arch/opcode.h> | 25 | #include <arch/opcode.h> |
25 | 26 | ||
26 | #ifdef CONFIG_DYNAMIC_FTRACE | 27 | #ifdef CONFIG_DYNAMIC_FTRACE |
27 | 28 | ||
28 | static inline tilegx_bundle_bits NOP(void) | ||
29 | { | ||
30 | return create_UnaryOpcodeExtension_X0(FNOP_UNARY_OPCODE_X0) | | ||
31 | create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | | ||
32 | create_Opcode_X0(RRR_0_OPCODE_X0) | | ||
33 | create_UnaryOpcodeExtension_X1(NOP_UNARY_OPCODE_X1) | | ||
34 | create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | | ||
35 | create_Opcode_X1(RRR_0_OPCODE_X1); | ||
36 | } | ||
37 | |||
38 | static int machine_stopped __read_mostly; | 29 | static int machine_stopped __read_mostly; |
39 | 30 | ||
40 | int ftrace_arch_code_modify_prepare(void) | 31 | int ftrace_arch_code_modify_prepare(void) |
diff --git a/arch/tile/kernel/jump_label.c b/arch/tile/kernel/jump_label.c new file mode 100644 index 000000000000..07802d586988 --- /dev/null +++ b/arch/tile/kernel/jump_label.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * jump label TILE-Gx support | ||
15 | */ | ||
16 | |||
17 | #include <linux/jump_label.h> | ||
18 | #include <linux/memory.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/cpu.h> | ||
22 | |||
23 | #include <asm/cacheflush.h> | ||
24 | #include <asm/insn.h> | ||
25 | |||
26 | #ifdef HAVE_JUMP_LABEL | ||
27 | |||
28 | static void __jump_label_transform(struct jump_entry *e, | ||
29 | enum jump_label_type type) | ||
30 | { | ||
31 | tilegx_bundle_bits opcode; | ||
32 | /* Operate on writable kernel text mapping. */ | ||
33 | unsigned long pc_wr = ktext_writable_addr(e->code); | ||
34 | |||
35 | if (type == JUMP_LABEL_JMP) | ||
36 | opcode = tilegx_gen_branch(e->code, e->target, false); | ||
37 | else | ||
38 | opcode = NOP(); | ||
39 | |||
40 | *(tilegx_bundle_bits *)pc_wr = opcode; | ||
41 | /* Make sure that above mem writes were issued towards the memory. */ | ||
42 | smp_wmb(); | ||
43 | } | ||
44 | |||
45 | void arch_jump_label_transform(struct jump_entry *e, | ||
46 | enum jump_label_type type) | ||
47 | { | ||
48 | get_online_cpus(); | ||
49 | mutex_lock(&text_mutex); | ||
50 | |||
51 | __jump_label_transform(e, type); | ||
52 | flush_icache_range(e->code, e->code + sizeof(tilegx_bundle_bits)); | ||
53 | |||
54 | mutex_unlock(&text_mutex); | ||
55 | put_online_cpus(); | ||
56 | } | ||
57 | |||
58 | __init_or_module void arch_jump_label_transform_static(struct jump_entry *e, | ||
59 | enum jump_label_type type) | ||
60 | { | ||
61 | __jump_label_transform(e, type); | ||
62 | } | ||
63 | |||
64 | #endif /* HAVE_JUMP_LABEL */ | ||