1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2020 Emil Renner Berthing 4 * 5 * Based on arch/arm64/kernel/jump_label.c 6 */ 7 #include <linux/jump_label.h> 8 #include <linux/kernel.h> 9 #include <linux/memory.h> 10 #include <linux/mutex.h> 11 #include <asm/bug.h> 12 #include <asm/patch.h> 13 14 #define RISCV_INSN_NOP 0x00000013U 15 #define RISCV_INSN_JAL 0x0000006fU 16 17 void arch_jump_label_transform(struct jump_entry *entry, 18 enum jump_label_type type) 19 { 20 void *addr = (void *)jump_entry_code(entry); 21 u32 insn; 22 23 if (type == JUMP_LABEL_JMP) { 24 long offset = jump_entry_target(entry) - jump_entry_code(entry); 25 26 if (WARN_ON(offset & 1 || offset < -524288 || offset >= 524288)) 27 return; 28 29 insn = RISCV_INSN_JAL | 30 (((u32)offset & GENMASK(19, 12)) << (12 - 12)) | 31 (((u32)offset & GENMASK(11, 11)) << (20 - 11)) | 32 (((u32)offset & GENMASK(10, 1)) << (21 - 1)) | 33 (((u32)offset & GENMASK(20, 20)) << (31 - 20)); 34 } else { 35 insn = RISCV_INSN_NOP; 36 } 37 38 mutex_lock(&text_mutex); 39 patch_text_nosync(addr, &insn, sizeof(insn)); 40 mutex_unlock(&text_mutex); 41 } 42 43 void arch_jump_label_transform_static(struct jump_entry *entry, 44 enum jump_label_type type) 45 { 46 /* 47 * We use the same instructions in the arch_static_branch and 48 * arch_static_branch_jump inline functions, so there's no 49 * need to patch them up here. 50 * The core will call arch_jump_label_transform when those 51 * instructions need to be replaced. 52 */ 53 } 54