Index: sys/arm64/arm64/elf_machdep.c =================================================================== --- sys/arm64/arm64/elf_machdep.c +++ sys/arm64/arm64/elf_machdep.c @@ -143,7 +143,7 @@ */ static int elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, - int type, int local, elf_lookup_fn lookup) + int type, int local, elf_lookup_fn lookup, int late_ifunc) { Elf_Addr *where, addr, addend, val; Elf_Word rtype, symidx; @@ -170,6 +170,13 @@ panic("unknown reloc type %d\n", type); } + if (late_ifunc) { + KASSERT(type == ELF_RELOC_RELA, + ("Only RELA ifunc relocations are supported")); + if (rtype != R_AARCH64_IRELATIVE) + return (0); + } + if (local) { if (rtype == R_AARCH64_RELATIVE) *where = elf_relocaddr(lf, relocbase + addend); @@ -229,7 +236,7 @@ int type, elf_lookup_fn lookup) { - return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); + return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup, 0)); } /* Process one elf relocation with addend. */ @@ -238,7 +245,15 @@ elf_lookup_fn lookup) { - return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); + return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup, 0)); +} + +int +elf_reloc_late(linker_file_t lf, Elf_Addr relocbase, const void *data, + int type, elf_lookup_fn lookup) +{ + + return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup, 1)); } int Index: sys/arm64/arm64/mp_machdep.c =================================================================== --- sys/arm64/arm64/mp_machdep.c +++ sys/arm64/arm64/mp_machdep.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -167,6 +168,8 @@ intr_pic_ipi_setup(IPI_STOP_HARD, "stop hard", ipi_stop, NULL); intr_pic_ipi_setup(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL); + link_elf_late_ireloc(); + atomic_store_rel_int(&aps_ready, 1); /* Wake up the other CPUs */ __asm __volatile( Index: sys/kern/link_elf.c =================================================================== --- sys/kern/link_elf.c +++ sys/kern/link_elf.c @@ -1925,4 +1925,18 @@ link_elf_preload_parse_symbols(ef); relocate_file1(ef, elf_lookup_ifunc, elf_reloc, true); } + +#if defined(__aarch64__) +void +link_elf_late_ireloc(void) +{ + elf_file_t ef; + + KASSERT(linker_kernel_file != NULL, + ("link_elf_late_ireloc: No kernel linker file found")); + ef = (elf_file_t)linker_kernel_file; + + relocate_file1(ef, elf_lookup_ifunc, elf_reloc_late, true); +} +#endif #endif Index: sys/sys/linker.h =================================================================== --- sys/sys/linker.h +++ sys/sys/linker.h @@ -289,6 +289,12 @@ const char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx); void link_elf_ireloc(caddr_t kmdp); +#if defined(__aarch64__) +int elf_reloc_late(linker_file_t _lf, Elf_Addr base, const void *_rel, + int _type, elf_lookup_fn _lu); +void link_elf_late_ireloc(void); +#endif + typedef struct linker_ctf { const uint8_t *ctftab; /* Decompressed CTF data. */ int ctfcnt; /* Number of CTF data bytes. */