Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

jump_label: make initial NOP patching the special case

Instead of defaulting to patching NOP opcodes at init time, and leaving
it to the architectures to override this if this is not needed, switch
to a model where doing nothing is the default. This is the common case
by far, as only MIPS requires NOP patching at init time. On all other
architectures, the correct encodings are emitted by the compiler and so
no initial patching is needed.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220615154142.1574619-4-ardb@kernel.org

authored by

Ard Biesheuvel and committed by
Peter Zijlstra
7e6b9db2 fdfd4289

+7 -85
-3
Documentation/staging/static-keys.rst
··· 201 201 * ``void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type)``, 202 202 see: arch/x86/kernel/jump_label.c 203 203 204 - * ``__init_or_module void arch_jump_label_transform_static(struct jump_entry *entry, enum jump_label_type type)``, 205 - see: arch/x86/kernel/jump_label.c 206 - 207 204 * ``struct jump_entry``, 208 205 see: arch/x86/include/asm/jump_label.h 209 206
-13
arch/arc/kernel/jump_label.c
··· 96 96 flush_icache_range(entry->code, entry->code + JUMP_LABEL_NOP_SIZE); 97 97 } 98 98 99 - void arch_jump_label_transform_static(struct jump_entry *entry, 100 - enum jump_label_type type) 101 - { 102 - /* 103 - * We use only one NOP type (1x, 4 byte) in arch_static_branch, so 104 - * there's no need to patch an identical NOP over the top of it here. 105 - * The generic code calls 'arch_jump_label_transform' if the NOP needs 106 - * to be replaced by a branch, so 'arch_jump_label_transform_static' is 107 - * never called with type other than JUMP_LABEL_NOP. 108 - */ 109 - BUG_ON(type != JUMP_LABEL_NOP); 110 - } 111 - 112 99 #ifdef CONFIG_ARC_DBG_JUMP_LABEL 113 100 #define SELFTEST_MSG "ARC: instruction generation self-test: " 114 101
-6
arch/arm/kernel/jump_label.c
··· 27 27 { 28 28 __arch_jump_label_transform(entry, type, false); 29 29 } 30 - 31 - void arch_jump_label_transform_static(struct jump_entry *entry, 32 - enum jump_label_type type) 33 - { 34 - __arch_jump_label_transform(entry, type, true); 35 - }
-11
arch/arm64/kernel/jump_label.c
··· 26 26 27 27 aarch64_insn_patch_text_nosync(addr, insn); 28 28 } 29 - 30 - void arch_jump_label_transform_static(struct jump_entry *entry, 31 - enum jump_label_type type) 32 - { 33 - /* 34 - * We use the architected A64 NOP in arch_static_branch, so there's no 35 - * need to patch an identical A64 NOP over the top of it here. The core 36 - * will call arch_jump_label_transform from a module notifier if the 37 - * NOP needs to be replaced by a branch. 38 - */ 39 - }
+2
arch/mips/include/asm/jump_label.h
··· 8 8 #ifndef _ASM_MIPS_JUMP_LABEL_H 9 9 #define _ASM_MIPS_JUMP_LABEL_H 10 10 11 + #define arch_jump_label_transform_static arch_jump_label_transform 12 + 11 13 #ifndef __ASSEMBLY__ 12 14 13 15 #include <linux/types.h>
-11
arch/parisc/kernel/jump_label.c
··· 42 42 43 43 patch_text(addr, insn); 44 44 } 45 - 46 - void arch_jump_label_transform_static(struct jump_entry *entry, 47 - enum jump_label_type type) 48 - { 49 - /* 50 - * We use the architected NOP in arch_static_branch, so there's no 51 - * need to patch an identical NOP over the top of it here. The core 52 - * will call arch_jump_label_transform from a module notifier if the 53 - * NOP needs to be replaced by a branch. 54 - */ 55 - }
-12
arch/riscv/kernel/jump_label.c
··· 39 39 patch_text_nosync(addr, &insn, sizeof(insn)); 40 40 mutex_unlock(&text_mutex); 41 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 - }
-5
arch/s390/kernel/jump_label.c
··· 80 80 { 81 81 text_poke_sync(); 82 82 } 83 - 84 - void __init_or_module arch_jump_label_transform_static(struct jump_entry *entry, 85 - enum jump_label_type type) 86 - { 87 - }
-13
arch/x86/kernel/jump_label.c
··· 146 146 text_poke_finish(); 147 147 mutex_unlock(&text_mutex); 148 148 } 149 - 150 - static enum { 151 - JL_STATE_START, 152 - JL_STATE_NO_UPDATE, 153 - JL_STATE_UPDATE, 154 - } jlstate __initdata_or_module = JL_STATE_START; 155 - 156 - __init_or_module void arch_jump_label_transform_static(struct jump_entry *entry, 157 - enum jump_label_type type) 158 - { 159 - if (jlstate == JL_STATE_UPDATE) 160 - jump_label_transform(entry, type, 1); 161 - }
-2
include/linux/jump_label.h
··· 220 220 extern void jump_label_unlock(void); 221 221 extern void arch_jump_label_transform(struct jump_entry *entry, 222 222 enum jump_label_type type); 223 - extern void arch_jump_label_transform_static(struct jump_entry *entry, 224 - enum jump_label_type type); 225 223 extern bool arch_jump_label_transform_queue(struct jump_entry *entry, 226 224 enum jump_label_type type); 227 225 extern void arch_jump_label_transform_apply(void);
+5 -9
kernel/jump_label.c
··· 332 332 return 0; 333 333 } 334 334 335 - /* 336 - * Update code which is definitely not currently executing. 337 - * Architectures which need heavyweight synchronization to modify 338 - * running code can override this to make the non-live update case 339 - * cheaper. 340 - */ 341 - void __weak __init_or_module arch_jump_label_transform_static(struct jump_entry *entry, 342 - enum jump_label_type type) 335 + #ifndef arch_jump_label_transform_static 336 + static void arch_jump_label_transform_static(struct jump_entry *entry, 337 + enum jump_label_type type) 343 338 { 344 - arch_jump_label_transform(entry, type); 339 + /* nothing to do on most architectures */ 345 340 } 341 + #endif 346 342 347 343 static inline struct jump_entry *static_key_entries(struct static_key *key) 348 344 {