^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2010 Cavium Networks, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/jump_label.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/inst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Define parameters for the standard MIPS and the microMIPS jump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * instruction encoding respectively:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * - the ISA bit of the target, either 0 or 1 respectively,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * - the amount the jump target address is shifted right to fit in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * immediate field of the machine instruction, either 2 or 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * - the mask determining the size of the jump region relative to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * delay-slot instruction, either 256MB or 128MB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * - the jump target alignment, either 4 or 2 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define J_ISA_BIT IS_ENABLED(CONFIG_CPU_MICROMIPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define J_RANGE_SHIFT (2 - J_ISA_BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define J_RANGE_MASK ((1ul << (26 + J_RANGE_SHIFT)) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define J_ALIGN_MASK ((1ul << J_RANGE_SHIFT) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) void arch_jump_label_transform(struct jump_entry *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) enum jump_label_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) union mips_instruction *insn_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) union mips_instruction insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) insn_p = (union mips_instruction *)msk_isa16_mode(e->code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Target must have the right alignment and ISA must be preserved. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) BUG_ON((e->target & J_ALIGN_MASK) != J_ISA_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (type == JUMP_LABEL_JMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!IS_ENABLED(CONFIG_CPU_MICROMIPS) && MIPS_ISA_REV >= 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) offset = e->target - ((unsigned long)insn_p + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) offset >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * The branch offset must fit in the instruction's 26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * bit field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) WARN_ON((offset >= BIT(25)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) (offset < -(long)BIT(25)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) insn.j_format.opcode = bc6_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) insn.j_format.target = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Jump only works within an aligned region its delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * slot is in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) WARN_ON((e->target & ~J_RANGE_MASK) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ((e->code + 4) & ~J_RANGE_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) insn.j_format.target = e->target >> J_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) insn.word = 0; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) mutex_lock(&text_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (IS_ENABLED(CONFIG_CPU_MICROMIPS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) insn_p->halfword[0] = insn.word >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) insn_p->halfword[1] = insn.word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *insn_p = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) flush_icache_range((unsigned long)insn_p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) (unsigned long)insn_p + sizeof(*insn_p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) mutex_unlock(&text_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }