mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 01:54:09 +08:00
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>
This commit is contained in:
parent
b3adc3844e
commit
4e3bca8f7c
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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*) }
|
||||
|
Loading…
Reference in New Issue
Block a user