Commit | Line | Data |
---|---|---|
94bb0c1a DD |
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 */ |