0001
0002 #include <linux/kernel.h>
0003 #include <linux/types.h>
0004 #include <linux/mutex.h>
0005 #include <linux/cpu.h>
0006
0007 #include <linux/jump_label.h>
0008 #include <linux/memory.h>
0009
0010 #include <asm/cacheflush.h>
0011
0012 void arch_jump_label_transform(struct jump_entry *entry,
0013 enum jump_label_type type)
0014 {
0015 u32 *insn = (u32 *) (unsigned long) entry->code;
0016 u32 val;
0017
0018 if (type == JUMP_LABEL_JMP) {
0019 s32 off = (s32)entry->target - (s32)entry->code;
0020 bool use_v9_branch = false;
0021
0022 BUG_ON(off & 3);
0023
0024 #ifdef CONFIG_SPARC64
0025 if (off <= 0xfffff && off >= -0x100000)
0026 use_v9_branch = true;
0027 #endif
0028 if (use_v9_branch) {
0029
0030
0031 val = 0x10680000 | (((u32) off >> 2) & 0x7ffff);
0032 } else {
0033
0034 BUG_ON(off > 0x7fffff);
0035 BUG_ON(off < -0x800000);
0036
0037 val = 0x10800000 | (((u32) off >> 2) & 0x3fffff);
0038 }
0039 } else {
0040 val = 0x01000000;
0041 }
0042
0043 mutex_lock(&text_mutex);
0044 *insn = val;
0045 flushi(insn);
0046 mutex_unlock(&text_mutex);
0047 }