1*4e8bb4baSGuo Ren // SPDX-License-Identifier: GPL-2.0-only 2*4e8bb4baSGuo Ren 3*4e8bb4baSGuo Ren #include <linux/jump_label.h> 4*4e8bb4baSGuo Ren #include <linux/kernel.h> 5*4e8bb4baSGuo Ren #include <linux/memory.h> 6*4e8bb4baSGuo Ren #include <linux/mutex.h> 7*4e8bb4baSGuo Ren #include <linux/uaccess.h> 8*4e8bb4baSGuo Ren #include <asm/cacheflush.h> 9*4e8bb4baSGuo Ren 10*4e8bb4baSGuo Ren #define NOP32_HI 0xc400 11*4e8bb4baSGuo Ren #define NOP32_LO 0x4820 12*4e8bb4baSGuo Ren #define BSR_LINK 0xe000 13*4e8bb4baSGuo Ren arch_jump_label_transform(struct jump_entry * entry,enum jump_label_type type)14*4e8bb4baSGuo Renvoid arch_jump_label_transform(struct jump_entry *entry, 15*4e8bb4baSGuo Ren enum jump_label_type type) 16*4e8bb4baSGuo Ren { 17*4e8bb4baSGuo Ren unsigned long addr = jump_entry_code(entry); 18*4e8bb4baSGuo Ren u16 insn[2]; 19*4e8bb4baSGuo Ren int ret = 0; 20*4e8bb4baSGuo Ren 21*4e8bb4baSGuo Ren if (type == JUMP_LABEL_JMP) { 22*4e8bb4baSGuo Ren long offset = jump_entry_target(entry) - jump_entry_code(entry); 23*4e8bb4baSGuo Ren 24*4e8bb4baSGuo Ren if (WARN_ON(offset & 1 || offset < -67108864 || offset >= 67108864)) 25*4e8bb4baSGuo Ren return; 26*4e8bb4baSGuo Ren 27*4e8bb4baSGuo Ren offset = offset >> 1; 28*4e8bb4baSGuo Ren 29*4e8bb4baSGuo Ren insn[0] = BSR_LINK | 30*4e8bb4baSGuo Ren ((uint16_t)((unsigned long) offset >> 16) & 0x3ff); 31*4e8bb4baSGuo Ren insn[1] = (uint16_t)((unsigned long) offset & 0xffff); 32*4e8bb4baSGuo Ren } else { 33*4e8bb4baSGuo Ren insn[0] = NOP32_HI; 34*4e8bb4baSGuo Ren insn[1] = NOP32_LO; 35*4e8bb4baSGuo Ren } 36*4e8bb4baSGuo Ren 37*4e8bb4baSGuo Ren ret = copy_to_kernel_nofault((void *)addr, insn, 4); 38*4e8bb4baSGuo Ren WARN_ON(ret); 39*4e8bb4baSGuo Ren 40*4e8bb4baSGuo Ren flush_icache_range(addr, addr + 4); 41*4e8bb4baSGuo Ren } 42*4e8bb4baSGuo Ren arch_jump_label_transform_static(struct jump_entry * entry,enum jump_label_type type)43*4e8bb4baSGuo Renvoid arch_jump_label_transform_static(struct jump_entry *entry, 44*4e8bb4baSGuo Ren enum jump_label_type type) 45*4e8bb4baSGuo Ren { 46*4e8bb4baSGuo Ren /* 47*4e8bb4baSGuo Ren * We use the same instructions in the arch_static_branch and 48*4e8bb4baSGuo Ren * arch_static_branch_jump inline functions, so there's no 49*4e8bb4baSGuo Ren * need to patch them up here. 50*4e8bb4baSGuo Ren * The core will call arch_jump_label_transform when those 51*4e8bb4baSGuo Ren * instructions need to be replaced. 52*4e8bb4baSGuo Ren */ 53*4e8bb4baSGuo Ren arch_jump_label_transform(entry, type); 54*4e8bb4baSGuo Ren } 55