1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2025 Chen Miao 4 * 5 * Based on arch/arm/kernel/jump_label.c 6 */ 7 #include <linux/jump_label.h> 8 #include <linux/kernel.h> 9 #include <linux/memory.h> 10 #include <asm/bug.h> 11 #include <asm/cacheflush.h> 12 #include <asm/text-patching.h> 13 14 bool arch_jump_label_transform_queue(struct jump_entry *entry, 15 enum jump_label_type type) 16 { 17 void *addr = (void *)jump_entry_code(entry); 18 u32 insn; 19 20 if (type == JUMP_LABEL_JMP) { 21 long offset; 22 23 offset = jump_entry_target(entry) - jump_entry_code(entry); 24 /* 25 * The actual maximum range of the l.j instruction's offset is -134,217,728 26 * ~ 134,217,724 (sign 26-bit imm). 27 * For the original jump range, we need to right-shift N by 2 to obtain the 28 * instruction's offset. 29 */ 30 WARN_ON_ONCE(offset < -134217728 || offset > 134217724); 31 32 /* 26bit imm mask */ 33 offset = (offset >> 2) & 0x03ffffff; 34 35 insn = offset; 36 } else { 37 insn = OPENRISC_INSN_NOP; 38 } 39 40 if (early_boot_irqs_disabled) 41 copy_to_kernel_nofault(addr, &insn, sizeof(insn)); 42 else 43 patch_insn_write(addr, insn); 44 45 return true; 46 } 47 48 void arch_jump_label_transform_apply(void) 49 { 50 kick_all_cpus_sync(); 51 } 52