xref: /netbsd-src/share/man/man9/versioningsyscalls.9 (revision 1cce6ebacabad3fa17ab09f4e597c6b4a52a4ffe)
1.\"	$NetBSD: versioningsyscalls.9,v 1.7 2024/05/23 06:35:45 pgoyette Exp $
2.\"
3.\" Copyright (c) 2023 The NetBSD Foundation, Inc.
4.\" All rights reserved.
5.\"
6.\" This code is derived from software contributed to The NetBSD Foundation
7.\" by Theodore Preduta.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE.
29.\"
30.Dd May 20, 2024
31.Dt VERSIONINGSYSCALLS 9
32.Os
33.
34.Sh NAME
35.Nm versioningsyscalls
36.Nd guide on versioning syscalls
37.
38.Sh DESCRIPTION
39.Nx
40has the ability to change the ABI of a syscall whilst retaining backwards
41compatibility with existing code.
42This means that existing code keeps working the same way as before, and
43new code can use new features and/or functionality.
44In the past this has allowed
45.Ft dev_t
46to move from 16 bits to 32 bits,
47.Ft ino_t
48and
49.Ft time_t
50to move from 32 bits to 64 bits,
51and adding fields to
52.Ft struct kevent
53without disturbing existing binaries.
54To achieve this both kernel and userland changes are required.
55.Pp
56In the kernel, a new syscall is added with a new ABI, and the old syscall
57is retained and moved to a new location that holds the compatibility syscalls
58.Pq Pa src/sys/compat .
59Kernels can be compiled with or without backwards compatibility syscalls.
60See the
61.Dv COMPAT_ Ns Ar XX
62options in
63.Xr options 4 .
64.Pp
65In userland, the original syscall stub is moved into
66.Pa src/lib/libc/compat
67retaining the same symbol name and ABI.
68The new stub is added to libc, and in the header file the syscall symbol is
69made to point to the new name with the new ABI.
70.Pp
71This is done via symbol renaming instead of ELF versioned symbols for
72historical reasons.
73.Nx
74has retained binary compatibility with most syscalls since
75.Nx 0.9
76with the exception of Scheduler Activation syscalls which are not being
77emulated because of the cost and safety of doing so.
78.Pp
79To avoid confusion, the following words are used to disambiguate which version
80of the system call is being described.
81.Bl -tag -offset indent -width Em
82.It Em old
83Any previous versions of the syscall, which have already been versioned and
84superseded by the current version of the syscall.
85.It Em current
86The version of the syscall currently in use.
87.It Em next
88The version of the syscall that will become standard in the next release.
89.El
90.Pp
91Additionally,
92.Ar CNUM
93always represents the last
94.Nx
95release where the current
96version of the system call is the default, multiplied by ten and retaining a
97leading zero.
98For example
99.Nx 0.9
100has
101.Dv COMPAT_09
102whereas
103.Nx 10.0
104has
105.Dv COMPAT_100 .
106.
107.Sh VERSIONING THE SYSCALL
108This section describes what needs to be modified to add the new version of the
109syscall.
110It assumes the current version of the syscall is
111.Fn my_syscall "struct my_struct *ms"
112and that
113.Ft my_struct
114will be versioned.
115If not versioning a struct, passages that mention
116.Ft my_struct
117can be ignored.
118.Pp
119The syscall version suffix
120.Dv VNUM
121indicates the first release of
122.Nx
123the system call will appear in.
124The compat version
125.Dv CNUM
126is the last version of
127.Nx the old system call was used.
128Typically VNUM = CNUM + 1 .
129.Pp
130For example if you are versioning
131.Xr getcontext 2
132just after
133.Nx 11
134was released, and the original system call was called
135.Fn getcontext ,
136the system call will become
137.Fn __getcontext12
138and the compat entry point will become
139.Fn compat_11_getcontext .
140.Pp
141Next time
142.Xr getcontext 2
143needs versioning, for example just after
144.Nx 15
145was released, it will become
146.Fn __getcontext16
147and the compat entry will become
148.Fn compat_15___getcontext12 .
149.Pp
150Please note that the historical practice up to
151.Nx 11
152has been that the syscall suffix matched the version when the syscall
153was last used.
154.
155.Ss Versioning structs
156To version
157.Ft struct my_struct ,
158first make a copy of
159.Ft my_struct
160renamed to
161.Ft my_structCNUM
162in an equivalent header in
163.Pa sys/compat/sys .
164After that, you can freely modify
165.Ft my_struct
166as desired.
167.
168.Ss Versioning the entry point
169The stub for the next version of the syscall will be
170.Fn __my_syscallVNUM ,
171and will have entry point
172.Fn sys___my_syscallVNUM .
173.
174.Ss Modifying syscalls.conf
175.Pa sys/kern/syscalls.conf
176may need to be modified to contain
177.Li compat_CNUM
178in the
179.Va compatopts
180variable.
181.
182.Ss Modifying syscalls.master
183First, add the next syscall to
184.Pa sys/kern/syscalls.master
185keeping
186.Fn my_syscall
187as the name, and set the (optional) compat field of the declaration to
188.Ar CNUM .
189.Pp
190Next, modify the current version of the syscall, and replace the type
191field
192.Pq usually just Li STD
193with
194.Dv COMPAT_CNUM MODULAR compat_CNUM .
195.Pp
196The keyword
197.Dv MODULAR
198indicates that the system call can be part of a kernel module.
199Even if the system call was not part of a module before, now it will be part
200of the
201.Dv COMPAT_CNUM
202module.
203.Pp
204Finally, if applicable, replace the types of the current and old versions of the
205syscall with the compat type.
206.Pp
207Overall, the final diff should look like
208.Bd -literal
209- 123 STD                           { int|sys||my_syscall(struct my_struct *ms); }
210+ 123 COMPAT_CNUM MODULAR compat_CNUM { int|sys||my_syscall(struct my_structCNUM *ms); }
211\&...
212+ 456 STD               	    { int|sys|VNUM|my_syscall(struct my_struct *ms); }
213.Ed
214.
215.Ss Modifying Makefile.rump
216If the current syscall is rump,
217.Pa sys/rump/Makefile.rump
218must contain
219.Ar CNUM
220in the
221.Dv RUMP_NBCOMPAT
222variable.
223.
224.Ss Regenerating the system calls
225If versioning structs, then modify
226.Pa sys/kern/makesyscalls.sh
227by adding an entry for
228.Ft struct my_structCNUM
229type to
230.Va uncompattypes .
231.Pp
232The
233.Va uncompattypes
234map is used in
235.Xr rump 7
236system call table generation, to map from the versioned types to the original
237names since
238.Xr rump 7
239wants to have a non-versioned copy of the system call table.
240.Pp
241Then regenerate the syscall tables in the usual way, first by running
242.Pa sys/kern/makesyscalls.sh ,
243then if the system call is rump, doing a build in
244.Pa sys/rump
245and then running
246.Pa sys/rump/makerumpsyscalls.sh
247passing it the path to the result of the build you just did as its first
248argument.
249.
250.Sh KERNEL COMPATIBILITY
251This section covers maintaining compatibility at the kernel level, by
252adding an entry point for the current syscall in an appropriate compat
253module.
254For the purposes of this section, we assume the current
255syscall has entry point
256.Fn sys_my_syscall
257and lives inside
258.Pa sys/kern/my_file.c .
259.
260.Ss Creating the compat current syscall
261The compat version of the current syscall has entry point
262.Fn compat_CNUM_sys_my_syscall ,
263and should be implemented in
264.Pa sys/compat/common/my_file_CNUM.c
265with the same semantics as the current syscall.
266Often this involves translating the arguments to the next syscall,
267and then calling that syscall's entry point.
268.
269.Ss Adding it to the compat module
270.Pa sys/compat/common/my_file_CNUM.c
271must contain an array of
272.Ft struct syscall_package
273that declares the mapping between syscall number and entry point,
274terminating in a zero element (see sample diff below).
275.Pp
276Additionally,
277.Pa sys/compat/common/my_file_CNUM.c
278must contain two functions,
279.Fn my_file_CNUM_init
280and
281.Fn my_file_CNUM_fini
282that are used to initialize/clean up anything related to this syscall.
283At the minimum they must make calls to
284.Fn syscall_establish
285and
286.Fn syscall_disestablish
287respectively, adding and removing the syscalls.
288The stubs for these functions should be located in
289.Pa sys/compat/common/compat_mod.h .
290.Pp
291Overall,
292.Pa sys/compat/common/my_file_CNUM.c
293must at the minimum contain
294.Bd -literal -offset indent
295static const struct syscall_package my_file_CNUM_syscalls[] = {
296        { SYS_compat_CNUM_my_syscall, 0,
297            (sy_call_t *)compat_CNUM_sys_my_syscall },
298        { 0, 0, NULL },
299};
300
301int
302compat_CNUM_my_syscall(...)
303{ /* Compat implementation goes here. */ }
304
305int
306my_file_CNUM_init(void)
307{ return syscall_establish(NULL, my_file_CNUM_syscalls); }
308
309int
310my_file_CNUM_fini(void)
311{ return syscall_disestablish(NULL, my_file_CNUM_syscalls); }
312.Ed
313.Pp
314Finally,
315.Pa sys/compat/common/compat_CNUM_mod.c
316needs to be modified to have its
317.Fn compat_CNUM_init
318and
319.Fn compat_CNUM_fini
320functions call
321.Fn my_file_CNUM_init
322and
323.Fn my_file_CNUM_fini
324respectively.
325.
326.Ss Modifying old compat syscalls
327If the current syscall has already been versioned, you might need to
328modify the old compat syscalls in
329.Pa sys/compat/common
330to either use the next syscall or the current compat syscall.
331Note that compat code can be made to depend on compat code for more
332recent releases.
333.Sh USERLAND COMPATIBILITY
334With the exception of the libraries described below, making the rest
335of userland work will just involve recompiling, and perhaps changing a
336constant or a
337.Li #define .
338.
339.Ss libc
340A userland version of any old and current versions of the syscall must be
341implemented.
342For the current syscall with stub
343.Fn my_syscall struct\ my_struct\ *ms
344in
345.Pa sys/sys/my_header.h ,
346an implementation of
347.Fn my_syscall
348must be written in
349.Pa lib/libc/compat/sys/compat_my_syscall.c .
350.Pp
351Additionally, a call to
352.Fn __warn_references
353must be added in
354.Pa lib/libc/compat/sys/compat_my_syscall.c
355to warn of any uses of the compat syscall and mention how to use the next
356version of the syscall.
357In almost all cases the instructions on how to use the next version of the
358syscall will be
359.Dq include <sys/my_header.h> to generate correct reference .
360.Pp
361Overall,
362.Pa lib/libc/compat/sys/compat_my_syscall.c
363must at the minimum include
364.Bd -literal -offset indent
365#include <sys/compat/my_header.h>
366
367__warn_references(my_syscall,
368    "warning: reference to compatibility my_syscall();"
369    " message on how to use the next my_syscall()");
370
371int
372my_syscall()
373{ /* Compat implementation goes here. */ }
374.Ed
375