Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tile/jump_label: add jump label support for TILE-Gx

Add the arch-specific code to support jump label for TILE-Gx. This
code shares NOP instruction with ftrace, so we move it to a common
header file.

Reviewed-by: Chris Metcalf <cmetcalf@ezchip.com>
Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>

authored by

Zhigang Lu and committed by
Chris Metcalf
65a792e8 f419e6f6

+184 -10
+1
arch/tile/Kconfig
··· 143 143 select HAVE_KRETPROBES 144 144 select HAVE_ARCH_KGDB 145 145 select ARCH_SUPPORTS_ATOMIC_RMW 146 + select HAVE_ARCH_JUMP_LABEL 146 147 147 148 config TILEPRO 148 149 def_bool !TILEGX
+59
arch/tile/include/asm/insn.h
··· 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 */
+58
arch/tile/include/asm/jump_label.h
··· 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 */
+1
arch/tile/kernel/Makefile
··· 32 32 obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount_64.o 33 33 obj-$(CONFIG_KPROBES) += kprobes.o 34 34 obj-$(CONFIG_KGDB) += kgdb.o 35 + obj-$(CONFIG_JUMP_LABEL) += jump_label.o 35 36 36 37 obj-y += vdso/
+1 -10
arch/tile/kernel/ftrace.c
··· 20 20 #include <asm/cacheflush.h> 21 21 #include <asm/ftrace.h> 22 22 #include <asm/sections.h> 23 + #include <asm/insn.h> 23 24 24 25 #include <arch/opcode.h> 25 26 26 27 #ifdef CONFIG_DYNAMIC_FTRACE 27 - 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 28 38 29 static int machine_stopped __read_mostly; 39 30
+64
arch/tile/kernel/jump_label.c
··· 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 */