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

arm64: alternative: patch alternatives in the vDSO

Make it possible to use alternatives in the vDSO, so that better
implementations can be used if possible.

Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Link: https://lore.kernel.org/r/20220830104833.34636-3-joey.gouly@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Joey Gouly and committed by
Catalin Marinas
4e3bca8f b3adc384

+38 -3
+3
arch/arm64/include/asm/vdso.h
··· 26 26 (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ 27 27 }) 28 28 29 + extern char vdso_start[], vdso_end[]; 30 + extern char vdso32_start[], vdso32_end[]; 31 + 29 32 #endif /* !__ASSEMBLY__ */ 30 33 31 34 #endif /* __ASM_VDSO_H */
+28
arch/arm64/kernel/alternative.c
··· 10 10 11 11 #include <linux/init.h> 12 12 #include <linux/cpu.h> 13 + #include <linux/elf.h> 13 14 #include <asm/cacheflush.h> 14 15 #include <asm/alternative.h> 15 16 #include <asm/cpufeature.h> 16 17 #include <asm/insn.h> 18 + #include <asm/module.h> 17 19 #include <asm/sections.h> 20 + #include <asm/vdso.h> 18 21 #include <linux/stop_machine.h> 19 22 20 23 #define __ALT_PTR(a, f) ((void *)&(a)->f + (a)->f) ··· 195 192 } 196 193 } 197 194 195 + void apply_alternatives_vdso(void) 196 + { 197 + struct alt_region region; 198 + const struct elf64_hdr *hdr; 199 + const struct elf64_shdr *shdr; 200 + const struct elf64_shdr *alt; 201 + DECLARE_BITMAP(all_capabilities, ARM64_NPATCHABLE); 202 + 203 + bitmap_fill(all_capabilities, ARM64_NPATCHABLE); 204 + 205 + hdr = (struct elf64_hdr *)vdso_start; 206 + shdr = (void *)hdr + hdr->e_shoff; 207 + alt = find_section(hdr, shdr, ".altinstructions"); 208 + if (!alt) 209 + return; 210 + 211 + region = (struct alt_region){ 212 + .begin = (void *)hdr + alt->sh_offset, 213 + .end = (void *)hdr + alt->sh_offset + alt->sh_size, 214 + }; 215 + 216 + __apply_alternatives(&region, false, &all_capabilities[0]); 217 + } 218 + 198 219 /* 199 220 * We might be patching the stop_machine state machine, so implement a 200 221 * really simple polling protocol here. ··· 252 225 253 226 void __init apply_alternatives_all(void) 254 227 { 228 + apply_alternatives_vdso(); 255 229 /* better not try code patching on a live SMP system */ 256 230 stop_machine(__apply_alternatives_multi_stop, NULL, cpu_online_mask); 257 231 }
-3
arch/arm64/kernel/vdso.c
··· 29 29 #include <asm/signal32.h> 30 30 #include <asm/vdso.h> 31 31 32 - extern char vdso_start[], vdso_end[]; 33 - extern char vdso32_start[], vdso32_end[]; 34 - 35 32 enum vdso_abi { 36 33 VDSO_ABI_AA64, 37 34 VDSO_ABI_AA32,
+7
arch/arm64/kernel/vdso/vdso.lds.S
··· 48 48 PROVIDE (_etext = .); 49 49 PROVIDE (etext = .); 50 50 51 + . = ALIGN(4); 52 + .altinstructions : { 53 + __alt_instructions = .; 54 + *(.altinstructions) 55 + __alt_instructions_end = .; 56 + } 57 + 51 58 .dynamic : { *(.dynamic) } :text :dynamic 52 59 53 60 .rela.dyn : ALIGN(8) { *(.rela .rela*) }