0001
0002
0003 #include <linux/jump_label.h>
0004 #include <linux/kernel.h>
0005 #include <linux/memory.h>
0006 #include <linux/mutex.h>
0007 #include <linux/uaccess.h>
0008 #include <asm/cacheflush.h>
0009
0010 #define NOP32_HI 0xc400
0011 #define NOP32_LO 0x4820
0012 #define BSR_LINK 0xe000
0013
0014 void arch_jump_label_transform(struct jump_entry *entry,
0015 enum jump_label_type type)
0016 {
0017 unsigned long addr = jump_entry_code(entry);
0018 u16 insn[2];
0019 int ret = 0;
0020
0021 if (type == JUMP_LABEL_JMP) {
0022 long offset = jump_entry_target(entry) - jump_entry_code(entry);
0023
0024 if (WARN_ON(offset & 1 || offset < -67108864 || offset >= 67108864))
0025 return;
0026
0027 offset = offset >> 1;
0028
0029 insn[0] = BSR_LINK |
0030 ((uint16_t)((unsigned long) offset >> 16) & 0x3ff);
0031 insn[1] = (uint16_t)((unsigned long) offset & 0xffff);
0032 } else {
0033 insn[0] = NOP32_HI;
0034 insn[1] = NOP32_LO;
0035 }
0036
0037 ret = copy_to_kernel_nofault((void *)addr, insn, 4);
0038 WARN_ON(ret);
0039
0040 flush_icache_range(addr, addr + 4);
0041 }
0042
0043 void arch_jump_label_transform_static(struct jump_entry *entry,
0044 enum jump_label_type type)
0045 {
0046
0047
0048
0049
0050
0051
0052
0053 arch_jump_label_transform(entry, type);
0054 }