Module Name:    src
Committed By:   christos
Date:           Sat Jul  8 16:14:11 UTC 2023

Modified Files:
        src/distrib/sets/lists/comp: mi
        src/share/man/man9: Makefile
Added Files:
        src/share/man/man9: versioningsyscalls.9

Log Message:
Document how system call versioning is done. From this summer's compat-linux
GSoC, by Theodore Preduta.


To generate a diff of this commit:
cvs rdiff -u -r1.2434 -r1.2435 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.466 -r1.467 src/share/man/man9/Makefile
cvs rdiff -u -r0 -r1.1 src/share/man/man9/versioningsyscalls.9

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.2434 src/distrib/sets/lists/comp/mi:1.2435
--- src/distrib/sets/lists/comp/mi:1.2434	Tue Jul  4 12:23:15 2023
+++ src/distrib/sets/lists/comp/mi	Sat Jul  8 12:14:11 2023
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.2434 2023/07/04 16:23:15 riastradh Exp $
+#	$NetBSD: mi,v 1.2435 2023/07/08 16:14:11 christos Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp				comp-sys-root
@@ -12908,6 +12908,7 @@
 ./usr/share/man/cat9/vdead_check.0		comp-sys-catman		.cat
 ./usr/share/man/cat9/vdevgone.0			comp-sys-catman		.cat
 ./usr/share/man/cat9/veriexec.0			comp-sys-catman		.cat
+./usr/share/man/cat9/versioningsyscalls.0	comp-sys-catman		.cat
 ./usr/share/man/cat9/vfinddev.0			comp-sys-catman		.cat
 ./usr/share/man/cat9/vflush.0			comp-sys-catman		.cat
 ./usr/share/man/cat9/vflushbuf.0		comp-sys-catman		.cat
@@ -21214,6 +21215,7 @@
 ./usr/share/man/html9/vdead_check.html		comp-sys-htmlman	html
 ./usr/share/man/html9/vdevgone.html		comp-sys-htmlman	html
 ./usr/share/man/html9/veriexec.html		comp-sys-htmlman	html
+./usr/share/man/html9/versigoningsyscalls.html	comp-sys-htmlman	html
 ./usr/share/man/html9/vfinddev.html		comp-sys-htmlman	html
 ./usr/share/man/html9/vflush.html		comp-sys-htmlman	html
 ./usr/share/man/html9/vflushbuf.html		comp-sys-htmlman	html
@@ -29753,6 +29755,7 @@
 ./usr/share/man/man9/vdead_check.9		comp-sys-man		.man
 ./usr/share/man/man9/vdevgone.9			comp-sys-man		.man
 ./usr/share/man/man9/veriexec.9			comp-sys-man		.man
+./usr/share/man/man9/versioningsyscalls.9	comp-sys-man		.man
 ./usr/share/man/man9/vfinddev.9			comp-sys-man		.man
 ./usr/share/man/man9/vflush.9			comp-sys-man		.man
 ./usr/share/man/man9/vflushbuf.9		comp-sys-man		.man

Index: src/share/man/man9/Makefile
diff -u src/share/man/man9/Makefile:1.466 src/share/man/man9/Makefile:1.467
--- src/share/man/man9/Makefile:1.466	Sun Mar  5 19:49:31 2023
+++ src/share/man/man9/Makefile	Sat Jul  8 12:14:11 2023
@@ -1,4 +1,4 @@
-#       $NetBSD: Makefile,v 1.466 2023/03/06 00:49:31 uwe Exp $
+#       $NetBSD: Makefile,v 1.467 2023/07/08 16:14:11 christos Exp $
 
 #	Makefile for section 9 (kernel function and variable) manual pages.
 
@@ -64,7 +64,8 @@ MAN=	accept_filter.9 accf_data.9 accf_ht
 	usbd_status.9 usbdi.9 usbnet.9 \
 	userret.9 ustore.9 \
 	uvm.9 uvm_hotplug.9 uvm_km.9 uvm_map.9 \
-	vattr.9 veriexec.9 vcons.9 vfs.9 vfs_hooks.9 vfsops.9 vfssubr.9 \
+	vattr.9 veriexec.9 vcons.9 versioningsyscalls.9 \
+	vfs.9 vfs_hooks.9 vfsops.9 vfssubr.9 \
 	video.9 vme.9 vnfileops.9 vnode.9 vnodeops.9 vnsubr.9 vmem.9  \
 	wapbl.9 wdc.9 workqueue.9 \
 	wsbell.9 wscons.9 wsdisplay.9 wsfont.9 wskbd.9 wsmouse.9 \

Added files:

Index: src/share/man/man9/versioningsyscalls.9
diff -u /dev/null src/share/man/man9/versioningsyscalls.9:1.1
--- /dev/null	Sat Jul  8 12:14:12 2023
+++ src/share/man/man9/versioningsyscalls.9	Sat Jul  8 12:14:11 2023
@@ -0,0 +1,289 @@
+.\"	$NetBSD: versioningsyscalls.9,v 1.1 2023/07/08 16:14:11 christos Exp $
+.\"
+.\" Copyright (c) 2023 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Theodore Preduta.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd June 23, 2023
+.Dt versioningsyscalls 9
+.Os
+.Sh NAME
+.Nm versioningsyscalls
+.Nd guide on versioning syscalls
+.Sh DESCRIPTION
+.Nx
+has the ability to change the ABI of a syscall whilst retaining backwards
+compatibility with existing code.
+This means that existing code keeps working the same way as before, and
+new code can use new features and/or functionality.
+In the past this has allowed
+.Ft dev_t
+to move from 16 bits to 32 bits,
+.Ft ino_t
+and
+.Ft time_t
+to move from 16 bits to 32 bits and
+adding fields to
+.Ft struct kevent
+without disturbing existing binaries.
+To achieve this both kernel and userland changes are required.
+.Pp
+In the kernel, a new syscall is added with a new ABI, and the old syscall
+is retained and moved to a new location that holds the compatibility syscalls
+.Pa ( src/sys/compat ) .
+Kernels can be compiled with or without backwards compatibility syscalls.
+See the
+.Li COMPAT_XX
+options in
+.Xr options 4 .
+.Pp
+In userland, the original syscall stub is moved into
+.Pa src/lib/libc/compat
+retaining the same symbol name and ABI.
+The new stub is added to libc, and in the header file the syscall symbol is
+made to point to the new name with the new ABI.
+.Pp
+This is done via symbol renaming instead of ELF versioned symbols for
+historical reasons.
+.Nx
+has retained binary compatibility with most syscalls since
+.Nx 0.9
+with the exception of Scheduler Activation syscalls which are not being
+emulated because of the cost and safety of doing so.
+.Pp
+To avoid confusion, the following words are used to disambiguate which version
+of the system call is being described.
+.Bl -tag -offset indent -width "current"
+.It old
+Any previous versions of the syscall, which have already been versioned and
+superseded by the current version of the syscall.
+.It current
+The version of the syscall currently in use.
+.It next
+The version of the syscall that will become standard in the next release.
+.El
+.Pp
+Additionally,
+.Em XYZ
+always represents the last
+.Nx
+release where the current
+version of the system call is the default, multiplied by ten and retaining a
+leading zero.
+For example
+.Nx 0.9
+has
+.Li COMPAT_09
+whereas
+.Nx 10.0
+has
+.Li COMPAT_100 .
+.Sh VERSIONING THE SYSCALL
+This section describes what needs to be modified to add the new version of the
+syscall.
+It assumes the current version of the syscall is
+.Fn my_syscall struct\ my_struct\ *ms
+and that
+.Li my_struct
+will be versioned.
+If not versioning a struct, passages that mention
+.Li my_struct
+can be ignored.
+.Ss Versioning structs
+To version
+.Li struct my_struct ,
+first make a copy of
+.Li my_struct
+renamed to
+.Li my_structXYZ
+in an equivalent header in
+.Pa sys/compat/sys .
+After that, you can freely modify
+.Li my_struct
+as desired.
+.Ss Versioning the entry point
+The stub for the next version of the syscall will be
+.Fn __my_syscallXYZ ,
+and will have entry point
+.Fn sys___my_syscallXYZ .
+.Ss Modifying syscalls.conf
+.Pa sys/kern/syscalls.conf
+may need to be modified to contain
+.Li compat_XYZ
+in the
+.Li compatopts
+field.
+.Ss Modifying syscalls.master
+First, add the next syscall to
+.Pa sys/kern/syscalls.master
+keeping
+.Li my_syscall
+as the name, and set the (optional) compat field of the declaration to XYZ.
+.Pp
+Next, modify the current version of the syscall, and replace the type
+field (usually just STD) with
+.Li COMPAT_XYZ MODULAR compat_XYZ .
+.Pp
+The keyword
+.Li MODULAR
+indicates that the system call can be part of a kernel module.
+Even if the system call was not part of a module before, now it will be part
+of the
+.Li COMPAT_XYZ
+module.
+.Pp
+Finally, if applicable, replace the types of the current and old versions of the
+syscall with the compat type.
+.Pp
+Overall, the final diff should look like
+.Bd -literal
+- 123 STD                           { int|sys||my_syscall(struct my_struct *ms); }
++ 123 COMPAT_XYZ MODULAR compat_XYZ { int|sys||my_syscall(struct my_structXYZ *ms); }
+\&.\&.\&.
++ 456 STD               	    { int|sys|XYZ|my_syscall(struct my_struct *ms); }
+.Ed
+.Ss Modifying Makefile.rump
+If the current syscall is rump,
+.Pa sys/rump/Makefile.rump
+must contain
+.Li XYZ
+in the
+.Li RUMP_NBCOMPAT
+variable.
+.Ss Regenerating the system calls
+If versioning structs, then modify
+.Pa sys/kern/makesyscalls.sh
+by adding and entry for
+.Li struct my_structXYZ
+type to
+.Li uncompattypes .
+.Pp
+The
+.Li uncompattypes
+map is used in
+.Xr rump 7
+system call table generation, to map from the versioned types to the original
+names since
+.Xr rump 7
+wants to have a non-versioned copy of the system call table.
+.Pp
+Then regenerate the syscall tables in the usual way, first by running
+.Pa sys/kern/makesyscalls.sh ,
+then if the system call is rump, doing a build in
+.Pa sys/rump
+and then running
+.Pa sys/rump/makerumpsyscalls.sh
+passing it the path to the result of the build you just did as its first
+argument.
+.Sh KERNEL COMPATIBILITY
+This section covers maintaining compatibility at the kernel level, by
+adding an entry point for the current syscall in an appropriate compat
+module.
+For the purposes of this section, we assume the current
+syscall has entry point
+.Fn sys_my_syscall
+and lives inside
+.Pa sys/kern/my_file.c .
+.Ss Creating the compat current syscall
+The compat version of the current syscall has entry point
+.Fn compat_XYZ_sys_my_syscall ,
+and should be implemented in
+.Pa sys/compat/common/my_file_XYZ.c
+with the same semantics as the current syscall.
+Often this involves translating the arguments to the next syscall,
+and then calling that syscall's entry point.
+.Ss Adding it to the compat module
+.Pa sys/compat/common/my_file_XYZ.c
+must contain an array of
+.Ft struct syscall_package
+that declares the mapping between syscall number and entry point,
+terminating in a zero element (see sample diff below).
+.Pp
+Additionally,
+.Pa sys/compat/common/my_file_XYZ.c
+must contain two functions,
+.Fn my_file_XYZ_init
+and
+.Fn my_file_XYZ_fini
+that are used to initialize/clean up anything related to this syscall.
+At the minimum they must make calls to
+.Fn syscall_establish
+and
+.Fn syscall_disestablish
+respectively, adding and removing the syscalls.
+The stubs for these functions should be located in
+.Pa sys/compat/common/compat_mod.h .
+.Pp
+Overall,
+.Pa sys/compat/common/my_file_XYZ.c
+must at the minimum include
+.Bd -literal
++ static const struct syscall_package my_file_XYZ_syscalls[] = {
++ 	{ SYS_compat_XYZ_my_syscall, 0, (sy_call_t *)compat_XYZ_sys_my_syscall },
++ 	{ 0, 0, NULL },
++ };
++
++ int
++ compat_XYZ_my_syscall(...)
++ { /* Compat implementation goes here. */ }
++
++ int
++ my_file_XYZ_init(void)
++ { return syscall_establish(NULL, my_file_XYZ_syscalls); }
++
++ int
++ my_file_XYZ_fini(void)
++ { return syscall_disestablish(NULL, my_file_XYZ_syscalls); }
+.Ed
+.Pp
+Finally,
+.Pa sys/compat/common/compat_XYZ_mod.c
+needs to be be modified to have its
+.Fn compat_XYZ_init
+and
+.Fn compat_XYZ_fini
+functions call
+.Fn my_file_XYZ_init
+and
+.Fn my_file_XYZ_fini .
+.Ss Modifying old compat syscalls
+If the current syscall has already been versioned, you might need to
+modify the old compat syscalls in
+.Pa sys/compat/common
+to either use the next syscall or the current compat syscall.
+Note that compat code can be made to depend on compat code for more
+recent releases.
+.Sh USERLAND COMPATIBILITY
+With the exception of the libraries described below, making the rest of userland
+work will just involve recompiling, and perhaps changing a constant or a
+.Li #define .
+.Ss libc
+A userland version of any old and current versions of the syscall should be
+implemented in terms of the next syscall in
+.Pa lib/libc/compat/sys
+and should contain an appropriate call to
+.Fn __warn_references
+for old and current versions of the syscall.

Reply via email to