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/cacheflush.h> 13 #include <asm/patch.h> 14 15 #define RISCV_INSN_NOP 0x00000013U 16 #define RISCV_INSN_JAL 0x0000006fU 17 18 bool arch_jump_label_transform_queue(struct jump_entry *entry, 19 enum jump_label_type type) 20 { 21 void *addr = (void *)jump_entry_code(entry); 22 u32 insn; 23 24 if (type == JUMP_LABEL_JMP) { 25 long offset = jump_entry_target(entry) - jump_entry_code(entry); 26 27 if (WARN_ON(offset & 1 || offset < -524288 || offset >= 524288)) 28 return true; 29 30 insn = RISCV_INSN_JAL | 31 (((u32)offset & GENMASK(19, 12)) << (12 - 12)) | 32 (((u32)offset & GENMASK(11, 11)) << (20 - 11)) | 33 (((u32)offset & GENMASK(10, 1)) << (21 - 1)) | 34 (((u32)offset & GENMASK(20, 20)) << (31 - 20)); 35 } else { 36 insn = RISCV_INSN_NOP; 37 } 38 39 mutex_lock(&text_mutex); 40 patch_insn_write(addr, &insn, sizeof(insn)); 41 mutex_unlock(&text_mutex); 42 43 return true; 44 } 45 46 void arch_jump_label_transform_apply(void) 47 { 48 flush_icache_all(); 49 } 50