s390/syscalls: add syscalltbl script
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>
Thu, 7 Dec 2017 14:36:36 +0000 (15:36 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 23 Jan 2018 06:36:51 +0000 (07:36 +0100)
Introduce the syscalltbl script to read the system call table and
generate respective uapi unistd.h header files.  Also it generates
the contents syscalls.S - the real system call table - which is
included by arch/s390/kernel/entry.S.

Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/syscalls/syscalltbl [new file with mode: 0755]

diff --git a/arch/s390/kernel/syscalls/syscalltbl b/arch/s390/kernel/syscalls/syscalltbl
new file mode 100755 (executable)
index 0000000..fbac173
--- /dev/null
@@ -0,0 +1,232 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generate system call table and header files
+#
+# Copyright IBM Corp. 2018
+# Author(s):  Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+
+#
+# File path to the system call table definition.
+# You can set the path with the -i option.  If omitted,
+# system call table definitions are read from standard input.
+#
+SYSCALL_TBL=""
+
+
+create_syscall_table_entries()
+{
+       local nr abi name entry64 entry32 _ignore
+       local temp=$(mktemp ${TMPDIR:-/tmp}/syscalltbl-common.XXXXXXXXX)
+
+       (
+       #
+       # Initialize with 0 to create an NI_SYSCALL for 0
+       #
+       local prev_nr=0 prev_32=sys_ni_syscall prev_64=sys_ni_syscall
+       while read nr abi name entry64 entry32 _ignore; do
+               test x$entry32 = x- && entry32=sys_ni_syscall
+               test x$entry64 = x- && entry64=sys_ni_syscall
+
+               if test $prev_nr -eq $nr; then
+                       #
+                       # Same syscall but different ABI, just update
+                       # the respective entry point
+                       #
+                       case $abi in
+                       32)
+                               prev_32=$entry32
+                       ;;
+                       64)
+                               prev_64=$entry64
+                       ;;
+                       esac
+                       continue;
+               else
+                       printf "%d\t%s\t%s\n" $prev_nr $prev_64 $prev_32
+               fi
+
+               prev_nr=$nr
+               prev_64=$entry64
+               prev_32=$entry32
+       done
+       printf "%d\t%s\t%s\n" $prev_nr $prev_64 $prev_32
+       ) >> $temp
+
+       #
+       # Check for duplicate syscall numbers
+       #
+       if ! cat $temp |cut -f1 |uniq -d 2>&1; then
+               echo "Error: generated system call table contains duplicate entries: $temp" >&2
+               exit 1
+       fi
+
+       #
+       # Generate syscall table
+       #
+       prev_nr=0
+       while read nr entry64 entry32; do
+               while test $prev_nr -lt $((nr - 1)); do
+                       printf "NI_SYSCALL\n"
+                       prev_nr=$((prev_nr + 1))
+               done
+               if test x$entry64 = xsys_ni_syscall &&
+                  test x$entry32 = xsys_ni_syscall; then
+                       printf "NI_SYSCALL\n"
+               else
+                       printf "SYSCALL(%s,%s)\n" $entry64 $entry32
+               fi
+               prev_nr=$nr
+       done < $temp
+       rm $temp
+}
+
+generate_syscall_table()
+{
+       cat <<-EoHEADER
+       /* SPDX-License-Identifier: GPL-2.0 */
+       /*
+        * Definitions for sys_call_table, each line represents an
+        * entry in the table in the form
+        * SYSCALL(64 bit syscall, 31 bit emulated syscall)
+        *
+        * This file is meant to be included from entry.S.
+        */
+
+       #define NI_SYSCALL SYSCALL(sys_ni_syscall,sys_ni_syscall)
+
+EoHEADER
+       grep -Ev '^(#|[[:blank:]]*$)' $SYSCALL_TBL      \
+               |sort -k1 -n                            \
+               |create_syscall_table_entries
+}
+
+create_header_defines()
+{
+       local nr abi name _ignore
+
+       while read nr abi name _ignore; do
+               printf "#define __NR_%s %d\n" $name $nr
+       done
+}
+
+normalize_fileguard()
+{
+       local fileguard="$1"
+
+       echo "$1" |tr '[[:lower:]]' '[[:upper:]]' \
+                 |sed -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'
+}
+
+generate_syscall_header()
+{
+       local abis=$(echo "($1)" | tr ',' '|')
+       local filename="$2"
+       local fileguard suffix
+
+       if test "$filename"; then
+               fileguard=$(normalize_fileguard "__UAPI_ASM_S390_$2")
+       else
+               case "$abis" in
+               *64*) suffix=64 ;;
+               *32*) suffix=32 ;;
+               esac
+               fileguard=$(normalize_fileguard "__UAPI_ASM_S390_SYSCALLS_$suffix")
+       fi
+
+       cat <<-EoHEADER
+       /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+       #ifndef ${fileguard}
+       #define ${fileguard}
+
+EoHEADER
+
+       grep -E "^[[:digit:]]+[[:space:]]+${abis}" $SYSCALL_TBL \
+               |sort -k1 -n                                    \
+               |create_header_defines
+
+       cat <<-EoFOOTER
+
+       #endif /* ${fileguard} */
+EoFOOTER
+}
+
+__max_syscall_nr()
+{
+       local abis=$(echo "($1)" | tr ',' '|')
+
+       grep -E "^[[:digit:]]+[[:space:]]+${abis}" $SYSCALL_TBL  \
+               |sed -ne 's/^\([[:digit:]]*\)[[:space:]].*/\1/p' \
+               |sort -n                                         \
+               |tail -1
+}
+
+
+generate_syscall_nr()
+{
+       local abis="$1"
+       local max_syscall_nr num_syscalls
+
+       max_syscall_nr=$(__max_syscall_nr "$abis")
+       num_syscalls=$((max_syscall_nr + 1))
+
+       cat <<-EoHEADER
+       /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+       #ifndef __ASM_S390_SYSCALLS_NR
+       #define __ASM_S390_SYSCALLS_NR
+
+       #define NR_syscalls ${num_syscalls}
+
+       #endif /* __ASM_S390_SYSCALLS_NR */
+EoHEADER
+}
+
+
+#
+# Parse command line arguments
+#
+do_syscall_header=""
+do_syscall_table=""
+do_syscall_nr=""
+output_file=""
+abi_list="common,64"
+filename=""
+while getopts ":HNSXi:a:f:" arg; do
+       case $arg in
+       a)
+               abi_list="$OPTARG"
+               ;;
+       i)
+               SYSCALL_TBL="$OPTARG"
+               ;;
+       f)
+               filename=${OPTARG##*/}
+               ;;
+       H)
+               do_syscall_header=1
+               ;;
+       N)
+               do_syscall_nr=1
+               ;;
+       S)
+               do_syscall_table=1
+               ;;
+       X)
+               set -x
+               ;;
+       :)
+               echo "Missing argument for -$OPTARG" >&2
+               exit 1
+       ;;
+       \?)
+               echo "Invalid option specified" >&2
+               exit 1
+       ;;
+       esac
+done
+
+test "$do_syscall_header" && generate_syscall_header "$abi_list" "$filename"
+test "$do_syscall_table" && generate_syscall_table
+test "$do_syscall_nr" && generate_syscall_nr "$abi_list"
+
+exit 0