xref: /freebsd/share/man/man9/DEFINE_IFUNC.9 (revision b0f79e328e18f454a54011ab1bb09e4910e73840)
1.\" Copyright (c) 2019 The FreeBSD Foundation
2.\"
3.\" This documentation was written by Mark Johnston <markj@FreeBSD.org>
4.\" under sponsorship from the FreeBSD Foundation.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\"
15.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25.\" SUCH DAMAGE.
26.\"
27.\" $FreeBSD$
28.\"
29.Dd May 18, 2019
30.Dt DEFINE_IFUNC 9
31.Os
32.Sh NAME
33.Nm DEFINE_IFUNC
34.Nd define a kernel function with an implementation selected at run-time
35.Sh SYNOPSIS
36.In machine/ifunc.h
37.Fn DEFINE_IFUNC qual ret_type name args
38.Sh DESCRIPTION
39ifuncs are a linker feature which allows the programmer to define functions
40whose implementation is selected at boot-time or module load-time.
41The
42.Nm
43macro can be used to define an ifunc.
44The selection is performed by a resolver function, which returns a pointer
45to the selected function.
46ifunc resolvers are invoked very early during the machine-dependent
47initialization routine, or at load time for dynamically loaded modules.
48Resolution must occur before the first call to an ifunc.
49ifunc resolution is performed after CPU features are enumerated and after the
50kernel's environment is initialized.
51The typical use-case for an ifunc is a routine whose behavior depends on
52optional CPU features.
53For example, newer generations of a given CPU architecture may provide an
54instruction to optimize a common operation.
55To avoid the overhead of testing for the CPU feature each time the operation
56is performed, an ifunc can be used to provide two implementations for the
57operation: one targeting platforms with the extra instruction, and one
58for older platforms.
59.Pp
60Because
61.Nm
62is a macro that defines a dynamically typed function, its usage looks somewhat
63unusual.
64The
65.Ar qual
66parameter is a list of zero or more C function qualifiers to be applied to the
67ifunc.
68This parameter is typically empty or the
69.Dv static
70qualifier.
71.Ar ret_type
72is the return type of the ifunc.
73.Ar name
74is the name of the ifunc.
75.Ar args
76is a parenthesized, comma-separated list of the parameter types of the function,
77as they would appear in a C function declaration.
78.Pp
79The
80.Nm
81usage must be followed by the resolver function body.
82The resolver must return a function with return type
83.Ar ret_type
84and parameter types
85.Ar args .
86The resolver function is defined with the
87.Ql resolver
88gcc-style function attribute, causing the corresponding
89.Xr elf 5
90function symbol to be of type
91.Dv STT_GNU_IFUNC
92instead of
93.Dv STT_FUNC .
94The kernel linker invokes the resolver to process relocations targeting ifunc
95calls and PLT entries referencing such symbols.
96.Sh EXAMPLES
97ifunc resolvers are executed early during boot, before most kernel facilities
98are available.
99They are effectively limited to checking CPU feature flags and tunables.
100.Bd -literal
101static size_t
102fast_strlen(const char *s __unused)
103{
104	size_t len;
105
106	/* Fast, but may not be correct in all cases. */
107	__asm("movq $42,%0\\n" : "=r" (len));
108	return (len);
109}
110
111static size_t
112slow_strlen(const char *s)
113{
114	const char *t;
115
116	for (t = s; *t != '\\0'; t++);
117	return (t - s);
118}
119
120DEFINE_IFUNC(, size_t, strlen, (const char *))
121{
122	int enabled;
123
124	enabled = 1;
125	TUNABLE_INT_FETCH("debug.use_fast_strlen", &enabled);
126	if (enabled && (cpu_features & CPUID_FAST_STRLEN) != 0)
127		return (fast_strlen);
128	else
129		return (slow_strlen);
130}
131.Ed
132.Pp
133This defines a
134.Fn strlen
135function with an optimized implementation for CPUs that advertise support.
136.Sh SEE ALSO
137.Xr elf 5
138.Sh NOTES
139ifuncs are not supported on all architectures.
140They require both toolchain support, to emit function symbols of type
141.Dv STT_GNU_IFUNC ,
142and kernel linker support to invoke ifunc resolvers during boot or
143during module load.
144