xref: /netbsd-src/share/man/man9/versioningsyscalls.9 (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1.\"	$NetBSD: versioningsyscalls.9,v 1.5 2023/07/14 09:03:37 rillig 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 June 23, 2023
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 XYZ
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.
119.Ss Versioning structs
120To version
121.Ft struct my_struct ,
122first make a copy of
123.Ft my_struct
124renamed to
125.Ft my_structXYZ
126in an equivalent header in
127.Pa sys/compat/sys .
128After that, you can freely modify
129.Ft my_struct
130as desired.
131.
132.Ss Versioning the entry point
133The stub for the next version of the syscall will be
134.Fn __my_syscallXYZ ,
135and will have entry point
136.Fn sys___my_syscallXYZ .
137.
138.Ss Modifying syscalls.conf
139.Pa sys/kern/syscalls.conf
140may need to be modified to contain
141.Li compat_XYZ
142in the
143.Va compatopts
144variable.
145.
146.Ss Modifying syscalls.master
147First, add the next syscall to
148.Pa sys/kern/syscalls.master
149keeping
150.Fn my_syscall
151as the name, and set the (optional) compat field of the declaration to
152.Ar XYZ .
153.Pp
154Next, modify the current version of the syscall, and replace the type
155field
156.Pq usually just Li STD
157with
158.Dv COMPAT_XYZ MODULAR compat_XYZ .
159.Pp
160The keyword
161.Dv MODULAR
162indicates that the system call can be part of a kernel module.
163Even if the system call was not part of a module before, now it will be part
164of the
165.Dv COMPAT_XYZ
166module.
167.Pp
168Finally, if applicable, replace the types of the current and old versions of the
169syscall with the compat type.
170.Pp
171Overall, the final diff should look like
172.Bd -literal
173- 123 STD                           { int|sys||my_syscall(struct my_struct *ms); }
174+ 123 COMPAT_XYZ MODULAR compat_XYZ { int|sys||my_syscall(struct my_structXYZ *ms); }
175\&...
176+ 456 STD               	    { int|sys|XYZ|my_syscall(struct my_struct *ms); }
177.Ed
178.
179.Ss Modifying Makefile.rump
180If the current syscall is rump,
181.Pa sys/rump/Makefile.rump
182must contain
183.Ar XYZ
184in the
185.Dv RUMP_NBCOMPAT
186variable.
187.
188.Ss Regenerating the system calls
189If versioning structs, then modify
190.Pa sys/kern/makesyscalls.sh
191by adding and entry for
192.Ft struct my_structXYZ
193type to
194.Va uncompattypes .
195.Pp
196The
197.Va uncompattypes
198map is used in
199.Xr rump 7
200system call table generation, to map from the versioned types to the original
201names since
202.Xr rump 7
203wants to have a non-versioned copy of the system call table.
204.Pp
205Then regenerate the syscall tables in the usual way, first by running
206.Pa sys/kern/makesyscalls.sh ,
207then if the system call is rump, doing a build in
208.Pa sys/rump
209and then running
210.Pa sys/rump/makerumpsyscalls.sh
211passing it the path to the result of the build you just did as its first
212argument.
213.
214.Sh KERNEL COMPATIBILITY
215This section covers maintaining compatibility at the kernel level, by
216adding an entry point for the current syscall in an appropriate compat
217module.
218For the purposes of this section, we assume the current
219syscall has entry point
220.Fn sys_my_syscall
221and lives inside
222.Pa sys/kern/my_file.c .
223.
224.Ss Creating the compat current syscall
225The compat version of the current syscall has entry point
226.Fn compat_XYZ_sys_my_syscall ,
227and should be implemented in
228.Pa sys/compat/common/my_file_XYZ.c
229with the same semantics as the current syscall.
230Often this involves translating the arguments to the next syscall,
231and then calling that syscall's entry point.
232.
233.Ss Adding it to the compat module
234.Pa sys/compat/common/my_file_XYZ.c
235must contain an array of
236.Ft struct syscall_package
237that declares the mapping between syscall number and entry point,
238terminating in a zero element (see sample diff below).
239.Pp
240Additionally,
241.Pa sys/compat/common/my_file_XYZ.c
242must contain two functions,
243.Fn my_file_XYZ_init
244and
245.Fn my_file_XYZ_fini
246that are used to initialize/clean up anything related to this syscall.
247At the minimum they must make calls to
248.Fn syscall_establish
249and
250.Fn syscall_disestablish
251respectively, adding and removing the syscalls.
252The stubs for these functions should be located in
253.Pa sys/compat/common/compat_mod.h .
254.Pp
255Overall,
256.Pa sys/compat/common/my_file_XYZ.c
257must at the minimum contain
258.Bd -literal -offset indent
259static const struct syscall_package my_file_XYZ_syscalls[] = {
260        { SYS_compat_XYZ_my_syscall, 0,
261            (sy_call_t *)compat_XYZ_sys_my_syscall },
262        { 0, 0, NULL },
263};
264
265int
266compat_XYZ_my_syscall(...)
267{ /* Compat implementation goes here. */ }
268
269int
270my_file_XYZ_init(void)
271{ return syscall_establish(NULL, my_file_XYZ_syscalls); }
272
273int
274my_file_XYZ_fini(void)
275{ return syscall_disestablish(NULL, my_file_XYZ_syscalls); }
276.Ed
277.Pp
278Finally,
279.Pa sys/compat/common/compat_XYZ_mod.c
280needs to be modified to have its
281.Fn compat_XYZ_init
282and
283.Fn compat_XYZ_fini
284functions call
285.Fn my_file_XYZ_init
286and
287.Fn my_file_XYZ_fini
288respectively.
289.
290.Ss Modifying old compat syscalls
291If the current syscall has already been versioned, you might need to
292modify the old compat syscalls in
293.Pa sys/compat/common
294to either use the next syscall or the current compat syscall.
295Note that compat code can be made to depend on compat code for more
296recent releases.
297.Sh USERLAND COMPATIBILITY
298With the exception of the libraries described below, making the rest
299of userland work will just involve recompiling, and perhaps changing a
300constant or a
301.Li #define .
302.
303.Ss libc
304A userland version of any old and current versions of the syscall must be
305implemented.
306For the current syscall with stub
307.Fn my_syscall struct\ my_struct\ *ms
308in
309.Pa sys/sys/my_header.h ,
310an implementation of
311.Fn my_syscall
312must be written in
313.Pa lib/libc/compat/sys/compat_my_syscall.c .
314.Pp
315Additionally, a call to
316.Fn __warn_references
317must be added in
318.Pa lib/libc/compat/sys/compat_my_syscall.c
319to warn of any uses of the compat syscall and mention how to use the next
320version of the syscall.
321In almost all cases the instructions on how to use the next version of the
322syscall will be
323.Dq include <sys/my_header.h> to generate correct reference .
324.Pp
325Overall,
326.Pa lib/libc/compat/sys/compat_my_syscall.c
327must at the minimum include
328.Bd -literal -offset indent
329#include <sys/compat/my_header.h>
330
331__warn_references(my_syscall,
332    "warning: reference to compatibility my_syscall();"
333    " message on how to use the next my_syscall()");
334
335int
336my_syscall()
337{ /* Compat implementation goes here. */ }
338.Ed
339