linux/arch/mips/kernel/jump_label.c
<<
>>
Prefs
   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
  23void 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