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