194bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney/* 294bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney * This file is subject to the terms and conditions of the GNU General Public 394bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney * License. See the file "COPYING" in the main directory of this archive 494bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney * for more details. 594bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney * 694bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney * Copyright (c) 2010 Cavium Networks, Inc. 794bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney */ 894bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 994bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#include <linux/jump_label.h> 1094bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#include <linux/kernel.h> 1194bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#include <linux/memory.h> 1294bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#include <linux/mutex.h> 1394bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#include <linux/types.h> 1494bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#include <linux/cpu.h> 1594bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 1694bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#include <asm/cacheflush.h> 1794bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#include <asm/inst.h> 1894bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 1994bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#ifdef HAVE_JUMP_LABEL 2094bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 21935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki/* 22935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * Define parameters for the standard MIPS and the microMIPS jump 23935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * instruction encoding respectively: 24935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * 25935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * - the ISA bit of the target, either 0 or 1 respectively, 26935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * 27935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * - the amount the jump target address is shifted right to fit in the 28935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * immediate field of the machine instruction, either 2 or 1, 29935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * 30935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * - the mask determining the size of the jump region relative to the 31935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * delay-slot instruction, either 256MB or 128MB, 32935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * 33935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki * - the jump target alignment, either 4 or 2 bytes. 34935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki */ 35935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki#define J_ISA_BIT IS_ENABLED(CONFIG_CPU_MICROMIPS) 36935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki#define J_RANGE_SHIFT (2 - J_ISA_BIT) 37935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki#define J_RANGE_MASK ((1ul << (26 + J_RANGE_SHIFT)) - 1) 38935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki#define J_ALIGN_MASK ((1ul << J_RANGE_SHIFT) - 1) 3994bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 4094bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daneyvoid arch_jump_label_transform(struct jump_entry *e, 4194bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney enum jump_label_type type) 4294bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney{ 43935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki union mips_instruction *insn_p; 4494bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney union mips_instruction insn; 4594bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 46935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki insn_p = (union mips_instruction *)msk_isa16_mode(e->code); 47935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki 48935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki /* Jump only works within an aligned region its delay slot is in. */ 4999436f7d69045800ffd1d66912f85d37150c7e2bMaciej W. Rozycki BUG_ON((e->target & ~J_RANGE_MASK) != ((e->code + 4) & ~J_RANGE_MASK)); 5094bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 51935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki /* Target must have the right alignment and ISA must be preserved. */ 52935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki BUG_ON((e->target & J_ALIGN_MASK) != J_ISA_BIT); 5394bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 5494bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney if (type == JUMP_LABEL_ENABLE) { 55935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op; 56935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki insn.j_format.target = e->target >> J_RANGE_SHIFT; 5794bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney } else { 5894bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney insn.word = 0; /* nop */ 5994bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney } 6094bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 6194bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney get_online_cpus(); 6294bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney mutex_lock(&text_mutex); 63935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki if (IS_ENABLED(CONFIG_CPU_MICROMIPS)) { 64935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki insn_p->halfword[0] = insn.word >> 16; 65935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki insn_p->halfword[1] = insn.word; 66935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki } else 67935c2dbec4d6d3163ee8e7409996904a734ad89aMaciej W. Rozycki *insn_p = insn; 6894bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 6994bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney flush_icache_range((unsigned long)insn_p, 7094bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney (unsigned long)insn_p + sizeof(*insn_p)); 7194bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 7294bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney mutex_unlock(&text_mutex); 7394bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney put_online_cpus(); 7494bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney} 7594bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney 7694bb0c1ab293c298a8852e4f10c4215bad6daa9bDavid Daney#endif /* HAVE_JUMP_LABEL */ 77