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 23 void 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 */ 55