Commit 3a790cc1 authored by Sven Schnelle's avatar Sven Schnelle Committed by Vasily Gorbik
Browse files

s390: pass struct pt_regs instead of registers to syscalls



Instead of fetching all registers from struct pt_regs and passing
them to the syscall wrappers, let the system call wrappers only
fetch the values really required.

Signed-off-by: default avatarSven Schnelle <svens@linux.ibm.com>
Reviewed-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 39589ada
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -40,9 +40,7 @@
#include <asm/fpu/internal.h>
#include <asm/irqflags.h>

typedef long (*sys_call_ptr_t)(unsigned long, unsigned long,
			       unsigned long, unsigned long,
			       unsigned long, unsigned long);
typedef long (*sys_call_ptr_t)(struct pt_regs *regs);

static inline void set_cpu_flag(int flag)
{
+72 −42
Original line number Diff line number Diff line
@@ -7,6 +7,33 @@
#ifndef _ASM_S390_SYSCALL_WRAPPER_H
#define _ASM_S390_SYSCALL_WRAPPER_H

#define __SC_TYPE(t, a) t

#define SYSCALL_PT_ARG6(regs, m, t1, t2, t3, t4, t5, t6)\
	SYSCALL_PT_ARG5(regs, m, t1, t2, t3, t4, t5),	\
		m(t6, (regs->gprs[7]))

#define SYSCALL_PT_ARG5(regs, m, t1, t2, t3, t4, t5)	\
	SYSCALL_PT_ARG4(regs, m, t1, t2, t3, t4),	\
		m(t5, (regs->gprs[6]))

#define SYSCALL_PT_ARG4(regs, m, t1, t2, t3, t4)	\
	SYSCALL_PT_ARG3(regs, m, t1, t2, t3),		\
		m(t4, (regs->gprs[5]))

#define SYSCALL_PT_ARG3(regs, m, t1, t2, t3)		\
	SYSCALL_PT_ARG2(regs, m, t1, t2),		\
		m(t3, (regs->gprs[4]))

#define SYSCALL_PT_ARG2(regs, m, t1, t2)		\
	SYSCALL_PT_ARG1(regs, m, t1),			\
		m(t2, (regs->gprs[3]))

#define SYSCALL_PT_ARG1(regs, m, t1)			\
		m(t1, (regs->orig_gpr2))

#define SYSCALL_PT_ARGS(x, ...) SYSCALL_PT_ARG##x(__VA_ARGS__)

#ifdef CONFIG_COMPAT
#define __SC_COMPAT_TYPE(t, a) \
	__typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
@@ -30,11 +57,12 @@
})

#define __S390_SYS_STUBx(x, name, ...)						\
	long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));		\
	long __s390_sys##name(struct pt_regs *regs);				\
	ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO);				\
	long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))		\
	long __s390_sys##name(struct pt_regs *regs)				\
	{									\
		long ret = __s390x_sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));\
		long ret = __do_sys##name(SYSCALL_PT_ARGS(x, regs,		\
			__SC_COMPAT_CAST, __MAP(x, __SC_TYPE, __VA_ARGS__)));	\
		__MAP(x,__SC_TEST,__VA_ARGS__);					\
		return ret;							\
	}
@@ -69,15 +97,16 @@
	__diag_push();									\
	__diag_ignore(GCC, 8, "-Wattribute-alias",					\
		      "Type aliasing is used to sanitize syscall arguments");		\
	long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));		\
	long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))		\
	long __s390_compat_sys##name(struct pt_regs *regs);				\
	long __s390_compat_sys##name(struct pt_regs *regs)				\
		__attribute__((alias(__stringify(__se_compat_sys##name))));		\
	ALLOW_ERROR_INJECTION(__s390_compat_sys##name, ERRNO);				\
	static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));	\
	long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));		\
	long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))		\
	long __se_compat_sys##name(struct pt_regs *regs);				\
	long __se_compat_sys##name(struct pt_regs *regs)				\
	{										\
		long ret = __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\
		long ret = __do_compat_sys##name(SYSCALL_PT_ARGS(x, regs, __SC_DELOUSE,	\
						 __MAP(x, __SC_TYPE, __VA_ARGS__)));	\
		__MAP(x,__SC_TEST,__VA_ARGS__);						\
		return ret;								\
	}										\
@@ -117,15 +146,16 @@
	__diag_push();									\
	__diag_ignore(GCC, 8, "-Wattribute-alias",					\
		      "Type aliasing is used to sanitize syscall arguments");		\
	long __s390x_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))			\
	long __s390x_sys##name(struct pt_regs *regs)					\
		__attribute__((alias(__stringify(__se_sys##name))));			\
	ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO);				\
	long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));			\
	static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));		\
	long __se_sys##name(struct pt_regs *regs);					\
	__S390_SYS_STUBx(x, name, __VA_ARGS__)						\
	long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))			\
	long __se_sys##name(struct pt_regs *regs)					\
	{										\
		long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));	\
		long ret = __do_sys##name(SYSCALL_PT_ARGS(x, regs,			\
				    __SC_CAST, __MAP(x, __SC_TYPE, __VA_ARGS__)));	\
		__MAP(x,__SC_TEST,__VA_ARGS__);						\
		return ret;								\
	}										\
+2 −6
Original line number Diff line number Diff line
@@ -132,12 +132,8 @@ void do_syscall(struct pt_regs *regs)
	 */
	if (!test_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)) {
		regs->gprs[2] = -ENOSYS;
		if (likely(nr < NR_syscalls)) {
			regs->gprs[2] = current->thread.sys_call_table[nr](
					regs->orig_gpr2, regs->gprs[3],
					regs->gprs[4], regs->gprs[5],
					regs->gprs[6], regs->gprs[7]);
		}
		if (likely(nr < NR_syscalls))
			regs->gprs[2] = current->thread.sys_call_table[nr](regs);
	} else {
		clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET);
	}