Re: [PATCH 0/3] syscalls: clean up stub naming convention

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Apr 08, 2018 at 11:15:36AM +0200, Dominik Brodowski wrote:
> On a somewhat related note: I'll try to prepare a patch this evening which
> lets us build just the __ia32_sys and __x32_compat_sys stubs we actually
> need. We have that information already in entry/syscalls/syscall_{32,64}.tbl,
> it just needs to be extracted into another header file (in the form of
> 	#define NEED_IA32_sys_xyzzz 1
> ) and then tested within the stubs. After some randconfig testing, this
> might be worthwile to add on top of the patches already in tip-asm and the
> three renaming patches currently under discussion.

So this got a bit more complicated than I though, for a -5k text size
decrease. I have my doubts whether the increased code complexity is really
worth that minor size decrease. I'll send another patch shortly, though,
which fixes up the naming of a few macros in <asm/syscall_wrapper.h>.

--------------------------------------------------------------------------
From: Dominik Brodowski <linux@xxxxxxxxxxxxxxxxxxxx>
Date: Sun, 8 Apr 2018 21:38:54 +0200
Subject: [PATCH] syscalls/x86: only build stubs which are actually needed

A new script arch/x86/entry/syscalls/syscallstubs.sh generates
defines in <asm/syscall_stubs.h>

	for all __ia32_sys_ stubs which are actually needed for
	IA32_EMULATION,

and

	for all __x32_compat_sys_ stubs which are actually needed
	for X32.

By omitting to build the remaining stubs (which are defined as
__SYSCALL_STUBx_UNUSED), there is a measurable decrease in kernel
size (-5k):

    text    data      bss      dec     hex filename
12892057 7094202 13570252 33556511 200081f vmlinux-orig
12886397 7087514 13570252 33544163 1ffd7e3 vmlinux

Further size cuttings could be achieved by not building stubs for
syscalls and compat_syscalls which are not referenced in the syscall
tables, such as (at least)

	sys_gethostname
	sys_sync_file_range2
	sys_send
	sys_recv
	compat_sys_mbind
	compat_sys_set_mempolicy
	compat_sys_migrate_pages
	compat_sys_sendtimedop
	compat_sys_msgrcv
	compat_sys_semctl
	compat_sys_send
	compat_sys_recv

Not-yet-signed-off-by: Dominik Brodowski <linux@xxxxxxxxxxxxxxxxxxxx>

diff --git a/arch/x86/entry/syscalls/Makefile b/arch/x86/entry/syscalls/Makefile
index 6fb9b57ed5ba..036199136513 100644
--- a/arch/x86/entry/syscalls/Makefile
+++ b/arch/x86/entry/syscalls/Makefile
@@ -11,6 +11,7 @@ syscall64 := $(srctree)/$(src)/syscall_64.tbl
 
 syshdr := $(srctree)/$(src)/syscallhdr.sh
 systbl := $(srctree)/$(src)/syscalltbl.sh
+sysstubs := $(srctree)/$(src)/syscallstubs.sh
 
 quiet_cmd_syshdr = SYSHDR  $@
       cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' '$<' '$@' \
@@ -20,6 +21,11 @@ quiet_cmd_syshdr = SYSHDR  $@
 quiet_cmd_systbl = SYSTBL  $@
       cmd_systbl = $(CONFIG_SHELL) '$(systbl)' $< $@
 
+quiet_cmd_sysstubs = SYSSTUBS  $@
+      cmd_sysstubs = $(CONFIG_SHELL) '$(sysstubs)' \
+		   '$(syscall32)' '$(syscall64)' \
+		    $@
+
 quiet_cmd_hypercalls = HYPERCALLS $@
       cmd_hypercalls = $(CONFIG_SHELL) '$<' $@ $(filter-out $<,$^)
 
@@ -51,6 +57,9 @@ $(out)/syscalls_32.h: $(syscall32) $(systbl)
 $(out)/syscalls_64.h: $(syscall64) $(systbl)
 	$(call if_changed,systbl)
 
+$(out)/syscall_stubs.h:  $(syscall32) $(syscall64) $(sysstubs)
+	$(call if_changed,sysstubs)
+
 $(out)/xen-hypercalls.h: $(srctree)/scripts/xen-hypercalls.sh
 	$(call if_changed,hypercalls)
 
@@ -60,6 +69,7 @@ uapisyshdr-y			+= unistd_32.h unistd_64.h unistd_x32.h
 syshdr-y			+= syscalls_32.h
 syshdr-$(CONFIG_X86_64)		+= unistd_32_ia32.h unistd_64_x32.h
 syshdr-$(CONFIG_X86_64)		+= syscalls_64.h
+syshdr-$(CONFIG_X86_64)		+= syscall_stubs.h
 syshdr-$(CONFIG_XEN)		+= xen-hypercalls.h
 
 targets	+= $(uapisyshdr-y) $(syshdr-y)
diff --git a/arch/x86/entry/syscalls/syscallstubs.sh b/arch/x86/entry/syscalls/syscallstubs.sh
new file mode 100644
index 000000000000..4db64d4db75a
--- /dev/null
+++ b/arch/x86/entry/syscalls/syscallstubs.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+in32="$1"
+in64="$2"
+out="$3"
+
+emit_stub() {
+    entry="$1"
+    if [ "${entry}" != "${entry#__ia32_sys_}" ]; then
+	# We need a stub named __ia32_sys which is common to 64-bit
+	# except for a different pt_regs layout.
+	stubname=${entry#__ia32_sys_}
+	echo "#define __IA32_SYS_STUBx_${stubname} __IA32_SYS_STUBx"
+	echo "#define ASM_X86_HAS__ia32_sys_${stubname} 1"
+    elif [ "$entry" != "${entry#__x32_compat_sys}" ]; then
+	# We need a stub named __x32_compat_sys_ which decodes a
+	# 64-bit pt_regs and then calls the real syscall function 
+	stubname="${entry%%/*}" # handle qualifier
+	stubname=${stubname#__x32_compat_sys_} # handle prefix
+	echo "#define __X32_COMPAT_SYS_STUBx_${stubname} __X32_COMPAT_SYS_STUBx"
+	echo "#define ASM_X86_HAS__x32_compat_sys_${stubname} 1"
+    elif [ "$entry" != "${entry#__ia32_compat_sys_x86}" ]; then
+	# The compat entry starts with __ia32_compat_sys_x86, so it
+	# is a specific x86 compat syscall; no need for __ia32_sys_*()
+	stubname=${entry#__ia32_compat_sys_x86_}
+	echo "#define __IA32_SYS_STUBx_${stubname} __SYSCALL_STUBx_UNUSED"
+	echo "#define ASM_X86_HAS__ia32_sys_${stubname} 1"
+    elif [ "$entry" != "${entry#__ia32_compat_sys_}" ]; then
+	# The compat entry starts with __ia32_compat_sys, so it is
+	# is a generic x86 compat syscall; no need for __ia32_sys_*()
+	stubname=${entry#__ia32_compat_sys_}
+	echo "#define __IA32_SYS_STUBx_${stubname} __SYSCALL_STUBx_UNUSED"
+	echo "#define ASM_X86_HAS__ia32_sys_${stubname} 1"
+    fi;
+}
+
+# First, we need to check which stubs we *need*. While at it, we can determine
+# quite many ia32 stubs we do *not* need as the syscall is handled by a compat
+# syscall
+grep '^[0-9]' "$in32" | sort -n | (
+    while read nr abi name entry compat; do
+	abi=`echo "$abi" | tr '[a-z]' '[A-Z]'`
+	if [ "$abi" = "I386" -a -n "$compat" ]; then
+	    emit_stub "$compat"
+	fi
+    done
+) > "$out"
+
+grep '^[0-9]' "$in64" | sort -n | (
+    while read nr abi name entry compat; do
+	abi=`echo "$abi" | tr '[a-z]' '[A-Z]'`
+	if [ "$abi" = "X32" -a -n "$entry" ]; then
+	    emit_stub "$entry"
+	fi
+    done
+) >> "$out"
+
+# Then, we need to determine all (remaining) stubs we *do not* need.
+grep '^[0-9]' "$in64" | sort -n | (
+    while read nr abi name entry compat; do
+	abi=`echo "$abi" | tr '[a-z]' '[A-Z]'`
+	if [ "$abi" = "COMMON" -o "$abi" = "64" ]; then
+	    if [ -n "$entry" -a "$entry" != "${entry#__x64_sys_}" ]; then
+		# what's the actual stubname?
+		stubname="${entry%%/*}" # handle qualifier
+		stubname="${stubname#__x64_sys_}" # handle prefix
+
+		# syscalls only referenced for 64-bit do not need a stub for
+		# IA32_EMULATION
+		echo "#ifndef ASM_X86_HAS__ia32_sys_${stubname}"
+		echo "#define __IA32_SYS_STUBx_${stubname} __SYSCALL_STUBx_UNUSED"
+		echo "#endif"
+
+		# A number of compat syscalls are built in even though they are
+		# completely unused -- e.g. mbind set_mempolicy migrate_pages
+		# sendtimedop msgrcv semctl. We probably define more compat
+		# syscalls than exist, but better be safe than sorry...
+		echo "#ifndef ASM_X86_HAS__x32_compat_sys_${stubname}"
+		echo "#define __X32_COMPAT_SYS_STUBx_${stubname} __SYSCALL_STUBx_UNUSED"
+		echo "#endif"
+	    fi
+	fi
+    done
+) >> "$out"
+
+grep '^[0-9]' "$in32" | sort -n | (
+    while read nr abi name entry compat; do
+	abi=`echo "$abi" | tr '[a-z]' '[A-Z]'`
+	if [ "$abi" = "I386" -a -n "$compat" ]; then
+	    if [ "$compat" != "${compat#__ia32_compat_sys}" ]; then
+		stubname="${compat#__ia32_compat_sys_}"
+		# If a compat syscall is not needed for x32 (see above),
+		# we need to assert that the stub is defined as unused
+		echo "#ifndef ASM_X86_HAS__x32_compat_sys_${stubname}"
+		echo "#define __X32_COMPAT_SYS_STUBx_${stubname} __SYSCALL_STUBx_UNUSED"
+		echo "#endif"
+	    fi
+	fi
+    done
+) >> "$out"
+
+# FIXME: These syscalls get build even though they are completely unused on x86
+( for unused_syscall in gethostname sync_file_range2 send recv; do
+    echo "#define __IA32_SYS_STUBx_${unused_syscall} __SYSCALL_STUBx_UNUSED"
+done ) >> "$out"
+( for unused_compat_syscall in send recv; do
+    echo "#define __X32_COMPAT_SYS_STUBx_${unused_compat_syscall} __SYSCALL_STUBx_UNUSED"
+done ) >> "$out"
+
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index de690c2d2e33..3aeb3a794da4 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -5,6 +5,7 @@ generated-y += syscalls_64.h
 generated-y += unistd_32_ia32.h
 generated-y += unistd_64_x32.h
 generated-y += xen-hypercalls.h
+generated-y += syscall_stubs.h
 
 generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h
index bad0295739bf..0b847f422bf6 100644
--- a/arch/x86/include/asm/syscall_wrapper.h
+++ b/arch/x86/include/asm/syscall_wrapper.h
@@ -4,7 +4,10 @@
  */
 
 #ifndef _ASM_X86_SYSCALL_WRAPPER_H
-#define _ASM_X86_SYSCALL_WRAPPER_H
+#define _ASM_X86_SYSCALL_WRAPPER_H 1
+
+#define __SYSCALL_STUBx_UNUSED(x, name, ...)
+#include <asm/syscall_stubs.h>
 
 /* Mapping of registers to parameters for syscalls on x86-64 and x32 */
 #define SC_X86_64_REGS_TO_ARGS(x, ...)					\
@@ -28,15 +31,15 @@
  * kernel/sys_ni.c and SYS_NI in kernel/time/posix-stubs.c to cover this
  * case as well.
  */
-#define COMPAT_SC_IA32_STUBx(x, name, ...)				\
+#define __IA32_COMPAT_SYS_STUBx(x, name, ...)				\
 	asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs);\
 	ALLOW_ERROR_INJECTION(__ia32_compat_sys##name, ERRNO);		\
 	asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs)\
 	{								\
 		return __do_compat_sys##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\
-	}								\
+	}
 
-#define SC_IA32_WRAPPERx(x, name, ...)					\
+#define __IA32_SYS_STUBx(x, name, ...)					\
 	asmlinkage long __ia32_sys##name(const struct pt_regs *regs);	\
 	ALLOW_ERROR_INJECTION(__ia32_sys##name, ERRNO);			\
 	asmlinkage long __ia32_sys##name(const struct pt_regs *regs)	\
@@ -64,8 +67,8 @@
 	SYSCALL_ALIAS(__ia32_sys_##name, sys_ni_posix_timers)
 
 #else /* CONFIG_IA32_EMULATION */
-#define COMPAT_SC_IA32_STUBx(x, name, ...)
-#define SC_IA32_WRAPPERx(x, fullname, name, ...)
+#define __IA32_COMPAT_SYS_STUBx(x, name, ...)
+#define __IA32_SYS_STUBx(x, name, ...)
 #endif /* CONFIG_IA32_EMULATION */
 
 
@@ -75,7 +78,7 @@
  * of the x86-64-style parameter ordering of x32 syscalls. The syscalls common
  * with x86_64 obviously do not need such care.
  */
-#define COMPAT_SC_X32_STUBx(x, name, ...)				\
+#define __X32_COMPAT_SYS_STUBx(x, name, ...)				\
 	asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs);\
 	ALLOW_ERROR_INJECTION(__x32_compat_sys##name, ERRNO);		\
 	asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs)\
@@ -84,7 +87,7 @@
 	}								\
 
 #else /* CONFIG_X86_X32 */
-#define COMPAT_SC_X32_STUBx(x, name, ...)
+#define __X32_COMPAT_SYS_STUBx(x, name, ...)
 #endif /* CONFIG_X86_X32 */
 
 
@@ -97,8 +100,8 @@
 #define COMPAT_SYSCALL_DEFINEx(x, name, ...)					\
 	static long __do_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));	\
 	static inline long __in_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
-	COMPAT_SC_IA32_STUBx(x, name, __VA_ARGS__)				\
-	COMPAT_SC_X32_STUBx(x, name, __VA_ARGS__)				\
+	__IA32_COMPAT_SYS_STUBx(x, name, __VA_ARGS__)				\
+	__X32_COMPAT_SYS_STUBx##name(x, name, __VA_ARGS__)			\
 	static long __do_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))	\
 	{									\
 		return __in_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\
@@ -120,7 +123,6 @@
 
 #endif /* CONFIG_COMPAT */
 
-
 /*
  * Instead of the generic __SYSCALL_DEFINEx() definition, this macro takes
  * struct pt_regs *regs as the only argument of the syscall stub named
@@ -163,7 +165,7 @@
 	{								\
 		return __do_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\
 	}								\
-	SC_IA32_WRAPPERx(x, name, __VA_ARGS__)				\
+	__IA32_SYS_STUBx##name(x, name, __VA_ARGS__)			\
 	static long __do_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))	\
 	{								\
 		long ret = __in_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\



[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux