git: d78cbf483fe7 - main - arm: Implement kernel ifunc

From: Michal Meloun <mmel_at_FreeBSD.org>
Date: Sun, 01 Feb 2026 08:18:07 UTC
The branch main has been updated by mmel:

URL: https://cgit.FreeBSD.org/src/commit/?id=d78cbf483fe73c987573967042f57f15bf590629

commit d78cbf483fe73c987573967042f57f15bf590629
Author:     Michal Meloun <mmel@FreeBSD.org>
AuthorDate: 2026-01-24 10:41:10 +0000
Commit:     Michal Meloun <mmel@FreeBSD.org>
CommitDate: 2026-02-01 08:17:43 +0000

    arm: Implement kernel ifunc
    
    Add kernel ifunc support on arm.
    
    MFC after :     3 weeks
    Reviewed by:    kib (previous version)
    Differential Revision:  https://reviews.freebsd.org/D54970
---
 sys/arm/arm/elf_machdep.c |  8 +++++++-
 sys/arm/arm/machdep.c     |  5 ++---
 sys/arm/include/ifunc.h   | 24 +++++++++++++++++++++---
 sys/conf/kern.pre.mk      |  5 ++---
 sys/kern/link_elf.c       |  2 +-
 sys/sys/elf_common.h      |  1 +
 6 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c
index 881c4fcff475..cf2add0c367c 100644
--- a/sys/arm/arm/elf_machdep.c
+++ b/sys/arm/arm/elf_machdep.c
@@ -150,7 +150,7 @@ bool
 elf_is_ifunc_reloc(Elf_Size r_info __unused)
 {
 
-	return (false);
+	return (ELF_R_TYPE(r_info) == R_ARM_IRELATIVE);
 }
 
 /*
@@ -253,6 +253,12 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
 		case R_ARM_RELATIVE:
 			break;
 
+		case R_ARM_IRELATIVE:
+			addr = relocbase + addend;
+			addr = ((Elf_Addr (*)(void))addr)();
+			if (*where != addr)
+				*where = addr;
+			break;
 		default:
 			printf("kldload: unexpected relocation type %d, "
 			    "symbol index %d\n", rtype, symidx);
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index 0b395d42fc4a..dc2205023820 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -447,6 +447,8 @@ initarm(struct arm_boot_params *abp)
 
 	set_cpufuncs();
 	cpuinfo_init();
+	sched_instance_select();
+	link_elf_ireloc();
 
 	/*
 	 * Find the dtb passed in by the boot loader.
@@ -523,9 +525,6 @@ initarm(struct arm_boot_params *abp)
 	/* Do basic tuning, hz etc */
 	init_param1();
 
-	sched_instance_select();
-	/* link_elf_ireloc(); */
-
 	/*
 	 * Allocate a page for the system page mapped to 0xffff0000
 	 * This page will just contain the system vectors and can be
diff --git a/sys/arm/include/ifunc.h b/sys/arm/include/ifunc.h
index 6b7cf20c720f..98cc354ae6ca 100644
--- a/sys/arm/include/ifunc.h
+++ b/sys/arm/include/ifunc.h
@@ -1,10 +1,28 @@
-/*
- * This file is in the public domain.
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025, Michal Meloun <mmel@freebsd.org>
+ *
  */
 
 #ifndef __ARM_IFUNC_H
 #define	__ARM_IFUNC_H
 
-#define	 __DO_NOT_HAVE_SYS_IFUNCS	1
+#define	DEFINE_IFUNC(qual, ret_type, name, args)			\
+    static ret_type (*name##_resolver(void))args __used;		\
+    qual ret_type name args __attribute__((ifunc(#name "_resolver")));	\
+    static ret_type (*name##_resolver(void))args
+
+#ifdef __not_yet__
+#define	DEFINE_UIFUNC(qual, ret_type, name, args)			\
+    static ret_type (*name##_resolver(uint32_t, uint32_t, uint32_t,	\
+	uint32_t))args __used;						\
+    qual ret_type name args __attribute__((ifunc(#name "_resolver")));	\
+    static ret_type (*name##_resolver(					\
+	uint32_t elf_hwcap __unused,					\
+	uint32_t elf_hwcap2 __unused,					\
+	uint32_t arg3 __unused,						\
+	uint32_t arg4 __unused))args
+#endif
 
 #endif
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index 440ed2df5644..93e291b45bb6 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -119,11 +119,10 @@ CFLAGS+=	${CONF_CFLAGS}
 LDFLAGS+=	--build-id=sha1
 .endif
 
-.if (${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \
-    ${MACHINE_CPUARCH} == "i386" || ${MACHINE} == "powerpc") && \
+.if ${MACHINE_CPUARCH} != "riscv" && \
     defined(LINKER_FEATURES) && ${LINKER_FEATURES:Mifunc} == "" && \
     !make(install)
-.error amd64/arm64/i386/ppc* kernel requires linker ifunc support
+.error amd64/arm/arm64/i386/ppc* kernel requires linker ifunc support
 .endif
 .if ${MACHINE_CPUARCH} == "amd64"
 LDFLAGS+=	-z max-page-size=2097152
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index 45edd186e6ce..2a9e2a02709d 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -2041,7 +2041,7 @@ link_elf_propagate_vnets(linker_file_t lf)
 }
 #endif
 
-#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) || defined(__powerpc__)
+#if !defined(__riscv)
 /*
  * Use this lookup routine when performing relocations early during boot.
  * The generic lookup routine depends on kobj, which is not initialized
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
index efda38279848..3782bfc2df9c 100644
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -1122,6 +1122,7 @@ typedef struct {
 #define	R_ARM_PLT32		27	/* Add PC-relative PLT offset. */
 #define	R_ARM_GNU_VTENTRY	100
 #define	R_ARM_GNU_VTINHERIT	101
+#define	R_ARM_IRELATIVE		160
 #define	R_ARM_RSBREL32		250
 #define	R_ARM_THM_RPC22		251
 #define	R_ARM_RREL32		252