[PATCH v2 2/3] arm64: alternative: patch alternatives in the vDSO
Mark Rutland
mark.rutland at arm.com
Tue Aug 30 06:17:44 PDT 2022
On Tue, Aug 30, 2022 at 11:48:32AM +0100, Joey Gouly wrote:
> 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 at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Vincenzo Frascino <vincenzo.frascino at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
Acked-by: Mark Rutland <mark.rutland at arm.com>
Mark.
> ---
> arch/arm64/include/asm/vdso.h | 3 +++
> arch/arm64/kernel/alternative.c | 28 ++++++++++++++++++++++++++++
> arch/arm64/kernel/vdso.c | 3 ---
> arch/arm64/kernel/vdso/vdso.lds.S | 7 +++++++
> 4 files changed, 38 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
> index f99dcb94b438..b4ae32109932 100644
> --- a/arch/arm64/include/asm/vdso.h
> +++ b/arch/arm64/include/asm/vdso.h
> @@ -26,6 +26,9 @@
> (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
> })
>
> +extern char vdso_start[], vdso_end[];
> +extern char vdso32_start[], vdso32_end[];
> +
> #endif /* !__ASSEMBLY__ */
>
> #endif /* __ASM_VDSO_H */
> diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
> index 9bcaa5eacf16..a97775963f35 100644
> --- a/arch/arm64/kernel/alternative.c
> +++ b/arch/arm64/kernel/alternative.c
> @@ -10,11 +10,14 @@
>
> #include <linux/init.h>
> #include <linux/cpu.h>
> +#include <linux/elf.h>
> #include <asm/cacheflush.h>
> #include <asm/alternative.h>
> #include <asm/cpufeature.h>
> #include <asm/insn.h>
> +#include <asm/module.h>
> #include <asm/sections.h>
> +#include <asm/vdso.h>
> #include <linux/stop_machine.h>
>
> #define __ALT_PTR(a, f) ((void *)&(a)->f + (a)->f)
> @@ -192,6 +195,30 @@ static void __nocfi __apply_alternatives(struct alt_region *region, bool is_modu
> }
> }
>
> +void apply_alternatives_vdso(void)
> +{
> + struct alt_region region;
> + const struct elf64_hdr *hdr;
> + const struct elf64_shdr *shdr;
> + const struct elf64_shdr *alt;
> + DECLARE_BITMAP(all_capabilities, ARM64_NPATCHABLE);
> +
> + bitmap_fill(all_capabilities, ARM64_NPATCHABLE);
> +
> + hdr = (struct elf64_hdr *)vdso_start;
> + shdr = (void *)hdr + hdr->e_shoff;
> + alt = find_section(hdr, shdr, ".altinstructions");
> + if (!alt)
> + return;
> +
> + region = (struct alt_region){
> + .begin = (void *)hdr + alt->sh_offset,
> + .end = (void *)hdr + alt->sh_offset + alt->sh_size,
> + };
> +
> + __apply_alternatives(®ion, false, &all_capabilities[0]);
> +}
> +
> /*
> * We might be patching the stop_machine state machine, so implement a
> * really simple polling protocol here.
> @@ -225,6 +252,7 @@ static int __apply_alternatives_multi_stop(void *unused)
>
> void __init apply_alternatives_all(void)
> {
> + apply_alternatives_vdso();
> /* better not try code patching on a live SMP system */
> stop_machine(__apply_alternatives_multi_stop, NULL, cpu_online_mask);
> }
> diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
> index a61fc4f989b3..ac93a2ee9c07 100644
> --- a/arch/arm64/kernel/vdso.c
> +++ b/arch/arm64/kernel/vdso.c
> @@ -29,9 +29,6 @@
> #include <asm/signal32.h>
> #include <asm/vdso.h>
>
> -extern char vdso_start[], vdso_end[];
> -extern char vdso32_start[], vdso32_end[];
> -
> enum vdso_abi {
> VDSO_ABI_AA64,
> VDSO_ABI_AA32,
> diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
> index e69fb4aaaf3e..6028f1fe2d1c 100644
> --- a/arch/arm64/kernel/vdso/vdso.lds.S
> +++ b/arch/arm64/kernel/vdso/vdso.lds.S
> @@ -48,6 +48,13 @@ SECTIONS
> PROVIDE (_etext = .);
> PROVIDE (etext = .);
>
> + . = ALIGN(4);
> + .altinstructions : {
> + __alt_instructions = .;
> + *(.altinstructions)
> + __alt_instructions_end = .;
> + }
> +
> .dynamic : { *(.dynamic) } :text :dynamic
>
> .rela.dyn : ALIGN(8) { *(.rela .rela*) }
> --
> 2.17.1
>
More information about the linux-arm-kernel
mailing list