new file mode 100755
@@ -0,0 +1,213 @@
+#!/bin/sh -eu
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) Linux Test Project, 2009-2024
+# Copyright (c) Marcin Juszkiewicz, 2023-2024
+#
+# This is an adaptation of the update-tables.sh script, included in the
+# syscalls-table project (https://github.com/hrw/syscalls-table) and released
+# under the MIT license.
+#
+# Author: Andrea Cervesato <andrea.cervesato@suse.com>
+
+if [ "$#" -eq "0" ]; then
+ echo "Please provide kernel sources:"
+ echo ""
+ echo "$0 path/to/Linux/kernel/sources"
+ echo ""
+ exit 1
+fi
+
+KERNELSRC="$1"
+
+# to keep sorting in order
+export LC_ALL=C
+
+if [ ! -d "${KERNELSRC}" ]; then
+ echo "${KERNELSRC} is not a directory"
+ exit 1
+fi
+
+if [ ! -e "${KERNELSRC}/Makefile" ]; then
+ echo "No Makefile in ${KERNELSRC} directory"
+ exit 1
+fi
+
+TEMP="$(mktemp -d)"
+KVER="$(make -C ${KERNELSRC} kernelversion -s)"
+
+SCRIPT_DIR="$(realpath $(dirname "$0"))"
+SUPPORTED_ARCH="${SCRIPT_DIR}/supported-arch.txt"
+LINUX_HEADERS="${TEMP}/headers"
+
+grab_syscall_names_from_tables() {
+ for tbl_file in $(find ${KERNELSRC}/arch -name syscall*.tbl); do
+ grep -E -v "(^#|^$|sys_ni_syscall)" $tbl_file |
+ awk '{ print $3 }' >>${TEMP}/syscall-names.tosort
+ done
+
+ drop_bad_entries
+}
+
+grab_syscall_names_from_unistd_h() {
+ grep -E -h "^#define __NR_" \
+ ${LINUX_HEADERS}/usr/include/asm/unistd*.h \
+ ${LINUX_HEADERS}/usr/include/asm-generic/unistd.h \
+ >${TEMP}/syscall-names.tosort
+
+ drop_bad_entries
+}
+
+drop_bad_entries() {
+ grep -E -v "(unistd.h|NR3264|__NR_syscall|__SC_COMP|__NR_.*Linux|__NR_FAST)" \
+ ${TEMP}/syscall-names.tosort |
+ grep -E -v "(__SYSCALL|SYSCALL_BASE|SYSCALL_MASK)" |
+ sed -e "s/#define\s*__NR_//g" -e "s/\s.*//g" |
+ sort -u >${TEMP}/syscall-names.txt
+}
+
+generate_table() {
+ echo "- $arch"
+
+ if [ "$bits" -eq "32" ]; then
+ extraflags="${extraflags} -D__BITS_PER_LONG=32"
+ fi
+
+ local uppercase_arch=$(echo "$arch" | tr '[:lower:]' '[:upper:]')
+
+ # ignore any error generated by gcc. We want to obtain all the
+ # available architecture syscalls for the current platform and to handle
+ # only supported architectures later on
+ gcc ${TEMP}/list-syscalls.c -U__LP64__ -U__ILP32__ -U__i386__ \
+ -D${uppercase_arch} \
+ -D__${arch}__ ${extraflags} \
+ -I ${LINUX_HEADERS}/usr/include/ \
+ -o ${TEMP}/list-syscalls || true
+
+ ${TEMP}/list-syscalls >"${TEMP}/${arch}.in.tosort"
+
+ sort -k2,2n "${TEMP}/${arch}.in.tosort" >"${TEMP}/${arch}.in"
+}
+
+generate_list_syscalls_c() {
+ (
+ printf "
+ #include <stdio.h>
+ #include <asm/unistd.h>
+
+ int main(void)
+ {
+ "
+ for syscall in $(cat ${TEMP}/syscall-names.txt); do
+ printf "
+ #ifdef __NR_$syscall
+ printf(\"$syscall %%d"
+ # i know the following print is ugly, but dash and bash
+ # treat double quoted strings in a different way and we
+ # really need to inject '\n' character in the C code
+ # rather than carriage return
+ printf '\\n'
+ printf "\", __NR_$syscall);
+ #endif
+ "
+ done
+ printf " return 0;
+ }"
+ ) >${TEMP}/list-syscalls.c
+}
+
+export_headers() {
+ make -s -C ${KERNELSRC} ARCH=${arch} O=${LINUX_HEADERS} \
+ headers_install >/dev/null 2>&1
+}
+
+do_all_tables() {
+ for archdir in ${KERNELSRC}/arch/*; do
+ arch=$(basename $archdir)
+
+ bits=64
+ extraflags=
+
+ case ${arch} in
+ Kconfig)
+ continue
+ ;;
+ um)
+ continue
+ ;;
+ esac
+
+ export_headers
+ grab_syscall_names_from_unistd_h
+
+ case ${arch} in
+ arm)
+ bits=32
+ arch=armoabi extraflags= generate_table
+ arch=arm extraflags=-D__ARM_EABI__ generate_table
+ ;;
+ loongarch)
+ # 32-bit variant of loongarch may appear
+ arch=loongarch64 extraflags=-D_LOONGARCH_SZLONG=64 generate_table
+ ;;
+ mips)
+ arch=mips64 extraflags=-D_MIPS_SIM=_MIPS_SIM_ABI64 generate_table
+ bits=32
+ arch=mipso32 extraflags=-D_MIPS_SIM=_MIPS_SIM_ABI32 generate_table
+ arch=mips64n32 extraflags=-D_MIPS_SIM=_MIPS_SIM_NABI32 generate_table
+ ;;
+ powerpc)
+ generate_table
+ arch=powerpc64 generate_table
+ ;;
+ riscv)
+ arch=riscv64 extraflags=-D__LP64__ generate_table
+ bits=32
+ arch=riscv32 extraflags=-D__SIZEOF_POINTER__=4 generate_table
+ ;;
+ s390)
+ bits=32
+ generate_table
+ bits=64
+ arch=s390x generate_table
+ ;;
+ sparc)
+ bits=32
+ extraflags=-D__32bit_syscall_numbers__ generate_table
+ bits=64
+ arch=sparc64 extraflags=-D__arch64__ generate_table
+ ;;
+ x86)
+ arch=x86_64 extraflags=-D__LP64__ generate_table
+ bits=32
+ arch=i386 generate_table
+ arch=x32 extraflags=-D__ILP32__ generate_table
+ ;;
+ arc | csky | hexagon | m68k | microblaze | nios2 | openrisc | sh | xtensa)
+ bits=32 generate_table
+ ;;
+ *)
+ generate_table
+ ;;
+ esac
+ done
+}
+
+copy_supported_arch() {
+ while IFS= read -r arch; do
+ if [ -f "${TEMP}/${arch}.in" ]; then
+ echo "- ${arch}"
+ cp "${TEMP}/${arch}.in" "${SCRIPT_DIR}/${arch}.in"
+ fi
+ done <${SUPPORTED_ARCH}
+}
+
+echo "Temporary directory ${TEMP}"
+echo "Extracting syscalls"
+
+grab_syscall_names_from_tables
+generate_list_syscalls_c
+
+do_all_tables
+
+echo "Copying supported syscalls"
+copy_supported_arch