diff options
Diffstat (limited to 'arch/s390/kernel')
50 files changed, 3629 insertions, 2804 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 4bb2a465616..a95c4ca9961 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -28,7 +28,7 @@ CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'  CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w -obj-y	:= bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o +obj-y	:= traps.o time.o process.o base.o early.o setup.o vtime.o  obj-y	+= processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o  obj-y	+= debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o  obj-y	+= sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o @@ -47,9 +47,8 @@ obj-$(CONFIG_SCHED_BOOK)	+= topology.o  obj-$(CONFIG_HIBERNATION)	+= suspend.o swsusp_asm64.o  obj-$(CONFIG_AUDIT)		+= audit.o  compat-obj-$(CONFIG_AUDIT)	+= compat_audit.o -obj-$(CONFIG_COMPAT)		+= compat_linux.o compat_signal.o \ -					compat_wrapper.o compat_exec_domain.o \ -					$(compat-obj-y) +obj-$(CONFIG_COMPAT)		+= compat_linux.o compat_signal.o +obj-$(CONFIG_COMPAT)		+= compat_wrapper.o $(compat-obj-y)  obj-$(CONFIG_STACKTRACE)	+= stacktrace.o  obj-$(CONFIG_KPROBES)		+= kprobes.o @@ -60,7 +59,8 @@ obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o  obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o  ifdef CONFIG_64BIT -obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o perf_cpum_cf.o +obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o perf_cpum_cf.o perf_cpum_sf.o \ +						perf_cpum_cf_events.o  obj-y				+= runtime_instr.o cache.o  endif diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 2416138ebd3..afe1715a4eb 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -50,6 +50,7 @@ int main(void)  	DEFINE(__PT_INT_CODE, offsetof(struct pt_regs, int_code));  	DEFINE(__PT_INT_PARM, offsetof(struct pt_regs, int_parm));  	DEFINE(__PT_INT_PARM_LONG, offsetof(struct pt_regs, int_parm_long)); +	DEFINE(__PT_FLAGS, offsetof(struct pt_regs, flags));  	DEFINE(__PT_SIZE, sizeof(struct pt_regs));  	BLANK();  	DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain)); @@ -65,12 +66,14 @@ int main(void)  	DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));  	DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));  	DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available)); -	DEFINE(__VDSO_NTP_MULT, offsetof(struct vdso_data, ntp_mult)); +	DEFINE(__VDSO_TK_MULT, offsetof(struct vdso_data, tk_mult)); +	DEFINE(__VDSO_TK_SHIFT, offsetof(struct vdso_data, tk_shift));  	DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base));  	DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time));  	/* constants used by the vdso */  	DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);  	DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC); +	DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);  	DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);  	BLANK();  	/* idle data offsets */ @@ -87,16 +90,22 @@ int main(void)  	DEFINE(__LC_PGM_ILC, offsetof(struct _lowcore, pgm_ilc));  	DEFINE(__LC_PGM_INT_CODE, offsetof(struct _lowcore, pgm_code));  	DEFINE(__LC_TRANS_EXC_CODE, offsetof(struct _lowcore, trans_exc_code)); -	DEFINE(__LC_PER_CAUSE, offsetof(struct _lowcore, per_perc_atmid)); +	DEFINE(__LC_MON_CLASS_NR, offsetof(struct _lowcore, mon_class_num)); +	DEFINE(__LC_PER_CODE, offsetof(struct _lowcore, per_code)); +	DEFINE(__LC_PER_ATMID, offsetof(struct _lowcore, per_atmid));  	DEFINE(__LC_PER_ADDRESS, offsetof(struct _lowcore, per_address)); -	DEFINE(__LC_PER_PAID, offsetof(struct _lowcore, per_access_id)); -	DEFINE(__LC_AR_MODE_ID, offsetof(struct _lowcore, ar_access_id)); +	DEFINE(__LC_EXC_ACCESS_ID, offsetof(struct _lowcore, exc_access_id)); +	DEFINE(__LC_PER_ACCESS_ID, offsetof(struct _lowcore, per_access_id)); +	DEFINE(__LC_OP_ACCESS_ID, offsetof(struct _lowcore, op_access_id)); +	DEFINE(__LC_AR_MODE_ID, offsetof(struct _lowcore, ar_mode_id)); +	DEFINE(__LC_MON_CODE, offsetof(struct _lowcore, monitor_code));  	DEFINE(__LC_SUBCHANNEL_ID, offsetof(struct _lowcore, subchannel_id));  	DEFINE(__LC_SUBCHANNEL_NR, offsetof(struct _lowcore, subchannel_nr));  	DEFINE(__LC_IO_INT_PARM, offsetof(struct _lowcore, io_int_parm));  	DEFINE(__LC_IO_INT_WORD, offsetof(struct _lowcore, io_int_word));  	DEFINE(__LC_STFL_FAC_LIST, offsetof(struct _lowcore, stfl_fac_list));  	DEFINE(__LC_MCCK_CODE, offsetof(struct _lowcore, mcck_interruption_code)); +	DEFINE(__LC_MCCK_EXT_DAM_CODE, offsetof(struct _lowcore, external_damage_code));  	DEFINE(__LC_RST_OLD_PSW, offsetof(struct _lowcore, restart_old_psw));  	DEFINE(__LC_EXT_OLD_PSW, offsetof(struct _lowcore, external_old_psw));  	DEFINE(__LC_SVC_OLD_PSW, offsetof(struct _lowcore, svc_old_psw)); @@ -113,6 +122,7 @@ int main(void)  	DEFINE(__LC_SAVE_AREA_SYNC, offsetof(struct _lowcore, save_area_sync));  	DEFINE(__LC_SAVE_AREA_ASYNC, offsetof(struct _lowcore, save_area_async));  	DEFINE(__LC_SAVE_AREA_RESTART, offsetof(struct _lowcore, save_area_restart)); +	DEFINE(__LC_CPU_FLAGS, offsetof(struct _lowcore, cpu_flags));  	DEFINE(__LC_RETURN_PSW, offsetof(struct _lowcore, return_psw));  	DEFINE(__LC_RETURN_MCCK_PSW, offsetof(struct _lowcore, return_mcck_psw));  	DEFINE(__LC_SYNC_ENTER_TIMER, offsetof(struct _lowcore, sync_enter_timer)); @@ -134,12 +144,12 @@ int main(void)  	DEFINE(__LC_RESTART_FN, offsetof(struct _lowcore, restart_fn));  	DEFINE(__LC_RESTART_DATA, offsetof(struct _lowcore, restart_data));  	DEFINE(__LC_RESTART_SOURCE, offsetof(struct _lowcore, restart_source)); +	DEFINE(__LC_KERNEL_ASCE, offsetof(struct _lowcore, kernel_asce));  	DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));  	DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));  	DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));  	DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags));  	DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); -	DEFINE(__LC_IRB, offsetof(struct _lowcore, irb));  	DEFINE(__LC_DUMP_REIPL, offsetof(struct _lowcore, ipib));  	BLANK();  	DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area)); @@ -153,6 +163,8 @@ int main(void)  #ifdef CONFIG_32BIT  	DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));  #else /* CONFIG_32BIT */ +	DEFINE(__LC_DATA_EXC_CODE, offsetof(struct _lowcore, data_exc_code)); +	DEFINE(__LC_MCCK_FAIL_STOR_ADDR, offsetof(struct _lowcore, failing_storage_address));  	DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2));  	DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area));  	DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste)); diff --git a/arch/s390/kernel/bitmap.c b/arch/s390/kernel/bitmap.c deleted file mode 100644 index 102da5e2303..00000000000 --- a/arch/s390/kernel/bitmap.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - *    Bitmaps for set_bit, clear_bit, test_and_set_bit, ... - *    See include/asm/{bitops.h|posix_types.h} for details - * - *    Copyright IBM Corp. 1999, 2009 - *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, - */ - -#include <linux/bitops.h> -#include <linux/module.h> - -const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; -EXPORT_SYMBOL(_oi_bitmap); - -const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; -EXPORT_SYMBOL(_ni_bitmap); - -const char _zb_findmap[] = { -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, -	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 }; -EXPORT_SYMBOL(_zb_findmap); - -const char _sb_findmap[] = { -	8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, -	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 }; -EXPORT_SYMBOL(_sb_findmap); diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c index dd62071624b..c0b03c28d15 100644 --- a/arch/s390/kernel/cache.c +++ b/arch/s390/kernel/cache.c @@ -146,15 +146,14 @@ static void __init cache_build_info(void)  	ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);  	for (level = 0; level < CACHE_MAX_LEVEL; level++) {  		switch (ct.ci[level].scope) { -		case CACHE_SCOPE_NOTEXISTS: -		case CACHE_SCOPE_RESERVED: -			return;  		case CACHE_SCOPE_SHARED:  			private = 0;  			break;  		case CACHE_SCOPE_PRIVATE:  			private = 1;  			break; +		default: +			return;  		}  		if (ct.ci[level].type == CACHE_TYPE_SEPARATE) {  			rc  = cache_add(level, private, CACHE_TYPE_DATA); @@ -379,9 +378,12 @@ static int __init cache_init(void)  	if (!test_facility(34))  		return 0;  	cache_build_info(); + +	cpu_notifier_register_begin();  	for_each_online_cpu(cpu)  		cache_add_cpu(cpu); -	hotcpu_notifier(cache_hotplug, 0); +	__hotcpu_notifier(cache_hotplug, 0); +	cpu_notifier_register_done();  	return 0;  }  device_initcall(cache_init); diff --git a/arch/s390/kernel/compat_exec_domain.c b/arch/s390/kernel/compat_exec_domain.c deleted file mode 100644 index 765fabdada9..00000000000 --- a/arch/s390/kernel/compat_exec_domain.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Support for 32-bit Linux for S390 personality. - * - * Copyright IBM Corp. 2000 - * Author(s): Gerhard Tonn (ton@de.ibm.com) - * - * - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/personality.h> -#include <linux/sched.h> - -static struct exec_domain s390_exec_domain; - -static int __init s390_init (void) -{ -	s390_exec_domain.name = "Linux/s390"; -	s390_exec_domain.handler = NULL; -	s390_exec_domain.pers_low = PER_LINUX32; -	s390_exec_domain.pers_high = PER_LINUX32; -	s390_exec_domain.signal_map = default_exec_domain.signal_map; -	s390_exec_domain.signal_invmap = default_exec_domain.signal_invmap; -	register_exec_domain(&s390_exec_domain); -	return 0; -} - -__initcall(s390_init); diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 1f1b8c70ab9..ca38139423a 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -58,10 +58,6 @@  #include "compat_linux.h" -u32 psw32_user_bits = PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT | -		      PSW32_DEFAULT_KEY | PSW32_MASK_BASE | PSW32_MASK_MCHECK | -		      PSW32_MASK_PSTATE | PSW32_ASC_HOME; -   /* For this source file, we want overflow handling. */  #undef high2lowuid @@ -90,48 +86,51 @@ u32 psw32_user_bits = PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT |  #define SET_STAT_UID(stat, uid)		(stat).st_uid = high2lowuid(uid)  #define SET_STAT_GID(stat, gid)		(stat).st_gid = high2lowgid(gid) -asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group) +COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename, +		       u16, user, u16, group)  {  	return sys_chown(filename, low2highuid(user), low2highgid(group));  } -asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group) +COMPAT_SYSCALL_DEFINE3(s390_lchown16, const char __user *, +		       filename, u16, user, u16, group)  {  	return sys_lchown(filename, low2highuid(user), low2highgid(group));  } -asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group) +COMPAT_SYSCALL_DEFINE3(s390_fchown16, unsigned int, fd, u16, user, u16, group)  {  	return sys_fchown(fd, low2highuid(user), low2highgid(group));  } -asmlinkage long sys32_setregid16(u16 rgid, u16 egid) +COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid)  {  	return sys_setregid(low2highgid(rgid), low2highgid(egid));  } -asmlinkage long sys32_setgid16(u16 gid) +COMPAT_SYSCALL_DEFINE1(s390_setgid16, u16, gid)  {  	return sys_setgid((gid_t)gid);  } -asmlinkage long sys32_setreuid16(u16 ruid, u16 euid) +COMPAT_SYSCALL_DEFINE2(s390_setreuid16, u16, ruid, u16, euid)  {  	return sys_setreuid(low2highuid(ruid), low2highuid(euid));  } -asmlinkage long sys32_setuid16(u16 uid) +COMPAT_SYSCALL_DEFINE1(s390_setuid16, u16, uid)  {  	return sys_setuid((uid_t)uid);  } -asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid) +COMPAT_SYSCALL_DEFINE3(s390_setresuid16, u16, ruid, u16, euid, u16, suid)  {  	return sys_setresuid(low2highuid(ruid), low2highuid(euid), -		low2highuid(suid)); +			     low2highuid(suid));  } -asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __user *suidp) +COMPAT_SYSCALL_DEFINE3(s390_getresuid16, u16 __user *, ruidp, +		       u16 __user *, euidp, u16 __user *, suidp)  {  	const struct cred *cred = current_cred();  	int retval; @@ -148,13 +147,14 @@ asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __us  	return retval;  } -asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid) +COMPAT_SYSCALL_DEFINE3(s390_setresgid16, u16, rgid, u16, egid, u16, sgid)  {  	return sys_setresgid(low2highgid(rgid), low2highgid(egid), -		low2highgid(sgid)); +			     low2highgid(sgid));  } -asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __user *sgidp) +COMPAT_SYSCALL_DEFINE3(s390_getresgid16, u16 __user *, rgidp, +		       u16 __user *, egidp, u16 __user *, sgidp)  {  	const struct cred *cred = current_cred();  	int retval; @@ -171,12 +171,12 @@ asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __us  	return retval;  } -asmlinkage long sys32_setfsuid16(u16 uid) +COMPAT_SYSCALL_DEFINE1(s390_setfsuid16, u16, uid)  {  	return sys_setfsuid((uid_t)uid);  } -asmlinkage long sys32_setfsgid16(u16 gid) +COMPAT_SYSCALL_DEFINE1(s390_setfsgid16, u16, gid)  {  	return sys_setfsgid((gid_t)gid);  } @@ -219,7 +219,7 @@ static int groups16_from_user(struct group_info *group_info, u16 __user *groupli  	return 0;  } -asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist) +COMPAT_SYSCALL_DEFINE2(s390_getgroups16, int, gidsetsize, u16 __user *, grouplist)  {  	const struct cred *cred = current_cred();  	int i; @@ -244,7 +244,7 @@ out:  	return i;  } -asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) +COMPAT_SYSCALL_DEFINE2(s390_setgroups16, int, gidsetsize, u16 __user *, grouplist)  {  	struct group_info *group_info;  	int retval; @@ -269,29 +269,29 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)  	return retval;  } -asmlinkage long sys32_getuid16(void) +COMPAT_SYSCALL_DEFINE0(s390_getuid16)  {  	return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));  } -asmlinkage long sys32_geteuid16(void) +COMPAT_SYSCALL_DEFINE0(s390_geteuid16)  {  	return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));  } -asmlinkage long sys32_getgid16(void) +COMPAT_SYSCALL_DEFINE0(s390_getgid16)  {  	return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));  } -asmlinkage long sys32_getegid16(void) +COMPAT_SYSCALL_DEFINE0(s390_getegid16)  {  	return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));  }  #ifdef CONFIG_SYSVIPC -COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second, -		unsigned long, third, compat_uptr_t, ptr) +COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second, +		compat_ulong_t, third, compat_uptr_t, ptr)  {  	if (call >> 16)		/* hack for backward compatibility */  		return -EINVAL; @@ -299,41 +299,35 @@ COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second,  }  #endif -asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low) +COMPAT_SYSCALL_DEFINE3(s390_truncate64, const char __user *, path, u32, high, u32, low)  { -	if ((int)high < 0) -		return -EINVAL; -	else -		return sys_truncate(path, (high << 32) | low); +	return sys_truncate(path, (unsigned long)high << 32 | low);  } -asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) +COMPAT_SYSCALL_DEFINE3(s390_ftruncate64, unsigned int, fd, u32, high, u32, low)  { -	if ((int)high < 0) -		return -EINVAL; -	else -		return sys_ftruncate(fd, (high << 32) | low); +	return sys_ftruncate(fd, (unsigned long)high << 32 | low);  } -asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, -				size_t count, u32 poshi, u32 poslo) +COMPAT_SYSCALL_DEFINE5(s390_pread64, unsigned int, fd, char __user *, ubuf, +		       compat_size_t, count, u32, high, u32, low)  {  	if ((compat_ssize_t) count < 0)  		return -EINVAL; -	return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); +	return sys_pread64(fd, ubuf, count, (unsigned long)high << 32 | low);  } -asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf, -				size_t count, u32 poshi, u32 poslo) +COMPAT_SYSCALL_DEFINE5(s390_pwrite64, unsigned int, fd, const char __user *, ubuf, +		       compat_size_t, count, u32, high, u32, low)  {  	if ((compat_ssize_t) count < 0)  		return -EINVAL; -	return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); +	return sys_pwrite64(fd, ubuf, count, (unsigned long)high << 32 | low);  } -asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count) +COMPAT_SYSCALL_DEFINE4(s390_readahead, int, fd, u32, high, u32, low, s32, count)  { -	return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); +	return sys_readahead(fd, (unsigned long)high << 32 | low, count);  }  struct stat64_emu31 { @@ -385,7 +379,7 @@ static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)  	return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;   } -asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf) +COMPAT_SYSCALL_DEFINE2(s390_stat64, const char __user *, filename, struct stat64_emu31 __user *, statbuf)  {  	struct kstat stat;  	int ret = vfs_stat(filename, &stat); @@ -394,7 +388,7 @@ asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 _  	return ret;  } -asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31 __user * statbuf) +COMPAT_SYSCALL_DEFINE2(s390_lstat64, const char __user *, filename, struct stat64_emu31 __user *, statbuf)  {  	struct kstat stat;  	int ret = vfs_lstat(filename, &stat); @@ -403,7 +397,7 @@ asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31  	return ret;  } -asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf) +COMPAT_SYSCALL_DEFINE2(s390_fstat64, unsigned int, fd, struct stat64_emu31 __user *, statbuf)  {  	struct kstat stat;  	int ret = vfs_fstat(fd, &stat); @@ -412,8 +406,8 @@ asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * sta  	return ret;  } -asmlinkage long sys32_fstatat64(unsigned int dfd, const char __user *filename, -				struct stat64_emu31 __user* statbuf, int flag) +COMPAT_SYSCALL_DEFINE4(s390_fstatat64, unsigned int, dfd, const char __user *, filename, +		       struct stat64_emu31 __user *, statbuf, int, flag)  {  	struct kstat stat;  	int error; @@ -439,7 +433,7 @@ struct mmap_arg_struct_emu31 {  	compat_ulong_t offset;  }; -asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) +COMPAT_SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct_emu31 __user *, arg)  {  	struct mmap_arg_struct_emu31 a; @@ -451,7 +445,7 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)  			      a.offset >> PAGE_SHIFT);  } -asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) +COMPAT_SYSCALL_DEFINE1(s390_mmap2, struct mmap_arg_struct_emu31 __user *, arg)  {  	struct mmap_arg_struct_emu31 a; @@ -460,7 +454,7 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)  	return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);  } -asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count) +COMPAT_SYSCALL_DEFINE3(s390_read, unsigned int, fd, char __user *, buf, compat_size_t, count)  {  	if ((compat_ssize_t) count < 0)  		return -EINVAL;  @@ -468,7 +462,7 @@ asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)  	return sys_read(fd, buf, count);  } -asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t count) +COMPAT_SYSCALL_DEFINE3(s390_write, unsigned int, fd, const char __user *, buf, compat_size_t, count)  {  	if ((compat_ssize_t) count < 0)  		return -EINVAL;  @@ -482,14 +476,13 @@ asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t cou   * because the 31 bit values differ from the 64 bit values.   */ -asmlinkage long -sys32_fadvise64(int fd, loff_t offset, size_t len, int advise) +COMPAT_SYSCALL_DEFINE5(s390_fadvise64, int, fd, u32, high, u32, low, compat_size_t, len, int, advise)  {  	if (advise == 4)  		advise = POSIX_FADV_DONTNEED;  	else if (advise == 5)  		advise = POSIX_FADV_NOREUSE; -	return sys_fadvise64(fd, offset, len, advise); +	return sys_fadvise64(fd, (unsigned long)high << 32 | low, len, advise);  }  struct fadvise64_64_args { @@ -499,8 +492,7 @@ struct fadvise64_64_args {  	int advice;  }; -asmlinkage long -sys32_fadvise64_64(struct fadvise64_64_args __user *args) +COMPAT_SYSCALL_DEFINE1(s390_fadvise64_64, struct fadvise64_64_args __user *, args)  {  	struct fadvise64_64_args a; @@ -512,3 +504,17 @@ sys32_fadvise64_64(struct fadvise64_64_args __user *args)  		a.advice = POSIX_FADV_NOREUSE;  	return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);  } + +COMPAT_SYSCALL_DEFINE6(s390_sync_file_range, int, fd, u32, offhigh, u32, offlow, +		       u32, nhigh, u32, nlow, unsigned int, flags) +{ +	return sys_sync_file_range(fd, ((loff_t)offhigh << 32) + offlow, +				   ((u64)nhigh << 32) + nlow, flags); +} + +COMPAT_SYSCALL_DEFINE6(s390_fallocate, int, fd, int, mode, u32, offhigh, u32, offlow, +		       u32, lenhigh, u32, lenlow) +{ +	return sys_fallocate(fd, mode, ((loff_t)offhigh << 32) + offlow, +			     ((u64)lenhigh << 32) + lenlow); +} diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index 976518c0592..70d4b7c4bea 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h @@ -27,6 +27,7 @@ typedef union  typedef struct  {  	unsigned int	fpc; +	unsigned int	pad;  	freg_t32	fprs[__NUM_FPRS];                } _s390_fp_regs32; @@ -68,53 +69,52 @@ struct ucontext32 {  	__u32			uc_link;	/* pointer */	  	compat_stack_t		uc_stack;  	_sigregs32		uc_mcontext; -	compat_sigset_t		uc_sigmask;	/* mask last for extensibility */ +	compat_sigset_t		uc_sigmask; +	/* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */ +	unsigned char		__unused[128 - sizeof(compat_sigset_t)];  };  struct stat64_emu31;  struct mmap_arg_struct_emu31;  struct fadvise64_64_args; -long sys32_chown16(const char __user * filename, u16 user, u16 group); -long sys32_lchown16(const char __user * filename, u16 user, u16 group); -long sys32_fchown16(unsigned int fd, u16 user, u16 group); -long sys32_setregid16(u16 rgid, u16 egid); -long sys32_setgid16(u16 gid); -long sys32_setreuid16(u16 ruid, u16 euid); -long sys32_setuid16(u16 uid); -long sys32_setresuid16(u16 ruid, u16 euid, u16 suid); -long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid); -long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid); -long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid); -long sys32_setfsuid16(u16 uid); -long sys32_setfsgid16(u16 gid); -long sys32_getgroups16(int gidsetsize, u16 __user *grouplist); -long sys32_setgroups16(int gidsetsize, u16 __user *grouplist); -long sys32_getuid16(void); -long sys32_geteuid16(void); -long sys32_getgid16(void); -long sys32_getegid16(void); -long sys32_truncate64(const char __user * path, unsigned long high, -		      unsigned long low); -long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low); -long sys32_init_module(void __user *umod, unsigned long len, -		       const char __user *uargs); -long sys32_delete_module(const char __user *name_user, unsigned int flags); -long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, -		   u32 poshi, u32 poslo); -long sys32_pwrite64(unsigned int fd, const char __user *ubuf, -		    size_t count, u32 poshi, u32 poslo); -compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count); -long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf); -long sys32_lstat64(const char __user * filename, -		   struct stat64_emu31 __user * statbuf); -long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf); -long sys32_fstatat64(unsigned int dfd, const char __user *filename, -		     struct stat64_emu31 __user* statbuf, int flag); -unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg); -long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg); -long sys32_read(unsigned int fd, char __user * buf, size_t count); -long sys32_write(unsigned int fd, const char __user * buf, size_t count); -long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise); -long sys32_fadvise64_64(struct fadvise64_64_args __user *args); +long compat_sys_s390_chown16(const char __user *filename, u16 user, u16 group); +long compat_sys_s390_lchown16(const char __user *filename, u16 user, u16 group); +long compat_sys_s390_fchown16(unsigned int fd, u16 user, u16 group); +long compat_sys_s390_setregid16(u16 rgid, u16 egid); +long compat_sys_s390_setgid16(u16 gid); +long compat_sys_s390_setreuid16(u16 ruid, u16 euid); +long compat_sys_s390_setuid16(u16 uid); +long compat_sys_s390_setresuid16(u16 ruid, u16 euid, u16 suid); +long compat_sys_s390_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid); +long compat_sys_s390_setresgid16(u16 rgid, u16 egid, u16 sgid); +long compat_sys_s390_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid); +long compat_sys_s390_setfsuid16(u16 uid); +long compat_sys_s390_setfsgid16(u16 gid); +long compat_sys_s390_getgroups16(int gidsetsize, u16 __user *grouplist); +long compat_sys_s390_setgroups16(int gidsetsize, u16 __user *grouplist); +long compat_sys_s390_getuid16(void); +long compat_sys_s390_geteuid16(void); +long compat_sys_s390_getgid16(void); +long compat_sys_s390_getegid16(void); +long compat_sys_s390_truncate64(const char __user *path, u32 high, u32 low); +long compat_sys_s390_ftruncate64(unsigned int fd, u32 high, u32 low); +long compat_sys_s390_pread64(unsigned int fd, char __user *ubuf, compat_size_t count, u32 high, u32 low); +long compat_sys_s390_pwrite64(unsigned int fd, const char __user *ubuf, compat_size_t count, u32 high, u32 low); +long compat_sys_s390_readahead(int fd, u32 high, u32 low, s32 count); +long compat_sys_s390_stat64(const char __user *filename, struct stat64_emu31 __user *statbuf); +long compat_sys_s390_lstat64(const char __user *filename, struct stat64_emu31 __user *statbuf); +long compat_sys_s390_fstat64(unsigned int fd, struct stat64_emu31 __user *statbuf); +long compat_sys_s390_fstatat64(unsigned int dfd, const char __user *filename, struct stat64_emu31 __user *statbuf, int flag); +long compat_sys_s390_old_mmap(struct mmap_arg_struct_emu31 __user *arg); +long compat_sys_s390_mmap2(struct mmap_arg_struct_emu31 __user *arg); +long compat_sys_s390_read(unsigned int fd, char __user * buf, compat_size_t count); +long compat_sys_s390_write(unsigned int fd, const char __user * buf, compat_size_t count); +long compat_sys_s390_fadvise64(int fd, u32 high, u32 low, compat_size_t len, int advise); +long compat_sys_s390_fadvise64_64(struct fadvise64_64_args __user *args); +long compat_sys_s390_sync_file_range(int fd, u32 offhigh, u32 offlow, u32 nhigh, u32 nlow, unsigned int flags); +long compat_sys_s390_fallocate(int fd, int mode, u32 offhigh, u32 offlow, u32 lenhigh, u32 lenlow); +long compat_sys_sigreturn(void); +long compat_sys_rt_sigreturn(void); +  #endif /* _ASM_S390X_S390_H */ diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 1389b637dae..f204d692036 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -49,7 +49,7 @@ typedef struct  	__u32 gprs_high[NUM_GPRS];  } rt_sigframe32; -int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) +int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)  {  	int err; @@ -99,7 +99,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)  			break;  		}  	} -	return err; +	return err ? -EFAULT : 0;  }  int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) @@ -148,63 +148,72 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)  			break;  		}  	} -	return err; +	return err ? -EFAULT : 0;  }  static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)  { -	_s390_regs_common32 regs32; -	int err, i; +	_sigregs32 user_sregs; +	int i; -	regs32.psw.mask = psw32_user_bits | -		((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER); -	regs32.psw.addr = (__u32) regs->psw.addr | +	user_sregs.regs.psw.mask = (__u32)(regs->psw.mask >> 32); +	user_sregs.regs.psw.mask &= PSW32_MASK_USER | PSW32_MASK_RI; +	user_sregs.regs.psw.mask |= PSW32_USER_BITS; +	user_sregs.regs.psw.addr = (__u32) regs->psw.addr |  		(__u32)(regs->psw.mask & PSW_MASK_BA);  	for (i = 0; i < NUM_GPRS; i++) -		regs32.gprs[i] = (__u32) regs->gprs[i]; +		user_sregs.regs.gprs[i] = (__u32) regs->gprs[i];  	save_access_regs(current->thread.acrs); -	memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs)); -	err = __copy_to_user(&sregs->regs, ®s32, sizeof(regs32)); -	if (err) -		return err; -	save_fp_regs(¤t->thread.fp_regs); -	/* s390_fp_regs and _s390_fp_regs32 are the same ! */ -	return __copy_to_user(&sregs->fpregs, ¤t->thread.fp_regs, -			      sizeof(_s390_fp_regs32)); +	memcpy(&user_sregs.regs.acrs, current->thread.acrs, +	       sizeof(user_sregs.regs.acrs)); +	save_fp_ctl(¤t->thread.fp_regs.fpc); +	save_fp_regs(current->thread.fp_regs.fprs); +	memcpy(&user_sregs.fpregs, ¤t->thread.fp_regs, +	       sizeof(user_sregs.fpregs)); +	if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32))) +		return -EFAULT; +	return 0;  }  static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)  { -	_s390_regs_common32 regs32; -	int err, i; +	_sigregs32 user_sregs; +	int i;  	/* Alwys make any pending restarted system call return -EINTR */  	current_thread_info()->restart_block.fn = do_no_restart_syscall; -	err = __copy_from_user(®s32, &sregs->regs, sizeof(regs32)); -	if (err) -		return err; -	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | -		(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | -		(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); +	if (__copy_from_user(&user_sregs, &sregs->regs, sizeof(user_sregs))) +		return -EFAULT; + +	if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW32_MASK_RI)) +		return -EINVAL; + +	/* Loading the floating-point-control word can fail. Do that first. */ +	if (restore_fp_ctl(&user_sregs.fpregs.fpc)) +		return -EINVAL; + +	/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */ +	regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) | +		(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 | +		(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_RI) << 32 | +		(__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_AMODE);  	/* Check for invalid user address space control. */ -	if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) -		regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | +	if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME) +		regs->psw.mask = PSW_ASC_PRIMARY |  			(regs->psw.mask & ~PSW_MASK_ASC); -	regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); +	regs->psw.addr = (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_INSN);  	for (i = 0; i < NUM_GPRS; i++) -		regs->gprs[i] = (__u64) regs32.gprs[i]; -	memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs)); +		regs->gprs[i] = (__u64) user_sregs.regs.gprs[i]; +	memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, +	       sizeof(current->thread.acrs));  	restore_access_regs(current->thread.acrs); -	err = __copy_from_user(¤t->thread.fp_regs, &sregs->fpregs, -			       sizeof(_s390_fp_regs32)); -	current->thread.fp_regs.fpc &= FPC_VALID_MASK; -	if (err) -		return err; +	memcpy(¤t->thread.fp_regs, &user_sregs.fpregs, +	       sizeof(current->thread.fp_regs)); -	restore_fp_regs(¤t->thread.fp_regs); -	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */ +	restore_fp_regs(current->thread.fp_regs.fprs); +	clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */  	return 0;  } @@ -215,24 +224,24 @@ static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)  	for (i = 0; i < NUM_GPRS; i++)  		gprs_high[i] = regs->gprs[i] >> 32; - -	return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high)); +	if (__copy_to_user(uregs, &gprs_high, sizeof(gprs_high))) +		return -EFAULT; +	return 0;  }  static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)  {  	__u32 gprs_high[NUM_GPRS]; -	int err, i; +	int i; -	err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high)); -	if (err) -		return err; +	if (__copy_from_user(&gprs_high, uregs, sizeof(gprs_high))) +		return -EFAULT;  	for (i = 0; i < NUM_GPRS; i++)  		*(__u32 *)®s->gprs[i] = gprs_high[i];  	return 0;  } -asmlinkage long sys32_sigreturn(void) +COMPAT_SYSCALL_DEFINE0(sigreturn)  {  	struct pt_regs *regs = task_pt_regs(current);  	sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; @@ -251,7 +260,7 @@ badframe:  	return 0;  } -asmlinkage long sys32_rt_sigreturn(void) +COMPAT_SYSCALL_DEFINE0(rt_sigreturn)  {  	struct pt_regs *regs = task_pt_regs(current);  	rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; @@ -348,7 +357,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka,  	regs->gprs[15] = (__force __u64) frame;  	/* Force 31 bit amode and default user address space control. */  	regs->psw.mask = PSW_MASK_BA | -		(psw_user_bits & PSW_MASK_ASC) | +		(PSW_USER_BITS & PSW_MASK_ASC) |  		(regs->psw.mask & ~PSW_MASK_ASC);  	regs->psw.addr = (__force __u64) ka->sa.sa_handler; @@ -403,8 +412,9 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,  		regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;  	} else {  		regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE; -		err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, -				  (u16 __force __user *)(frame->retcode)); +		if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, +			       (u16 __force __user *)(frame->retcode))) +			goto give_sigsegv;  	}  	/* Set up backchain. */ @@ -415,7 +425,7 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,  	regs->gprs[15] = (__force __u64) frame;  	/* Force 31 bit amode and default user address space control. */  	regs->psw.mask = PSW_MASK_BA | -		(psw_user_bits & PSW_MASK_ASC) | +		(PSW_USER_BITS & PSW_MASK_ASC) |  		(regs->psw.mask & ~PSW_MASK_ASC);  	regs->psw.addr = (__u64 __force) ka->sa.sa_handler; diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S deleted file mode 100644 index 9cb1b975b35..00000000000 --- a/arch/s390/kernel/compat_wrapper.S +++ /dev/null @@ -1,1414 +0,0 @@ -/* -*    wrapper for 31 bit compatible system calls. -* -*    Copyright IBM Corp. 2000, 2006 -*    Author(s): Gerhard Tonn (ton@de.ibm.com), -*		Thomas Spatzier (tspat@de.ibm.com) -*/ - -#include <linux/linkage.h> - -ENTRY(sys32_exit_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_exit		# branch to sys_exit - -ENTRY(sys32_read_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# char * -	llgfr	%r4,%r4			# size_t -	jg	sys32_read		# branch to sys_read - -ENTRY(sys32_write_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# const char * -	llgfr	%r4,%r4			# size_t -	jg	sys32_write		# branch to system call - -ENTRY(sys32_close_wrapper) -	llgfr	%r2,%r2			# unsigned int -	jg	sys_close		# branch to system call - -ENTRY(sys32_creat_wrapper) -	llgtr	%r2,%r2			# const char * -	lgfr	%r3,%r3			# int -	jg	sys_creat		# branch to system call - -ENTRY(sys32_link_wrapper) -	llgtr	%r2,%r2			# const char * -	llgtr	%r3,%r3			# const char * -	jg	sys_link		# branch to system call - -ENTRY(sys32_unlink_wrapper) -	llgtr	%r2,%r2			# const char * -	jg	sys_unlink		# branch to system call - -ENTRY(sys32_chdir_wrapper) -	llgtr	%r2,%r2			# const char * -	jg	sys_chdir		# branch to system call - -ENTRY(sys32_time_wrapper) -	llgtr	%r2,%r2			# int * -	jg	compat_sys_time		# branch to system call - -ENTRY(sys32_mknod_wrapper) -	llgtr	%r2,%r2			# const char * -	lgfr	%r3,%r3			# int -	llgfr	%r4,%r4			# dev -	jg	sys_mknod		# branch to system call - -ENTRY(sys32_chmod_wrapper) -	llgtr	%r2,%r2			# const char * -	llgfr	%r3,%r3			# mode_t -	jg	sys_chmod		# branch to system call - -ENTRY(sys32_lchown16_wrapper) -	llgtr	%r2,%r2			# const char * -	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t -	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t -	jg	sys32_lchown16		# branch to system call - -#sys32_getpid_wrapper				# void - -ENTRY(sys32_mount_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# char * -	llgfr	%r5,%r5			# unsigned long -	llgtr	%r6,%r6			# void * -	jg	compat_sys_mount	# branch to system call - -ENTRY(sys32_oldumount_wrapper) -	llgtr	%r2,%r2			# char * -	jg	sys_oldumount		# branch to system call - -ENTRY(sys32_setuid16_wrapper) -	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t -	jg	sys32_setuid16		# branch to system call - -#sys32_getuid16_wrapper			# void - -ENTRY(sys32_ptrace_wrapper) -	lgfr	%r2,%r2			# long -	lgfr	%r3,%r3			# long -	llgtr	%r4,%r4			# long -	llgfr	%r5,%r5			# long -	jg	compat_sys_ptrace	# branch to system call - -ENTRY(sys32_alarm_wrapper) -	llgfr	%r2,%r2			# unsigned int -	jg	sys_alarm		# branch to system call - -ENTRY(compat_sys_utime_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# struct compat_utimbuf * -	jg	compat_sys_utime	# branch to system call - -ENTRY(sys32_access_wrapper) -	llgtr	%r2,%r2			# const char * -	lgfr	%r3,%r3			# int -	jg	sys_access		# branch to system call - -ENTRY(sys32_nice_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_nice		# branch to system call - -#sys32_sync_wrapper			# void - -ENTRY(sys32_kill_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	jg	sys_kill		# branch to system call - -ENTRY(sys32_rename_wrapper) -	llgtr	%r2,%r2			# const char * -	llgtr	%r3,%r3			# const char * -	jg	sys_rename		# branch to system call - -ENTRY(sys32_mkdir_wrapper) -	llgtr	%r2,%r2			# const char * -	lgfr	%r3,%r3			# int -	jg	sys_mkdir		# branch to system call - -ENTRY(sys32_rmdir_wrapper) -	llgtr	%r2,%r2			# const char * -	jg	sys_rmdir		# branch to system call - -ENTRY(sys32_dup_wrapper) -	llgfr	%r2,%r2			# unsigned int -	jg	sys_dup			# branch to system call - -ENTRY(sys32_pipe_wrapper) -	llgtr	%r2,%r2			# u32 * -	jg	sys_pipe		# branch to system call - -ENTRY(compat_sys_times_wrapper) -	llgtr	%r2,%r2			# struct compat_tms * -	jg	compat_sys_times	# branch to system call - -ENTRY(sys32_brk_wrapper) -	llgtr	%r2,%r2			# unsigned long -	jg	sys_brk			# branch to system call - -ENTRY(sys32_setgid16_wrapper) -	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t -	jg	sys32_setgid16		# branch to system call - -#sys32_getgid16_wrapper			# void - -ENTRY(sys32_signal_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# __sighandler_t -	jg	sys_signal - -#sys32_geteuid16_wrapper		# void - -#sys32_getegid16_wrapper		# void - -ENTRY(sys32_acct_wrapper) -	llgtr	%r2,%r2			# char * -	jg	sys_acct		# branch to system call - -ENTRY(sys32_umount_wrapper) -	llgtr	%r2,%r2			# char * -	lgfr	%r3,%r3			# int -	jg	sys_umount		# branch to system call - -ENTRY(compat_sys_ioctl_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned int -	llgfr	%r4,%r4			# unsigned int -	jg	compat_sys_ioctl	# branch to system call - -ENTRY(compat_sys_fcntl_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned int -	llgfr	%r4,%r4			# unsigned long -	jg	compat_sys_fcntl	# branch to system call - -ENTRY(sys32_setpgid_wrapper) -	lgfr	%r2,%r2			# pid_t -	lgfr	%r3,%r3			# pid_t -	jg	sys_setpgid		# branch to system call - -ENTRY(sys32_umask_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_umask		# branch to system call - -ENTRY(sys32_chroot_wrapper) -	llgtr	%r2,%r2			# char * -	jg	sys_chroot		# branch to system call - -ENTRY(sys32_ustat_wrapper) -	llgfr	%r2,%r2			# dev_t -	llgtr	%r3,%r3			# struct ustat * -	jg	compat_sys_ustat - -ENTRY(sys32_dup2_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned int -	jg	sys_dup2		# branch to system call - -#sys32_getppid_wrapper			# void - -#sys32_getpgrp_wrapper			# void - -#sys32_setsid_wrapper			# void - -ENTRY(sys32_setreuid16_wrapper) -	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t -	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t -	jg	sys32_setreuid16	# branch to system call - -ENTRY(sys32_setregid16_wrapper) -	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t -	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t -	jg	sys32_setregid16	# branch to system call - -ENTRY(sys_sigsuspend_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	llgfr	%r4,%r4			# old_sigset_t -	jg	sys_sigsuspend - -ENTRY(compat_sys_sigpending_wrapper) -	llgtr	%r2,%r2			# compat_old_sigset_t * -	jg	compat_sys_sigpending	# branch to system call - -ENTRY(sys32_sethostname_wrapper) -	llgtr	%r2,%r2			# char * -	lgfr	%r3,%r3			# int -	jg	sys_sethostname		# branch to system call - -ENTRY(compat_sys_setrlimit_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# struct rlimit_emu31 * -	jg	compat_sys_setrlimit	# branch to system call - -ENTRY(compat_sys_old_getrlimit_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# struct rlimit_emu31 * -	jg	compat_sys_old_getrlimit # branch to system call - -ENTRY(compat_sys_getrlimit_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# struct rlimit_emu31 * -	jg	compat_sys_getrlimit	# branch to system call - -ENTRY(sys32_mmap2_wrapper) -	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 * -	jg	sys32_mmap2			# branch to system call - -ENTRY(compat_sys_gettimeofday_wrapper) -	llgtr	%r2,%r2			# struct timeval_emu31 * -	llgtr	%r3,%r3			# struct timezone * -	jg	compat_sys_gettimeofday	# branch to system call - -ENTRY(compat_sys_settimeofday_wrapper) -	llgtr	%r2,%r2			# struct timeval_emu31 * -	llgtr	%r3,%r3			# struct timezone * -	jg	compat_sys_settimeofday	# branch to system call - -ENTRY(sys32_getgroups16_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t * -	jg	sys32_getgroups16	# branch to system call - -ENTRY(sys32_setgroups16_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t * -	jg	sys32_setgroups16	# branch to system call - -ENTRY(sys32_symlink_wrapper) -	llgtr	%r2,%r2			# const char * -	llgtr	%r3,%r3			# const char * -	jg	sys_symlink		# branch to system call - -ENTRY(sys32_readlink_wrapper) -	llgtr	%r2,%r2			# const char * -	llgtr	%r3,%r3			# char * -	lgfr	%r4,%r4			# int -	jg	sys_readlink		# branch to system call - -ENTRY(sys32_uselib_wrapper) -	llgtr	%r2,%r2			# const char * -	jg	sys_uselib		# branch to system call - -ENTRY(sys32_swapon_wrapper) -	llgtr	%r2,%r2			# const char * -	lgfr	%r3,%r3			# int -	jg	sys_swapon		# branch to system call - -ENTRY(sys32_reboot_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	llgfr	%r4,%r4			# unsigned int -	llgtr	%r5,%r5			# void * -	jg	sys_reboot		# branch to system call - -ENTRY(old32_readdir_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# void * -	llgfr	%r4,%r4			# unsigned int -	jg	compat_sys_old_readdir	# branch to system call - -ENTRY(old32_mmap_wrapper) -	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 * -	jg	old32_mmap		# branch to system call - -ENTRY(sys32_munmap_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# size_t -	jg	sys_munmap		# branch to system call - -ENTRY(sys32_fchmod_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# mode_t -	jg	sys_fchmod		# branch to system call - -ENTRY(sys32_fchown16_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# compat_uid_t -	llgfr	%r4,%r4			# compat_uid_t -	jg	sys32_fchown16		# branch to system call - -ENTRY(sys32_getpriority_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	jg	sys_getpriority		# branch to system call - -ENTRY(sys32_setpriority_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	lgfr	%r4,%r4			# int -	jg	sys_setpriority		# branch to system call - -ENTRY(compat_sys_statfs_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# struct compat_statfs * -	jg	compat_sys_statfs	# branch to system call - -ENTRY(compat_sys_fstatfs_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# struct compat_statfs * -	jg	compat_sys_fstatfs	# branch to system call - -ENTRY(compat_sys_socketcall_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# u32 * -	jg	compat_sys_socketcall	# branch to system call - -ENTRY(sys32_syslog_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# char * -	lgfr	%r4,%r4			# int -	jg	sys_syslog		# branch to system call - -ENTRY(compat_sys_newstat_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# struct stat_emu31 * -	jg	compat_sys_newstat	# branch to system call - -ENTRY(compat_sys_newlstat_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# struct stat_emu31 * -	jg	compat_sys_newlstat	# branch to system call - -ENTRY(compat_sys_newfstat_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# struct stat_emu31 * -	jg	compat_sys_newfstat	# branch to system call - -#sys32_vhangup_wrapper			# void - -ENTRY(sys32_swapoff_wrapper) -	llgtr	%r2,%r2			# const char * -	jg	sys_swapoff		# branch to system call - -ENTRY(compat_sys_sysinfo_wrapper) -	llgtr	%r2,%r2			# struct sysinfo_emu31 * -	jg	compat_sys_sysinfo	# branch to system call - -ENTRY(sys32_fsync_wrapper) -	llgfr	%r2,%r2			# unsigned int -	jg	sys_fsync		# branch to system call - -#sys32_sigreturn_wrapper		# done in sigreturn_glue - -#sys32_clone_wrapper			# done in clone_glue - -ENTRY(sys32_setdomainname_wrapper) -	llgtr	%r2,%r2			# char * -	lgfr	%r3,%r3			# int -	jg	sys_setdomainname	# branch to system call - -ENTRY(sys32_newuname_wrapper) -	llgtr	%r2,%r2			# struct new_utsname * -	jg	sys_newuname		# branch to system call - -ENTRY(compat_sys_adjtimex_wrapper) -	llgtr	%r2,%r2			# struct compat_timex * -	jg	compat_sys_adjtimex	# branch to system call - -ENTRY(sys32_mprotect_wrapper) -	llgtr	%r2,%r2			# unsigned long (actually pointer -	llgfr	%r3,%r3			# size_t -	llgfr	%r4,%r4			# unsigned long -	jg	sys_mprotect		# branch to system call - -ENTRY(sys_init_module_wrapper) -	llgtr	%r2,%r2			# void * -	llgfr	%r3,%r3			# unsigned long -	llgtr	%r4,%r4			# char * -	jg	sys_init_module		# branch to system call - -ENTRY(sys_delete_module_wrapper) -	llgtr	%r2,%r2			# const char * -	llgfr	%r3,%r3			# unsigned int -	jg	sys_delete_module	# branch to system call - -ENTRY(sys32_quotactl_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# const char * -	llgfr	%r4,%r4			# qid_t -	llgtr	%r5,%r5			# caddr_t -	jg	sys_quotactl		# branch to system call - -ENTRY(sys32_getpgid_wrapper) -	lgfr	%r2,%r2			# pid_t -	jg	sys_getpgid		# branch to system call - -ENTRY(sys32_fchdir_wrapper) -	llgfr	%r2,%r2			# unsigned int -	jg	sys_fchdir		# branch to system call - -ENTRY(sys32_bdflush_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# long -	jg	sys_bdflush		# branch to system call - -ENTRY(sys32_sysfs_wrapper) -	lgfr	%r2,%r2			# int -	llgfr	%r3,%r3			# unsigned long -	llgfr	%r4,%r4			# unsigned long -	jg	sys_sysfs		# branch to system call - -ENTRY(sys32_personality_wrapper) -	llgfr	%r2,%r2			# unsigned int -	jg	sys_s390_personality	# branch to system call - -ENTRY(sys32_setfsuid16_wrapper) -	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t -	jg	sys32_setfsuid16	# branch to system call - -ENTRY(sys32_setfsgid16_wrapper) -	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t -	jg	sys32_setfsgid16	# branch to system call - -ENTRY(sys32_llseek_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned long -	llgfr	%r4,%r4			# unsigned long -	llgtr	%r5,%r5			# loff_t * -	llgfr	%r6,%r6			# unsigned int -	jg	sys_llseek		# branch to system call - -ENTRY(sys32_getdents_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# void * -	llgfr	%r4,%r4			# unsigned int -	jg	compat_sys_getdents	# branch to system call - -ENTRY(compat_sys_select_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# compat_fd_set * -	llgtr	%r4,%r4			# compat_fd_set * -	llgtr	%r5,%r5			# compat_fd_set * -	llgtr	%r6,%r6			# struct compat_timeval * -	jg	compat_sys_select	# branch to system call - -ENTRY(sys32_flock_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned int -	jg	sys_flock		# branch to system call - -ENTRY(sys32_msync_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# size_t -	lgfr	%r4,%r4			# int -	jg	sys_msync		# branch to system call - -ENTRY(compat_sys_readv_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const struct compat_iovec * -	llgfr	%r4,%r4			# unsigned long -	jg	compat_sys_readv	# branch to system call - -ENTRY(compat_sys_writev_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const struct compat_iovec * -	llgfr	%r4,%r4			# unsigned long -	jg	compat_sys_writev	# branch to system call - -ENTRY(sys32_getsid_wrapper) -	lgfr	%r2,%r2			# pid_t -	jg	sys_getsid		# branch to system call - -ENTRY(sys32_fdatasync_wrapper) -	llgfr	%r2,%r2			# unsigned int -	jg	sys_fdatasync		# branch to system call - -ENTRY(sys32_mlock_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# size_t -	jg	sys_mlock		# branch to system call - -ENTRY(sys32_munlock_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# size_t -	jg	sys_munlock		# branch to system call - -ENTRY(sys32_mlockall_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_mlockall		# branch to system call - -#sys32_munlockall_wrapper		# void - -ENTRY(sys32_sched_setparam_wrapper) -	lgfr	%r2,%r2			# pid_t -	llgtr	%r3,%r3			# struct sched_param * -	jg	sys_sched_setparam	# branch to system call - -ENTRY(sys32_sched_getparam_wrapper) -	lgfr	%r2,%r2			# pid_t -	llgtr	%r3,%r3			# struct sched_param * -	jg	sys_sched_getparam	# branch to system call - -ENTRY(sys32_sched_setscheduler_wrapper) -	lgfr	%r2,%r2			# pid_t -	lgfr	%r3,%r3			# int -	llgtr	%r4,%r4			# struct sched_param * -	jg	sys_sched_setscheduler	# branch to system call - -ENTRY(sys32_sched_getscheduler_wrapper) -	lgfr	%r2,%r2			# pid_t -	jg	sys_sched_getscheduler	# branch to system call - -#sys32_sched_yield_wrapper		# void - -ENTRY(sys32_sched_get_priority_max_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_sched_get_priority_max	# branch to system call - -ENTRY(sys32_sched_get_priority_min_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_sched_get_priority_min	# branch to system call - -ENTRY(compat_sys_nanosleep_wrapper) -	llgtr	%r2,%r2			# struct compat_timespec * -	llgtr	%r3,%r3			# struct compat_timespec * -	jg	compat_sys_nanosleep		# branch to system call - -ENTRY(sys32_mremap_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# unsigned long -	llgfr	%r4,%r4			# unsigned long -	llgfr	%r5,%r5			# unsigned long -	llgfr	%r6,%r6			# unsigned long -	jg	sys_mremap		# branch to system call - -ENTRY(sys32_setresuid16_wrapper) -	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t -	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t -	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t -	jg	sys32_setresuid16	# branch to system call - -ENTRY(sys32_getresuid16_wrapper) -	llgtr	%r2,%r2			# __kernel_old_uid_emu31_t * -	llgtr	%r3,%r3			# __kernel_old_uid_emu31_t * -	llgtr	%r4,%r4			# __kernel_old_uid_emu31_t * -	jg	sys32_getresuid16	# branch to system call - -ENTRY(sys32_poll_wrapper) -	llgtr	%r2,%r2			# struct pollfd * -	llgfr	%r3,%r3			# unsigned int -	lgfr	%r4,%r4			# int -	jg	sys_poll		# branch to system call - -ENTRY(sys32_setresgid16_wrapper) -	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t -	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t -	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t -	jg	sys32_setresgid16	# branch to system call - -ENTRY(sys32_getresgid16_wrapper) -	llgtr	%r2,%r2			# __kernel_old_gid_emu31_t * -	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t * -	llgtr	%r4,%r4			# __kernel_old_gid_emu31_t * -	jg	sys32_getresgid16	# branch to system call - -ENTRY(sys32_prctl_wrapper) -	lgfr	%r2,%r2			# int -	llgfr	%r3,%r3			# unsigned long -	llgfr	%r4,%r4			# unsigned long -	llgfr	%r5,%r5			# unsigned long -	llgfr	%r6,%r6			# unsigned long -	jg	sys_prctl		# branch to system call - -#sys32_rt_sigreturn_wrapper		# done in rt_sigreturn_glue - -ENTRY(sys32_pread64_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# char * -	llgfr	%r4,%r4			# size_t -	llgfr	%r5,%r5			# u32 -	llgfr	%r6,%r6			# u32 -	jg	sys32_pread64		# branch to system call - -ENTRY(sys32_pwrite64_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# const char * -	llgfr	%r4,%r4			# size_t -	llgfr	%r5,%r5			# u32 -	llgfr	%r6,%r6			# u32 -	jg	sys32_pwrite64		# branch to system call - -ENTRY(sys32_chown16_wrapper) -	llgtr	%r2,%r2			# const char * -	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t -	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t -	jg	sys32_chown16		# branch to system call - -ENTRY(sys32_getcwd_wrapper) -	llgtr	%r2,%r2			# char * -	llgfr	%r3,%r3			# unsigned long -	jg	sys_getcwd		# branch to system call - -ENTRY(sys32_capget_wrapper) -	llgtr	%r2,%r2			# cap_user_header_t -	llgtr	%r3,%r3			# cap_user_data_t -	jg	sys_capget		# branch to system call - -ENTRY(sys32_capset_wrapper) -	llgtr	%r2,%r2			# cap_user_header_t -	llgtr	%r3,%r3			# const cap_user_data_t -	jg	sys_capset		# branch to system call - -#sys32_vfork_wrapper			# done in vfork_glue - -ENTRY(sys32_truncate64_wrapper) -	llgtr	%r2,%r2			# const char * -	llgfr	%r3,%r3			# unsigned long -	llgfr	%r4,%r4			# unsigned long -	jg	sys32_truncate64	# branch to system call - -ENTRY(sys32_ftruncate64_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned long -	llgfr	%r4,%r4			# unsigned long -	jg	sys32_ftruncate64	# branch to system call - -ENTRY(sys32_lchown_wrapper) -	llgtr	%r2,%r2			# const char * -	llgfr	%r3,%r3			# uid_t -	llgfr	%r4,%r4			# gid_t -	jg	sys_lchown		# branch to system call - -#sys32_getuid_wrapper			# void -#sys32_getgid_wrapper			# void -#sys32_geteuid_wrapper			# void -#sys32_getegid_wrapper			# void - -ENTRY(sys32_setreuid_wrapper) -	llgfr	%r2,%r2			# uid_t -	llgfr	%r3,%r3			# uid_t -	jg	sys_setreuid		# branch to system call - -ENTRY(sys32_setregid_wrapper) -	llgfr	%r2,%r2			# gid_t -	llgfr	%r3,%r3			# gid_t -	jg	sys_setregid		# branch to system call - -ENTRY(sys32_getgroups_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# gid_t * -	jg	sys_getgroups		# branch to system call - -ENTRY(sys32_setgroups_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# gid_t * -	jg	sys_setgroups		# branch to system call - -ENTRY(sys32_fchown_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# uid_t -	llgfr	%r4,%r4			# gid_t -	jg	sys_fchown		# branch to system call - -ENTRY(sys32_setresuid_wrapper) -	llgfr	%r2,%r2			# uid_t -	llgfr	%r3,%r3			# uid_t -	llgfr	%r4,%r4			# uid_t -	jg	sys_setresuid		# branch to system call - -ENTRY(sys32_getresuid_wrapper) -	llgtr	%r2,%r2			# uid_t * -	llgtr	%r3,%r3			# uid_t * -	llgtr	%r4,%r4			# uid_t * -	jg	sys_getresuid		# branch to system call - -ENTRY(sys32_setresgid_wrapper) -	llgfr	%r2,%r2			# gid_t -	llgfr	%r3,%r3			# gid_t -	llgfr	%r4,%r4			# gid_t -	jg	sys_setresgid		# branch to system call - -ENTRY(sys32_getresgid_wrapper) -	llgtr	%r2,%r2			# gid_t * -	llgtr	%r3,%r3			# gid_t * -	llgtr	%r4,%r4			# gid_t * -	jg	sys_getresgid		# branch to system call - -ENTRY(sys32_chown_wrapper) -	llgtr	%r2,%r2			# const char * -	llgfr	%r3,%r3			# uid_t -	llgfr	%r4,%r4			# gid_t -	jg	sys_chown		# branch to system call - -ENTRY(sys32_setuid_wrapper) -	llgfr	%r2,%r2			# uid_t -	jg	sys_setuid		# branch to system call - -ENTRY(sys32_setgid_wrapper) -	llgfr	%r2,%r2			# gid_t -	jg	sys_setgid		# branch to system call - -ENTRY(sys32_setfsuid_wrapper) -	llgfr	%r2,%r2			# uid_t -	jg	sys_setfsuid		# branch to system call - -ENTRY(sys32_setfsgid_wrapper) -	llgfr	%r2,%r2			# gid_t -	jg	sys_setfsgid		# branch to system call - -ENTRY(sys32_pivot_root_wrapper) -	llgtr	%r2,%r2			# const char * -	llgtr	%r3,%r3			# const char * -	jg	sys_pivot_root		# branch to system call - -ENTRY(sys32_mincore_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# size_t -	llgtr	%r4,%r4			# unsigned char * -	jg	sys_mincore		# branch to system call - -ENTRY(sys32_madvise_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# size_t -	lgfr	%r4,%r4			# int -	jg	sys_madvise		# branch to system call - -ENTRY(sys32_getdents64_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# void * -	llgfr	%r4,%r4			# unsigned int -	jg	sys_getdents64		# branch to system call - -ENTRY(compat_sys_fcntl64_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned int -	llgfr	%r4,%r4			# unsigned long -	jg	compat_sys_fcntl64	# branch to system call - -ENTRY(sys32_stat64_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# struct stat64 * -	jg	sys32_stat64		# branch to system call - -ENTRY(sys32_lstat64_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# struct stat64 * -	jg	sys32_lstat64		# branch to system call - -ENTRY(sys32_stime_wrapper) -	llgtr	%r2,%r2			# long * -	jg	compat_sys_stime	# branch to system call - -ENTRY(sys32_fstat64_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgtr	%r3,%r3			# struct stat64 * -	jg	sys32_fstat64		# branch to system call - -ENTRY(sys32_setxattr_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# void * -	llgfr	%r5,%r5			# size_t -	lgfr	%r6,%r6			# int -	jg	sys_setxattr - -ENTRY(sys32_lsetxattr_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# void * -	llgfr	%r5,%r5			# size_t -	lgfr	%r6,%r6			# int -	jg	sys_lsetxattr - -ENTRY(sys32_fsetxattr_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# void * -	llgfr	%r5,%r5			# size_t -	lgfr	%r6,%r6			# int -	jg	sys_fsetxattr - -ENTRY(sys32_getxattr_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# void * -	llgfr	%r5,%r5			# size_t -	jg	sys_getxattr - -ENTRY(sys32_lgetxattr_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# void * -	llgfr	%r5,%r5			# size_t -	jg	sys_lgetxattr - -ENTRY(sys32_fgetxattr_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# void * -	llgfr	%r5,%r5			# size_t -	jg	sys_fgetxattr - -ENTRY(sys32_listxattr_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	llgfr	%r4,%r4			# size_t -	jg	sys_listxattr - -ENTRY(sys32_llistxattr_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	llgfr	%r4,%r4			# size_t -	jg	sys_llistxattr - -ENTRY(sys32_flistxattr_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# char * -	llgfr	%r4,%r4			# size_t -	jg	sys_flistxattr - -ENTRY(sys32_removexattr_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	jg	sys_removexattr - -ENTRY(sys32_lremovexattr_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# char * -	jg	sys_lremovexattr - -ENTRY(sys32_fremovexattr_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# char * -	jg	sys_fremovexattr - -ENTRY(sys32_sched_setaffinity_wrapper) -	lgfr	%r2,%r2			# int -	llgfr	%r3,%r3			# unsigned int -	llgtr	%r4,%r4			# unsigned long * -	jg	compat_sys_sched_setaffinity - -ENTRY(sys32_sched_getaffinity_wrapper) -	lgfr	%r2,%r2			# int -	llgfr	%r3,%r3			# unsigned int -	llgtr	%r4,%r4			# unsigned long * -	jg	compat_sys_sched_getaffinity - -ENTRY(sys32_exit_group_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_exit_group		# branch to system call - -ENTRY(sys32_set_tid_address_wrapper) -	llgtr	%r2,%r2			# int * -	jg	sys_set_tid_address	# branch to system call - -ENTRY(sys_epoll_create_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_epoll_create	# branch to system call - -ENTRY(sys_epoll_ctl_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	lgfr	%r4,%r4			# int -	llgtr	%r5,%r5			# struct epoll_event * -	jg	sys_epoll_ctl		# branch to system call - -ENTRY(sys_epoll_wait_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# struct epoll_event * -	lgfr	%r4,%r4			# int -	lgfr	%r5,%r5			# int -	jg	sys_epoll_wait		# branch to system call - -ENTRY(sys32_fadvise64_wrapper) -	lgfr	%r2,%r2			# int -	sllg	%r3,%r3,32		# get high word of 64bit loff_t -	or	%r3,%r4			# get low word of 64bit loff_t -	llgfr	%r4,%r5			# size_t (unsigned long) -	lgfr	%r5,%r6			# int -	jg	sys32_fadvise64 - -ENTRY(sys32_fadvise64_64_wrapper) -	llgtr	%r2,%r2			# struct fadvise64_64_args * -	jg	sys32_fadvise64_64 - -ENTRY(sys32_clock_settime_wrapper) -	lgfr	%r2,%r2			# clockid_t (int) -	llgtr	%r3,%r3			# struct compat_timespec * -	jg	compat_sys_clock_settime - -ENTRY(sys32_clock_gettime_wrapper) -	lgfr	%r2,%r2			# clockid_t (int) -	llgtr	%r3,%r3			# struct compat_timespec * -	jg	compat_sys_clock_gettime - -ENTRY(sys32_clock_getres_wrapper) -	lgfr	%r2,%r2			# clockid_t (int) -	llgtr	%r3,%r3			# struct compat_timespec * -	jg	compat_sys_clock_getres - -ENTRY(sys32_clock_nanosleep_wrapper) -	lgfr	%r2,%r2			# clockid_t (int) -	lgfr	%r3,%r3			# int -	llgtr	%r4,%r4			# struct compat_timespec * -	llgtr	%r5,%r5			# struct compat_timespec * -	jg	compat_sys_clock_nanosleep - -ENTRY(sys32_timer_create_wrapper) -	lgfr	%r2,%r2			# timer_t (int) -	llgtr	%r3,%r3			# struct compat_sigevent * -	llgtr	%r4,%r4			# timer_t * -	jg	compat_sys_timer_create - -ENTRY(sys32_timer_settime_wrapper) -	lgfr	%r2,%r2			# timer_t (int) -	lgfr	%r3,%r3			# int -	llgtr	%r4,%r4			# struct compat_itimerspec * -	llgtr	%r5,%r5			# struct compat_itimerspec * -	jg	compat_sys_timer_settime - -ENTRY(sys32_timer_gettime_wrapper) -	lgfr	%r2,%r2			# timer_t (int) -	llgtr	%r3,%r3			# struct compat_itimerspec * -	jg	compat_sys_timer_gettime - -ENTRY(sys32_timer_getoverrun_wrapper) -	lgfr	%r2,%r2			# timer_t (int) -	jg	sys_timer_getoverrun - -ENTRY(sys32_timer_delete_wrapper) -	lgfr	%r2,%r2			# timer_t (int) -	jg	sys_timer_delete - -ENTRY(sys32_io_setup_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# u32 * -	jg	compat_sys_io_setup - -ENTRY(sys32_io_destroy_wrapper) -	llgfr	%r2,%r2			# (aio_context_t) u32 -	jg	sys_io_destroy - -ENTRY(sys32_io_getevents_wrapper) -	llgfr	%r2,%r2			# (aio_context_t) u32 -	lgfr	%r3,%r3			# long -	lgfr	%r4,%r4			# long -	llgtr	%r5,%r5			# struct io_event * -	llgtr	%r6,%r6			# struct compat_timespec * -	jg	compat_sys_io_getevents - -ENTRY(sys32_io_submit_wrapper) -	llgfr	%r2,%r2			# (aio_context_t) u32 -	lgfr	%r3,%r3			# long -	llgtr	%r4,%r4			# struct iocb ** -	jg	compat_sys_io_submit - -ENTRY(sys32_io_cancel_wrapper) -	llgfr	%r2,%r2			# (aio_context_t) u32 -	llgtr	%r3,%r3			# struct iocb * -	llgtr	%r4,%r4			# struct io_event * -	jg	sys_io_cancel - -ENTRY(compat_sys_statfs64_wrapper) -	llgtr	%r2,%r2			# const char * -	llgfr	%r3,%r3			# compat_size_t -	llgtr	%r4,%r4			# struct compat_statfs64 * -	jg	compat_sys_statfs64 - -ENTRY(compat_sys_fstatfs64_wrapper) -	llgfr	%r2,%r2			# unsigned int fd -	llgfr	%r3,%r3			# compat_size_t -	llgtr	%r4,%r4			# struct compat_statfs64 * -	jg	compat_sys_fstatfs64 - -ENTRY(compat_sys_mq_open_wrapper) -	llgtr	%r2,%r2			# const char * -	lgfr	%r3,%r3			# int -	llgfr	%r4,%r4			# mode_t -	llgtr	%r5,%r5			# struct compat_mq_attr * -	jg	compat_sys_mq_open - -ENTRY(sys32_mq_unlink_wrapper) -	llgtr	%r2,%r2			# const char * -	jg	sys_mq_unlink - -ENTRY(compat_sys_mq_timedsend_wrapper) -	lgfr	%r2,%r2			# mqd_t -	llgtr	%r3,%r3			# const char * -	llgfr	%r4,%r4			# size_t -	llgfr	%r5,%r5			# unsigned int -	llgtr	%r6,%r6			# const struct compat_timespec * -	jg	compat_sys_mq_timedsend - -ENTRY(compat_sys_mq_timedreceive_wrapper) -	lgfr	%r2,%r2			# mqd_t -	llgtr	%r3,%r3			# char * -	llgfr	%r4,%r4			# size_t -	llgtr	%r5,%r5			# unsigned int * -	llgtr	%r6,%r6			# const struct compat_timespec * -	jg	compat_sys_mq_timedreceive - -ENTRY(compat_sys_mq_notify_wrapper) -	lgfr	%r2,%r2			# mqd_t -	llgtr	%r3,%r3			# struct compat_sigevent * -	jg	compat_sys_mq_notify - -ENTRY(compat_sys_mq_getsetattr_wrapper) -	lgfr	%r2,%r2			# mqd_t -	llgtr	%r3,%r3			# struct compat_mq_attr * -	llgtr	%r4,%r4			# struct compat_mq_attr * -	jg	compat_sys_mq_getsetattr - -ENTRY(compat_sys_add_key_wrapper) -	llgtr	%r2,%r2			# const char * -	llgtr	%r3,%r3			# const char * -	llgtr	%r4,%r4			# const void * -	llgfr	%r5,%r5			# size_t -	llgfr	%r6,%r6			# (key_serial_t) u32 -	jg	sys_add_key - -ENTRY(compat_sys_request_key_wrapper) -	llgtr	%r2,%r2			# const char * -	llgtr	%r3,%r3			# const char * -	llgtr	%r4,%r4			# const void * -	llgfr	%r5,%r5			# (key_serial_t) u32 -	jg	sys_request_key - -ENTRY(sys32_remap_file_pages_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# unsigned long -	llgfr	%r4,%r4			# unsigned long -	llgfr	%r5,%r5			# unsigned long -	llgfr	%r6,%r6			# unsigned long -	jg	sys_remap_file_pages - -ENTRY(compat_sys_kexec_load_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# unsigned long -	llgtr	%r4,%r4			# struct kexec_segment * -	llgfr	%r5,%r5			# unsigned long -	jg	compat_sys_kexec_load - -ENTRY(sys_ioprio_set_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	lgfr	%r4,%r4			# int -	jg	sys_ioprio_set - -ENTRY(sys_ioprio_get_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	jg	sys_ioprio_get - -ENTRY(sys_inotify_add_watch_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	llgfr	%r4,%r4			# u32 -	jg	sys_inotify_add_watch - -ENTRY(sys_inotify_rm_watch_wrapper) -	lgfr	%r2,%r2			# int -	llgfr	%r3,%r3			# u32 -	jg	sys_inotify_rm_watch - -ENTRY(sys_mkdirat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	lgfr	%r4,%r4			# int -	jg	sys_mkdirat - -ENTRY(sys_mknodat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	lgfr	%r4,%r4			# int -	llgfr	%r5,%r5			# unsigned int -	jg	sys_mknodat - -ENTRY(sys_fchownat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	llgfr	%r4,%r4			# uid_t -	llgfr	%r5,%r5			# gid_t -	lgfr	%r6,%r6			# int -	jg	sys_fchownat - -ENTRY(compat_sys_futimesat_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# struct timeval * -	jg	compat_sys_futimesat - -ENTRY(sys32_fstatat64_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# struct stat64 * -	lgfr	%r5,%r5			# int -	jg	sys32_fstatat64 - -ENTRY(sys_unlinkat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	lgfr	%r4,%r4			# int -	jg	sys_unlinkat - -ENTRY(sys_renameat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	lgfr	%r4,%r4			# int -	llgtr	%r5,%r5			# const char * -	jg	sys_renameat - -ENTRY(sys_linkat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	lgfr	%r4,%r4			# int -	llgtr	%r5,%r5			# const char * -	lgfr	%r6,%r6			# int -	jg	sys_linkat - -ENTRY(sys_symlinkat_wrapper) -	llgtr	%r2,%r2			# const char * -	lgfr	%r3,%r3			# int -	llgtr	%r4,%r4			# const char * -	jg	sys_symlinkat - -ENTRY(sys_readlinkat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	llgtr	%r4,%r4			# char * -	lgfr	%r5,%r5			# int -	jg	sys_readlinkat - -ENTRY(sys_fchmodat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	llgfr	%r4,%r4			# mode_t -	jg	sys_fchmodat - -ENTRY(sys_faccessat_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char * -	lgfr	%r4,%r4			# int -	jg	sys_faccessat - -ENTRY(compat_sys_pselect6_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# fd_set * -	llgtr	%r4,%r4			# fd_set * -	llgtr	%r5,%r5			# fd_set * -	llgtr	%r6,%r6			# struct timespec * -	llgt	%r0,164(%r15)		# void * -	stg	%r0,160(%r15) -	jg	compat_sys_pselect6 - -ENTRY(compat_sys_ppoll_wrapper) -	llgtr	%r2,%r2			# struct pollfd * -	llgfr	%r3,%r3			# unsigned int -	llgtr	%r4,%r4			# struct timespec * -	llgtr	%r5,%r5			# const sigset_t * -	llgfr	%r6,%r6			# size_t -	jg	compat_sys_ppoll - -ENTRY(sys_unshare_wrapper) -	llgfr	%r2,%r2			# unsigned long -	jg	sys_unshare - -ENTRY(sys_splice_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# loff_t * -	lgfr	%r4,%r4			# int -	llgtr	%r5,%r5			# loff_t * -	llgfr	%r6,%r6			# size_t -	llgf	%r0,164(%r15)		# unsigned int -	stg	%r0,160(%r15) -	jg	sys_splice - -ENTRY(sys_sync_file_range_wrapper) -	lgfr	%r2,%r2			# int -	sllg	%r3,%r3,32		# get high word of 64bit loff_t -	or	%r3,%r4			# get low word of 64bit loff_t -	sllg	%r4,%r5,32		# get high word of 64bit loff_t -	or	%r4,%r6			# get low word of 64bit loff_t -	llgf	%r5,164(%r15)		# unsigned int -	jg	sys_sync_file_range - -ENTRY(sys_tee_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	llgfr	%r4,%r4			# size_t -	llgfr	%r5,%r5			# unsigned int -	jg	sys_tee - -ENTRY(sys_getcpu_wrapper) -	llgtr	%r2,%r2			# unsigned * -	llgtr	%r3,%r3			# unsigned * -	llgtr	%r4,%r4			# struct getcpu_cache * -	jg	sys_getcpu - -ENTRY(compat_sys_utimes_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# struct compat_timeval * -	jg	compat_sys_utimes - -ENTRY(compat_sys_utimensat_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgtr	%r3,%r3			# char * -	llgtr	%r4,%r4			# struct compat_timespec * -	lgfr	%r5,%r5			# int -	jg	compat_sys_utimensat - -ENTRY(sys_eventfd_wrapper) -	llgfr	%r2,%r2			# unsigned int -	jg	sys_eventfd - -ENTRY(sys_fallocate_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	sllg	%r4,%r4,32		# get high word of 64bit loff_t -	lr	%r4,%r5			# get low word of 64bit loff_t -	sllg	%r5,%r6,32		# get high word of 64bit loff_t -	l	%r5,164(%r15)		# get low word of 64bit loff_t -	jg	sys_fallocate - -ENTRY(sys_timerfd_create_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	jg	sys_timerfd_create - -ENTRY(sys_eventfd2_wrapper) -	llgfr	%r2,%r2			# unsigned int -	lgfr	%r3,%r3			# int -	jg	sys_eventfd2 - -ENTRY(sys_inotify_init1_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_inotify_init1 - -ENTRY(sys_pipe2_wrapper) -	llgtr	%r2,%r2			# u32 * -	lgfr	%r3,%r3			# int -	jg	sys_pipe2		# branch to system call - -ENTRY(sys_dup3_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned int -	lgfr	%r4,%r4			# int -	jg	sys_dup3		# branch to system call - -ENTRY(sys_epoll_create1_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_epoll_create1	# branch to system call - -ENTRY(sys32_readahead_wrapper) -	lgfr	%r2,%r2			# int -	llgfr	%r3,%r3			# u32 -	llgfr	%r4,%r4			# u32 -	lgfr	%r5,%r5			# s32 -	jg	sys32_readahead		# branch to system call - -ENTRY(sys_tkill_wrapper) -	lgfr	%r2,%r2			# pid_t -	lgfr	%r3,%r3			# int -	jg	sys_tkill		# branch to system call - -ENTRY(sys_tgkill_wrapper) -	lgfr	%r2,%r2			# pid_t -	lgfr	%r3,%r3			# pid_t -	lgfr	%r4,%r4			# int -	jg	sys_tgkill		# branch to system call - -ENTRY(compat_sys_keyctl_wrapper) -	llgfr	%r2,%r2			# u32 -	llgfr	%r3,%r3			# u32 -	llgfr	%r4,%r4			# u32 -	llgfr	%r5,%r5			# u32 -	llgfr	%r6,%r6			# u32 -	jg	compat_sys_keyctl	# branch to system call - -ENTRY(sys_perf_event_open_wrapper) -	llgtr	%r2,%r2			# const struct perf_event_attr * -	lgfr	%r3,%r3			# pid_t -	lgfr	%r4,%r4			# int -	lgfr	%r5,%r5			# int -	llgfr	%r6,%r6			# unsigned long -	jg	sys_perf_event_open	# branch to system call - -ENTRY(sys_clone_wrapper) -	llgfr	%r2,%r2			# unsigned long -	llgfr	%r3,%r3			# unsigned long -	llgtr	%r4,%r4			# int * -	llgtr	%r5,%r5			# int * -	jg	sys_clone		# branch to system call - -ENTRY(sys32_execve_wrapper) -	llgtr	%r2,%r2			# char * -	llgtr	%r3,%r3			# compat_uptr_t * -	llgtr	%r4,%r4			# compat_uptr_t * -	jg	compat_sys_execve	# branch to system call - -ENTRY(sys_fanotify_init_wrapper) -	llgfr	%r2,%r2			# unsigned int -	llgfr	%r3,%r3			# unsigned int -	jg	sys_fanotify_init	# branch to system call - -ENTRY(sys_prlimit64_wrapper) -	lgfr	%r2,%r2			# pid_t -	llgfr	%r3,%r3			# unsigned int -	llgtr	%r4,%r4			# const struct rlimit64 __user * -	llgtr	%r5,%r5			# struct rlimit64 __user * -	jg	sys_prlimit64		# branch to system call - -ENTRY(sys_name_to_handle_at_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char __user * -	llgtr	%r4,%r4			# struct file_handle __user * -	llgtr	%r5,%r5			# int __user * -	lgfr	%r6,%r6			# int -	jg	sys_name_to_handle_at - -ENTRY(compat_sys_clock_adjtime_wrapper) -	lgfr	%r2,%r2			# clockid_t (int) -	llgtr	%r3,%r3			# struct compat_timex __user * -	jg	compat_sys_clock_adjtime - -ENTRY(sys_syncfs_wrapper) -	lgfr	%r2,%r2			# int -	jg	sys_syncfs - -ENTRY(sys_setns_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	jg	sys_setns - -ENTRY(compat_sys_process_vm_readv_wrapper) -	lgfr	%r2,%r2			# compat_pid_t -	llgtr	%r3,%r3			# struct compat_iovec __user * -	llgfr	%r4,%r4			# unsigned long -	llgtr	%r5,%r5			# struct compat_iovec __user * -	llgfr	%r6,%r6			# unsigned long -	llgf	%r0,164(%r15)		# unsigned long -	stg	%r0,160(%r15) -	jg	compat_sys_process_vm_readv - -ENTRY(compat_sys_process_vm_writev_wrapper) -	lgfr	%r2,%r2			# compat_pid_t -	llgtr	%r3,%r3			# struct compat_iovec __user * -	llgfr	%r4,%r4			# unsigned long -	llgtr	%r5,%r5			# struct compat_iovec __user * -	llgfr	%r6,%r6			# unsigned long -	llgf	%r0,164(%r15)		# unsigned long -	stg	%r0,160(%r15) -	jg	compat_sys_process_vm_writev - -ENTRY(sys_s390_runtime_instr_wrapper) -	lgfr	%r2,%r2			# int -	lgfr	%r3,%r3			# int -	jg	sys_s390_runtime_instr - -ENTRY(sys_kcmp_wrapper) -	lgfr	%r2,%r2			# pid_t -	lgfr	%r3,%r3			# pid_t -	lgfr	%r4,%r4			# int -	llgfr	%r5,%r5			# unsigned long -	llgfr	%r6,%r6			# unsigned long -	jg	sys_kcmp - -ENTRY(sys_finit_module_wrapper) -	lgfr	%r2,%r2			# int -	llgtr	%r3,%r3			# const char __user * -	lgfr	%r4,%r4			# int -	jg	sys_finit_module diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c new file mode 100644 index 00000000000..45cdb37aa6f --- /dev/null +++ b/arch/s390/kernel/compat_wrapper.c @@ -0,0 +1,216 @@ +/* + *  Compat system call wrappers. + * + *    Copyright IBM Corp. 2014 + */ + +#include <linux/syscalls.h> +#include <linux/compat.h> +#include "entry.h" + +#define COMPAT_SYSCALL_WRAP1(name, ...) \ +	COMPAT_SYSCALL_WRAPx(1, _##name, __VA_ARGS__) +#define COMPAT_SYSCALL_WRAP2(name, ...) \ +	COMPAT_SYSCALL_WRAPx(2, _##name, __VA_ARGS__) +#define COMPAT_SYSCALL_WRAP3(name, ...) \ +	COMPAT_SYSCALL_WRAPx(3, _##name, __VA_ARGS__) +#define COMPAT_SYSCALL_WRAP4(name, ...) \ +	COMPAT_SYSCALL_WRAPx(4, _##name, __VA_ARGS__) +#define COMPAT_SYSCALL_WRAP5(name, ...) \ +	COMPAT_SYSCALL_WRAPx(5, _##name, __VA_ARGS__) +#define COMPAT_SYSCALL_WRAP6(name, ...) \ +	COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__) + +#define __SC_COMPAT_TYPE(t, a) \ +	__typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a + +#define __SC_COMPAT_CAST(t, a)						\ +({									\ +	long __ReS = a;							\ +									\ +	BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&		\ +		     !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));		\ +	if (__TYPE_IS_L(t))						\ +		__ReS = (s32)a;						\ +	if (__TYPE_IS_UL(t))						\ +		__ReS = (u32)a;						\ +	if (__TYPE_IS_PTR(t))						\ +		__ReS = a & 0x7fffffff;					\ +	(t)__ReS;							\ +}) + +/* + * The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by + * compat tasks. These wrappers will only be used for system calls where only + * the system call arguments need sign or zero extension or zeroing of the upper + * 33 bits of pointers. + * Note: since the wrapper function will afterwards call a system call which + * again performs zero and sign extension for all system call arguments with + * a size of less than eight bytes, these compat wrappers only touch those + * system call arguments with a size of eight bytes ((unsigned) long and + * pointers). Zero and sign extension for e.g. int parameters will be done by + * the regular system call wrappers. + */ +#define COMPAT_SYSCALL_WRAPx(x, name, ...)					\ +	asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));		\ +	asmlinkage long compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));\ +	asmlinkage long compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__))	\ +	{									\ +		return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));	\ +	} + +COMPAT_SYSCALL_WRAP1(exit, int, error_code); +COMPAT_SYSCALL_WRAP1(close, unsigned int, fd); +COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode); +COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname); +COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname); +COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename); +COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev); +COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode); +COMPAT_SYSCALL_WRAP1(oldumount, char __user *, name); +COMPAT_SYSCALL_WRAP1(alarm, unsigned int, seconds); +COMPAT_SYSCALL_WRAP2(access, const char __user *, filename, int, mode); +COMPAT_SYSCALL_WRAP1(nice, int, increment); +COMPAT_SYSCALL_WRAP2(kill, int, pid, int, sig); +COMPAT_SYSCALL_WRAP2(rename, const char __user *, oldname, const char __user *, newname); +COMPAT_SYSCALL_WRAP2(mkdir, const char __user *, pathname, umode_t, mode); +COMPAT_SYSCALL_WRAP1(rmdir, const char __user *, pathname); +COMPAT_SYSCALL_WRAP1(dup, unsigned int, fildes); +COMPAT_SYSCALL_WRAP1(pipe, int __user *, fildes); +COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk); +COMPAT_SYSCALL_WRAP2(signal, int, sig, __sighandler_t, handler); +COMPAT_SYSCALL_WRAP1(acct, const char __user *, name); +COMPAT_SYSCALL_WRAP2(umount, char __user *, name, int, flags); +COMPAT_SYSCALL_WRAP2(setpgid, pid_t, pid, pid_t, pgid); +COMPAT_SYSCALL_WRAP1(umask, int, mask); +COMPAT_SYSCALL_WRAP1(chroot, const char __user *, filename); +COMPAT_SYSCALL_WRAP2(dup2, unsigned int, oldfd, unsigned int, newfd); +COMPAT_SYSCALL_WRAP3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask); +COMPAT_SYSCALL_WRAP2(sethostname, char __user *, name, int, len); +COMPAT_SYSCALL_WRAP2(symlink, const char __user *, old, const char __user *, new); +COMPAT_SYSCALL_WRAP3(readlink, const char __user *, path, char __user *, buf, int, bufsiz); +COMPAT_SYSCALL_WRAP1(uselib, const char __user *, library); +COMPAT_SYSCALL_WRAP2(swapon, const char __user *, specialfile, int, swap_flags); +COMPAT_SYSCALL_WRAP4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg); +COMPAT_SYSCALL_WRAP2(munmap, unsigned long, addr, size_t, len); +COMPAT_SYSCALL_WRAP2(fchmod, unsigned int, fd, umode_t, mode); +COMPAT_SYSCALL_WRAP2(getpriority, int, which, int, who); +COMPAT_SYSCALL_WRAP3(setpriority, int, which, int, who, int, niceval); +COMPAT_SYSCALL_WRAP3(syslog, int, type, char __user *, buf, int, len); +COMPAT_SYSCALL_WRAP1(swapoff, const char __user *, specialfile); +COMPAT_SYSCALL_WRAP1(fsync, unsigned int, fd); +COMPAT_SYSCALL_WRAP2(setdomainname, char __user *, name, int, len); +COMPAT_SYSCALL_WRAP1(newuname, struct new_utsname __user *, name); +COMPAT_SYSCALL_WRAP3(mprotect, unsigned long, start, size_t, len, unsigned long, prot); +COMPAT_SYSCALL_WRAP3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs); +COMPAT_SYSCALL_WRAP2(delete_module, const char __user *, name_user, unsigned int, flags); +COMPAT_SYSCALL_WRAP4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr); +COMPAT_SYSCALL_WRAP1(getpgid, pid_t, pid); +COMPAT_SYSCALL_WRAP1(fchdir, unsigned int, fd); +COMPAT_SYSCALL_WRAP2(bdflush, int, func, long, data); +COMPAT_SYSCALL_WRAP3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2); +COMPAT_SYSCALL_WRAP1(s390_personality, unsigned int, personality); +COMPAT_SYSCALL_WRAP5(llseek, unsigned int, fd, unsigned long, high, unsigned long, low, loff_t __user *, result, unsigned int, whence); +COMPAT_SYSCALL_WRAP2(flock, unsigned int, fd, unsigned int, cmd); +COMPAT_SYSCALL_WRAP3(msync, unsigned long, start, size_t, len, int, flags); +COMPAT_SYSCALL_WRAP1(getsid, pid_t, pid); +COMPAT_SYSCALL_WRAP1(fdatasync, unsigned int, fd); +COMPAT_SYSCALL_WRAP2(mlock, unsigned long, start, size_t, len); +COMPAT_SYSCALL_WRAP2(munlock, unsigned long, start, size_t, len); +COMPAT_SYSCALL_WRAP1(mlockall, int, flags); +COMPAT_SYSCALL_WRAP2(sched_setparam, pid_t, pid, struct sched_param __user *, param); +COMPAT_SYSCALL_WRAP2(sched_getparam, pid_t, pid, struct sched_param __user *, param); +COMPAT_SYSCALL_WRAP3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param); +COMPAT_SYSCALL_WRAP1(sched_getscheduler, pid_t, pid); +COMPAT_SYSCALL_WRAP1(sched_get_priority_max, int, policy); +COMPAT_SYSCALL_WRAP1(sched_get_priority_min, int, policy); +COMPAT_SYSCALL_WRAP5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr); +COMPAT_SYSCALL_WRAP3(poll, struct pollfd __user *, ufds, unsigned int, nfds, int, timeout); +COMPAT_SYSCALL_WRAP5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5); +COMPAT_SYSCALL_WRAP2(getcwd, char __user *, buf, unsigned long, size); +COMPAT_SYSCALL_WRAP2(capget, cap_user_header_t, header, cap_user_data_t, dataptr); +COMPAT_SYSCALL_WRAP2(capset, cap_user_header_t, header, const cap_user_data_t, data); +COMPAT_SYSCALL_WRAP3(lchown, const char __user *, filename, uid_t, user, gid_t, group); +COMPAT_SYSCALL_WRAP2(setreuid, uid_t, ruid, uid_t, euid); +COMPAT_SYSCALL_WRAP2(setregid, gid_t, rgid, gid_t, egid); +COMPAT_SYSCALL_WRAP2(getgroups, int, gidsetsize, gid_t __user *, grouplist); +COMPAT_SYSCALL_WRAP2(setgroups, int, gidsetsize, gid_t __user *, grouplist); +COMPAT_SYSCALL_WRAP3(fchown, unsigned int, fd, uid_t, user, gid_t, group); +COMPAT_SYSCALL_WRAP3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid); +COMPAT_SYSCALL_WRAP3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid); +COMPAT_SYSCALL_WRAP3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid); +COMPAT_SYSCALL_WRAP3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid); +COMPAT_SYSCALL_WRAP3(chown, const char __user *, filename, uid_t, user, gid_t, group); +COMPAT_SYSCALL_WRAP1(setuid, uid_t, uid); +COMPAT_SYSCALL_WRAP1(setgid, gid_t, gid); +COMPAT_SYSCALL_WRAP1(setfsuid, uid_t, uid); +COMPAT_SYSCALL_WRAP1(setfsgid, gid_t, gid); +COMPAT_SYSCALL_WRAP2(pivot_root, const char __user *, new_root, const char __user *, put_old); +COMPAT_SYSCALL_WRAP3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec); +COMPAT_SYSCALL_WRAP3(madvise, unsigned long, start, size_t, len, int, behavior); +COMPAT_SYSCALL_WRAP5(setxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags); +COMPAT_SYSCALL_WRAP5(lsetxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags); +COMPAT_SYSCALL_WRAP5(fsetxattr, int, fd, const char __user *, name, const void __user *, value, size_t, size, int, flags); +COMPAT_SYSCALL_WRAP3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count); +COMPAT_SYSCALL_WRAP4(getxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size); +COMPAT_SYSCALL_WRAP4(lgetxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size); +COMPAT_SYSCALL_WRAP4(fgetxattr, int, fd, const char __user *, name, void __user *, value, size_t, size); +COMPAT_SYSCALL_WRAP3(listxattr, const char __user *, path, char __user *, list, size_t, size); +COMPAT_SYSCALL_WRAP3(llistxattr, const char __user *, path, char __user *, list, size_t, size); +COMPAT_SYSCALL_WRAP3(flistxattr, int, fd, char __user *, list, size_t, size); +COMPAT_SYSCALL_WRAP2(removexattr, const char __user *, path, const char __user *, name); +COMPAT_SYSCALL_WRAP2(lremovexattr, const char __user *, path, const char __user *, name); +COMPAT_SYSCALL_WRAP2(fremovexattr, int, fd, const char __user *, name); +COMPAT_SYSCALL_WRAP1(exit_group, int, error_code); +COMPAT_SYSCALL_WRAP1(set_tid_address, int __user *, tidptr); +COMPAT_SYSCALL_WRAP1(epoll_create, int, size); +COMPAT_SYSCALL_WRAP4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event); +COMPAT_SYSCALL_WRAP4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout); +COMPAT_SYSCALL_WRAP1(timer_getoverrun, timer_t, timer_id); +COMPAT_SYSCALL_WRAP1(timer_delete, compat_timer_t, compat_timer_id); +COMPAT_SYSCALL_WRAP1(io_destroy, aio_context_t, ctx); +COMPAT_SYSCALL_WRAP3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result); +COMPAT_SYSCALL_WRAP1(mq_unlink, const char __user *, name); +COMPAT_SYSCALL_WRAP5(add_key, const char __user *, tp, const char __user *, dsc, const void __user *, pld, size_t, len, key_serial_t, id); +COMPAT_SYSCALL_WRAP4(request_key, const char __user *, tp, const char __user *, dsc, const char __user *, info, key_serial_t, id); +COMPAT_SYSCALL_WRAP5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags); +COMPAT_SYSCALL_WRAP3(ioprio_set, int, which, int, who, int, ioprio); +COMPAT_SYSCALL_WRAP2(ioprio_get, int, which, int, who); +COMPAT_SYSCALL_WRAP3(inotify_add_watch, int, fd, const char __user *, path, u32, mask); +COMPAT_SYSCALL_WRAP2(inotify_rm_watch, int, fd, __s32, wd); +COMPAT_SYSCALL_WRAP3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode); +COMPAT_SYSCALL_WRAP4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, unsigned, dev); +COMPAT_SYSCALL_WRAP5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag); +COMPAT_SYSCALL_WRAP3(unlinkat, int, dfd, const char __user *, pathname, int, flag); +COMPAT_SYSCALL_WRAP4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname); +COMPAT_SYSCALL_WRAP5(linkat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, int, flags); +COMPAT_SYSCALL_WRAP3(symlinkat, const char __user *, oldname, int, newdfd, const char __user *, newname); +COMPAT_SYSCALL_WRAP4(readlinkat, int, dfd, const char __user *, path, char __user *, buf, int, bufsiz); +COMPAT_SYSCALL_WRAP3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode); +COMPAT_SYSCALL_WRAP3(faccessat, int, dfd, const char __user *, filename, int, mode); +COMPAT_SYSCALL_WRAP1(unshare, unsigned long, unshare_flags); +COMPAT_SYSCALL_WRAP6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags); +COMPAT_SYSCALL_WRAP4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags); +COMPAT_SYSCALL_WRAP3(getcpu, unsigned __user *, cpu, unsigned __user *, node, struct getcpu_cache __user *, cache); +COMPAT_SYSCALL_WRAP1(eventfd, unsigned int, count); +COMPAT_SYSCALL_WRAP2(timerfd_create, int, clockid, int, flags); +COMPAT_SYSCALL_WRAP2(eventfd2, unsigned int, count, int, flags); +COMPAT_SYSCALL_WRAP1(inotify_init1, int, flags); +COMPAT_SYSCALL_WRAP2(pipe2, int __user *, fildes, int, flags); +COMPAT_SYSCALL_WRAP3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags); +COMPAT_SYSCALL_WRAP1(epoll_create1, int, flags); +COMPAT_SYSCALL_WRAP2(tkill, int, pid, int, sig); +COMPAT_SYSCALL_WRAP3(tgkill, int, tgid, int, pid, int, sig); +COMPAT_SYSCALL_WRAP5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags); +COMPAT_SYSCALL_WRAP5(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr, int, tls_val); +COMPAT_SYSCALL_WRAP2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags); +COMPAT_SYSCALL_WRAP4(prlimit64, pid_t, pid, unsigned int, resource, const struct rlimit64 __user *, new_rlim, struct rlimit64 __user *, old_rlim); +COMPAT_SYSCALL_WRAP5(name_to_handle_at, int, dfd, const char __user *, name, struct file_handle __user *, handle, int __user *, mnt_id, int, flag); +COMPAT_SYSCALL_WRAP1(syncfs, int, fd); +COMPAT_SYSCALL_WRAP2(setns, int, fd, int, nstype); +COMPAT_SYSCALL_WRAP2(s390_runtime_instr, int, command, int, signum); +COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2); +COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags); +COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags); +COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags); +COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags); diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index c84f33d51f7..a3b9150e680 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -13,6 +13,7 @@  #include <linux/slab.h>  #include <linux/bootmem.h>  #include <linux/elf.h> +#include <linux/memblock.h>  #include <asm/os_info.h>  #include <asm/elf.h>  #include <asm/ipl.h> @@ -22,6 +23,50 @@  #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))  #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y)))) +static struct memblock_region oldmem_region; + +static struct memblock_type oldmem_type = { +	.cnt = 1, +	.max = 1, +	.total_size = 0, +	.regions = &oldmem_region, +}; + +#define for_each_dump_mem_range(i, nid, p_start, p_end, p_nid)		\ +	for (i = 0, __next_mem_range(&i, nid, &memblock.physmem,	\ +				     &oldmem_type, p_start,		\ +				     p_end, p_nid);			\ +	     i != (u64)ULLONG_MAX;					\ +	     __next_mem_range(&i, nid, &memblock.physmem,		\ +			      &oldmem_type,				\ +			      p_start, p_end, p_nid)) + +struct dump_save_areas dump_save_areas; + +/* + * Allocate and add a save area for a CPU + */ +struct save_area *dump_save_area_create(int cpu) +{ +	struct save_area **save_areas, *save_area; + +	save_area = kmalloc(sizeof(*save_area), GFP_KERNEL); +	if (!save_area) +		return NULL; +	if (cpu + 1 > dump_save_areas.count) { +		dump_save_areas.count = cpu + 1; +		save_areas = krealloc(dump_save_areas.areas, +				      dump_save_areas.count * sizeof(void *), +				      GFP_KERNEL | __GFP_ZERO); +		if (!save_areas) { +			kfree(save_area); +			return NULL; +		} +		dump_save_areas.areas = save_areas; +	} +	dump_save_areas.areas[cpu] = save_area; +	return save_area; +}  /*   * Return physical address for virtual address @@ -40,28 +85,25 @@ static inline void *load_real_addr(void *addr)  }  /* - * Copy up to one page to vmalloc or real memory + * Copy real to virtual or real memory   */ -static ssize_t copy_page_real(void *buf, void *src, size_t csize) +static int copy_from_realmem(void *dest, void *src, size_t count)  { -	size_t size; +	unsigned long size; -	if (is_vmalloc_addr(buf)) { -		BUG_ON(csize >= PAGE_SIZE); -		/* If buf is not page aligned, copy first part */ -		size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize); -		if (size) { -			if (memcpy_real(load_real_addr(buf), src, size)) -				return -EFAULT; -			buf += size; -			src += size; -		} -		/* Copy second part */ -		size = csize - size; -		return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0; -	} else { -		return memcpy_real(buf, src, csize); -	} +	if (!count) +		return 0; +	if (!is_vmalloc_or_module_addr(dest)) +		return memcpy_real(dest, src, count); +	do { +		size = min(count, PAGE_SIZE - (__pa(dest) & ~PAGE_MASK)); +		if (memcpy_real(load_real_addr(dest), src, size)) +			return -EFAULT; +		count -= size; +		dest += size; +		src += size; +	} while (count); +	return 0;  }  /* @@ -72,7 +114,7 @@ static void *elfcorehdr_newmem;  /*   * Copy one page from zfcpdump "oldmem"   * - * For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise + * For pages below HSA size memory from the HSA is copied. Otherwise   * real memory copy is used.   */  static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, @@ -80,7 +122,7 @@ static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize,  {  	int rc; -	if (src < ZFCPDUMP_HSA_SIZE) { +	if (src < sclp_get_hsa_size()) {  		rc = memcpy_hsa(buf, src, csize, userbuf);  	} else {  		if (userbuf) @@ -114,7 +156,7 @@ static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize,  		rc = copy_to_user_real((void __force __user *) buf,  				       (void *) src, csize);  	else -		rc = copy_page_real(buf, (void *) src, csize); +		rc = copy_from_realmem(buf, (void *) src, csize);  	return (rc == 0) ? rc : csize;  } @@ -165,18 +207,19 @@ static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,  /*   * Remap "oldmem" for zfcpdump   * - * We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below - * ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function. + * We only map available memory above HSA size. Memory below HSA size + * is read on demand using the copy_oldmem_page() function.   */  static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,  					   unsigned long from,  					   unsigned long pfn,  					   unsigned long size, pgprot_t prot)  { +	unsigned long hsa_end = sclp_get_hsa_size();  	unsigned long size_hsa; -	if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) { -		size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT)); +	if (pfn < hsa_end >> PAGE_SHIFT) { +		size_hsa = min(size, hsa_end - (pfn << PAGE_SHIFT));  		if (size == size_hsa)  			return 0;  		size -= size_hsa; @@ -210,20 +253,20 @@ int copy_from_oldmem(void *dest, void *src, size_t count)  	if (OLDMEM_BASE) {  		if ((unsigned long) src < OLDMEM_SIZE) {  			copied = min(count, OLDMEM_SIZE - (unsigned long) src); -			rc = memcpy_real(dest, src + OLDMEM_BASE, copied); +			rc = copy_from_realmem(dest, src + OLDMEM_BASE, copied);  			if (rc)  				return rc;  		}  	} else { -		if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) { -			copied = min(count, -				     ZFCPDUMP_HSA_SIZE - (unsigned long) src); +		unsigned long hsa_end = sclp_get_hsa_size(); +		if ((unsigned long) src < hsa_end) { +			copied = min(count, hsa_end - (unsigned long) src);  			rc = memcpy_hsa(dest, (unsigned long) src, copied, 0);  			if (rc)  				return rc;  		}  	} -	return memcpy_real(dest + copied, src + copied, count - copied); +	return copy_from_realmem(dest + copied, src + copied, count - copied);  }  /* @@ -240,19 +283,6 @@ static void *kzalloc_panic(int len)  }  /* - * Get memory layout and create hole for oldmem - */ -static struct mem_chunk *get_memory_layout(void) -{ -	struct mem_chunk *chunk_array; - -	chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk)); -	detect_memory_layout(chunk_array, 0); -	create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE); -	return chunk_array; -} - -/*   * Initialize ELF note   */  static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len, @@ -453,8 +483,8 @@ static int get_cpu_cnt(void)  {  	int i, cpus = 0; -	for (i = 0; zfcpdump_save_areas[i]; i++) { -		if (zfcpdump_save_areas[i]->pref_reg == 0) +	for (i = 0; i < dump_save_areas.count; i++) { +		if (dump_save_areas.areas[i]->pref_reg == 0)  			continue;  		cpus++;  	} @@ -466,52 +496,33 @@ static int get_cpu_cnt(void)   */  static int get_mem_chunk_cnt(void)  { -	struct mem_chunk *chunk_array, *mem_chunk; -	int i, cnt = 0; +	int cnt = 0; +	u64 idx; -	chunk_array = get_memory_layout(); -	for (i = 0; i < MEMORY_CHUNKS; i++) { -		mem_chunk = &chunk_array[i]; -		if (chunk_array[i].type != CHUNK_READ_WRITE && -		    chunk_array[i].type != CHUNK_READ_ONLY) -			continue; -		if (mem_chunk->size == 0) -			continue; +	for_each_dump_mem_range(idx, NUMA_NO_NODE, NULL, NULL, NULL)  		cnt++; -	} -	kfree(chunk_array);  	return cnt;  }  /*   * Initialize ELF loads (new kernel)   */ -static int loads_init(Elf64_Phdr *phdr, u64 loads_offset) +static void loads_init(Elf64_Phdr *phdr, u64 loads_offset)  { -	struct mem_chunk *chunk_array, *mem_chunk; -	int i; +	phys_addr_t start, end; +	u64 idx; -	chunk_array = get_memory_layout(); -	for (i = 0; i < MEMORY_CHUNKS; i++) { -		mem_chunk = &chunk_array[i]; -		if (mem_chunk->size == 0) -			continue; -		if (chunk_array[i].type != CHUNK_READ_WRITE && -		    chunk_array[i].type != CHUNK_READ_ONLY) -			continue; -		else -			phdr->p_filesz = mem_chunk->size; +	for_each_dump_mem_range(idx, NUMA_NO_NODE, &start, &end, NULL) { +		phdr->p_filesz = end - start;  		phdr->p_type = PT_LOAD; -		phdr->p_offset = mem_chunk->addr; -		phdr->p_vaddr = mem_chunk->addr; -		phdr->p_paddr = mem_chunk->addr; -		phdr->p_memsz = mem_chunk->size; +		phdr->p_offset = start; +		phdr->p_vaddr = start; +		phdr->p_paddr = start; +		phdr->p_memsz = end - start;  		phdr->p_flags = PF_R | PF_W | PF_X;  		phdr->p_align = PAGE_SIZE;  		phdr++;  	} -	kfree(chunk_array); -	return i;  }  /* @@ -525,8 +536,8 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)  	ptr = nt_prpsinfo(ptr); -	for (i = 0; zfcpdump_save_areas[i]; i++) { -		sa = zfcpdump_save_areas[i]; +	for (i = 0; i < dump_save_areas.count; i++) { +		sa = dump_save_areas.areas[i];  		if (sa->pref_reg == 0)  			continue;  		ptr = fill_cpu_elf_notes(ptr, sa); @@ -557,6 +568,17 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)  	/* If elfcorehdr= has been passed via cmdline, we use that one */  	if (elfcorehdr_addr != ELFCORE_ADDR_MAX)  		return 0; +	/* If we cannot get HSA size for zfcpdump return error */ +	if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp_get_hsa_size()) +		return -ENODEV; + +	/* For kdump, exclude previous crashkernel memory */ +	if (OLDMEM_BASE) { +		oldmem_region.base = OLDMEM_BASE; +		oldmem_region.size = OLDMEM_SIZE; +		oldmem_type.total_size = OLDMEM_SIZE; +	} +  	mem_chunk_cnt = get_mem_chunk_cnt();  	alloc_size = 0x1000 + get_cpu_cnt() * 0x300 + diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index f1279dc2e1b..ee8390da6ea 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -867,7 +867,7 @@ static inline void  debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,  			int exception)  { -	active->id.stck = get_tod_clock(); +	active->id.stck = get_tod_clock_fast();  	active->id.fields.cpuid = smp_processor_id();  	active->caller = __builtin_return_address(0);  	active->id.fields.exception = exception; @@ -889,7 +889,7 @@ static int debug_active=1;   * if debug_active is already off   */  static int -s390dbf_procactive(ctl_table *table, int write, +s390dbf_procactive(struct ctl_table *table, int write,                       void __user *buffer, size_t *lenp, loff_t *ppos)  {  	if (!write || debug_stoppable || !debug_active) diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index be87d3e05a5..993efe6a887 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c @@ -23,6 +23,7 @@  #include <linux/kdebug.h>  #include <asm/uaccess.h> +#include <asm/dis.h>  #include <asm/io.h>  #include <linux/atomic.h>  #include <asm/mathemu.h> @@ -37,17 +38,6 @@  #define ONELONG "%016lx: "  #endif /* CONFIG_64BIT */ -#define OPERAND_GPR	0x1	/* Operand printed as %rx */ -#define OPERAND_FPR	0x2	/* Operand printed as %fx */ -#define OPERAND_AR	0x4	/* Operand printed as %ax */ -#define OPERAND_CR	0x8	/* Operand printed as %cx */ -#define OPERAND_DISP	0x10	/* Operand printed as displacement */ -#define OPERAND_BASE	0x20	/* Operand printed as base register */ -#define OPERAND_INDEX	0x40	/* Operand printed as index register */ -#define OPERAND_PCREL	0x80	/* Operand printed as pc-relative symbol */ -#define OPERAND_SIGNED	0x100	/* Operand printed as signed value */ -#define OPERAND_LENGTH	0x200	/* Operand printed as length (+1) */ -  enum {  	UNUSED,	/* Indicates the end of the operand list */  	R_8,	/* GPR starting at position 8 */ @@ -155,19 +145,7 @@ enum {  	INSTR_S_00, INSTR_S_RD,  }; -struct operand { -	int bits;		/* The number of bits in the operand. */ -	int shift;		/* The number of bits to shift. */ -	int flags;		/* One bit syntax flags. */ -}; - -struct insn { -	const char name[5]; -	unsigned char opfrag; -	unsigned char format; -}; - -static const struct operand operands[] = +static const struct s390_operand operands[] =  {  	[UNUSED]  = { 0, 0, 0 },  	[R_8]	 = {  4,  8, OPERAND_GPR }, @@ -479,7 +457,7 @@ static char *long_insn_name[] = {  	[LONG_INSN_PCISTB] = "pcistb",  }; -static struct insn opcode[] = { +static struct s390_insn opcode[] = {  #ifdef CONFIG_64BIT  	{ "bprp", 0xc5, INSTR_MII_UPI },  	{ "bpp", 0xc7, INSTR_SMI_U0RDP }, @@ -668,7 +646,7 @@ static struct insn opcode[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_01[] = { +static struct s390_insn opcode_01[] = {  #ifdef CONFIG_64BIT  	{ "ptff", 0x04, INSTR_E },  	{ "pfpo", 0x0a, INSTR_E }, @@ -684,7 +662,7 @@ static struct insn opcode_01[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_a5[] = { +static struct s390_insn opcode_a5[] = {  #ifdef CONFIG_64BIT  	{ "iihh", 0x00, INSTR_RI_RU },  	{ "iihl", 0x01, INSTR_RI_RU }, @@ -706,7 +684,7 @@ static struct insn opcode_a5[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_a7[] = { +static struct s390_insn opcode_a7[] = {  #ifdef CONFIG_64BIT  	{ "tmhh", 0x02, INSTR_RI_RU },  	{ "tmhl", 0x03, INSTR_RI_RU }, @@ -728,7 +706,7 @@ static struct insn opcode_a7[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_aa[] = { +static struct s390_insn opcode_aa[] = {  #ifdef CONFIG_64BIT  	{ { 0, LONG_INSN_RINEXT }, 0x00, INSTR_RI_RI },  	{ "rion", 0x01, INSTR_RI_RI }, @@ -739,7 +717,7 @@ static struct insn opcode_aa[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_b2[] = { +static struct s390_insn opcode_b2[] = {  #ifdef CONFIG_64BIT  	{ "stckf", 0x7c, INSTR_S_RD },  	{ "lpp", 0x80, INSTR_S_RD }, @@ -851,7 +829,7 @@ static struct insn opcode_b2[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_b3[] = { +static struct s390_insn opcode_b3[] = {  #ifdef CONFIG_64BIT  	{ "maylr", 0x38, INSTR_RRF_F0FF },  	{ "mylr", 0x39, INSTR_RRF_F0FF }, @@ -1034,7 +1012,7 @@ static struct insn opcode_b3[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_b9[] = { +static struct s390_insn opcode_b9[] = {  #ifdef CONFIG_64BIT  	{ "lpgr", 0x00, INSTR_RRE_RR },  	{ "lngr", 0x01, INSTR_RRE_RR }, @@ -1167,7 +1145,7 @@ static struct insn opcode_b9[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_c0[] = { +static struct s390_insn opcode_c0[] = {  #ifdef CONFIG_64BIT  	{ "lgfi", 0x01, INSTR_RIL_RI },  	{ "xihf", 0x06, INSTR_RIL_RU }, @@ -1187,7 +1165,7 @@ static struct insn opcode_c0[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_c2[] = { +static struct s390_insn opcode_c2[] = {  #ifdef CONFIG_64BIT  	{ "msgfi", 0x00, INSTR_RIL_RI },  	{ "msfi", 0x01, INSTR_RIL_RI }, @@ -1205,7 +1183,7 @@ static struct insn opcode_c2[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_c4[] = { +static struct s390_insn opcode_c4[] = {  #ifdef CONFIG_64BIT  	{ "llhrl", 0x02, INSTR_RIL_RP },  	{ "lghrl", 0x04, INSTR_RIL_RP }, @@ -1222,7 +1200,7 @@ static struct insn opcode_c4[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_c6[] = { +static struct s390_insn opcode_c6[] = {  #ifdef CONFIG_64BIT  	{ "exrl", 0x00, INSTR_RIL_RP },  	{ "pfdrl", 0x02, INSTR_RIL_UP }, @@ -1240,7 +1218,7 @@ static struct insn opcode_c6[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_c8[] = { +static struct s390_insn opcode_c8[] = {  #ifdef CONFIG_64BIT  	{ "mvcos", 0x00, INSTR_SSF_RRDRD },  	{ "ectg", 0x01, INSTR_SSF_RRDRD }, @@ -1251,7 +1229,7 @@ static struct insn opcode_c8[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_cc[] = { +static struct s390_insn opcode_cc[] = {  #ifdef CONFIG_64BIT  	{ "brcth", 0x06, INSTR_RIL_RP },  	{ "aih", 0x08, INSTR_RIL_RI }, @@ -1263,7 +1241,7 @@ static struct insn opcode_cc[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_e3[] = { +static struct s390_insn opcode_e3[] = {  #ifdef CONFIG_64BIT  	{ "ltg", 0x02, INSTR_RXY_RRRD },  	{ "lrag", 0x03, INSTR_RXY_RRRD }, @@ -1369,7 +1347,7 @@ static struct insn opcode_e3[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_e5[] = { +static struct s390_insn opcode_e5[] = {  #ifdef CONFIG_64BIT  	{ "strag", 0x02, INSTR_SSE_RDRD },  	{ "mvhhi", 0x44, INSTR_SIL_RDI }, @@ -1391,7 +1369,7 @@ static struct insn opcode_e5[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_eb[] = { +static struct s390_insn opcode_eb[] = {  #ifdef CONFIG_64BIT  	{ "lmg", 0x04, INSTR_RSY_RRRD },  	{ "srag", 0x0a, INSTR_RSY_RRRD }, @@ -1465,7 +1443,7 @@ static struct insn opcode_eb[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_ec[] = { +static struct s390_insn opcode_ec[] = {  #ifdef CONFIG_64BIT  	{ "brxhg", 0x44, INSTR_RIE_RRP },  	{ "brxlg", 0x45, INSTR_RIE_RRP }, @@ -1504,7 +1482,7 @@ static struct insn opcode_ec[] = {  	{ "", 0, INSTR_INVALID }  }; -static struct insn opcode_ed[] = { +static struct s390_insn opcode_ed[] = {  #ifdef CONFIG_64BIT  	{ "mayl", 0x38, INSTR_RXF_FRRDF },  	{ "myl", 0x39, INSTR_RXF_FRRDF }, @@ -1572,7 +1550,7 @@ static struct insn opcode_ed[] = {  /* Extracts an operand value from an instruction.  */  static unsigned int extract_operand(unsigned char *code, -				    const struct operand *operand) +				    const struct s390_operand *operand)  {  	unsigned int val;  	int bits; @@ -1608,16 +1586,11 @@ static unsigned int extract_operand(unsigned char *code,  	return val;  } -static inline int insn_length(unsigned char code) -{ -	return ((((int) code + 64) >> 7) + 1) << 1; -} - -static struct insn *find_insn(unsigned char *code) +struct s390_insn *find_insn(unsigned char *code)  {  	unsigned char opfrag = code[1];  	unsigned char opmask; -	struct insn *table; +	struct s390_insn *table;  	switch (code[0]) {  	case 0x01: @@ -1706,7 +1679,7 @@ static struct insn *find_insn(unsigned char *code)   */  int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len)  { -	struct insn *insn; +	struct s390_insn *insn;  	insn = find_insn(instruction);  	if (!insn) @@ -1722,9 +1695,9 @@ EXPORT_SYMBOL_GPL(insn_to_mnemonic);  static int print_insn(char *buffer, unsigned char *code, unsigned long addr)  { -	struct insn *insn; +	struct s390_insn *insn;  	const unsigned char *ops; -	const struct operand *operand; +	const struct s390_operand *operand;  	unsigned int value;  	char separator;  	char *ptr; diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c index 99e7f603589..acb412442e5 100644 --- a/arch/s390/kernel/dumpstack.c +++ b/arch/s390/kernel/dumpstack.c @@ -15,6 +15,7 @@  #include <linux/sched.h>  #include <asm/processor.h>  #include <asm/debug.h> +#include <asm/dis.h>  #include <asm/ipl.h>  #ifndef CONFIG_64BIT @@ -143,10 +144,10 @@ void show_registers(struct pt_regs *regs)  	char *mode;  	mode = user_mode(regs) ? "User" : "Krnl"; -	printk("%s PSW : %p %p (%pSR)\n", -	       mode, (void *) regs->psw.mask, -	       (void *) regs->psw.addr, -	       (void *) regs->psw.addr); +	printk("%s PSW : %p %p", mode, (void *)regs->psw.mask, (void *)regs->psw.addr); +	if (!user_mode(regs)) +		printk(" (%pSR)", (void *)regs->psw.addr); +	printk("\n");  	printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "  	       "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),  	       mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO), diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index dc8770d7173..0dff972a169 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -206,6 +206,7 @@ static noinline __init void clear_bss_section(void)   */  static noinline __init void init_kernel_storage_key(void)  { +#if PAGE_DEFAULT_KEY  	unsigned long end_pfn, init_pfn;  	end_pfn = PFN_UP(__pa(&_end)); @@ -213,6 +214,7 @@ static noinline __init void init_kernel_storage_key(void)  	for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)  		page_set_storage_key(init_pfn << PAGE_SHIFT,  				     PAGE_DEFAULT_KEY, 0); +#endif  }  static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE); @@ -256,13 +258,19 @@ static __init void setup_topology(void)  static void early_pgm_check_handler(void)  {  	const struct exception_table_entry *fixup; +	unsigned long cr0, cr0_new;  	unsigned long addr;  	addr = S390_lowcore.program_old_psw.addr;  	fixup = search_exception_tables(addr & PSW_ADDR_INSN);  	if (!fixup)  		disabled_wait(0); +	/* Disable low address protection before storing into lowcore. */ +	__ctl_store(cr0, 0, 0); +	cr0_new = cr0 & ~(1UL << 28); +	__ctl_load(cr0_new, 0, 0);  	S390_lowcore.program_old_psw.addr = extable_fixup(fixup)|PSW_ADDR_AMODE; +	__ctl_load(cr0, 0, 0);  }  static noinline __init void setup_lowcore_early(void) @@ -378,14 +386,14 @@ static __init void detect_machine_facilities(void)  		S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2;  	if (test_facility(3))  		S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; -	if (test_facility(27)) -		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;  	if (test_facility(40))  		S390_lowcore.machine_flags |= MACHINE_FLAG_LPP;  	if (test_facility(50) && test_facility(73))  		S390_lowcore.machine_flags |= MACHINE_FLAG_TE;  	if (test_facility(66))  		S390_lowcore.machine_flags |= MACHINE_FLAG_RRBM; +	if (test_facility(51)) +		S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;  #endif  } @@ -481,7 +489,7 @@ void __init startup_init(void)  	detect_diag44();  	detect_machine_facilities();  	setup_topology(); -	sclp_facilities_detect(); +	sclp_early_detect();  #ifdef CONFIG_DYNAMIC_FTRACE  	S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;  #endif diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index cc30d1fb000..70203265196 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -10,6 +10,7 @@  #include <linux/init.h>  #include <linux/linkage.h> +#include <asm/processor.h>  #include <asm/cache.h>  #include <asm/errno.h>  #include <asm/ptrace.h> @@ -37,17 +38,16 @@ __PT_R13     =	__PT_GPRS + 524  __PT_R14     =	__PT_GPRS + 56  __PT_R15     =	__PT_GPRS + 60 -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ -		 _TIF_MCCK_PENDING | _TIF_PER_TRAP ) -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ -		 _TIF_MCCK_PENDING) -_TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ -		 _TIF_SYSCALL_TRACEPOINT) -  STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER  STACK_SIZE  = 1 << STACK_SHIFT  STACK_INIT  = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE +_TIF_WORK	= (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) +_TIF_TRACE	= (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ +		   _TIF_SYSCALL_TRACEPOINT) +_CIF_WORK	= (_CIF_MCCK_PENDING | _CIF_ASCE) +_PIF_WORK	= (_PIF_PER_TRAP) +  #define BASED(name) name-system_call(%r13)  	.macro	TRACE_IRQS_ON @@ -159,11 +159,7 @@ ENTRY(__switch_to)  	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4  	mvc	__LC_CURRENT_PID(4,%r0),__TASK_pid(%r3)	# store pid of next  	l	%r15,__THREAD_ksp(%r3)		# load kernel stack of next -	tm	__TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending? -	jz	0f -	ni	__TI_flags+3(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev -	oi	__TI_flags+3(%r5),_TIF_MCCK_PENDING	# set it in next -0:	lm	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task +	lm	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task  	br	%r14  __critical_start: @@ -178,6 +174,7 @@ sysc_stm:  	stm	%r8,%r15,__LC_SAVE_AREA_SYNC  	l	%r12,__LC_THREAD_INFO  	l	%r13,__LC_SVC_NEW_PSW+4 +	lhi	%r14,_PIF_SYSCALL  sysc_per:  	l	%r15,__LC_KERNEL_STACK  	la	%r11,STACK_FRAME_OVERHEAD(%r15)	# pointer to pt_regs @@ -187,8 +184,8 @@ sysc_vtime:  	mvc	__PT_R8(32,%r11),__LC_SAVE_AREA_SYNC  	mvc	__PT_PSW(8,%r11),__LC_SVC_OLD_PSW  	mvc	__PT_INT_CODE(4,%r11),__LC_SVC_ILC +	st	%r14,__PT_FLAGS(%r11)  sysc_do_svc: -	oi	__TI_flags+3(%r12),_TIF_SYSCALL  	l	%r10,__TI_sysc_table(%r12)	# 31 bit system call table  	lh	%r8,__PT_INT_CODE+2(%r11)  	sla	%r8,2				# shift and test for svc0 @@ -204,7 +201,7 @@ sysc_nr_ok:  	st	%r2,__PT_ORIG_GPR2(%r11)  	st	%r7,STACK_FRAME_OVERHEAD(%r15)  	l	%r9,0(%r8,%r10)			# get system call addr. -	tm	__TI_flags+2(%r12),_TIF_TRACE >> 8 +	tm	__TI_flags+3(%r12),_TIF_TRACE  	jnz	sysc_tracesys  	basr	%r14,%r9			# call sys_xxxx  	st	%r2,__PT_R2(%r11)		# store return value @@ -214,9 +211,12 @@ sysc_return:  sysc_tif:  	tm	__PT_PSW+1(%r11),0x01		# returning to user ?  	jno	sysc_restore -	tm	__TI_flags+3(%r12),_TIF_WORK_SVC -	jnz	sysc_work			# check for work -	ni	__TI_flags+3(%r12),255-_TIF_SYSCALL +	tm	__PT_FLAGS+3(%r11),_PIF_WORK +	jnz	sysc_work +	tm	__TI_flags+3(%r12),_TIF_WORK +	jnz	sysc_work			# check for thread work +	tm	__LC_CPU_FLAGS+3,_CIF_WORK +	jnz	sysc_work  sysc_restore:  	mvc	__LC_RETURN_PSW(8),__PT_PSW(%r11)  	stpt	__LC_EXIT_TIMER @@ -228,16 +228,18 @@ sysc_done:  # One of the work bits is on. Find out which one.  #  sysc_work: -	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING +	tm	__LC_CPU_FLAGS+3,_CIF_MCCK_PENDING  	jo	sysc_mcck_pending  	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED  	jo	sysc_reschedule -	tm	__TI_flags+3(%r12),_TIF_PER_TRAP +	tm	__PT_FLAGS+3(%r11),_PIF_PER_TRAP  	jo	sysc_singlestep  	tm	__TI_flags+3(%r12),_TIF_SIGPENDING  	jo	sysc_sigpending  	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME  	jo	sysc_notify_resume +	tm	__LC_CPU_FLAGS+3,_CIF_ASCE +	jo	sysc_uaccess  	j	sysc_return		# beware of critical section cleanup  # @@ -249,7 +251,7 @@ sysc_reschedule:  	br	%r1			# call schedule  # -# _TIF_MCCK_PENDING is set, call handler +# _CIF_MCCK_PENDING is set, call handler  #  sysc_mcck_pending:  	l	%r1,BASED(.Lhandle_mcck) @@ -257,15 +259,24 @@ sysc_mcck_pending:  	br	%r1			# TIF bit will be cleared by handler  # +# _CIF_ASCE is set, load user space asce +# +sysc_uaccess: +	ni	__LC_CPU_FLAGS+3,255-_CIF_ASCE +	lctl	%c1,%c1,__LC_USER_ASCE	# load primary asce +	j	sysc_return + +#  # _TIF_SIGPENDING is set, call do_signal  #  sysc_sigpending:  	lr	%r2,%r11		# pass pointer to pt_regs  	l	%r1,BASED(.Ldo_signal)  	basr	%r14,%r1		# call do_signal -	tm	__TI_flags+3(%r12),_TIF_SYSCALL +	tm	__PT_FLAGS+3(%r11),_PIF_SYSCALL  	jno	sysc_return  	lm	%r2,%r7,__PT_R2(%r11)	# load svc arguments +	l	%r10,__TI_sysc_table(%r12)	# 31 bit system call table  	xr	%r8,%r8			# svc 0 returns -ENOSYS  	clc	__PT_INT_CODE+2(2,%r11),BASED(.Lnr_syscalls+2)  	jnl	sysc_nr_ok		# invalid svc number -> do svc 0 @@ -283,10 +294,10 @@ sysc_notify_resume:  	br	%r1			# call do_notify_resume  # -# _TIF_PER_TRAP is set, call do_per_trap +# _PIF_PER_TRAP is set, call do_per_trap  #  sysc_singlestep: -	ni	__TI_flags+3(%r12),255-_TIF_PER_TRAP +	ni	__PT_FLAGS+3(%r11),255-_PIF_PER_TRAP  	lr	%r2,%r11		# pass pointer to pt_regs  	l	%r1,BASED(.Ldo_per_trap)  	la	%r14,BASED(sysc_return) @@ -316,7 +327,7 @@ sysc_tracego:  	basr	%r14,%r9		# call sys_xxx  	st	%r2,__PT_R2(%r11)	# store return value  sysc_tracenogo: -	tm	__TI_flags+2(%r12),_TIF_TRACE >> 8 +	tm	__TI_flags+3(%r12),_TIF_TRACE  	jz	sysc_return  	l	%r1,BASED(.Ltrace_exit)  	lr	%r2,%r11		# pass pointer to pt_regs @@ -370,15 +381,16 @@ ENTRY(pgm_check_handler)  	stm	%r8,%r9,__PT_PSW(%r11)  	mvc	__PT_INT_CODE(4,%r11),__LC_PGM_ILC  	mvc	__PT_INT_PARM_LONG(4,%r11),__LC_TRANS_EXC_CODE +	xc	__PT_FLAGS(4,%r11),__PT_FLAGS(%r11)  	tm	__LC_PGM_ILC+3,0x80	# check for per exception  	jz	0f  	l	%r1,__TI_task(%r12)  	tmh	%r8,0x0001		# kernel per event ?  	jz	pgm_kprobe -	oi	__TI_flags+3(%r12),_TIF_PER_TRAP +	oi	__PT_FLAGS+3(%r11),_PIF_PER_TRAP  	mvc	__THREAD_per_address(4,%r1),__LC_PER_ADDRESS -	mvc	__THREAD_per_cause(2,%r1),__LC_PER_CAUSE -	mvc	__THREAD_per_paid(1,%r1),__LC_PER_PAID +	mvc	__THREAD_per_cause(2,%r1),__LC_PER_CODE +	mvc	__THREAD_per_paid(1,%r1),__LC_PER_ACCESS_ID  0:	REENABLE_IRQS  	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)  	l	%r1,BASED(.Ljump_table) @@ -406,9 +418,9 @@ pgm_kprobe:  # single stepped system call  #  pgm_svcper: -	oi	__TI_flags+3(%r12),_TIF_PER_TRAP  	mvc	__LC_RETURN_PSW(4),__LC_SVC_NEW_PSW  	mvc	__LC_RETURN_PSW+4(4),BASED(.Lsysc_per) +	lhi	%r14,_PIF_SYSCALL | _PIF_PER_TRAP  	lpsw	__LC_RETURN_PSW		# branch to sysc_per and enable irqs  /* @@ -431,6 +443,7 @@ io_skip:  	mvc	__PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC  	stm	%r8,%r9,__PT_PSW(%r11)  	mvc	__PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID +	xc	__PT_FLAGS(4,%r11),__PT_FLAGS(%r11)  	TRACE_IRQS_OFF  	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)  io_loop: @@ -452,8 +465,10 @@ io_return:  	LOCKDEP_SYS_EXIT  	TRACE_IRQS_ON  io_tif: -	tm	__TI_flags+3(%r12),_TIF_WORK_INT +	tm	__TI_flags+3(%r12),_TIF_WORK  	jnz	io_work			# there is work to do (signals etc.) +	tm	__LC_CPU_FLAGS+3,_CIF_WORK +	jnz	io_work  io_restore:  	mvc	__LC_RETURN_PSW(8),__PT_PSW(%r11)  	stpt	__LC_EXIT_TIMER @@ -463,7 +478,7 @@ io_done:  #  # There is work todo, find out in which context we have been interrupted: -# 1) if we return to user space we can do all _TIF_WORK_INT work +# 1) if we return to user space we can do all _TIF_WORK work  # 2) if we return to kernel code and preemptive scheduling is enabled check  #    the preemption counter and if it is zero call preempt_schedule_irq  # Before any work can be done, a switch to the kernel stack is required. @@ -506,11 +521,9 @@ io_work_user:  #  # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED -#		and _TIF_MCCK_PENDING  #  io_work_tif: -	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING +	tm	__LC_CPU_FLAGS+3(%r12),_CIF_MCCK_PENDING  	jo	io_mcck_pending  	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED  	jo	io_reschedule @@ -518,10 +531,12 @@ io_work_tif:  	jo	io_sigpending  	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME  	jo	io_notify_resume +	tm	__LC_CPU_FLAGS+3,_CIF_ASCE +	jo	io_uaccess  	j	io_return		# beware of critical section cleanup  # -# _TIF_MCCK_PENDING is set, call handler +# _CIF_MCCK_PENDING is set, call handler  #  io_mcck_pending:  	# TRACE_IRQS_ON already done at io_return @@ -531,6 +546,14 @@ io_mcck_pending:  	j	io_return  # +# _CIF_ASCE is set, load user space asce +# +io_uaccess: +	ni	__LC_CPU_FLAGS+3,255-_CIF_ASCE +	lctl	%c1,%c1,__LC_USER_ASCE	# load primary asce +	j	io_return + +#  # _TIF_NEED_RESCHED is set, call schedule  #  io_reschedule: @@ -589,6 +612,7 @@ ext_skip:  	stm	%r8,%r9,__PT_PSW(%r11)  	mvc	__PT_INT_CODE(4,%r11),__LC_EXT_CPU_ADDR  	mvc	__PT_INT_PARM(4,%r11),__LC_EXT_PARAMS +	xc	__PT_FLAGS(4,%r11),__PT_FLAGS(%r11)  	TRACE_IRQS_OFF  	l	%r1,BASED(.Ldo_IRQ)  	lr	%r2,%r11		# pass pointer to pt_regs @@ -653,6 +677,7 @@ mcck_skip:  	stm	%r0,%r7,__PT_R0(%r11)  	mvc	__PT_R8(32,%r11),__LC_GPREGS_SAVE_AREA+32  	stm	%r8,%r9,__PT_PSW(%r11) +	xc	__PT_FLAGS(4,%r11),__PT_FLAGS(%r11)  	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)  	l	%r1,BASED(.Ldo_machine_check)  	lr	%r2,%r11		# pass pointer to pt_regs @@ -665,7 +690,7 @@ mcck_skip:  	la	%r11,STACK_FRAME_OVERHEAD(%r15)  	lr	%r15,%r1  	ssm	__LC_PGM_NEW_PSW	# turn dat on, keep irqs off -	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING +	tm	__LC_CPU_FLAGS+3,_CIF_MCCK_PENDING  	jno	mcck_return  	TRACE_IRQS_OFF  	l	%r1,BASED(.Lhandle_mcck) @@ -818,6 +843,8 @@ cleanup_system_call:  	stm	%r0,%r7,__PT_R0(%r9)  	mvc	__PT_PSW(8,%r9),__LC_SVC_OLD_PSW  	mvc	__PT_INT_CODE(4,%r9),__LC_SVC_ILC +	xc	__PT_FLAGS(4,%r9),__PT_FLAGS(%r9) +	mvi	__PT_FLAGS+3(%r9),_PIF_SYSCALL  	# setup saved register 15  	st	%r15,28(%r11)		# r15 stack pointer  	# set new psw address and exit diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index e9b04c33d38..6ac78192455 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h @@ -23,7 +23,6 @@ asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);  void do_protection_exception(struct pt_regs *regs);  void do_dat_exception(struct pt_regs *regs); -void do_asce_exception(struct pt_regs *regs);  void addressing_exception(struct pt_regs *regs);  void data_exception(struct pt_regs *regs); @@ -68,9 +67,7 @@ struct s390_mmap_arg_struct;  struct fadvise64_64_args;  struct old_sigaction; -long sys_sigreturn(void); -long sys_rt_sigreturn(void); -long sys32_sigreturn(void); -long sys32_rt_sigreturn(void); +long sys_s390_personality(unsigned int personality); +long sys_s390_runtime_instr(int command, int signum);  #endif /* _ENTRY_H */ diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 2b2188b97c6..f2e674c702e 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -42,12 +42,11 @@ STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER  STACK_SIZE  = 1 << STACK_SHIFT  STACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ -		 _TIF_MCCK_PENDING | _TIF_PER_TRAP ) -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ -		 _TIF_MCCK_PENDING) -_TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ -		 _TIF_SYSCALL_TRACEPOINT) +_TIF_WORK	= (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) +_TIF_TRACE	= (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ +		   _TIF_SYSCALL_TRACEPOINT) +_CIF_WORK	= (_CIF_MCCK_PENDING | _CIF_ASCE) +_PIF_WORK	= (_PIF_PER_TRAP)  #define BASED(name) name-system_call(%r13) @@ -74,7 +73,7 @@ _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \  	.endm  	.macro LPP newpp -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +#if IS_ENABLED(CONFIG_KVM)  	tm	__LC_MACHINE_FLAGS+6,0x20	# MACHINE_FLAG_LPP  	jz	.+8  	.insn	s,0xb2800000,\newpp @@ -82,7 +81,7 @@ _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \  	.endm  	.macro	HANDLE_SIE_INTERCEPT scratch,reason -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +#if IS_ENABLED(CONFIG_KVM)  	tmhh	%r8,0x0001		# interrupting from user ?  	jnz	.+62  	lgr	\scratch,%r9 @@ -189,11 +188,7 @@ ENTRY(__switch_to)  	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4  	mvc	__LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next  	lg	%r15,__THREAD_ksp(%r3)		# load kernel stack of next -	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending? -	jz	0f -	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev -	oi	__TI_flags+7(%r5),_TIF_MCCK_PENDING	# set it in next -0:	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task +	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task  	br	%r14  __critical_start: @@ -208,6 +203,7 @@ sysc_stmg:  	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC  	lg	%r10,__LC_LAST_BREAK  	lg	%r12,__LC_THREAD_INFO +	lghi	%r14,_PIF_SYSCALL  sysc_per:  	lg	%r15,__LC_KERNEL_STACK  	la	%r11,STACK_FRAME_OVERHEAD(%r15)	# pointer to pt_regs @@ -218,8 +214,8 @@ sysc_vtime:  	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_SYNC  	mvc	__PT_PSW(16,%r11),__LC_SVC_OLD_PSW  	mvc	__PT_INT_CODE(4,%r11),__LC_SVC_ILC +	stg	%r14,__PT_FLAGS(%r11)  sysc_do_svc: -	oi	__TI_flags+7(%r12),_TIF_SYSCALL  	lg	%r10,__TI_sysc_table(%r12)	# address of system call table  	llgh	%r8,__PT_INT_CODE+2(%r11)  	slag	%r8,%r8,2			# shift and test for svc 0 @@ -235,7 +231,7 @@ sysc_nr_ok:  	stg	%r2,__PT_ORIG_GPR2(%r11)  	stg	%r7,STACK_FRAME_OVERHEAD(%r15)  	lgf	%r9,0(%r8,%r10)			# get system call add. -	tm	__TI_flags+6(%r12),_TIF_TRACE >> 8 +	tm	__TI_flags+7(%r12),_TIF_TRACE  	jnz	sysc_tracesys  	basr	%r14,%r9			# call sys_xxxx  	stg	%r2,__PT_R2(%r11)		# store return value @@ -245,9 +241,12 @@ sysc_return:  sysc_tif:  	tm	__PT_PSW+1(%r11),0x01		# returning to user ?  	jno	sysc_restore -	tm	__TI_flags+7(%r12),_TIF_WORK_SVC +	tm	__PT_FLAGS+7(%r11),_PIF_WORK +	jnz	sysc_work +	tm	__TI_flags+7(%r12),_TIF_WORK  	jnz	sysc_work			# check for work -	ni	__TI_flags+7(%r12),255-_TIF_SYSCALL +	tm	__LC_CPU_FLAGS+7,_CIF_WORK +	jnz	sysc_work  sysc_restore:  	lg	%r14,__LC_VDSO_PER_CPU  	lmg	%r0,%r10,__PT_R0(%r11) @@ -262,16 +261,18 @@ sysc_done:  # One of the work bits is on. Find out which one.  #  sysc_work: -	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING +	tm	__LC_CPU_FLAGS+7,_CIF_MCCK_PENDING  	jo	sysc_mcck_pending  	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED  	jo	sysc_reschedule -	tm	__TI_flags+7(%r12),_TIF_PER_TRAP +	tm	__PT_FLAGS+7(%r11),_PIF_PER_TRAP  	jo	sysc_singlestep  	tm	__TI_flags+7(%r12),_TIF_SIGPENDING  	jo	sysc_sigpending  	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME  	jo	sysc_notify_resume +	tm	__LC_CPU_FLAGS+7,_CIF_ASCE +	jo	sysc_uaccess  	j	sysc_return		# beware of critical section cleanup  # @@ -282,21 +283,30 @@ sysc_reschedule:  	jg	schedule  # -# _TIF_MCCK_PENDING is set, call handler +# _CIF_MCCK_PENDING is set, call handler  #  sysc_mcck_pending:  	larl	%r14,sysc_return  	jg	s390_handle_mcck	# TIF bit will be cleared by handler  # +# _CIF_ASCE is set, load user space asce +# +sysc_uaccess: +	ni	__LC_CPU_FLAGS+7,255-_CIF_ASCE +	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce +	j	sysc_return + +#  # _TIF_SIGPENDING is set, call do_signal  #  sysc_sigpending:  	lgr	%r2,%r11		# pass pointer to pt_regs  	brasl	%r14,do_signal -	tm	__TI_flags+7(%r12),_TIF_SYSCALL +	tm	__PT_FLAGS+7(%r11),_PIF_SYSCALL  	jno	sysc_return  	lmg	%r2,%r7,__PT_R2(%r11)	# load svc arguments +	lg	%r10,__TI_sysc_table(%r12)	# address of system call table  	lghi	%r8,0			# svc 0 returns -ENOSYS  	llgh	%r1,__PT_INT_CODE+2(%r11)	# load new svc number  	cghi	%r1,NR_syscalls @@ -313,10 +323,10 @@ sysc_notify_resume:  	jg	do_notify_resume  # -# _TIF_PER_TRAP is set, call do_per_trap +# _PIF_PER_TRAP is set, call do_per_trap  #  sysc_singlestep: -	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP +	ni	__PT_FLAGS+7(%r11),255-_PIF_PER_TRAP  	lgr	%r2,%r11		# pass pointer to pt_regs  	larl	%r14,sysc_return  	jg	do_per_trap @@ -343,7 +353,7 @@ sysc_tracego:  	basr	%r14,%r9		# call sys_xxx  	stg	%r2,__PT_R2(%r11)	# store return value  sysc_tracenogo: -	tm	__TI_flags+6(%r12),_TIF_TRACE >> 8 +	tm	__TI_flags+7(%r12),_TIF_TRACE  	jz	sysc_return  	lgr	%r2,%r11		# pass pointer to pt_regs  	larl	%r14,sysc_return @@ -402,15 +412,16 @@ ENTRY(pgm_check_handler)  	stmg	%r8,%r9,__PT_PSW(%r11)  	mvc	__PT_INT_CODE(4,%r11),__LC_PGM_ILC  	mvc	__PT_INT_PARM_LONG(8,%r11),__LC_TRANS_EXC_CODE +	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)  	stg	%r10,__PT_ARGS(%r11)  	tm	__LC_PGM_ILC+3,0x80	# check for per exception  	jz	0f  	tmhh	%r8,0x0001		# kernel per event ?  	jz	pgm_kprobe -	oi	__TI_flags+7(%r12),_TIF_PER_TRAP +	oi	__PT_FLAGS+7(%r11),_PIF_PER_TRAP  	mvc	__THREAD_per_address(8,%r14),__LC_PER_ADDRESS -	mvc	__THREAD_per_cause(2,%r14),__LC_PER_CAUSE -	mvc	__THREAD_per_paid(1,%r14),__LC_PER_PAID +	mvc	__THREAD_per_cause(2,%r14),__LC_PER_CODE +	mvc	__THREAD_per_paid(1,%r14),__LC_PER_ACCESS_ID  0:	REENABLE_IRQS  	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)  	larl	%r1,pgm_check_table @@ -437,10 +448,10 @@ pgm_kprobe:  # single stepped system call  #  pgm_svcper: -	oi	__TI_flags+7(%r12),_TIF_PER_TRAP  	mvc	__LC_RETURN_PSW(8),__LC_SVC_NEW_PSW  	larl	%r14,sysc_per  	stg	%r14,__LC_RETURN_PSW+8 +	lghi	%r14,_PIF_SYSCALL | _PIF_PER_TRAP  	lpswe	__LC_RETURN_PSW		# branch to sysc_per and enable irqs  /* @@ -465,6 +476,7 @@ io_skip:  	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC  	stmg	%r8,%r9,__PT_PSW(%r11)  	mvc	__PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID +	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)  	TRACE_IRQS_OFF  	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)  io_loop: @@ -485,8 +497,10 @@ io_return:  	LOCKDEP_SYS_EXIT  	TRACE_IRQS_ON  io_tif: -	tm	__TI_flags+7(%r12),_TIF_WORK_INT +	tm	__TI_flags+7(%r12),_TIF_WORK  	jnz	io_work 		# there is work to do (signals etc.) +	tm	__LC_CPU_FLAGS+7,_CIF_WORK +	jnz	io_work  io_restore:  	lg	%r14,__LC_VDSO_PER_CPU  	lmg	%r0,%r10,__PT_R0(%r11) @@ -499,7 +513,7 @@ io_done:  #  # There is work todo, find out in which context we have been interrupted: -# 1) if we return to user space we can do all _TIF_WORK_INT work +# 1) if we return to user space we can do all _TIF_WORK work  # 2) if we return to kernel code and kvm is enabled check if we need to  #    modify the psw to leave SIE  # 3) if we return to kernel code and preemptive scheduling is enabled check @@ -543,11 +557,9 @@ io_work_user:  #  # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED -#	       and _TIF_MCCK_PENDING  #  io_work_tif: -	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING +	tm	__LC_CPU_FLAGS+7,_CIF_MCCK_PENDING  	jo	io_mcck_pending  	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED  	jo	io_reschedule @@ -555,10 +567,12 @@ io_work_tif:  	jo	io_sigpending  	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME  	jo	io_notify_resume +	tm	__LC_CPU_FLAGS+7,_CIF_ASCE +	jo	io_uaccess  	j	io_return		# beware of critical section cleanup  # -# _TIF_MCCK_PENDING is set, call handler +# _CIF_MCCK_PENDING is set, call handler  #  io_mcck_pending:  	# TRACE_IRQS_ON already done at io_return @@ -567,6 +581,14 @@ io_mcck_pending:  	j	io_return  # +# _CIF_ASCE is set, load user space asce +# +io_uaccess: +	ni	__LC_CPU_FLAGS+7,255-_CIF_ASCE +	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce +	j	io_return + +#  # _TIF_NEED_RESCHED is set, call schedule  #  io_reschedule: @@ -626,6 +648,7 @@ ext_skip:  	mvc	__PT_INT_CODE(4,%r11),__LC_EXT_CPU_ADDR  	mvc	__PT_INT_PARM(4,%r11),__LC_EXT_PARAMS  	mvc	__PT_INT_PARM_LONG(8,%r11),0(%r1) +	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)  	TRACE_IRQS_OFF  	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)  	lgr	%r2,%r11		# pass pointer to pt_regs @@ -692,6 +715,7 @@ mcck_skip:  	stmg	%r0,%r7,__PT_R0(%r11)  	mvc	__PT_R8(64,%r11),0(%r14)  	stmg	%r8,%r9,__PT_PSW(%r11) +	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)  	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)  	lgr	%r2,%r11		# pass pointer to pt_regs  	brasl	%r14,s390_do_machine_check @@ -703,7 +727,7 @@ mcck_skip:  	la	%r11,STACK_FRAME_OVERHEAD(%r1)  	lgr	%r15,%r1  	ssm	__LC_PGM_NEW_PSW	# turn dat on, keep irqs off -	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING +	tm	__LC_CPU_FLAGS+7,_CIF_MCCK_PENDING  	jno	mcck_return  	TRACE_IRQS_OFF  	brasl	%r14,s390_handle_mcck @@ -860,6 +884,8 @@ cleanup_system_call:  	stmg	%r0,%r7,__PT_R0(%r9)  	mvc	__PT_PSW(16,%r9),__LC_SVC_OLD_PSW  	mvc	__PT_INT_CODE(4,%r9),__LC_SVC_ILC +	xc	__PT_FLAGS(8,%r9),__PT_FLAGS(%r9) +	mvi	__PT_FLAGS+7(%r9),_PIF_SYSCALL  	# setup saved register r15  	stg	%r15,56(%r11)		# r15 stack pointer  	# set new psw address and exit @@ -945,7 +971,7 @@ cleanup_idle_insn:  	.quad	__critical_end - __critical_start -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +#if IS_ENABLED(CONFIG_KVM)  /*   * sie64a calling convention:   * %r2 pointer to sie control block @@ -974,7 +1000,7 @@ sie_done:  	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce  # some program checks are suppressing. C code (e.g. do_protection_exception)  # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other -# instructions beween sie64a and sie_done should not cause program +# instructions between sie64a and sie_done should not cause program  # interrupts. So lets use a nop (47 00 00 00) as a landing pad.  # See also HANDLE_SIE_INTERCEPT  rewind_pad: diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 1014ad5f769..54d6493c4a5 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -130,9 +130,8 @@ int ftrace_update_ftrace_func(ftrace_func_t func)  	return 0;  } -int __init ftrace_dyn_arch_init(void *data) +int __init ftrace_dyn_arch_init(void)  { -	*(unsigned long *) data = 0;  	return 0;  } @@ -151,14 +150,13 @@ unsigned long __kprobes prepare_ftrace_return(unsigned long parent,  	if (unlikely(atomic_read(¤t->tracing_graph_pause)))  		goto out;  	ip = (ip & PSW_ADDR_INSN) - MCOUNT_INSN_SIZE; -	if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY) -		goto out;  	trace.func = ip; +	trace.depth = current->curr_ret_stack + 1;  	/* Only trace if the calling function expects to. */ -	if (!ftrace_graph_entry(&trace)) { -		current->curr_ret_stack--; +	if (!ftrace_graph_entry(&trace)) +		goto out; +	if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)  		goto out; -	}  	parent = (unsigned long) return_to_handler;  out:  	return parent; diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index fd8db63dfc9..e88d35d7495 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -437,13 +437,13 @@ ENTRY(startup_kdump)  #if defined(CONFIG_64BIT)  #if defined(CONFIG_MARCH_ZEC12) -	.long 3, 0xc100efe3, 0xf46ce000, 0x00400000 +	.long 3, 0xc100eff2, 0xf46ce800, 0x00400000  #elif defined(CONFIG_MARCH_Z196) -	.long 2, 0xc100efe3, 0xf46c0000 +	.long 2, 0xc100eff2, 0xf46c0000  #elif defined(CONFIG_MARCH_Z10) -	.long 2, 0xc100efe3, 0xf0680000 +	.long 2, 0xc100eff2, 0xf0680000  #elif defined(CONFIG_MARCH_Z9_109) -	.long 1, 0xc100efc3 +	.long 1, 0xc100efc2  #elif defined(CONFIG_MARCH_Z990)  	.long 1, 0xc0002000  #elif defined(CONFIG_MARCH_Z900) diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index 9a99856df1c..6dbe80983a2 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -59,7 +59,6 @@ ENTRY(startup_continue)  	.long	0			# cr13: home space segment table  	.long	0xc0000000		# cr14: machine check handling off  	.long	0			# cr15: linkage stack operations -.Lmchunk:.long	memory_chunk  .Lbss_bgn:  .long __bss_start  .Lbss_end:  .long _end  .Lparmaddr: .long PARMAREA diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index b9e25ae2579..d7c00507568 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -59,7 +59,7 @@ ENTRY(startup_continue)  	.quad	0			# cr12: tracing off  	.quad	0			# cr13: home space segment table  	.quad	0xc0000000		# cr14: machine check handling off -	.quad	0			# cr15: linkage stack operations +	.quad	.Llinkage_stack		# cr15: linkage stack operations  .Lpcmsk:.quad	0x0000000180000000  .L4malign:.quad 0xffffffffffc00000  .Lscan2g:.quad	0x80000000 + 0x20000 - 8	# 2GB + 128K - 8 @@ -67,12 +67,15 @@ ENTRY(startup_continue)  .Lparmaddr:  	.quad	PARMAREA  	.align	64 -.Lduct: .long	0,0,0,0,.Lduald,0,0,0 +.Lduct: .long	0,.Laste,.Laste,0,.Lduald,0,0,0  	.long	0,0,0,0,0,0,0,0 +.Laste:	.quad	0,0xffffffffffffffff,0,0,0,0,0,0  	.align	128  .Lduald:.rept	8  	.long	0x80000000,0,0,0	# invalid access-list entries  	.endr +.Llinkage_stack: +	.long	0,0,0x89000000,0,0,0,0x8a000000,0  ENTRY(_ehead) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index feb719d3c85..633ca750453 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -2051,12 +2051,12 @@ void s390_reset_system(void (*func)(void *), void *data)  	__ctl_clear_bit(0,28);  	/* Set new machine check handler */ -	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT; +	S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;  	S390_lowcore.mcck_new_psw.addr =  		PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;  	/* Set new program check handler */ -	S390_lowcore.program_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT; +	S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;  	S390_lowcore.program_new_psw.addr =  		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler; diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 8ac2097f13d..99b0b09646c 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -18,6 +18,7 @@  #include <linux/errno.h>  #include <linux/slab.h>  #include <linux/cpu.h> +#include <linux/irq.h>  #include <asm/irq_regs.h>  #include <asm/cputime.h>  #include <asm/lowcore.h> @@ -84,13 +85,13 @@ static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {  	[IRQIO_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },  	[IRQIO_MSI]  = {.name = "MSI", .desc = "[I/O] MSI Interrupt" },  	[IRQIO_VIR]  = {.name = "VIR", .desc = "[I/O] Virtual I/O Devices"}, +	[IRQIO_VAI]  = {.name = "VAI", .desc = "[I/O] Virtual I/O Devices AI"},  	[NMI_NMI]    = {.name = "NMI", .desc = "[NMI] Machine Check"},  	[CPU_RST]    = {.name = "RST", .desc = "[CPU] CPU Restart"},  };  void __init init_IRQ(void)  { -	irq_reserve_irqs(0, THIN_INTERRUPT);  	init_cio_interrupts();  	init_airq_interrupts();  	init_ext_interrupts(); @@ -149,47 +150,37 @@ out:  	return 0;  } -int arch_show_interrupts(struct seq_file *p, int prec) +unsigned int arch_dynirq_lower_bound(unsigned int from)  { -	return 0; +	return from < THIN_INTERRUPT ? THIN_INTERRUPT : from;  }  /*   * Switch to the asynchronous interrupt stack for softirq execution.   */ -asmlinkage void do_softirq(void) +void do_softirq_own_stack(void)  { -	unsigned long flags, old, new; - -	if (in_interrupt()) -		return; - -	local_irq_save(flags); - -	if (local_softirq_pending()) { -		/* Get current stack pointer. */ -		asm volatile("la %0,0(15)" : "=a" (old)); -		/* Check against async. stack address range. */ -		new = S390_lowcore.async_stack; -		if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) { -			/* Need to switch to the async. stack. */ -			new -= STACK_FRAME_OVERHEAD; -			((struct stack_frame *) new)->back_chain = old; - -			asm volatile("   la    15,0(%0)\n" -				     "   basr  14,%2\n" -				     "   la    15,0(%1)\n" -				     : : "a" (new), "a" (old), -				         "a" (__do_softirq) -				     : "0", "1", "2", "3", "4", "5", "14", -				       "cc", "memory" ); -		} else { -			/* We are already on the async stack. */ -			__do_softirq(); -		} +	unsigned long old, new; + +	/* Get current stack pointer. */ +	asm volatile("la %0,0(15)" : "=a" (old)); +	/* Check against async. stack address range. */ +	new = S390_lowcore.async_stack; +	if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) { +		/* Need to switch to the async. stack. */ +		new -= STACK_FRAME_OVERHEAD; +		((struct stack_frame *) new)->back_chain = old; +		asm volatile("   la    15,0(%0)\n" +			     "   basr  14,%2\n" +			     "   la    15,0(%1)\n" +			     : : "a" (new), "a" (old), +			         "a" (__do_softirq) +			     : "0", "1", "2", "3", "4", "5", "14", +			       "cc", "memory" ); +	} else { +		/* We are already on the async stack. */ +		__do_softirq();  	} - -	local_irq_restore(flags);  }  /* @@ -215,7 +206,7 @@ static inline int ext_hash(u16 code)  	return (code + (code >> 9)) & (ARRAY_SIZE(ext_int_hash) - 1);  } -int register_external_interrupt(u16 code, ext_int_handler_t handler) +int register_external_irq(u16 code, ext_int_handler_t handler)  {  	struct ext_int_info *p;  	unsigned long flags; @@ -233,9 +224,9 @@ int register_external_interrupt(u16 code, ext_int_handler_t handler)  	spin_unlock_irqrestore(&ext_int_hash_lock, flags);  	return 0;  } -EXPORT_SYMBOL(register_external_interrupt); +EXPORT_SYMBOL(register_external_irq); -int unregister_external_interrupt(u16 code, ext_int_handler_t handler) +int unregister_external_irq(u16 code, ext_int_handler_t handler)  {  	struct ext_int_info *p;  	unsigned long flags; @@ -251,7 +242,7 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler)  	spin_unlock_irqrestore(&ext_int_hash_lock, flags);  	return 0;  } -EXPORT_SYMBOL(unregister_external_interrupt); +EXPORT_SYMBOL(unregister_external_irq);  static irqreturn_t do_ext_interrupt(int irq, void *dummy)  { @@ -261,7 +252,7 @@ static irqreturn_t do_ext_interrupt(int irq, void *dummy)  	int index;  	ext_code = *(struct ext_code *) ®s->int_code; -	if (ext_code.code != 0x1004) +	if (ext_code.code != EXT_IRQ_CLK_COMP)  		__get_cpu_var(s390_idle).nohz_delay = 1;  	index = ext_hash(ext_code.code); diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 0ce9fb24503..bc71a7b95af 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -26,11 +26,12 @@  #include <linux/stop_machine.h>  #include <linux/kdebug.h>  #include <linux/uaccess.h> -#include <asm/cacheflush.h> -#include <asm/sections.h>  #include <linux/module.h>  #include <linux/slab.h>  #include <linux/hardirq.h> +#include <asm/cacheflush.h> +#include <asm/sections.h> +#include <asm/dis.h>  DEFINE_PER_CPU(struct kprobe *, current_kprobe);  DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); @@ -59,6 +60,8 @@ struct kprobe_insn_cache kprobe_dmainsn_slots = {  static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)  { +	if (!is_known_insn((unsigned char *)insn)) +		return -EINVAL;  	switch (insn[0] >> 8) {  	case 0x0c:	/* bassm */  	case 0x0b:	/* bsm	 */ @@ -67,6 +70,11 @@ static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)  	case 0xac:	/* stnsm */  	case 0xad:	/* stosm */  		return -EINVAL; +	case 0xc6: +		switch (insn[0] & 0x0f) { +		case 0x00: /* exrl   */ +			return -EINVAL; +		}  	}  	switch (insn[0]) {  	case 0x0101:	/* pr	 */ @@ -180,7 +188,6 @@ static int __kprobes is_insn_relative_long(kprobe_opcode_t *insn)  		break;  	case 0xc6:  		switch (insn[0] & 0x0f) { -		case 0x00: /* exrl   */  		case 0x02: /* pfdrl  */  		case 0x04: /* cghrl  */  		case 0x05: /* chrl   */ @@ -204,7 +211,7 @@ static void __kprobes copy_instruction(struct kprobe *p)  	s64 disp, new_disp;  	u64 addr, new_addr; -	memcpy(p->ainsn.insn, p->addr, ((p->opcode >> 14) + 3) & -2); +	memcpy(p->ainsn.insn, p->addr, insn_length(p->opcode >> 8));  	if (!is_insn_relative_long(p->ainsn.insn))  		return;  	/* @@ -248,7 +255,7 @@ static int __kprobes s390_get_insn_slot(struct kprobe *p)  	p->ainsn.insn = NULL;  	if (is_kernel_addr(p->addr))  		p->ainsn.insn = get_dmainsn_slot(); -	if (is_module_addr(p->addr)) +	else if (is_module_addr(p->addr))  		p->ainsn.insn = get_insn_slot();  	return p->ainsn.insn ? 0 : -ENOMEM;  } @@ -604,7 +611,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)  		ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn;  	if (fixup & FIXUP_BRANCH_NOT_TAKEN) { -		int ilen = ((p->ainsn.insn[0] >> 14) + 3) & -2; +		int ilen = insn_length(p->ainsn.insn[0] >> 8);  		if (ip - (unsigned long) p->ainsn.insn == ilen)  			ip = (unsigned long) p->addr + ilen;  	} @@ -673,7 +680,7 @@ static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr)  	case KPROBE_HIT_SSDONE:  		/*  		 * We increment the nmissed count for accounting, -		 * we can also use npre/npostfault count for accouting +		 * we can also use npre/npostfault count for accounting  		 * these specific fault cases.  		 */  		kprobes_inc_nmissed_count(p); diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 7845e15a17d..b89b59158b9 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -50,7 +50,7 @@ void *module_alloc(unsigned long size)  	if (PAGE_ALIGN(size) > MODULES_LEN)  		return NULL;  	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, -				    GFP_KERNEL, PAGE_KERNEL, -1, +				    GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,  				    __builtin_return_address(0));  }  #endif diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index c4c03381987..210e1285f75 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -55,7 +55,7 @@ void s390_handle_mcck(void)  	local_mcck_disable();  	mcck = __get_cpu_var(cpu_mcck);  	memset(&__get_cpu_var(cpu_mcck), 0, sizeof(struct mcck_struct)); -	clear_thread_flag(TIF_MCCK_PENDING); +	clear_cpu_flag(CIF_MCCK_PENDING);  	local_mcck_enable();  	local_irq_restore(flags); @@ -313,7 +313,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)  			 */  			mcck->kill_task = 1;  			mcck->mcck_code = *(unsigned long long *) mci; -			set_thread_flag(TIF_MCCK_PENDING); +			set_cpu_flag(CIF_MCCK_PENDING);  		} else {  			/*  			 * Couldn't restore all register contents while in @@ -352,12 +352,12 @@ void notrace s390_do_machine_check(struct pt_regs *regs)  	if (mci->cp) {  		/* Channel report word pending */  		mcck->channel_report = 1; -		set_thread_flag(TIF_MCCK_PENDING); +		set_cpu_flag(CIF_MCCK_PENDING);  	}  	if (mci->w) {  		/* Warning pending */  		mcck->warning = 1; -		set_thread_flag(TIF_MCCK_PENDING); +		set_cpu_flag(CIF_MCCK_PENDING);  	}  	nmi_exit();  } diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 1105502bf6e..ea75d011a6f 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -673,17 +673,20 @@ static int __init cpumf_pmu_init(void)  	ctl_clear_bit(0, 48);  	/* register handler for measurement-alert interruptions */ -	rc = register_external_interrupt(0x1407, cpumf_measurement_alert); +	rc = register_external_irq(EXT_IRQ_MEASURE_ALERT, +				   cpumf_measurement_alert);  	if (rc) {  		pr_err("Registering for CPU-measurement alerts "  		       "failed with rc=%i\n", rc);  		goto out;  	} +	cpumf_pmu.attr_groups = cpumf_cf_event_group();  	rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);  	if (rc) {  		pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc); -		unregister_external_interrupt(0x1407, cpumf_measurement_alert); +		unregister_external_irq(EXT_IRQ_MEASURE_ALERT, +					cpumf_measurement_alert);  		goto out;  	}  	perf_cpu_notifier(cpumf_pmu_notifier); diff --git a/arch/s390/kernel/perf_cpum_cf_events.c b/arch/s390/kernel/perf_cpum_cf_events.c new file mode 100644 index 00000000000..4554a4bae39 --- /dev/null +++ b/arch/s390/kernel/perf_cpum_cf_events.c @@ -0,0 +1,322 @@ +/* + * Perf PMU sysfs events attributes for available CPU-measurement counters + * + */ + +#include <linux/slab.h> +#include <linux/perf_event.h> + + +/* BEGIN: CPUM_CF COUNTER DEFINITIONS =================================== */ + +CPUMF_EVENT_ATTR(cf, CPU_CYCLES, 0x0000); +CPUMF_EVENT_ATTR(cf, INSTRUCTIONS, 0x0001); +CPUMF_EVENT_ATTR(cf, L1I_DIR_WRITES, 0x0002); +CPUMF_EVENT_ATTR(cf, L1I_PENALTY_CYCLES, 0x0003); +CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_CPU_CYCLES, 0x0020); +CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_INSTRUCTIONS, 0x0021); +CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1I_DIR_WRITES, 0x0022); +CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1I_PENALTY_CYCLES, 0x0023); +CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1D_DIR_WRITES, 0x0024); +CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1D_PENALTY_CYCLES, 0x0025); +CPUMF_EVENT_ATTR(cf, L1D_DIR_WRITES, 0x0004); +CPUMF_EVENT_ATTR(cf, L1D_PENALTY_CYCLES, 0x0005); +CPUMF_EVENT_ATTR(cf, PRNG_FUNCTIONS, 0x0040); +CPUMF_EVENT_ATTR(cf, PRNG_CYCLES, 0x0041); +CPUMF_EVENT_ATTR(cf, PRNG_BLOCKED_FUNCTIONS, 0x0042); +CPUMF_EVENT_ATTR(cf, PRNG_BLOCKED_CYCLES, 0x0043); +CPUMF_EVENT_ATTR(cf, SHA_FUNCTIONS, 0x0044); +CPUMF_EVENT_ATTR(cf, SHA_CYCLES, 0x0045); +CPUMF_EVENT_ATTR(cf, SHA_BLOCKED_FUNCTIONS, 0x0046); +CPUMF_EVENT_ATTR(cf, SHA_BLOCKED_CYCLES, 0x0047); +CPUMF_EVENT_ATTR(cf, DEA_FUNCTIONS, 0x0048); +CPUMF_EVENT_ATTR(cf, DEA_CYCLES, 0x0049); +CPUMF_EVENT_ATTR(cf, DEA_BLOCKED_FUNCTIONS, 0x004a); +CPUMF_EVENT_ATTR(cf, DEA_BLOCKED_CYCLES, 0x004b); +CPUMF_EVENT_ATTR(cf, AES_FUNCTIONS, 0x004c); +CPUMF_EVENT_ATTR(cf, AES_CYCLES, 0x004d); +CPUMF_EVENT_ATTR(cf, AES_BLOCKED_FUNCTIONS, 0x004e); +CPUMF_EVENT_ATTR(cf, AES_BLOCKED_CYCLES, 0x004f); +CPUMF_EVENT_ATTR(cf_z10, L1I_L2_SOURCED_WRITES, 0x0080); +CPUMF_EVENT_ATTR(cf_z10, L1D_L2_SOURCED_WRITES, 0x0081); +CPUMF_EVENT_ATTR(cf_z10, L1I_L3_LOCAL_WRITES, 0x0082); +CPUMF_EVENT_ATTR(cf_z10, L1D_L3_LOCAL_WRITES, 0x0083); +CPUMF_EVENT_ATTR(cf_z10, L1I_L3_REMOTE_WRITES, 0x0084); +CPUMF_EVENT_ATTR(cf_z10, L1D_L3_REMOTE_WRITES, 0x0085); +CPUMF_EVENT_ATTR(cf_z10, L1D_LMEM_SOURCED_WRITES, 0x0086); +CPUMF_EVENT_ATTR(cf_z10, L1I_LMEM_SOURCED_WRITES, 0x0087); +CPUMF_EVENT_ATTR(cf_z10, L1D_RO_EXCL_WRITES, 0x0088); +CPUMF_EVENT_ATTR(cf_z10, L1I_CACHELINE_INVALIDATES, 0x0089); +CPUMF_EVENT_ATTR(cf_z10, ITLB1_WRITES, 0x008a); +CPUMF_EVENT_ATTR(cf_z10, DTLB1_WRITES, 0x008b); +CPUMF_EVENT_ATTR(cf_z10, TLB2_PTE_WRITES, 0x008c); +CPUMF_EVENT_ATTR(cf_z10, TLB2_CRSTE_WRITES, 0x008d); +CPUMF_EVENT_ATTR(cf_z10, TLB2_CRSTE_HPAGE_WRITES, 0x008e); +CPUMF_EVENT_ATTR(cf_z10, ITLB1_MISSES, 0x0091); +CPUMF_EVENT_ATTR(cf_z10, DTLB1_MISSES, 0x0092); +CPUMF_EVENT_ATTR(cf_z10, L2C_STORES_SENT, 0x0093); +CPUMF_EVENT_ATTR(cf_z196, L1D_L2_SOURCED_WRITES, 0x0080); +CPUMF_EVENT_ATTR(cf_z196, L1I_L2_SOURCED_WRITES, 0x0081); +CPUMF_EVENT_ATTR(cf_z196, DTLB1_MISSES, 0x0082); +CPUMF_EVENT_ATTR(cf_z196, ITLB1_MISSES, 0x0083); +CPUMF_EVENT_ATTR(cf_z196, L2C_STORES_SENT, 0x0085); +CPUMF_EVENT_ATTR(cf_z196, L1D_OFFBOOK_L3_SOURCED_WRITES, 0x0086); +CPUMF_EVENT_ATTR(cf_z196, L1D_ONBOOK_L4_SOURCED_WRITES, 0x0087); +CPUMF_EVENT_ATTR(cf_z196, L1I_ONBOOK_L4_SOURCED_WRITES, 0x0088); +CPUMF_EVENT_ATTR(cf_z196, L1D_RO_EXCL_WRITES, 0x0089); +CPUMF_EVENT_ATTR(cf_z196, L1D_OFFBOOK_L4_SOURCED_WRITES, 0x008a); +CPUMF_EVENT_ATTR(cf_z196, L1I_OFFBOOK_L4_SOURCED_WRITES, 0x008b); +CPUMF_EVENT_ATTR(cf_z196, DTLB1_HPAGE_WRITES, 0x008c); +CPUMF_EVENT_ATTR(cf_z196, L1D_LMEM_SOURCED_WRITES, 0x008d); +CPUMF_EVENT_ATTR(cf_z196, L1I_LMEM_SOURCED_WRITES, 0x008e); +CPUMF_EVENT_ATTR(cf_z196, L1I_OFFBOOK_L3_SOURCED_WRITES, 0x008f); +CPUMF_EVENT_ATTR(cf_z196, DTLB1_WRITES, 0x0090); +CPUMF_EVENT_ATTR(cf_z196, ITLB1_WRITES, 0x0091); +CPUMF_EVENT_ATTR(cf_z196, TLB2_PTE_WRITES, 0x0092); +CPUMF_EVENT_ATTR(cf_z196, TLB2_CRSTE_HPAGE_WRITES, 0x0093); +CPUMF_EVENT_ATTR(cf_z196, TLB2_CRSTE_WRITES, 0x0094); +CPUMF_EVENT_ATTR(cf_z196, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0096); +CPUMF_EVENT_ATTR(cf_z196, L1D_OFFCHIP_L3_SOURCED_WRITES, 0x0098); +CPUMF_EVENT_ATTR(cf_z196, L1I_ONCHIP_L3_SOURCED_WRITES, 0x0099); +CPUMF_EVENT_ATTR(cf_z196, L1I_OFFCHIP_L3_SOURCED_WRITES, 0x009b); +CPUMF_EVENT_ATTR(cf_zec12, DTLB1_MISSES, 0x0080); +CPUMF_EVENT_ATTR(cf_zec12, ITLB1_MISSES, 0x0081); +CPUMF_EVENT_ATTR(cf_zec12, L1D_L2I_SOURCED_WRITES, 0x0082); +CPUMF_EVENT_ATTR(cf_zec12, L1I_L2I_SOURCED_WRITES, 0x0083); +CPUMF_EVENT_ATTR(cf_zec12, L1D_L2D_SOURCED_WRITES, 0x0084); +CPUMF_EVENT_ATTR(cf_zec12, DTLB1_WRITES, 0x0085); +CPUMF_EVENT_ATTR(cf_zec12, L1D_LMEM_SOURCED_WRITES, 0x0087); +CPUMF_EVENT_ATTR(cf_zec12, L1I_LMEM_SOURCED_WRITES, 0x0089); +CPUMF_EVENT_ATTR(cf_zec12, L1D_RO_EXCL_WRITES, 0x008a); +CPUMF_EVENT_ATTR(cf_zec12, DTLB1_HPAGE_WRITES, 0x008b); +CPUMF_EVENT_ATTR(cf_zec12, ITLB1_WRITES, 0x008c); +CPUMF_EVENT_ATTR(cf_zec12, TLB2_PTE_WRITES, 0x008d); +CPUMF_EVENT_ATTR(cf_zec12, TLB2_CRSTE_HPAGE_WRITES, 0x008e); +CPUMF_EVENT_ATTR(cf_zec12, TLB2_CRSTE_WRITES, 0x008f); +CPUMF_EVENT_ATTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0090); +CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES, 0x0091); +CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES, 0x0092); +CPUMF_EVENT_ATTR(cf_zec12, L1D_ONBOOK_L4_SOURCED_WRITES, 0x0093); +CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L4_SOURCED_WRITES, 0x0094); +CPUMF_EVENT_ATTR(cf_zec12, TX_NC_TEND, 0x0095); +CPUMF_EVENT_ATTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES_IV, 0x0096); +CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES_IV, 0x0097); +CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES_IV, 0x0098); +CPUMF_EVENT_ATTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES, 0x0099); +CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES, 0x009a); +CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES, 0x009b); +CPUMF_EVENT_ATTR(cf_zec12, L1I_ONBOOK_L4_SOURCED_WRITES, 0x009c); +CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L4_SOURCED_WRITES, 0x009d); +CPUMF_EVENT_ATTR(cf_zec12, TX_C_TEND, 0x009e); +CPUMF_EVENT_ATTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES_IV, 0x009f); +CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES_IV, 0x00a0); +CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES_IV, 0x00a1); +CPUMF_EVENT_ATTR(cf_zec12, TX_NC_TABORT, 0x00b1); +CPUMF_EVENT_ATTR(cf_zec12, TX_C_TABORT_NO_SPECIAL, 0x00b2); +CPUMF_EVENT_ATTR(cf_zec12, TX_C_TABORT_SPECIAL, 0x00b3); + +static struct attribute *cpumcf_pmu_event_attr[] = { +	CPUMF_EVENT_PTR(cf, CPU_CYCLES), +	CPUMF_EVENT_PTR(cf, INSTRUCTIONS), +	CPUMF_EVENT_PTR(cf, L1I_DIR_WRITES), +	CPUMF_EVENT_PTR(cf, L1I_PENALTY_CYCLES), +	CPUMF_EVENT_PTR(cf, PROBLEM_STATE_CPU_CYCLES), +	CPUMF_EVENT_PTR(cf, PROBLEM_STATE_INSTRUCTIONS), +	CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1I_DIR_WRITES), +	CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1I_PENALTY_CYCLES), +	CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1D_DIR_WRITES), +	CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1D_PENALTY_CYCLES), +	CPUMF_EVENT_PTR(cf, L1D_DIR_WRITES), +	CPUMF_EVENT_PTR(cf, L1D_PENALTY_CYCLES), +	CPUMF_EVENT_PTR(cf, PRNG_FUNCTIONS), +	CPUMF_EVENT_PTR(cf, PRNG_CYCLES), +	CPUMF_EVENT_PTR(cf, PRNG_BLOCKED_FUNCTIONS), +	CPUMF_EVENT_PTR(cf, PRNG_BLOCKED_CYCLES), +	CPUMF_EVENT_PTR(cf, SHA_FUNCTIONS), +	CPUMF_EVENT_PTR(cf, SHA_CYCLES), +	CPUMF_EVENT_PTR(cf, SHA_BLOCKED_FUNCTIONS), +	CPUMF_EVENT_PTR(cf, SHA_BLOCKED_CYCLES), +	CPUMF_EVENT_PTR(cf, DEA_FUNCTIONS), +	CPUMF_EVENT_PTR(cf, DEA_CYCLES), +	CPUMF_EVENT_PTR(cf, DEA_BLOCKED_FUNCTIONS), +	CPUMF_EVENT_PTR(cf, DEA_BLOCKED_CYCLES), +	CPUMF_EVENT_PTR(cf, AES_FUNCTIONS), +	CPUMF_EVENT_PTR(cf, AES_CYCLES), +	CPUMF_EVENT_PTR(cf, AES_BLOCKED_FUNCTIONS), +	CPUMF_EVENT_PTR(cf, AES_BLOCKED_CYCLES), +	NULL, +}; + +static struct attribute *cpumcf_z10_pmu_event_attr[] __initdata = { +	CPUMF_EVENT_PTR(cf_z10, L1I_L2_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1D_L2_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1I_L3_LOCAL_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1D_L3_LOCAL_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1I_L3_REMOTE_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1D_L3_REMOTE_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1D_LMEM_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1I_LMEM_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1D_RO_EXCL_WRITES), +	CPUMF_EVENT_PTR(cf_z10, L1I_CACHELINE_INVALIDATES), +	CPUMF_EVENT_PTR(cf_z10, ITLB1_WRITES), +	CPUMF_EVENT_PTR(cf_z10, DTLB1_WRITES), +	CPUMF_EVENT_PTR(cf_z10, TLB2_PTE_WRITES), +	CPUMF_EVENT_PTR(cf_z10, TLB2_CRSTE_WRITES), +	CPUMF_EVENT_PTR(cf_z10, TLB2_CRSTE_HPAGE_WRITES), +	CPUMF_EVENT_PTR(cf_z10, ITLB1_MISSES), +	CPUMF_EVENT_PTR(cf_z10, DTLB1_MISSES), +	CPUMF_EVENT_PTR(cf_z10, L2C_STORES_SENT), +	NULL, +}; + +static struct attribute *cpumcf_z196_pmu_event_attr[] __initdata = { +	CPUMF_EVENT_PTR(cf_z196, L1D_L2_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1I_L2_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, DTLB1_MISSES), +	CPUMF_EVENT_PTR(cf_z196, ITLB1_MISSES), +	CPUMF_EVENT_PTR(cf_z196, L2C_STORES_SENT), +	CPUMF_EVENT_PTR(cf_z196, L1D_OFFBOOK_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1D_ONBOOK_L4_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1I_ONBOOK_L4_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1D_RO_EXCL_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1D_OFFBOOK_L4_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1I_OFFBOOK_L4_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, DTLB1_HPAGE_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1D_LMEM_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1I_LMEM_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1I_OFFBOOK_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, DTLB1_WRITES), +	CPUMF_EVENT_PTR(cf_z196, ITLB1_WRITES), +	CPUMF_EVENT_PTR(cf_z196, TLB2_PTE_WRITES), +	CPUMF_EVENT_PTR(cf_z196, TLB2_CRSTE_HPAGE_WRITES), +	CPUMF_EVENT_PTR(cf_z196, TLB2_CRSTE_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1D_ONCHIP_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1D_OFFCHIP_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1I_ONCHIP_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_z196, L1I_OFFCHIP_L3_SOURCED_WRITES), +	NULL, +}; + +static struct attribute *cpumcf_zec12_pmu_event_attr[] __initdata = { +	CPUMF_EVENT_PTR(cf_zec12, DTLB1_MISSES), +	CPUMF_EVENT_PTR(cf_zec12, ITLB1_MISSES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_L2I_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1I_L2I_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_L2D_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, DTLB1_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_LMEM_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1I_LMEM_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_RO_EXCL_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, DTLB1_HPAGE_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, ITLB1_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, TLB2_PTE_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, TLB2_CRSTE_HPAGE_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, TLB2_CRSTE_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_ONBOOK_L4_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L4_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, TX_NC_TEND), +	CPUMF_EVENT_PTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES_IV), +	CPUMF_EVENT_PTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES_IV), +	CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES_IV), +	CPUMF_EVENT_PTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1I_ONBOOK_L4_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L4_SOURCED_WRITES), +	CPUMF_EVENT_PTR(cf_zec12, TX_C_TEND), +	CPUMF_EVENT_PTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES_IV), +	CPUMF_EVENT_PTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES_IV), +	CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES_IV), +	CPUMF_EVENT_PTR(cf_zec12, TX_NC_TABORT), +	CPUMF_EVENT_PTR(cf_zec12, TX_C_TABORT_NO_SPECIAL), +	CPUMF_EVENT_PTR(cf_zec12, TX_C_TABORT_SPECIAL), +	NULL, +}; + +/* END: CPUM_CF COUNTER DEFINITIONS ===================================== */ + +static struct attribute_group cpumsf_pmu_events_group = { +	.name = "events", +	.attrs = cpumcf_pmu_event_attr, +}; + +PMU_FORMAT_ATTR(event, "config:0-63"); + +static struct attribute *cpumsf_pmu_format_attr[] = { +	&format_attr_event.attr, +	NULL, +}; + +static struct attribute_group cpumsf_pmu_format_group = { +	.name = "format", +	.attrs = cpumsf_pmu_format_attr, +}; + +static const struct attribute_group *cpumsf_pmu_attr_groups[] = { +	&cpumsf_pmu_events_group, +	&cpumsf_pmu_format_group, +	NULL, +}; + + +static __init struct attribute **merge_attr(struct attribute **a, +					    struct attribute **b) +{ +	struct attribute **new; +	int j, i; + +	for (j = 0; a[j]; j++) +		; +	for (i = 0; b[i]; i++) +		j++; +	j++; + +	new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL); +	if (!new) +		return NULL; +	j = 0; +	for (i = 0; a[i]; i++) +		new[j++] = a[i]; +	for (i = 0; b[i]; i++) +		new[j++] = b[i]; +	new[j] = NULL; + +	return new; +} + +__init const struct attribute_group **cpumf_cf_event_group(void) +{ +	struct attribute **combined, **model; +	struct cpuid cpu_id; + +	get_cpu_id(&cpu_id); +	switch (cpu_id.machine) { +	case 0x2097: +	case 0x2098: +		model = cpumcf_z10_pmu_event_attr; +		break; +	case 0x2817: +	case 0x2818: +		model = cpumcf_z196_pmu_event_attr; +		break; +	case 0x2827: +	case 0x2828: +		model = cpumcf_zec12_pmu_event_attr; +		break; +	default: +		model = NULL; +		break; +	}; + +	if (!model) +		goto out; + +	combined = merge_attr(cpumcf_pmu_event_attr, model); +	if (combined) +		cpumsf_pmu_events_group.attrs = combined; +out: +	return cpumsf_pmu_attr_groups; +} diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c new file mode 100644 index 00000000000..ea0c7b2ef03 --- /dev/null +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -0,0 +1,1643 @@ +/* + * Performance event support for the System z CPU-measurement Sampling Facility + * + * Copyright IBM Corp. 2013 + * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + */ +#define KMSG_COMPONENT	"cpum_sf" +#define pr_fmt(fmt)	KMSG_COMPONENT ": " fmt + +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/perf_event.h> +#include <linux/percpu.h> +#include <linux/notifier.h> +#include <linux/export.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/moduleparam.h> +#include <asm/cpu_mf.h> +#include <asm/irq.h> +#include <asm/debug.h> +#include <asm/timex.h> + +/* Minimum number of sample-data-block-tables: + * At least one table is required for the sampling buffer structure. + * A single table contains up to 511 pointers to sample-data-blocks. + */ +#define CPUM_SF_MIN_SDBT	1 + +/* Number of sample-data-blocks per sample-data-block-table (SDBT): + * A table contains SDB pointers (8 bytes) and one table-link entry + * that points to the origin of the next SDBT. + */ +#define CPUM_SF_SDB_PER_TABLE	((PAGE_SIZE - 8) / 8) + +/* Maximum page offset for an SDBT table-link entry: + * If this page offset is reached, a table-link entry to the next SDBT + * must be added. + */ +#define CPUM_SF_SDBT_TL_OFFSET	(CPUM_SF_SDB_PER_TABLE * 8) +static inline int require_table_link(const void *sdbt) +{ +	return ((unsigned long) sdbt & ~PAGE_MASK) == CPUM_SF_SDBT_TL_OFFSET; +} + +/* Minimum and maximum sampling buffer sizes: + * + * This number represents the maximum size of the sampling buffer taking + * the number of sample-data-block-tables into account.  Note that these + * numbers apply to the basic-sampling function only. + * The maximum number of SDBs is increased by CPUM_SF_SDB_DIAG_FACTOR if + * the diagnostic-sampling function is active. + * + * Sampling buffer size		Buffer characteristics + * --------------------------------------------------- + *	 64KB		    ==	  16 pages (4KB per page) + *				   1 page  for SDB-tables + *				  15 pages for SDBs + * + *  32MB		    ==	8192 pages (4KB per page) + *				  16 pages for SDB-tables + *				8176 pages for SDBs + */ +static unsigned long __read_mostly CPUM_SF_MIN_SDB = 15; +static unsigned long __read_mostly CPUM_SF_MAX_SDB = 8176; +static unsigned long __read_mostly CPUM_SF_SDB_DIAG_FACTOR = 1; + +struct sf_buffer { +	unsigned long	 *sdbt;	    /* Sample-data-block-table origin */ +	/* buffer characteristics (required for buffer increments) */ +	unsigned long  num_sdb;	    /* Number of sample-data-blocks */ +	unsigned long num_sdbt;	    /* Number of sample-data-block-tables */ +	unsigned long	 *tail;	    /* last sample-data-block-table */ +}; + +struct cpu_hw_sf { +	/* CPU-measurement sampling information block */ +	struct hws_qsi_info_block qsi; +	/* CPU-measurement sampling control block */ +	struct hws_lsctl_request_block lsctl; +	struct sf_buffer sfb;	    /* Sampling buffer */ +	unsigned int flags;	    /* Status flags */ +	struct perf_event *event;   /* Scheduled perf event */ +}; +static DEFINE_PER_CPU(struct cpu_hw_sf, cpu_hw_sf); + +/* Debug feature */ +static debug_info_t *sfdbg; + +/* + * sf_disable() - Switch off sampling facility + */ +static int sf_disable(void) +{ +	struct hws_lsctl_request_block sreq; + +	memset(&sreq, 0, sizeof(sreq)); +	return lsctl(&sreq); +} + +/* + * sf_buffer_available() - Check for an allocated sampling buffer + */ +static int sf_buffer_available(struct cpu_hw_sf *cpuhw) +{ +	return !!cpuhw->sfb.sdbt; +} + +/* + * deallocate sampling facility buffer + */ +static void free_sampling_buffer(struct sf_buffer *sfb) +{ +	unsigned long *sdbt, *curr; + +	if (!sfb->sdbt) +		return; + +	sdbt = sfb->sdbt; +	curr = sdbt; + +	/* Free the SDBT after all SDBs are processed... */ +	while (1) { +		if (!*curr || !sdbt) +			break; + +		/* Process table-link entries */ +		if (is_link_entry(curr)) { +			curr = get_next_sdbt(curr); +			if (sdbt) +				free_page((unsigned long) sdbt); + +			/* If the origin is reached, sampling buffer is freed */ +			if (curr == sfb->sdbt) +				break; +			else +				sdbt = curr; +		} else { +			/* Process SDB pointer */ +			if (*curr) { +				free_page(*curr); +				curr++; +			} +		} +	} + +	debug_sprintf_event(sfdbg, 5, +			    "free_sampling_buffer: freed sdbt=%p\n", sfb->sdbt); +	memset(sfb, 0, sizeof(*sfb)); +} + +static int alloc_sample_data_block(unsigned long *sdbt, gfp_t gfp_flags) +{ +	unsigned long sdb, *trailer; + +	/* Allocate and initialize sample-data-block */ +	sdb = get_zeroed_page(gfp_flags); +	if (!sdb) +		return -ENOMEM; +	trailer = trailer_entry_ptr(sdb); +	*trailer = SDB_TE_ALERT_REQ_MASK; + +	/* Link SDB into the sample-data-block-table */ +	*sdbt = sdb; + +	return 0; +} + +/* + * realloc_sampling_buffer() - extend sampler memory + * + * Allocates new sample-data-blocks and adds them to the specified sampling + * buffer memory. + * + * Important: This modifies the sampling buffer and must be called when the + *	      sampling facility is disabled. + * + * Returns zero on success, non-zero otherwise. + */ +static int realloc_sampling_buffer(struct sf_buffer *sfb, +				   unsigned long num_sdb, gfp_t gfp_flags) +{ +	int i, rc; +	unsigned long *new, *tail; + +	if (!sfb->sdbt || !sfb->tail) +		return -EINVAL; + +	if (!is_link_entry(sfb->tail)) +		return -EINVAL; + +	/* Append to the existing sampling buffer, overwriting the table-link +	 * register. +	 * The tail variables always points to the "tail" (last and table-link) +	 * entry in an SDB-table. +	 */ +	tail = sfb->tail; + +	/* Do a sanity check whether the table-link entry points to +	 * the sampling buffer origin. +	 */ +	if (sfb->sdbt != get_next_sdbt(tail)) { +		debug_sprintf_event(sfdbg, 3, "realloc_sampling_buffer: " +				    "sampling buffer is not linked: origin=%p" +				    "tail=%p\n", +				    (void *) sfb->sdbt, (void *) tail); +		return -EINVAL; +	} + +	/* Allocate remaining SDBs */ +	rc = 0; +	for (i = 0; i < num_sdb; i++) { +		/* Allocate a new SDB-table if it is full. */ +		if (require_table_link(tail)) { +			new = (unsigned long *) get_zeroed_page(gfp_flags); +			if (!new) { +				rc = -ENOMEM; +				break; +			} +			sfb->num_sdbt++; +			/* Link current page to tail of chain */ +			*tail = (unsigned long)(void *) new + 1; +			tail = new; +		} + +		/* Allocate a new sample-data-block. +		 * If there is not enough memory, stop the realloc process +		 * and simply use what was allocated.  If this is a temporary +		 * issue, a new realloc call (if required) might succeed. +		 */ +		rc = alloc_sample_data_block(tail, gfp_flags); +		if (rc) +			break; +		sfb->num_sdb++; +		tail++; +	} + +	/* Link sampling buffer to its origin */ +	*tail = (unsigned long) sfb->sdbt + 1; +	sfb->tail = tail; + +	debug_sprintf_event(sfdbg, 4, "realloc_sampling_buffer: new buffer" +			    " settings: sdbt=%lu sdb=%lu\n", +			    sfb->num_sdbt, sfb->num_sdb); +	return rc; +} + +/* + * allocate_sampling_buffer() - allocate sampler memory + * + * Allocates and initializes a sampling buffer structure using the + * specified number of sample-data-blocks (SDB).  For each allocation, + * a 4K page is used.  The number of sample-data-block-tables (SDBT) + * are calculated from SDBs. + * Also set the ALERT_REQ mask in each SDBs trailer. + * + * Returns zero on success, non-zero otherwise. + */ +static int alloc_sampling_buffer(struct sf_buffer *sfb, unsigned long num_sdb) +{ +	int rc; + +	if (sfb->sdbt) +		return -EINVAL; + +	/* Allocate the sample-data-block-table origin */ +	sfb->sdbt = (unsigned long *) get_zeroed_page(GFP_KERNEL); +	if (!sfb->sdbt) +		return -ENOMEM; +	sfb->num_sdb = 0; +	sfb->num_sdbt = 1; + +	/* Link the table origin to point to itself to prepare for +	 * realloc_sampling_buffer() invocation. +	 */ +	sfb->tail = sfb->sdbt; +	*sfb->tail = (unsigned long)(void *) sfb->sdbt + 1; + +	/* Allocate requested number of sample-data-blocks */ +	rc = realloc_sampling_buffer(sfb, num_sdb, GFP_KERNEL); +	if (rc) { +		free_sampling_buffer(sfb); +		debug_sprintf_event(sfdbg, 4, "alloc_sampling_buffer: " +			"realloc_sampling_buffer failed with rc=%i\n", rc); +	} else +		debug_sprintf_event(sfdbg, 4, +			"alloc_sampling_buffer: tear=%p dear=%p\n", +			sfb->sdbt, (void *) *sfb->sdbt); +	return rc; +} + +static void sfb_set_limits(unsigned long min, unsigned long max) +{ +	struct hws_qsi_info_block si; + +	CPUM_SF_MIN_SDB = min; +	CPUM_SF_MAX_SDB = max; + +	memset(&si, 0, sizeof(si)); +	if (!qsi(&si)) +		CPUM_SF_SDB_DIAG_FACTOR = DIV_ROUND_UP(si.dsdes, si.bsdes); +} + +static unsigned long sfb_max_limit(struct hw_perf_event *hwc) +{ +	return SAMPL_DIAG_MODE(hwc) ? CPUM_SF_MAX_SDB * CPUM_SF_SDB_DIAG_FACTOR +				    : CPUM_SF_MAX_SDB; +} + +static unsigned long sfb_pending_allocs(struct sf_buffer *sfb, +					struct hw_perf_event *hwc) +{ +	if (!sfb->sdbt) +		return SFB_ALLOC_REG(hwc); +	if (SFB_ALLOC_REG(hwc) > sfb->num_sdb) +		return SFB_ALLOC_REG(hwc) - sfb->num_sdb; +	return 0; +} + +static int sfb_has_pending_allocs(struct sf_buffer *sfb, +				   struct hw_perf_event *hwc) +{ +	return sfb_pending_allocs(sfb, hwc) > 0; +} + +static void sfb_account_allocs(unsigned long num, struct hw_perf_event *hwc) +{ +	/* Limit the number of SDBs to not exceed the maximum */ +	num = min_t(unsigned long, num, sfb_max_limit(hwc) - SFB_ALLOC_REG(hwc)); +	if (num) +		SFB_ALLOC_REG(hwc) += num; +} + +static void sfb_init_allocs(unsigned long num, struct hw_perf_event *hwc) +{ +	SFB_ALLOC_REG(hwc) = 0; +	sfb_account_allocs(num, hwc); +} + +static size_t event_sample_size(struct hw_perf_event *hwc) +{ +	struct sf_raw_sample *sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(hwc); +	size_t sample_size; + +	/* The sample size depends on the sampling function: The basic-sampling +	 * function must be always enabled, diagnostic-sampling function is +	 * optional. +	 */ +	sample_size = sfr->bsdes; +	if (SAMPL_DIAG_MODE(hwc)) +		sample_size += sfr->dsdes; + +	return sample_size; +} + +static void deallocate_buffers(struct cpu_hw_sf *cpuhw) +{ +	if (cpuhw->sfb.sdbt) +		free_sampling_buffer(&cpuhw->sfb); +} + +static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc) +{ +	unsigned long n_sdb, freq, factor; +	size_t sfr_size, sample_size; +	struct sf_raw_sample *sfr; + +	/* Allocate raw sample buffer +	 * +	 *    The raw sample buffer is used to temporarily store sampling data +	 *    entries for perf raw sample processing.  The buffer size mainly +	 *    depends on the size of diagnostic-sampling data entries which is +	 *    machine-specific.  The exact size calculation includes: +	 *	1. The first 4 bytes of diagnostic-sampling data entries are +	 *	   already reflected in the sf_raw_sample structure.  Subtract +	 *	   these bytes. +	 *	2. The perf raw sample data must be 8-byte aligned (u64) and +	 *	   perf's internal data size must be considered too.  So add +	 *	   an additional u32 for correct alignment and subtract before +	 *	   allocating the buffer. +	 *	3. Store the raw sample buffer pointer in the perf event +	 *	   hardware structure. +	 */ +	sfr_size = ALIGN((sizeof(*sfr) - sizeof(sfr->diag) + cpuhw->qsi.dsdes) + +			 sizeof(u32), sizeof(u64)); +	sfr_size -= sizeof(u32); +	sfr = kzalloc(sfr_size, GFP_KERNEL); +	if (!sfr) +		return -ENOMEM; +	sfr->size = sfr_size; +	sfr->bsdes = cpuhw->qsi.bsdes; +	sfr->dsdes = cpuhw->qsi.dsdes; +	RAWSAMPLE_REG(hwc) = (unsigned long) sfr; + +	/* Calculate sampling buffers using 4K pages +	 * +	 *    1. Determine the sample data size which depends on the used +	 *	 sampling functions, for example, basic-sampling or +	 *	 basic-sampling with diagnostic-sampling. +	 * +	 *    2. Use the sampling frequency as input.  The sampling buffer is +	 *	 designed for almost one second.  This can be adjusted through +	 *	 the "factor" variable. +	 *	 In any case, alloc_sampling_buffer() sets the Alert Request +	 *	 Control indicator to trigger a measurement-alert to harvest +	 *	 sample-data-blocks (sdb). +	 * +	 *    3. Compute the number of sample-data-blocks and ensure a minimum +	 *	 of CPUM_SF_MIN_SDB.  Also ensure the upper limit does not +	 *	 exceed a "calculated" maximum.  The symbolic maximum is +	 *	 designed for basic-sampling only and needs to be increased if +	 *	 diagnostic-sampling is active. +	 *	 See also the remarks for these symbolic constants. +	 * +	 *    4. Compute the number of sample-data-block-tables (SDBT) and +	 *	 ensure a minimum of CPUM_SF_MIN_SDBT (one table can manage up +	 *	 to 511 SDBs). +	 */ +	sample_size = event_sample_size(hwc); +	freq = sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc)); +	factor = 1; +	n_sdb = DIV_ROUND_UP(freq, factor * ((PAGE_SIZE-64) / sample_size)); +	if (n_sdb < CPUM_SF_MIN_SDB) +		n_sdb = CPUM_SF_MIN_SDB; + +	/* If there is already a sampling buffer allocated, it is very likely +	 * that the sampling facility is enabled too.  If the event to be +	 * initialized requires a greater sampling buffer, the allocation must +	 * be postponed.  Changing the sampling buffer requires the sampling +	 * facility to be in the disabled state.  So, account the number of +	 * required SDBs and let cpumsf_pmu_enable() resize the buffer just +	 * before the event is started. +	 */ +	sfb_init_allocs(n_sdb, hwc); +	if (sf_buffer_available(cpuhw)) +		return 0; + +	debug_sprintf_event(sfdbg, 3, +			    "allocate_buffers: rate=%lu f=%lu sdb=%lu/%lu" +			    " sample_size=%lu cpuhw=%p\n", +			    SAMPL_RATE(hwc), freq, n_sdb, sfb_max_limit(hwc), +			    sample_size, cpuhw); + +	return alloc_sampling_buffer(&cpuhw->sfb, +				     sfb_pending_allocs(&cpuhw->sfb, hwc)); +} + +static unsigned long min_percent(unsigned int percent, unsigned long base, +				 unsigned long min) +{ +	return min_t(unsigned long, min, DIV_ROUND_UP(percent * base, 100)); +} + +static unsigned long compute_sfb_extent(unsigned long ratio, unsigned long base) +{ +	/* Use a percentage-based approach to extend the sampling facility +	 * buffer.  Accept up to 5% sample data loss. +	 * Vary the extents between 1% to 5% of the current number of +	 * sample-data-blocks. +	 */ +	if (ratio <= 5) +		return 0; +	if (ratio <= 25) +		return min_percent(1, base, 1); +	if (ratio <= 50) +		return min_percent(1, base, 1); +	if (ratio <= 75) +		return min_percent(2, base, 2); +	if (ratio <= 100) +		return min_percent(3, base, 3); +	if (ratio <= 250) +		return min_percent(4, base, 4); + +	return min_percent(5, base, 8); +} + +static void sfb_account_overflows(struct cpu_hw_sf *cpuhw, +				  struct hw_perf_event *hwc) +{ +	unsigned long ratio, num; + +	if (!OVERFLOW_REG(hwc)) +		return; + +	/* The sample_overflow contains the average number of sample data +	 * that has been lost because sample-data-blocks were full. +	 * +	 * Calculate the total number of sample data entries that has been +	 * discarded.  Then calculate the ratio of lost samples to total samples +	 * per second in percent. +	 */ +	ratio = DIV_ROUND_UP(100 * OVERFLOW_REG(hwc) * cpuhw->sfb.num_sdb, +			     sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc))); + +	/* Compute number of sample-data-blocks */ +	num = compute_sfb_extent(ratio, cpuhw->sfb.num_sdb); +	if (num) +		sfb_account_allocs(num, hwc); + +	debug_sprintf_event(sfdbg, 5, "sfb: overflow: overflow=%llu ratio=%lu" +			    " num=%lu\n", OVERFLOW_REG(hwc), ratio, num); +	OVERFLOW_REG(hwc) = 0; +} + +/* extend_sampling_buffer() - Extend sampling buffer + * @sfb:	Sampling buffer structure (for local CPU) + * @hwc:	Perf event hardware structure + * + * Use this function to extend the sampling buffer based on the overflow counter + * and postponed allocation extents stored in the specified Perf event hardware. + * + * Important: This function disables the sampling facility in order to safely + *	      change the sampling buffer structure.  Do not call this function + *	      when the PMU is active. + */ +static void extend_sampling_buffer(struct sf_buffer *sfb, +				   struct hw_perf_event *hwc) +{ +	unsigned long num, num_old; +	int rc; + +	num = sfb_pending_allocs(sfb, hwc); +	if (!num) +		return; +	num_old = sfb->num_sdb; + +	/* Disable the sampling facility to reset any states and also +	 * clear pending measurement alerts. +	 */ +	sf_disable(); + +	/* Extend the sampling buffer. +	 * This memory allocation typically happens in an atomic context when +	 * called by perf.  Because this is a reallocation, it is fine if the +	 * new SDB-request cannot be satisfied immediately. +	 */ +	rc = realloc_sampling_buffer(sfb, num, GFP_ATOMIC); +	if (rc) +		debug_sprintf_event(sfdbg, 5, "sfb: extend: realloc " +				    "failed with rc=%i\n", rc); + +	if (sfb_has_pending_allocs(sfb, hwc)) +		debug_sprintf_event(sfdbg, 5, "sfb: extend: " +				    "req=%lu alloc=%lu remaining=%lu\n", +				    num, sfb->num_sdb - num_old, +				    sfb_pending_allocs(sfb, hwc)); +} + + +/* Number of perf events counting hardware events */ +static atomic_t num_events; +/* Used to avoid races in calling reserve/release_cpumf_hardware */ +static DEFINE_MUTEX(pmc_reserve_mutex); + +#define PMC_INIT      0 +#define PMC_RELEASE   1 +#define PMC_FAILURE   2 +static void setup_pmc_cpu(void *flags) +{ +	int err; +	struct cpu_hw_sf *cpusf = &__get_cpu_var(cpu_hw_sf); + +	err = 0; +	switch (*((int *) flags)) { +	case PMC_INIT: +		memset(cpusf, 0, sizeof(*cpusf)); +		err = qsi(&cpusf->qsi); +		if (err) +			break; +		cpusf->flags |= PMU_F_RESERVED; +		err = sf_disable(); +		if (err) +			pr_err("Switching off the sampling facility failed " +			       "with rc=%i\n", err); +		debug_sprintf_event(sfdbg, 5, +				    "setup_pmc_cpu: initialized: cpuhw=%p\n", cpusf); +		break; +	case PMC_RELEASE: +		cpusf->flags &= ~PMU_F_RESERVED; +		err = sf_disable(); +		if (err) { +			pr_err("Switching off the sampling facility failed " +			       "with rc=%i\n", err); +		} else +			deallocate_buffers(cpusf); +		debug_sprintf_event(sfdbg, 5, +				    "setup_pmc_cpu: released: cpuhw=%p\n", cpusf); +		break; +	} +	if (err) +		*((int *) flags) |= PMC_FAILURE; +} + +static void release_pmc_hardware(void) +{ +	int flags = PMC_RELEASE; + +	irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); +	on_each_cpu(setup_pmc_cpu, &flags, 1); +	perf_release_sampling(); +} + +static int reserve_pmc_hardware(void) +{ +	int flags = PMC_INIT; +	int err; + +	err = perf_reserve_sampling(); +	if (err) +		return err; +	on_each_cpu(setup_pmc_cpu, &flags, 1); +	if (flags & PMC_FAILURE) { +		release_pmc_hardware(); +		return -ENODEV; +	} +	irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); + +	return 0; +} + +static void hw_perf_event_destroy(struct perf_event *event) +{ +	/* Free raw sample buffer */ +	if (RAWSAMPLE_REG(&event->hw)) +		kfree((void *) RAWSAMPLE_REG(&event->hw)); + +	/* Release PMC if this is the last perf event */ +	if (!atomic_add_unless(&num_events, -1, 1)) { +		mutex_lock(&pmc_reserve_mutex); +		if (atomic_dec_return(&num_events) == 0) +			release_pmc_hardware(); +		mutex_unlock(&pmc_reserve_mutex); +	} +} + +static void hw_init_period(struct hw_perf_event *hwc, u64 period) +{ +	hwc->sample_period = period; +	hwc->last_period = hwc->sample_period; +	local64_set(&hwc->period_left, hwc->sample_period); +} + +static void hw_reset_registers(struct hw_perf_event *hwc, +			       unsigned long *sdbt_origin) +{ +	struct sf_raw_sample *sfr; + +	/* (Re)set to first sample-data-block-table */ +	TEAR_REG(hwc) = (unsigned long) sdbt_origin; + +	/* (Re)set raw sampling buffer register */ +	sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(hwc); +	memset(&sfr->basic, 0, sizeof(sfr->basic)); +	memset(&sfr->diag, 0, sfr->dsdes); +} + +static unsigned long hw_limit_rate(const struct hws_qsi_info_block *si, +				   unsigned long rate) +{ +	return clamp_t(unsigned long, rate, +		       si->min_sampl_rate, si->max_sampl_rate); +} + +static int __hw_perf_event_init(struct perf_event *event) +{ +	struct cpu_hw_sf *cpuhw; +	struct hws_qsi_info_block si; +	struct perf_event_attr *attr = &event->attr; +	struct hw_perf_event *hwc = &event->hw; +	unsigned long rate; +	int cpu, err; + +	/* Reserve CPU-measurement sampling facility */ +	err = 0; +	if (!atomic_inc_not_zero(&num_events)) { +		mutex_lock(&pmc_reserve_mutex); +		if (atomic_read(&num_events) == 0 && reserve_pmc_hardware()) +			err = -EBUSY; +		else +			atomic_inc(&num_events); +		mutex_unlock(&pmc_reserve_mutex); +	} +	event->destroy = hw_perf_event_destroy; + +	if (err) +		goto out; + +	/* Access per-CPU sampling information (query sampling info) */ +	/* +	 * The event->cpu value can be -1 to count on every CPU, for example, +	 * when attaching to a task.  If this is specified, use the query +	 * sampling info from the current CPU, otherwise use event->cpu to +	 * retrieve the per-CPU information. +	 * Later, cpuhw indicates whether to allocate sampling buffers for a +	 * particular CPU (cpuhw!=NULL) or each online CPU (cpuw==NULL). +	 */ +	memset(&si, 0, sizeof(si)); +	cpuhw = NULL; +	if (event->cpu == -1) +		qsi(&si); +	else { +		/* Event is pinned to a particular CPU, retrieve the per-CPU +		 * sampling structure for accessing the CPU-specific QSI. +		 */ +		cpuhw = &per_cpu(cpu_hw_sf, event->cpu); +		si = cpuhw->qsi; +	} + +	/* Check sampling facility authorization and, if not authorized, +	 * fall back to other PMUs.  It is safe to check any CPU because +	 * the authorization is identical for all configured CPUs. +	 */ +	if (!si.as) { +		err = -ENOENT; +		goto out; +	} + +	/* Always enable basic sampling */ +	SAMPL_FLAGS(hwc) = PERF_CPUM_SF_BASIC_MODE; + +	/* Check if diagnostic sampling is requested.  Deny if the required +	 * sampling authorization is missing. +	 */ +	if (attr->config == PERF_EVENT_CPUM_SF_DIAG) { +		if (!si.ad) { +			err = -EPERM; +			goto out; +		} +		SAMPL_FLAGS(hwc) |= PERF_CPUM_SF_DIAG_MODE; +	} + +	/* Check and set other sampling flags */ +	if (attr->config1 & PERF_CPUM_SF_FULL_BLOCKS) +		SAMPL_FLAGS(hwc) |= PERF_CPUM_SF_FULL_BLOCKS; + +	/* The sampling information (si) contains information about the +	 * min/max sampling intervals and the CPU speed.  So calculate the +	 * correct sampling interval and avoid the whole period adjust +	 * feedback loop. +	 */ +	rate = 0; +	if (attr->freq) { +		rate = freq_to_sample_rate(&si, attr->sample_freq); +		rate = hw_limit_rate(&si, rate); +		attr->freq = 0; +		attr->sample_period = rate; +	} else { +		/* The min/max sampling rates specifies the valid range +		 * of sample periods.  If the specified sample period is +		 * out of range, limit the period to the range boundary. +		 */ +		rate = hw_limit_rate(&si, hwc->sample_period); + +		/* The perf core maintains a maximum sample rate that is +		 * configurable through the sysctl interface.  Ensure the +		 * sampling rate does not exceed this value.  This also helps +		 * to avoid throttling when pushing samples with +		 * perf_event_overflow(). +		 */ +		if (sample_rate_to_freq(&si, rate) > +		      sysctl_perf_event_sample_rate) { +			err = -EINVAL; +			debug_sprintf_event(sfdbg, 1, "Sampling rate exceeds maximum perf sample rate\n"); +			goto out; +		} +	} +	SAMPL_RATE(hwc) = rate; +	hw_init_period(hwc, SAMPL_RATE(hwc)); + +	/* Initialize sample data overflow accounting */ +	hwc->extra_reg.reg = REG_OVERFLOW; +	OVERFLOW_REG(hwc) = 0; + +	/* Allocate the per-CPU sampling buffer using the CPU information +	 * from the event.  If the event is not pinned to a particular +	 * CPU (event->cpu == -1; or cpuhw == NULL), allocate sampling +	 * buffers for each online CPU. +	 */ +	if (cpuhw) +		/* Event is pinned to a particular CPU */ +		err = allocate_buffers(cpuhw, hwc); +	else { +		/* Event is not pinned, allocate sampling buffer on +		 * each online CPU +		 */ +		for_each_online_cpu(cpu) { +			cpuhw = &per_cpu(cpu_hw_sf, cpu); +			err = allocate_buffers(cpuhw, hwc); +			if (err) +				break; +		} +	} +out: +	return err; +} + +static int cpumsf_pmu_event_init(struct perf_event *event) +{ +	int err; + +	/* No support for taken branch sampling */ +	if (has_branch_stack(event)) +		return -EOPNOTSUPP; + +	switch (event->attr.type) { +	case PERF_TYPE_RAW: +		if ((event->attr.config != PERF_EVENT_CPUM_SF) && +		    (event->attr.config != PERF_EVENT_CPUM_SF_DIAG)) +			return -ENOENT; +		break; +	case PERF_TYPE_HARDWARE: +		/* Support sampling of CPU cycles in addition to the +		 * counter facility.  However, the counter facility +		 * is more precise and, hence, restrict this PMU to +		 * sampling events only. +		 */ +		if (event->attr.config != PERF_COUNT_HW_CPU_CYCLES) +			return -ENOENT; +		if (!is_sampling_event(event)) +			return -ENOENT; +		break; +	default: +		return -ENOENT; +	} + +	/* Check online status of the CPU to which the event is pinned */ +	if (event->cpu >= nr_cpumask_bits || +	    (event->cpu >= 0 && !cpu_online(event->cpu))) +		return -ENODEV; + +	/* Force reset of idle/hv excludes regardless of what the +	 * user requested. +	 */ +	if (event->attr.exclude_hv) +		event->attr.exclude_hv = 0; +	if (event->attr.exclude_idle) +		event->attr.exclude_idle = 0; + +	err = __hw_perf_event_init(event); +	if (unlikely(err)) +		if (event->destroy) +			event->destroy(event); +	return err; +} + +static void cpumsf_pmu_enable(struct pmu *pmu) +{ +	struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); +	struct hw_perf_event *hwc; +	int err; + +	if (cpuhw->flags & PMU_F_ENABLED) +		return; + +	if (cpuhw->flags & PMU_F_ERR_MASK) +		return; + +	/* Check whether to extent the sampling buffer. +	 * +	 * Two conditions trigger an increase of the sampling buffer for a +	 * perf event: +	 *    1. Postponed buffer allocations from the event initialization. +	 *    2. Sampling overflows that contribute to pending allocations. +	 * +	 * Note that the extend_sampling_buffer() function disables the sampling +	 * facility, but it can be fully re-enabled using sampling controls that +	 * have been saved in cpumsf_pmu_disable(). +	 */ +	if (cpuhw->event) { +		hwc = &cpuhw->event->hw; +		/* Account number of overflow-designated buffer extents */ +		sfb_account_overflows(cpuhw, hwc); +		if (sfb_has_pending_allocs(&cpuhw->sfb, hwc)) +			extend_sampling_buffer(&cpuhw->sfb, hwc); +	} + +	/* (Re)enable the PMU and sampling facility */ +	cpuhw->flags |= PMU_F_ENABLED; +	barrier(); + +	err = lsctl(&cpuhw->lsctl); +	if (err) { +		cpuhw->flags &= ~PMU_F_ENABLED; +		pr_err("Loading sampling controls failed: op=%i err=%i\n", +			1, err); +		return; +	} + +	debug_sprintf_event(sfdbg, 6, "pmu_enable: es=%i cs=%i ed=%i cd=%i " +			    "tear=%p dear=%p\n", cpuhw->lsctl.es, cpuhw->lsctl.cs, +			    cpuhw->lsctl.ed, cpuhw->lsctl.cd, +			    (void *) cpuhw->lsctl.tear, (void *) cpuhw->lsctl.dear); +} + +static void cpumsf_pmu_disable(struct pmu *pmu) +{ +	struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); +	struct hws_lsctl_request_block inactive; +	struct hws_qsi_info_block si; +	int err; + +	if (!(cpuhw->flags & PMU_F_ENABLED)) +		return; + +	if (cpuhw->flags & PMU_F_ERR_MASK) +		return; + +	/* Switch off sampling activation control */ +	inactive = cpuhw->lsctl; +	inactive.cs = 0; +	inactive.cd = 0; + +	err = lsctl(&inactive); +	if (err) { +		pr_err("Loading sampling controls failed: op=%i err=%i\n", +			2, err); +		return; +	} + +	/* Save state of TEAR and DEAR register contents */ +	if (!qsi(&si)) { +		/* TEAR/DEAR values are valid only if the sampling facility is +		 * enabled.  Note that cpumsf_pmu_disable() might be called even +		 * for a disabled sampling facility because cpumsf_pmu_enable() +		 * controls the enable/disable state. +		 */ +		if (si.es) { +			cpuhw->lsctl.tear = si.tear; +			cpuhw->lsctl.dear = si.dear; +		} +	} else +		debug_sprintf_event(sfdbg, 3, "cpumsf_pmu_disable: " +				    "qsi() failed with err=%i\n", err); + +	cpuhw->flags &= ~PMU_F_ENABLED; +} + +/* perf_exclude_event() - Filter event + * @event:	The perf event + * @regs:	pt_regs structure + * @sde_regs:	Sample-data-entry (sde) regs structure + * + * Filter perf events according to their exclude specification. + * + * Return non-zero if the event shall be excluded. + */ +static int perf_exclude_event(struct perf_event *event, struct pt_regs *regs, +			      struct perf_sf_sde_regs *sde_regs) +{ +	if (event->attr.exclude_user && user_mode(regs)) +		return 1; +	if (event->attr.exclude_kernel && !user_mode(regs)) +		return 1; +	if (event->attr.exclude_guest && sde_regs->in_guest) +		return 1; +	if (event->attr.exclude_host && !sde_regs->in_guest) +		return 1; +	return 0; +} + +/* perf_push_sample() - Push samples to perf + * @event:	The perf event + * @sample:	Hardware sample data + * + * Use the hardware sample data to create perf event sample.  The sample + * is the pushed to the event subsystem and the function checks for + * possible event overflows.  If an event overflow occurs, the PMU is + * stopped. + * + * Return non-zero if an event overflow occurred. + */ +static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr) +{ +	int overflow; +	struct pt_regs regs; +	struct perf_sf_sde_regs *sde_regs; +	struct perf_sample_data data; +	struct perf_raw_record raw; + +	/* Setup perf sample */ +	perf_sample_data_init(&data, 0, event->hw.last_period); +	raw.size = sfr->size; +	raw.data = sfr; +	data.raw = &raw; + +	/* Setup pt_regs to look like an CPU-measurement external interrupt +	 * using the Program Request Alert code.  The regs.int_parm_long +	 * field which is unused contains additional sample-data-entry related +	 * indicators. +	 */ +	memset(®s, 0, sizeof(regs)); +	regs.int_code = 0x1407; +	regs.int_parm = CPU_MF_INT_SF_PRA; +	sde_regs = (struct perf_sf_sde_regs *) ®s.int_parm_long; + +	regs.psw.addr = sfr->basic.ia; +	if (sfr->basic.T) +		regs.psw.mask |= PSW_MASK_DAT; +	if (sfr->basic.W) +		regs.psw.mask |= PSW_MASK_WAIT; +	if (sfr->basic.P) +		regs.psw.mask |= PSW_MASK_PSTATE; +	switch (sfr->basic.AS) { +	case 0x0: +		regs.psw.mask |= PSW_ASC_PRIMARY; +		break; +	case 0x1: +		regs.psw.mask |= PSW_ASC_ACCREG; +		break; +	case 0x2: +		regs.psw.mask |= PSW_ASC_SECONDARY; +		break; +	case 0x3: +		regs.psw.mask |= PSW_ASC_HOME; +		break; +	} + +	/* The host-program-parameter (hpp) contains the sie control +	 * block that is set by sie64a() in entry64.S.	Check if hpp +	 * refers to a valid control block and set sde_regs flags +	 * accordingly.  This would allow to use hpp values for other +	 * purposes too. +	 * For now, simply use a non-zero value as guest indicator. +	 */ +	if (sfr->basic.hpp) +		sde_regs->in_guest = 1; + +	overflow = 0; +	if (perf_exclude_event(event, ®s, sde_regs)) +		goto out; +	if (perf_event_overflow(event, &data, ®s)) { +		overflow = 1; +		event->pmu->stop(event, 0); +	} +	perf_event_update_userpage(event); +out: +	return overflow; +} + +static void perf_event_count_update(struct perf_event *event, u64 count) +{ +	local64_add(count, &event->count); +} + +static int sample_format_is_valid(struct hws_combined_entry *sample, +				   unsigned int flags) +{ +	if (likely(flags & PERF_CPUM_SF_BASIC_MODE)) +		/* Only basic-sampling data entries with data-entry-format +		 * version of 0x0001 can be processed. +		 */ +		if (sample->basic.def != 0x0001) +			return 0; +	if (flags & PERF_CPUM_SF_DIAG_MODE) +		/* The data-entry-format number of diagnostic-sampling data +		 * entries can vary.  Because diagnostic data is just passed +		 * through, do only a sanity check on the DEF. +		 */ +		if (sample->diag.def < 0x8001) +			return 0; +	return 1; +} + +static int sample_is_consistent(struct hws_combined_entry *sample, +				unsigned long flags) +{ +	/* This check applies only to basic-sampling data entries of potentially +	 * combined-sampling data entries.  Invalid entries cannot be processed +	 * by the PMU and, thus, do not deliver an associated +	 * diagnostic-sampling data entry. +	 */ +	if (unlikely(!(flags & PERF_CPUM_SF_BASIC_MODE))) +		return 0; +	/* +	 * Samples are skipped, if they are invalid or for which the +	 * instruction address is not predictable, i.e., the wait-state bit is +	 * set. +	 */ +	if (sample->basic.I || sample->basic.W) +		return 0; +	return 1; +} + +static void reset_sample_slot(struct hws_combined_entry *sample, +			      unsigned long flags) +{ +	if (likely(flags & PERF_CPUM_SF_BASIC_MODE)) +		sample->basic.def = 0; +	if (flags & PERF_CPUM_SF_DIAG_MODE) +		sample->diag.def = 0; +} + +static void sfr_store_sample(struct sf_raw_sample *sfr, +			     struct hws_combined_entry *sample) +{ +	if (likely(sfr->format & PERF_CPUM_SF_BASIC_MODE)) +		sfr->basic = sample->basic; +	if (sfr->format & PERF_CPUM_SF_DIAG_MODE) +		memcpy(&sfr->diag, &sample->diag, sfr->dsdes); +} + +static void debug_sample_entry(struct hws_combined_entry *sample, +			       struct hws_trailer_entry *te, +			       unsigned long flags) +{ +	debug_sprintf_event(sfdbg, 4, "hw_collect_samples: Found unknown " +			    "sampling data entry: te->f=%i basic.def=%04x (%p)" +			    " diag.def=%04x (%p)\n", te->f, +			    sample->basic.def, &sample->basic, +			    (flags & PERF_CPUM_SF_DIAG_MODE) +					? sample->diag.def : 0xFFFF, +			    (flags & PERF_CPUM_SF_DIAG_MODE) +					?  &sample->diag : NULL); +} + +/* hw_collect_samples() - Walk through a sample-data-block and collect samples + * @event:	The perf event + * @sdbt:	Sample-data-block table + * @overflow:	Event overflow counter + * + * Walks through a sample-data-block and collects sampling data entries that are + * then pushed to the perf event subsystem.  Depending on the sampling function, + * there can be either basic-sampling or combined-sampling data entries.  A + * combined-sampling data entry consists of a basic- and a diagnostic-sampling + * data entry.	The sampling function is determined by the flags in the perf + * event hardware structure.  The function always works with a combined-sampling + * data entry but ignores the the diagnostic portion if it is not available. + * + * Note that the implementation focuses on basic-sampling data entries and, if + * such an entry is not valid, the entire combined-sampling data entry is + * ignored. + * + * The overflow variables counts the number of samples that has been discarded + * due to a perf event overflow. + */ +static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, +			       unsigned long long *overflow) +{ +	unsigned long flags = SAMPL_FLAGS(&event->hw); +	struct hws_combined_entry *sample; +	struct hws_trailer_entry *te; +	struct sf_raw_sample *sfr; +	size_t sample_size; + +	/* Prepare and initialize raw sample data */ +	sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(&event->hw); +	sfr->format = flags & PERF_CPUM_SF_MODE_MASK; + +	sample_size = event_sample_size(&event->hw); +	te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt); +	sample = (struct hws_combined_entry *) *sdbt; +	while ((unsigned long *) sample < (unsigned long *) te) { +		/* Check for an empty sample */ +		if (!sample->basic.def) +			break; + +		/* Update perf event period */ +		perf_event_count_update(event, SAMPL_RATE(&event->hw)); + +		/* Check sampling data entry */ +		if (sample_format_is_valid(sample, flags)) { +			/* If an event overflow occurred, the PMU is stopped to +			 * throttle event delivery.  Remaining sample data is +			 * discarded. +			 */ +			if (!*overflow) { +				if (sample_is_consistent(sample, flags)) { +					/* Deliver sample data to perf */ +					sfr_store_sample(sfr, sample); +					*overflow = perf_push_sample(event, sfr); +				} +			} else +				/* Count discarded samples */ +				*overflow += 1; +		} else { +			debug_sample_entry(sample, te, flags); +			/* Sample slot is not yet written or other record. +			 * +			 * This condition can occur if the buffer was reused +			 * from a combined basic- and diagnostic-sampling. +			 * If only basic-sampling is then active, entries are +			 * written into the larger diagnostic entries. +			 * This is typically the case for sample-data-blocks +			 * that are not full.  Stop processing if the first +			 * invalid format was detected. +			 */ +			if (!te->f) +				break; +		} + +		/* Reset sample slot and advance to next sample */ +		reset_sample_slot(sample, flags); +		sample += sample_size; +	} +} + +/* hw_perf_event_update() - Process sampling buffer + * @event:	The perf event + * @flush_all:	Flag to also flush partially filled sample-data-blocks + * + * Processes the sampling buffer and create perf event samples. + * The sampling buffer position are retrieved and saved in the TEAR_REG + * register of the specified perf event. + * + * Only full sample-data-blocks are processed.	Specify the flash_all flag + * to also walk through partially filled sample-data-blocks.  It is ignored + * if PERF_CPUM_SF_FULL_BLOCKS is set.	The PERF_CPUM_SF_FULL_BLOCKS flag + * enforces the processing of full sample-data-blocks only (trailer entries + * with the block-full-indicator bit set). + */ +static void hw_perf_event_update(struct perf_event *event, int flush_all) +{ +	struct hw_perf_event *hwc = &event->hw; +	struct hws_trailer_entry *te; +	unsigned long *sdbt; +	unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags; +	int done; + +	if (flush_all && SDB_FULL_BLOCKS(hwc)) +		flush_all = 0; + +	sdbt = (unsigned long *) TEAR_REG(hwc); +	done = event_overflow = sampl_overflow = num_sdb = 0; +	while (!done) { +		/* Get the trailer entry of the sample-data-block */ +		te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt); + +		/* Leave loop if no more work to do (block full indicator) */ +		if (!te->f) { +			done = 1; +			if (!flush_all) +				break; +		} + +		/* Check the sample overflow count */ +		if (te->overflow) +			/* Account sample overflows and, if a particular limit +			 * is reached, extend the sampling buffer. +			 * For details, see sfb_account_overflows(). +			 */ +			sampl_overflow += te->overflow; + +		/* Timestamps are valid for full sample-data-blocks only */ +		debug_sprintf_event(sfdbg, 6, "hw_perf_event_update: sdbt=%p " +				    "overflow=%llu timestamp=0x%llx\n", +				    sdbt, te->overflow, +				    (te->f) ? trailer_timestamp(te) : 0ULL); + +		/* Collect all samples from a single sample-data-block and +		 * flag if an (perf) event overflow happened.  If so, the PMU +		 * is stopped and remaining samples will be discarded. +		 */ +		hw_collect_samples(event, sdbt, &event_overflow); +		num_sdb++; + +		/* Reset trailer (using compare-double-and-swap) */ +		do { +			te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK; +			te_flags |= SDB_TE_ALERT_REQ_MASK; +		} while (!cmpxchg_double(&te->flags, &te->overflow, +					 te->flags, te->overflow, +					 te_flags, 0ULL)); + +		/* Advance to next sample-data-block */ +		sdbt++; +		if (is_link_entry(sdbt)) +			sdbt = get_next_sdbt(sdbt); + +		/* Update event hardware registers */ +		TEAR_REG(hwc) = (unsigned long) sdbt; + +		/* Stop processing sample-data if all samples of the current +		 * sample-data-block were flushed even if it was not full. +		 */ +		if (flush_all && done) +			break; + +		/* If an event overflow happened, discard samples by +		 * processing any remaining sample-data-blocks. +		 */ +		if (event_overflow) +			flush_all = 1; +	} + +	/* Account sample overflows in the event hardware structure */ +	if (sampl_overflow) +		OVERFLOW_REG(hwc) = DIV_ROUND_UP(OVERFLOW_REG(hwc) + +						 sampl_overflow, 1 + num_sdb); +	if (sampl_overflow || event_overflow) +		debug_sprintf_event(sfdbg, 4, "hw_perf_event_update: " +				    "overflow stats: sample=%llu event=%llu\n", +				    sampl_overflow, event_overflow); +} + +static void cpumsf_pmu_read(struct perf_event *event) +{ +	/* Nothing to do ... updates are interrupt-driven */ +} + +/* Activate sampling control. + * Next call of pmu_enable() starts sampling. + */ +static void cpumsf_pmu_start(struct perf_event *event, int flags) +{ +	struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); + +	if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) +		return; + +	if (flags & PERF_EF_RELOAD) +		WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); + +	perf_pmu_disable(event->pmu); +	event->hw.state = 0; +	cpuhw->lsctl.cs = 1; +	if (SAMPL_DIAG_MODE(&event->hw)) +		cpuhw->lsctl.cd = 1; +	perf_pmu_enable(event->pmu); +} + +/* Deactivate sampling control. + * Next call of pmu_enable() stops sampling. + */ +static void cpumsf_pmu_stop(struct perf_event *event, int flags) +{ +	struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); + +	if (event->hw.state & PERF_HES_STOPPED) +		return; + +	perf_pmu_disable(event->pmu); +	cpuhw->lsctl.cs = 0; +	cpuhw->lsctl.cd = 0; +	event->hw.state |= PERF_HES_STOPPED; + +	if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) { +		hw_perf_event_update(event, 1); +		event->hw.state |= PERF_HES_UPTODATE; +	} +	perf_pmu_enable(event->pmu); +} + +static int cpumsf_pmu_add(struct perf_event *event, int flags) +{ +	struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); +	int err; + +	if (cpuhw->flags & PMU_F_IN_USE) +		return -EAGAIN; + +	if (!cpuhw->sfb.sdbt) +		return -EINVAL; + +	err = 0; +	perf_pmu_disable(event->pmu); + +	event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED; + +	/* Set up sampling controls.  Always program the sampling register +	 * using the SDB-table start.  Reset TEAR_REG event hardware register +	 * that is used by hw_perf_event_update() to store the sampling buffer +	 * position after samples have been flushed. +	 */ +	cpuhw->lsctl.s = 0; +	cpuhw->lsctl.h = 1; +	cpuhw->lsctl.tear = (unsigned long) cpuhw->sfb.sdbt; +	cpuhw->lsctl.dear = *(unsigned long *) cpuhw->sfb.sdbt; +	cpuhw->lsctl.interval = SAMPL_RATE(&event->hw); +	hw_reset_registers(&event->hw, cpuhw->sfb.sdbt); + +	/* Ensure sampling functions are in the disabled state.  If disabled, +	 * switch on sampling enable control. */ +	if (WARN_ON_ONCE(cpuhw->lsctl.es == 1 || cpuhw->lsctl.ed == 1)) { +		err = -EAGAIN; +		goto out; +	} +	cpuhw->lsctl.es = 1; +	if (SAMPL_DIAG_MODE(&event->hw)) +		cpuhw->lsctl.ed = 1; + +	/* Set in_use flag and store event */ +	event->hw.idx = 0;	  /* only one sampling event per CPU supported */ +	cpuhw->event = event; +	cpuhw->flags |= PMU_F_IN_USE; + +	if (flags & PERF_EF_START) +		cpumsf_pmu_start(event, PERF_EF_RELOAD); +out: +	perf_event_update_userpage(event); +	perf_pmu_enable(event->pmu); +	return err; +} + +static void cpumsf_pmu_del(struct perf_event *event, int flags) +{ +	struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); + +	perf_pmu_disable(event->pmu); +	cpumsf_pmu_stop(event, PERF_EF_UPDATE); + +	cpuhw->lsctl.es = 0; +	cpuhw->lsctl.ed = 0; +	cpuhw->flags &= ~PMU_F_IN_USE; +	cpuhw->event = NULL; + +	perf_event_update_userpage(event); +	perf_pmu_enable(event->pmu); +} + +static int cpumsf_pmu_event_idx(struct perf_event *event) +{ +	return event->hw.idx; +} + +CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC, PERF_EVENT_CPUM_SF); +CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC_DIAG, PERF_EVENT_CPUM_SF_DIAG); + +static struct attribute *cpumsf_pmu_events_attr[] = { +	CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC), +	CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC_DIAG), +	NULL, +}; + +PMU_FORMAT_ATTR(event, "config:0-63"); + +static struct attribute *cpumsf_pmu_format_attr[] = { +	&format_attr_event.attr, +	NULL, +}; + +static struct attribute_group cpumsf_pmu_events_group = { +	.name = "events", +	.attrs = cpumsf_pmu_events_attr, +}; +static struct attribute_group cpumsf_pmu_format_group = { +	.name = "format", +	.attrs = cpumsf_pmu_format_attr, +}; +static const struct attribute_group *cpumsf_pmu_attr_groups[] = { +	&cpumsf_pmu_events_group, +	&cpumsf_pmu_format_group, +	NULL, +}; + +static struct pmu cpumf_sampling = { +	.pmu_enable   = cpumsf_pmu_enable, +	.pmu_disable  = cpumsf_pmu_disable, + +	.event_init   = cpumsf_pmu_event_init, +	.add	      = cpumsf_pmu_add, +	.del	      = cpumsf_pmu_del, + +	.start	      = cpumsf_pmu_start, +	.stop	      = cpumsf_pmu_stop, +	.read	      = cpumsf_pmu_read, + +	.event_idx    = cpumsf_pmu_event_idx, +	.attr_groups  = cpumsf_pmu_attr_groups, +}; + +static void cpumf_measurement_alert(struct ext_code ext_code, +				    unsigned int alert, unsigned long unused) +{ +	struct cpu_hw_sf *cpuhw; + +	if (!(alert & CPU_MF_INT_SF_MASK)) +		return; +	inc_irq_stat(IRQEXT_CMS); +	cpuhw = &__get_cpu_var(cpu_hw_sf); + +	/* Measurement alerts are shared and might happen when the PMU +	 * is not reserved.  Ignore these alerts in this case. */ +	if (!(cpuhw->flags & PMU_F_RESERVED)) +		return; + +	/* The processing below must take care of multiple alert events that +	 * might be indicated concurrently. */ + +	/* Program alert request */ +	if (alert & CPU_MF_INT_SF_PRA) { +		if (cpuhw->flags & PMU_F_IN_USE) +			hw_perf_event_update(cpuhw->event, 0); +		else +			WARN_ON_ONCE(!(cpuhw->flags & PMU_F_IN_USE)); +	} + +	/* Report measurement alerts only for non-PRA codes */ +	if (alert != CPU_MF_INT_SF_PRA) +		debug_sprintf_event(sfdbg, 6, "measurement alert: 0x%x\n", alert); + +	/* Sampling authorization change request */ +	if (alert & CPU_MF_INT_SF_SACA) +		qsi(&cpuhw->qsi); + +	/* Loss of sample data due to high-priority machine activities */ +	if (alert & CPU_MF_INT_SF_LSDA) { +		pr_err("Sample data was lost\n"); +		cpuhw->flags |= PMU_F_ERR_LSDA; +		sf_disable(); +	} + +	/* Invalid sampling buffer entry */ +	if (alert & (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE)) { +		pr_err("A sampling buffer entry is incorrect (alert=0x%x)\n", +		       alert); +		cpuhw->flags |= PMU_F_ERR_IBE; +		sf_disable(); +	} +} + +static int cpumf_pmu_notifier(struct notifier_block *self, +			      unsigned long action, void *hcpu) +{ +	unsigned int cpu = (long) hcpu; +	int flags; + +	/* Ignore the notification if no events are scheduled on the PMU. +	 * This might be racy... +	 */ +	if (!atomic_read(&num_events)) +		return NOTIFY_OK; + +	switch (action & ~CPU_TASKS_FROZEN) { +	case CPU_ONLINE: +	case CPU_ONLINE_FROZEN: +		flags = PMC_INIT; +		smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1); +		break; +	case CPU_DOWN_PREPARE: +		flags = PMC_RELEASE; +		smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1); +		break; +	default: +		break; +	} + +	return NOTIFY_OK; +} + +static int param_get_sfb_size(char *buffer, const struct kernel_param *kp) +{ +	if (!cpum_sf_avail()) +		return -ENODEV; +	return sprintf(buffer, "%lu,%lu", CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB); +} + +static int param_set_sfb_size(const char *val, const struct kernel_param *kp) +{ +	int rc; +	unsigned long min, max; + +	if (!cpum_sf_avail()) +		return -ENODEV; +	if (!val || !strlen(val)) +		return -EINVAL; + +	/* Valid parameter values: "min,max" or "max" */ +	min = CPUM_SF_MIN_SDB; +	max = CPUM_SF_MAX_SDB; +	if (strchr(val, ',')) +		rc = (sscanf(val, "%lu,%lu", &min, &max) == 2) ? 0 : -EINVAL; +	else +		rc = kstrtoul(val, 10, &max); + +	if (min < 2 || min >= max || max > get_num_physpages()) +		rc = -EINVAL; +	if (rc) +		return rc; + +	sfb_set_limits(min, max); +	pr_info("The sampling buffer limits have changed to: " +		"min=%lu max=%lu (diag=x%lu)\n", +		CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB, CPUM_SF_SDB_DIAG_FACTOR); +	return 0; +} + +#define param_check_sfb_size(name, p) __param_check(name, p, void) +static struct kernel_param_ops param_ops_sfb_size = { +	.set = param_set_sfb_size, +	.get = param_get_sfb_size, +}; + +#define RS_INIT_FAILURE_QSI	  0x0001 +#define RS_INIT_FAILURE_BSDES	  0x0002 +#define RS_INIT_FAILURE_ALRT	  0x0003 +#define RS_INIT_FAILURE_PERF	  0x0004 +static void __init pr_cpumsf_err(unsigned int reason) +{ +	pr_err("Sampling facility support for perf is not available: " +	       "reason=%04x\n", reason); +} + +static int __init init_cpum_sampling_pmu(void) +{ +	struct hws_qsi_info_block si; +	int err; + +	if (!cpum_sf_avail()) +		return -ENODEV; + +	memset(&si, 0, sizeof(si)); +	if (qsi(&si)) { +		pr_cpumsf_err(RS_INIT_FAILURE_QSI); +		return -ENODEV; +	} + +	if (si.bsdes != sizeof(struct hws_basic_entry)) { +		pr_cpumsf_err(RS_INIT_FAILURE_BSDES); +		return -EINVAL; +	} + +	if (si.ad) +		sfb_set_limits(CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB); + +	sfdbg = debug_register(KMSG_COMPONENT, 2, 1, 80); +	if (!sfdbg) +		pr_err("Registering for s390dbf failed\n"); +	debug_register_view(sfdbg, &debug_sprintf_view); + +	err = register_external_irq(EXT_IRQ_MEASURE_ALERT, +				    cpumf_measurement_alert); +	if (err) { +		pr_cpumsf_err(RS_INIT_FAILURE_ALRT); +		goto out; +	} + +	err = perf_pmu_register(&cpumf_sampling, "cpum_sf", PERF_TYPE_RAW); +	if (err) { +		pr_cpumsf_err(RS_INIT_FAILURE_PERF); +		unregister_external_irq(EXT_IRQ_MEASURE_ALERT, +					cpumf_measurement_alert); +		goto out; +	} +	perf_cpu_notifier(cpumf_pmu_notifier); +out: +	return err; +} +arch_initcall(init_cpum_sampling_pmu); +core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0640); diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c index 2343c218b8f..61595c1f0a0 100644 --- a/arch/s390/kernel/perf_event.c +++ b/arch/s390/kernel/perf_event.c @@ -1,7 +1,7 @@  /*   * Performance event support for s390x   * - *  Copyright IBM Corp. 2012 + *  Copyright IBM Corp. 2012, 2013   *  Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>   *   * This program is free software; you can redistribute it and/or modify @@ -16,15 +16,19 @@  #include <linux/kvm_host.h>  #include <linux/percpu.h>  #include <linux/export.h> +#include <linux/seq_file.h> +#include <linux/spinlock.h> +#include <linux/sysfs.h>  #include <asm/irq.h>  #include <asm/cpu_mf.h>  #include <asm/lowcore.h>  #include <asm/processor.h> +#include <asm/sysinfo.h>  const char *perf_pmu_name(void)  {  	if (cpum_cf_avail() || cpum_sf_avail()) -		return "CPU-measurement facilities (CPUMF)"; +		return "CPU-Measurement Facilities (CPU-MF)";  	return "pmu";  }  EXPORT_SYMBOL(perf_pmu_name); @@ -35,6 +39,8 @@ int perf_num_counters(void)  	if (cpum_cf_avail())  		num += PERF_CPUM_CF_MAX_CTR; +	if (cpum_sf_avail()) +		num += PERF_CPUM_SF_MAX_CTR;  	return num;  } @@ -54,7 +60,7 @@ static bool is_in_guest(struct pt_regs *regs)  {  	if (user_mode(regs))  		return false; -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +#if IS_ENABLED(CONFIG_KVM)  	return instruction_pointer(regs) == (unsigned long) &sie_exit;  #else  	return false; @@ -83,8 +89,31 @@ static unsigned long perf_misc_guest_flags(struct pt_regs *regs)  					: PERF_RECORD_MISC_GUEST_KERNEL;  } +static unsigned long perf_misc_flags_sf(struct pt_regs *regs) +{ +	struct perf_sf_sde_regs *sde_regs; +	unsigned long flags; + +	sde_regs = (struct perf_sf_sde_regs *) ®s->int_parm_long; +	if (sde_regs->in_guest) +		flags = user_mode(regs) ? PERF_RECORD_MISC_GUEST_USER +					: PERF_RECORD_MISC_GUEST_KERNEL; +	else +		flags = user_mode(regs) ? PERF_RECORD_MISC_USER +					: PERF_RECORD_MISC_KERNEL; +	return flags; +} +  unsigned long perf_misc_flags(struct pt_regs *regs)  { +	/* Check if the cpum_sf PMU has created the pt_regs structure. +	 * In this case, perf misc flags can be easily extracted.  Otherwise, +	 * do regular checks on the pt_regs content. +	 */ +	if (regs->int_code == 0x1407 && regs->int_parm == CPU_MF_INT_SF_PRA) +		if (!regs->gprs[15]) +			return perf_misc_flags_sf(regs); +  	if (is_in_guest(regs))  		return perf_misc_guest_flags(regs); @@ -92,27 +121,107 @@ unsigned long perf_misc_flags(struct pt_regs *regs)  			       : PERF_RECORD_MISC_KERNEL;  } -void perf_event_print_debug(void) +static void print_debug_cf(void)  {  	struct cpumf_ctr_info cf_info; -	unsigned long flags; -	int cpu; - -	if (!cpum_cf_avail()) -		return; - -	local_irq_save(flags); +	int cpu = smp_processor_id(); -	cpu = smp_processor_id();  	memset(&cf_info, 0, sizeof(cf_info));  	if (!qctri(&cf_info))  		pr_info("CPU[%i] CPUM_CF: ver=%u.%u A=%04x E=%04x C=%04x\n",  			cpu, cf_info.cfvn, cf_info.csvn,  			cf_info.auth_ctl, cf_info.enable_ctl, cf_info.act_ctl); +} + +static void print_debug_sf(void) +{ +	struct hws_qsi_info_block si; +	int cpu = smp_processor_id(); +	memset(&si, 0, sizeof(si)); +	if (qsi(&si)) +		return; + +	pr_info("CPU[%i] CPUM_SF: basic=%i diag=%i min=%lu max=%lu cpu_speed=%u\n", +		cpu, si.as, si.ad, si.min_sampl_rate, si.max_sampl_rate, +		si.cpu_speed); + +	if (si.as) +		pr_info("CPU[%i] CPUM_SF: Basic-sampling: a=%i e=%i c=%i" +			" bsdes=%i tear=%016lx dear=%016lx\n", cpu, +			si.as, si.es, si.cs, si.bsdes, si.tear, si.dear); +	if (si.ad) +		pr_info("CPU[%i] CPUM_SF: Diagnostic-sampling: a=%i e=%i c=%i" +			" dsdes=%i tear=%016lx dear=%016lx\n", cpu, +			si.ad, si.ed, si.cd, si.dsdes, si.tear, si.dear); +} + +void perf_event_print_debug(void) +{ +	unsigned long flags; + +	local_irq_save(flags); +	if (cpum_cf_avail()) +		print_debug_cf(); +	if (cpum_sf_avail()) +		print_debug_sf();  	local_irq_restore(flags);  } +/* Service level infrastructure */ +static void sl_print_counter(struct seq_file *m) +{ +	struct cpumf_ctr_info ci; + +	memset(&ci, 0, sizeof(ci)); +	if (qctri(&ci)) +		return; + +	seq_printf(m, "CPU-MF: Counter facility: version=%u.%u " +		   "authorization=%04x\n", ci.cfvn, ci.csvn, ci.auth_ctl); +} + +static void sl_print_sampling(struct seq_file *m) +{ +	struct hws_qsi_info_block si; + +	memset(&si, 0, sizeof(si)); +	if (qsi(&si)) +		return; + +	if (!si.as && !si.ad) +		return; + +	seq_printf(m, "CPU-MF: Sampling facility: min_rate=%lu max_rate=%lu" +		   " cpu_speed=%u\n", si.min_sampl_rate, si.max_sampl_rate, +		   si.cpu_speed); +	if (si.as) +		seq_printf(m, "CPU-MF: Sampling facility: mode=basic" +			   " sample_size=%u\n", si.bsdes); +	if (si.ad) +		seq_printf(m, "CPU-MF: Sampling facility: mode=diagnostic" +			   " sample_size=%u\n", si.dsdes); +} + +static void service_level_perf_print(struct seq_file *m, +				     struct service_level *sl) +{ +	if (cpum_cf_avail()) +		sl_print_counter(m); +	if (cpum_sf_avail()) +		sl_print_sampling(m); +} + +static struct service_level service_level_perf = { +	.seq_print = service_level_perf_print, +}; + +static int __init service_level_perf_register(void) +{ +	return register_service_level(&service_level_perf); +} +arch_initcall(service_level_perf_register); +  /* See also arch/s390/kernel/traps.c */  static unsigned long __store_trace(struct perf_callchain_entry *entry,  				   unsigned long sp, @@ -172,3 +281,44 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,  	__store_trace(entry, head, S390_lowcore.thread_info,  		      S390_lowcore.thread_info + THREAD_SIZE);  } + +/* Perf defintions for PMU event attributes in sysfs */ +ssize_t cpumf_events_sysfs_show(struct device *dev, +				struct device_attribute *attr, char *page) +{ +	struct perf_pmu_events_attr *pmu_attr; + +	pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); +	return sprintf(page, "event=0x%04llx,name=%s\n", +		       pmu_attr->id, attr->attr.name); +} + +/* Reserve/release functions for sharing perf hardware */ +static DEFINE_SPINLOCK(perf_hw_owner_lock); +static void *perf_sampling_owner; + +int perf_reserve_sampling(void) +{ +	int err; + +	err = 0; +	spin_lock(&perf_hw_owner_lock); +	if (perf_sampling_owner) { +		pr_warn("The sampling facility is already reserved by %p\n", +			perf_sampling_owner); +		err = -EBUSY; +	} else +		perf_sampling_owner = __builtin_return_address(0); +	spin_unlock(&perf_hw_owner_lock); +	return err; +} +EXPORT_SYMBOL(perf_reserve_sampling); + +void perf_release_sampling(void) +{ +	spin_lock(&perf_hw_owner_lock); +	WARN_ON(!perf_sampling_owner); +	perf_sampling_owner = NULL; +	spin_unlock(&perf_hw_owner_lock); +} +EXPORT_SYMBOL(perf_release_sampling); diff --git a/arch/s390/kernel/pgm_check.S b/arch/s390/kernel/pgm_check.S index 14bdecb6192..813ec726087 100644 --- a/arch/s390/kernel/pgm_check.S +++ b/arch/s390/kernel/pgm_check.S @@ -78,7 +78,7 @@ PGM_CHECK_DEFAULT			/* 34 */  PGM_CHECK_DEFAULT			/* 35 */  PGM_CHECK_DEFAULT			/* 36 */  PGM_CHECK_DEFAULT			/* 37 */ -PGM_CHECK_64BIT(do_asce_exception)	/* 38 */ +PGM_CHECK_64BIT(do_dat_exception)	/* 38 */  PGM_CHECK_64BIT(do_dat_exception)	/* 39 */  PGM_CHECK_64BIT(do_dat_exception)	/* 3a */  PGM_CHECK_64BIT(do_dat_exception)	/* 3b */ diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index c5dbb335716..93b9ca42e5c 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -64,7 +64,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)  void arch_cpu_idle(void)  {  	local_mcck_disable(); -	if (test_thread_flag(TIF_MCCK_PENDING)) { +	if (test_cpu_flag(CIF_MCCK_PENDING)) {  		local_mcck_enable();  		local_irq_enable();  		return; @@ -76,7 +76,7 @@ void arch_cpu_idle(void)  void arch_cpu_idle_exit(void)  { -	if (test_thread_flag(TIF_MCCK_PENDING)) +	if (test_cpu_flag(CIF_MCCK_PENDING))  		s390_handle_mcck();  } @@ -123,7 +123,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,  	memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));  	memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));  	clear_tsk_thread_flag(p, TIF_SINGLE_STEP); -	clear_tsk_thread_flag(p, TIF_PER_TRAP);  	/* Initialize per thread user and system timer values */  	ti = task_thread_info(p);  	ti->user_timer = 0; @@ -139,7 +138,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,  	if (unlikely(p->flags & PF_KTHREAD)) {  		/* kernel thread */  		memset(&frame->childregs, 0, sizeof(struct pt_regs)); -		frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | +		frame->childregs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT |  				PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;  		frame->childregs.psw.addr = PSW_ADDR_AMODE |  				(unsigned long) kernel_thread_starter; @@ -152,6 +151,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,  	}  	frame->childregs = *current_pt_regs();  	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */ +	frame->childregs.flags = 0;  	if (new_stackp)  		frame->childregs.gprs[15] = new_stackp; @@ -165,7 +165,8 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,  	 * save fprs to current->thread.fp_regs to merge them with  	 * the emulated registers and then copy the result to the child.  	 */ -	save_fp_regs(¤t->thread.fp_regs); +	save_fp_ctl(¤t->thread.fp_regs.fpc); +	save_fp_regs(current->thread.fp_regs.fprs);  	memcpy(&p->thread.fp_regs, ¤t->thread.fp_regs,  	       sizeof(s390_fp_regs));  	/* Set a new TLS ?  */ @@ -173,7 +174,9 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,  		p->thread.acrs[0] = frame->childregs.gprs[6];  #else /* CONFIG_64BIT */  	/* Save the fpu registers to new thread structure. */ -	save_fp_regs(&p->thread.fp_regs); +	save_fp_ctl(&p->thread.fp_regs.fpc); +	save_fp_regs(p->thread.fp_regs.fprs); +	p->thread.fp_regs.pad = 0;  	/* Set a new TLS ?  */  	if (clone_flags & CLONE_SETTLS) {  		unsigned long tls = frame->childregs.gprs[6]; @@ -205,10 +208,12 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)  	 * save fprs to current->thread.fp_regs to merge them with  	 * the emulated registers and then copy the result to the dump.  	 */ -	save_fp_regs(¤t->thread.fp_regs); +	save_fp_ctl(¤t->thread.fp_regs.fpc); +	save_fp_regs(current->thread.fp_regs.fprs);  	memcpy(fpregs, ¤t->thread.fp_regs, sizeof(s390_fp_regs));  #else /* CONFIG_64BIT */ -	save_fp_regs(fpregs); +	save_fp_ctl(&fpregs->fpc); +	save_fp_regs(fpregs->fprs);  #endif /* CONFIG_64BIT */  	return 1;  } @@ -256,20 +261,18 @@ static inline unsigned long brk_rnd(void)  unsigned long arch_randomize_brk(struct mm_struct *mm)  { -	unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); +	unsigned long ret; -	if (ret < mm->brk) -		return mm->brk; -	return ret; +	ret = PAGE_ALIGN(mm->brk + brk_rnd()); +	return (ret > mm->brk) ? ret : mm->brk;  }  unsigned long randomize_et_dyn(unsigned long base)  { -	unsigned long ret = PAGE_ALIGN(base + brk_rnd()); +	unsigned long ret;  	if (!(current->flags & PF_RANDOMIZE))  		return base; -	if (ret < base) -		return base; -	return ret; +	ret = PAGE_ALIGN(base + brk_rnd()); +	return (ret > base) ? ret : base;  } diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 9556905bd3c..5dc7ad9e2fb 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -56,25 +56,26 @@ void update_cr_regs(struct task_struct *task)  #ifdef CONFIG_64BIT  	/* Take care of the enable/disable of transactional execution. */  	if (MACHINE_HAS_TE) { -		unsigned long cr[3], cr_new[3]; +		unsigned long cr, cr_new; -		__ctl_store(cr, 0, 2); -		cr_new[1] = cr[1]; +		__ctl_store(cr, 0, 0);  		/* Set or clear transaction execution TXC bit 8. */ +		cr_new = cr | (1UL << 55);  		if (task->thread.per_flags & PER_FLAG_NO_TE) -			cr_new[0] = cr[0] & ~(1UL << 55); -		else -			cr_new[0] = cr[0] | (1UL << 55); +			cr_new &= ~(1UL << 55); +		if (cr_new != cr) +			__ctl_load(cr_new, 0, 0);  		/* Set or clear transaction execution TDC bits 62 and 63. */ -		cr_new[2] = cr[2] & ~3UL; +		__ctl_store(cr, 2, 2); +		cr_new = cr & ~3UL;  		if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {  			if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND) -				cr_new[2] |= 1UL; +				cr_new |= 1UL;  			else -				cr_new[2] |= 2UL; +				cr_new |= 2UL;  		} -		if (memcmp(&cr_new, &cr, sizeof(cr))) -			__ctl_load(cr_new, 0, 2); +		if (cr_new != cr) +			__ctl_load(cr_new, 2, 2);  	}  #endif  	/* Copy user specified PER registers */ @@ -84,7 +85,10 @@ void update_cr_regs(struct task_struct *task)  	/* merge TIF_SINGLE_STEP into user specified PER registers. */  	if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) { -		new.control |= PER_EVENT_IFETCH; +		if (test_tsk_thread_flag(task, TIF_BLOCK_STEP)) +			new.control |= PER_EVENT_BRANCH; +		else +			new.control |= PER_EVENT_IFETCH;  #ifdef CONFIG_64BIT  		new.control |= PER_CONTROL_SUSPENSION;  		new.control |= PER_EVENT_TRANSACTION_END; @@ -106,16 +110,20 @@ void update_cr_regs(struct task_struct *task)  void user_enable_single_step(struct task_struct *task)  { +	clear_tsk_thread_flag(task, TIF_BLOCK_STEP);  	set_tsk_thread_flag(task, TIF_SINGLE_STEP); -	if (task == current) -		update_cr_regs(task);  }  void user_disable_single_step(struct task_struct *task)  { +	clear_tsk_thread_flag(task, TIF_BLOCK_STEP);  	clear_tsk_thread_flag(task, TIF_SINGLE_STEP); -	if (task == current) -		update_cr_regs(task); +} + +void user_enable_block_step(struct task_struct *task) +{ +	set_tsk_thread_flag(task, TIF_SINGLE_STEP); +	set_tsk_thread_flag(task, TIF_BLOCK_STEP);  }  /* @@ -128,7 +136,7 @@ void ptrace_disable(struct task_struct *task)  	memset(&task->thread.per_user, 0, sizeof(task->thread.per_user));  	memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));  	clear_tsk_thread_flag(task, TIF_SINGLE_STEP); -	clear_tsk_thread_flag(task, TIF_PER_TRAP); +	clear_pt_regs_flag(task_pt_regs(task), PIF_PER_TRAP);  	task->thread.per_flags = 0;  } @@ -198,9 +206,11 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)  		 * psw and gprs are stored on the stack  		 */  		tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr); -		if (addr == (addr_t) &dummy->regs.psw.mask) +		if (addr == (addr_t) &dummy->regs.psw.mask) {  			/* Return a clean psw mask. */ -			tmp = psw_user_bits | (tmp & PSW_MASK_USER); +			tmp &= PSW_MASK_USER | PSW_MASK_RI; +			tmp |= PSW_USER_BITS; +		}  	} else if (addr < (addr_t) &dummy->regs.orig_gpr2) {  		/* @@ -239,8 +249,7 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)  		offset = addr - (addr_t) &dummy->regs.fp_regs;  		tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset);  		if (addr == (addr_t) &dummy->regs.fp_regs.fpc) -			tmp &= (unsigned long) FPC_VALID_MASK -				<< (BITS_PER_LONG - 32); +			tmp <<= BITS_PER_LONG - 32;  	} else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {  		/* @@ -321,11 +330,20 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)  		/*  		 * psw and gprs are stored on the stack  		 */ -		if (addr == (addr_t) &dummy->regs.psw.mask && -		    ((data & ~PSW_MASK_USER) != psw_user_bits || -		     ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA)))) -			/* Invalid psw mask. */ -			return -EINVAL; +		if (addr == (addr_t) &dummy->regs.psw.mask) { +			unsigned long mask = PSW_MASK_USER; + +			mask |= is_ri_task(child) ? PSW_MASK_RI : 0; +			if ((data ^ PSW_USER_BITS) & ~mask) +				/* Invalid psw mask. */ +				return -EINVAL; +			if ((data & PSW_MASK_ASC) == PSW_ASC_HOME) +				/* Invalid address-space-control bits */ +				return -EINVAL; +			if ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA)) +				/* Invalid addressing mode bits */ +				return -EINVAL; +		}  		*(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;  	} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { @@ -363,10 +381,10 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)  		/*  		 * floating point regs. are stored in the thread structure  		 */ -		if (addr == (addr_t) &dummy->regs.fp_regs.fpc && -		    (data & ~((unsigned long) FPC_VALID_MASK -			      << (BITS_PER_LONG - 32))) != 0) -			return -EINVAL; +		if (addr == (addr_t) &dummy->regs.fp_regs.fpc) +			if ((unsigned int) data != 0 || +			    test_fp_ctl(data >> (BITS_PER_LONG - 32))) +				return -EINVAL;  		offset = addr - (addr_t) &dummy->regs.fp_regs;  		*(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data; @@ -557,7 +575,8 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)  		if (addr == (addr_t) &dummy32->regs.psw.mask) {  			/* Fake a 31 bit psw mask. */  			tmp = (__u32)(regs->psw.mask >> 32); -			tmp = psw32_user_bits | (tmp & PSW32_MASK_USER); +			tmp &= PSW32_MASK_USER | PSW32_MASK_RI; +			tmp |= PSW32_USER_BITS;  		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {  			/* Fake a 31 bit psw address. */  			tmp = (__u32) regs->psw.addr | @@ -654,13 +673,19 @@ static int __poke_user_compat(struct task_struct *child,  		 * psw, gprs, acrs and orig_gpr2 are stored on the stack  		 */  		if (addr == (addr_t) &dummy32->regs.psw.mask) { +			__u32 mask = PSW32_MASK_USER; + +			mask |= is_ri_task(child) ? PSW32_MASK_RI : 0;  			/* Build a 64 bit psw mask from 31 bit mask. */ -			if ((tmp & ~PSW32_MASK_USER) != psw32_user_bits) +			if ((tmp ^ PSW32_USER_BITS) & ~mask)  				/* Invalid psw mask. */  				return -EINVAL; +			if ((data & PSW32_MASK_ASC) == PSW32_ASC_HOME) +				/* Invalid address-space-control bits */ +				return -EINVAL;  			regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |  				(regs->psw.mask & PSW_MASK_BA) | -				(__u64)(tmp & PSW32_MASK_USER) << 32; +				(__u64)(tmp & mask) << 32;  		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {  			/* Build a 64 bit psw address from 31 bit address. */  			regs->psw.addr = (__u64) tmp & PSW32_ADDR_INSN; @@ -696,8 +721,7 @@ static int __poke_user_compat(struct task_struct *child,  		 * floating point regs. are stored in the thread structure   		 */  		if (addr == (addr_t) &dummy32->regs.fp_regs.fpc && -		    (tmp & ~FPC_VALID_MASK) != 0) -			/* Invalid floating point control. */ +		    test_fp_ctl(tmp))  			return -EINVAL;  	        offset = addr - (addr_t) &dummy32->regs.fp_regs;  		*(__u32 *)((addr_t) &child->thread.fp_regs + offset) = tmp; @@ -797,7 +821,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)  		 * debugger stored an invalid system call number. Skip  		 * the system call and the system call restart handling.  		 */ -		clear_thread_flag(TIF_SYSCALL); +		clear_pt_regs_flag(regs, PIF_SYSCALL);  		ret = -1;  	} @@ -895,8 +919,10 @@ static int s390_fpregs_get(struct task_struct *target,  			   const struct user_regset *regset, unsigned int pos,  			   unsigned int count, void *kbuf, void __user *ubuf)  { -	if (target == current) -		save_fp_regs(&target->thread.fp_regs); +	if (target == current) { +		save_fp_ctl(&target->thread.fp_regs.fpc); +		save_fp_regs(target->thread.fp_regs.fprs); +	}  	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,  				   &target->thread.fp_regs, 0, -1); @@ -909,19 +935,21 @@ static int s390_fpregs_set(struct task_struct *target,  {  	int rc = 0; -	if (target == current) -		save_fp_regs(&target->thread.fp_regs); +	if (target == current) { +		save_fp_ctl(&target->thread.fp_regs.fpc); +		save_fp_regs(target->thread.fp_regs.fprs); +	}  	/* If setting FPC, must validate it first. */  	if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) { -		u32 fpc[2] = { target->thread.fp_regs.fpc, 0 }; -		rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fpc, +		u32 ufpc[2] = { target->thread.fp_regs.fpc, 0 }; +		rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ufpc,  					0, offsetof(s390_fp_regs, fprs));  		if (rc)  			return rc; -		if ((fpc[0] & ~FPC_VALID_MASK) != 0 || fpc[1] != 0) +		if (ufpc[1] != 0 || test_fp_ctl(ufpc[0]))  			return -EINVAL; -		target->thread.fp_regs.fpc = fpc[0]; +		target->thread.fp_regs.fpc = ufpc[0];  	}  	if (rc == 0 && count > 0) @@ -929,8 +957,10 @@ static int s390_fpregs_set(struct task_struct *target,  					target->thread.fp_regs.fprs,  					offsetof(s390_fp_regs, fprs), -1); -	if (rc == 0 && target == current) -		restore_fp_regs(&target->thread.fp_regs); +	if (rc == 0 && target == current) { +		restore_fp_ctl(&target->thread.fp_regs.fpc); +		restore_fp_regs(target->thread.fp_regs.fprs); +	}  	return rc;  } diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c index e1c9d1c292f..26b4ae96fdd 100644 --- a/arch/s390/kernel/runtime_instr.c +++ b/arch/s390/kernel/runtime_instr.c @@ -40,8 +40,6 @@ static void disable_runtime_instr(void)  static void init_runtime_instr_cb(struct runtime_instr_cb *cb)  {  	cb->buf_limit = 0xfff; -	if (s390_user_mode == HOME_SPACE_MODE) -		cb->home_space = 1;  	cb->int_requested = 1;  	cb->pstate = 1;  	cb->pstate_set_buf = 1; @@ -140,7 +138,8 @@ static int __init runtime_instr_init(void)  		return 0;  	irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); -	rc = register_external_interrupt(0x1407, runtime_instr_int_handler); +	rc = register_external_irq(EXT_IRQ_MEASURE_ALERT, +				   runtime_instr_int_handler);  	if (rc)  		irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT);  	else diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 3bac589844a..9f60467938d 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -5,7 +5,7 @@  #ifdef CONFIG_FUNCTION_TRACER  EXPORT_SYMBOL(_mcount);  #endif -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +#if IS_ENABLED(CONFIG_KVM)  EXPORT_SYMBOL(sie64a);  EXPORT_SYMBOL(sie_exit);  #endif diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S index 29bd7bec417..a41f2c99dcc 100644 --- a/arch/s390/kernel/sclp.S +++ b/arch/s390/kernel/sclp.S @@ -9,6 +9,7 @@   */  #include <linux/linkage.h> +#include <asm/irq.h>  LC_EXT_NEW_PSW		= 0x58			# addr of ext int handler  LC_EXT_NEW_PSW_64	= 0x1b0			# addr of ext int handler 64 bit @@ -73,9 +74,9 @@ _sclp_wait_int:  	lpsw	.LwaitpswS1-.LbaseS1(%r13)	# wait until interrupt  .LwaitS1:  	lh	%r7,LC_EXT_INT_CODE -	chi	%r7,0x1004			# timeout? +	chi	%r7,EXT_IRQ_CLK_COMP		# timeout?  	je	.LtimeoutS1 -	chi	%r7,0x2401			# service int? +	chi	%r7,EXT_IRQ_SERVICE_SIG		# service int?  	jne	.LloopS1  	sr	%r2,%r2  	l	%r3,LC_EXT_INT_PARAM diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index aeed8a61fa0..1e2264b46e4 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -47,7 +47,6 @@  #include <linux/compat.h>  #include <asm/ipl.h> -#include <asm/uaccess.h>  #include <asm/facility.h>  #include <asm/smp.h>  #include <asm/mmu_context.h> @@ -64,18 +63,6 @@  #include <asm/sclp.h>  #include "entry.h" -long psw_kernel_bits	= PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY | -			  PSW_MASK_EA | PSW_MASK_BA; -long psw_user_bits	= PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | -			  PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK | -			  PSW_MASK_PSTATE | PSW_ASC_HOME; - -/* - * User copy operations. - */ -struct uaccess_ops uaccess; -EXPORT_SYMBOL(uaccess); -  /*   * Machine setup..   */ @@ -91,10 +78,9 @@ EXPORT_SYMBOL(console_irq);  unsigned long elf_hwcap = 0;  char elf_platform[ELF_PLATFORM_SIZE]; -struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS]; -  int __initdata memory_end_set;  unsigned long __initdata memory_end; +unsigned long __initdata max_physmem_end;  unsigned long VMALLOC_START;  EXPORT_SYMBOL(VMALLOC_START); @@ -225,7 +211,7 @@ static void __init conmode_default(void)  	}  } -#ifdef CONFIG_ZFCPDUMP +#ifdef CONFIG_CRASH_DUMP  static void __init setup_zfcpdump(void)  {  	if (ipl_info.type != IPL_TYPE_FCP_DUMP) @@ -237,7 +223,7 @@ static void __init setup_zfcpdump(void)  }  #else  static inline void setup_zfcpdump(void) {} -#endif /* CONFIG_ZFCPDUMP */ +#endif /* CONFIG_CRASH_DUMP */   /*   * Reboot, halt and power_off stubs. They just call _machine_restart, @@ -286,6 +272,7 @@ EXPORT_SYMBOL_GPL(pm_power_off);  static int __init early_parse_mem(char *p)  {  	memory_end = memparse(p, &p); +	memory_end &= PAGE_MASK;  	memory_end_set = 1;  	return 0;  } @@ -300,43 +287,6 @@ static int __init parse_vmalloc(char *arg)  }  early_param("vmalloc", parse_vmalloc); -unsigned int s390_user_mode = PRIMARY_SPACE_MODE; -EXPORT_SYMBOL_GPL(s390_user_mode); - -static void __init set_user_mode_primary(void) -{ -	psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME; -	psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY; -#ifdef CONFIG_COMPAT -	psw32_user_bits = -		(psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY; -#endif -	uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos_switch : uaccess_pt; -} - -static int __init early_parse_user_mode(char *p) -{ -	if (p && strcmp(p, "primary") == 0) -		s390_user_mode = PRIMARY_SPACE_MODE; -	else if (!p || strcmp(p, "home") == 0) -		s390_user_mode = HOME_SPACE_MODE; -	else -		return 1; -	return 0; -} -early_param("user_mode", early_parse_user_mode); - -static void __init setup_addressing_mode(void) -{ -	if (s390_user_mode != PRIMARY_SPACE_MODE) -		return; -	set_user_mode_primary(); -	if (MACHINE_HAS_MVCOS) -		pr_info("Address spaces switched, mvcos available\n"); -	else -		pr_info("Address spaces switched, mvcos not available\n"); -} -  void *restart_stack __attribute__((__section__(".data")));  static void __init setup_lowcore(void) @@ -348,24 +298,24 @@ static void __init setup_lowcore(void)  	 */  	BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);  	lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0); -	lc->restart_psw.mask = psw_kernel_bits; +	lc->restart_psw.mask = PSW_KERNEL_BITS;  	lc->restart_psw.addr =  		PSW_ADDR_AMODE | (unsigned long) restart_int_handler; -	lc->external_new_psw.mask = psw_kernel_bits | +	lc->external_new_psw.mask = PSW_KERNEL_BITS |  		PSW_MASK_DAT | PSW_MASK_MCHECK;  	lc->external_new_psw.addr =  		PSW_ADDR_AMODE | (unsigned long) ext_int_handler; -	lc->svc_new_psw.mask = psw_kernel_bits | +	lc->svc_new_psw.mask = PSW_KERNEL_BITS |  		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;  	lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call; -	lc->program_new_psw.mask = psw_kernel_bits | +	lc->program_new_psw.mask = PSW_KERNEL_BITS |  		PSW_MASK_DAT | PSW_MASK_MCHECK;  	lc->program_new_psw.addr =  		PSW_ADDR_AMODE | (unsigned long) pgm_check_handler; -	lc->mcck_new_psw.mask = psw_kernel_bits; +	lc->mcck_new_psw.mask = PSW_KERNEL_BITS;  	lc->mcck_new_psw.addr =  		PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; -	lc->io_new_psw.mask = psw_kernel_bits | +	lc->io_new_psw.mask = PSW_KERNEL_BITS |  		PSW_MASK_DAT | PSW_MASK_MCHECK;  	lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;  	lc->clock_comparator = -1ULL; @@ -408,7 +358,7 @@ static void __init setup_lowcore(void)  	/*  	 * Set up PSW restart to call ipl.c:do_restart(). Copy the relevant -	 * restart data to the absolute zero lowcore. This is necesary if +	 * restart data to the absolute zero lowcore. This is necessary if  	 * PSW restart is done on an offline CPU that has lowcore zero.  	 */  	lc->restart_stack = (unsigned long) restart_stack; @@ -423,6 +373,10 @@ static void __init setup_lowcore(void)  	mem_assign_absolute(S390_lowcore.restart_source, lc->restart_source);  	mem_assign_absolute(S390_lowcore.restart_psw, lc->restart_psw); +#ifdef CONFIG_SMP +	lc->spinlock_lockval = arch_spin_lockval(0); +#endif +  	set_prefix((u32)(unsigned long) lc);  	lowcore_ptr[0] = lc;  } @@ -451,7 +405,8 @@ static struct resource __initdata *standard_resources[] = {  static void __init setup_resources(void)  {  	struct resource *res, *std_res, *sub_res; -	int i, j; +	struct memblock_region *reg; +	int j;  	code_resource.start = (unsigned long) &_text;  	code_resource.end = (unsigned long) &_etext - 1; @@ -460,24 +415,13 @@ static void __init setup_resources(void)  	bss_resource.start = (unsigned long) &__bss_start;  	bss_resource.end = (unsigned long) &__bss_stop - 1; -	for (i = 0; i < MEMORY_CHUNKS; i++) { -		if (!memory_chunk[i].size) -			continue; +	for_each_memblock(memory, reg) {  		res = alloc_bootmem_low(sizeof(*res));  		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; -		switch (memory_chunk[i].type) { -		case CHUNK_READ_WRITE: -			res->name = "System RAM"; -			break; -		case CHUNK_READ_ONLY: -			res->name = "System ROM"; -			res->flags |= IORESOURCE_READONLY; -			break; -		default: -			res->name = "reserved"; -		} -		res->start = memory_chunk[i].addr; -		res->end = res->start + memory_chunk[i].size - 1; + +		res->name = "System RAM"; +		res->start = reg->base; +		res->end = reg->base + reg->size - 1;  		request_resource(&iomem_resource, res);  		for (j = 0; j < ARRAY_SIZE(standard_resources); j++) { @@ -501,47 +445,11 @@ static void __init setup_resources(void)  static void __init setup_memory_end(void)  {  	unsigned long vmax, vmalloc_size, tmp; -	unsigned long real_memory_size = 0; -	int i; - - -#ifdef CONFIG_ZFCPDUMP -	if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) { -		memory_end = ZFCPDUMP_HSA_SIZE; -		memory_end_set = 1; -	} -#endif -	memory_end &= PAGE_MASK; - -	/* -	 * Make sure all chunks are MAX_ORDER aligned so we don't need the -	 * extra checks that HOLES_IN_ZONE would require. -	 */ -	for (i = 0; i < MEMORY_CHUNKS; i++) { -		unsigned long start, end; -		struct mem_chunk *chunk; -		unsigned long align; - -		chunk = &memory_chunk[i]; -		if (!chunk->size) -			continue; -		align = 1UL << (MAX_ORDER + PAGE_SHIFT - 1); -		start = (chunk->addr + align - 1) & ~(align - 1); -		end = (chunk->addr + chunk->size) & ~(align - 1); -		if (start >= end) -			memset(chunk, 0, sizeof(*chunk)); -		else { -			chunk->addr = start; -			chunk->size = end - start; -		} -		real_memory_size = max(real_memory_size, -				       chunk->addr + chunk->size); -	}  	/* Choose kernel address space layout: 2, 3, or 4 levels. */  #ifdef CONFIG_64BIT  	vmalloc_size = VMALLOC_END ?: (128UL << 30) - MODULES_LEN; -	tmp = (memory_end ?: real_memory_size) / PAGE_SIZE; +	tmp = (memory_end ?: max_physmem_end) / PAGE_SIZE;  	tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size;  	if (tmp <= (1UL << 42))  		vmax = 1UL << 42;	/* 3-level kernel page table */ @@ -569,21 +477,11 @@ static void __init setup_memory_end(void)  	vmemmap = (struct page *) tmp;  	/* Take care that memory_end is set and <= vmemmap */ -	memory_end = min(memory_end ?: real_memory_size, tmp); +	memory_end = min(memory_end ?: max_physmem_end, tmp); +	max_pfn = max_low_pfn = PFN_DOWN(memory_end); +	memblock_remove(memory_end, ULONG_MAX); -	/* Fixup memory chunk array to fit into 0..memory_end */ -	for (i = 0; i < MEMORY_CHUNKS; i++) { -		struct mem_chunk *chunk = &memory_chunk[i]; - -		if (!chunk->size) -			continue; -		if (chunk->addr >= memory_end) { -			memset(chunk, 0, sizeof(*chunk)); -			continue; -		} -		if (chunk->addr + chunk->size > memory_end) -			chunk->size = memory_end - chunk->addr; -	} +	pr_notice("Max memory size: %luMB\n", memory_end >> 20);  }  static void __init setup_vmcoreinfo(void) @@ -594,89 +492,6 @@ static void __init setup_vmcoreinfo(void)  #ifdef CONFIG_CRASH_DUMP  /* - * Find suitable location for crashkernel memory - */ -static unsigned long __init find_crash_base(unsigned long crash_size, -					    char **msg) -{ -	unsigned long crash_base; -	struct mem_chunk *chunk; -	int i; - -	if (memory_chunk[0].size < crash_size) { -		*msg = "first memory chunk must be at least crashkernel size"; -		return 0; -	} -	if (OLDMEM_BASE && crash_size == OLDMEM_SIZE) -		return OLDMEM_BASE; - -	for (i = MEMORY_CHUNKS - 1; i >= 0; i--) { -		chunk = &memory_chunk[i]; -		if (chunk->size == 0) -			continue; -		if (chunk->type != CHUNK_READ_WRITE) -			continue; -		if (chunk->size < crash_size) -			continue; -		crash_base = (chunk->addr + chunk->size) - crash_size; -		if (crash_base < crash_size) -			continue; -		if (crash_base < ZFCPDUMP_HSA_SIZE_MAX) -			continue; -		if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE) -			continue; -		return crash_base; -	} -	*msg = "no suitable area found"; -	return 0; -} - -/* - * Check if crash_base and crash_size is valid - */ -static int __init verify_crash_base(unsigned long crash_base, -				    unsigned long crash_size, -				    char **msg) -{ -	struct mem_chunk *chunk; -	int i; - -	/* -	 * Because we do the swap to zero, we must have at least 'crash_size' -	 * bytes free space before crash_base -	 */ -	if (crash_size > crash_base) { -		*msg = "crashkernel offset must be greater than size"; -		return -EINVAL; -	} - -	/* First memory chunk must be at least crash_size */ -	if (memory_chunk[0].size < crash_size) { -		*msg = "first memory chunk must be at least crashkernel size"; -		return -EINVAL; -	} -	/* Check if we fit into the respective memory chunk */ -	for (i = 0; i < MEMORY_CHUNKS; i++) { -		chunk = &memory_chunk[i]; -		if (chunk->size == 0) -			continue; -		if (crash_base < chunk->addr) -			continue; -		if (crash_base >= chunk->addr + chunk->size) -			continue; -		/* we have found the memory chunk */ -		if (crash_base + crash_size > chunk->addr + chunk->size) { -			*msg = "selected memory chunk is too small for " -				"crashkernel memory"; -			return -EINVAL; -		} -		return 0; -	} -	*msg = "invalid memory range specified"; -	return -EINVAL; -} - -/*   * When kdump is enabled, we have to ensure that no memory from   * the area [0 - crashkernel memory size] and   * [crashk_res.start - crashk_res.end] is set offline. @@ -702,23 +517,44 @@ static struct notifier_block kdump_mem_nb = {  #endif  /* + * Make sure that the area behind memory_end is protected + */ +static void reserve_memory_end(void) +{ +#ifdef CONFIG_CRASH_DUMP +	if (ipl_info.type == IPL_TYPE_FCP_DUMP && +	    !OLDMEM_BASE && sclp_get_hsa_size()) { +		memory_end = sclp_get_hsa_size(); +		memory_end &= PAGE_MASK; +		memory_end_set = 1; +	} +#endif +	if (!memory_end_set) +		return; +	memblock_reserve(memory_end, ULONG_MAX); +} + +/*   * Make sure that oldmem, where the dump is stored, is protected   */  static void reserve_oldmem(void)  {  #ifdef CONFIG_CRASH_DUMP -	unsigned long real_size = 0; -	int i; - -	if (!OLDMEM_BASE) -		return; -	for (i = 0; i < MEMORY_CHUNKS; i++) { -		struct mem_chunk *chunk = &memory_chunk[i]; +	if (OLDMEM_BASE) +		/* Forget all memory above the running kdump system */ +		memblock_reserve(OLDMEM_SIZE, (phys_addr_t)ULONG_MAX); +#endif +} -		real_size = max(real_size, chunk->addr + chunk->size); -	} -	create_mem_hole(memory_chunk, OLDMEM_BASE, OLDMEM_SIZE); -	create_mem_hole(memory_chunk, OLDMEM_SIZE, real_size - OLDMEM_SIZE); +/* + * Make sure that oldmem, where the dump is stored, is protected + */ +static void remove_oldmem(void) +{ +#ifdef CONFIG_CRASH_DUMP +	if (OLDMEM_BASE) +		/* Forget all memory above the running kdump system */ +		memblock_remove(OLDMEM_SIZE, (phys_addr_t)ULONG_MAX);  #endif  } @@ -729,167 +565,132 @@ static void __init reserve_crashkernel(void)  {  #ifdef CONFIG_CRASH_DUMP  	unsigned long long crash_base, crash_size; -	char *msg = NULL; +	phys_addr_t low, high;  	int rc;  	rc = parse_crashkernel(boot_command_line, memory_end, &crash_size,  			       &crash_base); -	if (rc || crash_size == 0) -		return; +  	crash_base = ALIGN(crash_base, KEXEC_CRASH_MEM_ALIGN);  	crash_size = ALIGN(crash_size, KEXEC_CRASH_MEM_ALIGN); -	if (register_memory_notifier(&kdump_mem_nb)) +	if (rc || crash_size == 0)  		return; -	if (!crash_base) -		crash_base = find_crash_base(crash_size, &msg); -	if (!crash_base) { -		pr_info("crashkernel reservation failed: %s\n", msg); -		unregister_memory_notifier(&kdump_mem_nb); + +	if (memblock.memory.regions[0].size < crash_size) { +		pr_info("crashkernel reservation failed: %s\n", +			"first memory chunk must be at least crashkernel size");  		return;  	} -	if (verify_crash_base(crash_base, crash_size, &msg)) { -		pr_info("crashkernel reservation failed: %s\n", msg); -		unregister_memory_notifier(&kdump_mem_nb); + +	low = crash_base ?: OLDMEM_BASE; +	high = low + crash_size; +	if (low >= OLDMEM_BASE && high <= OLDMEM_BASE + OLDMEM_SIZE) { +		/* The crashkernel fits into OLDMEM, reuse OLDMEM */ +		crash_base = low; +	} else { +		/* Find suitable area in free memory */ +		low = max_t(unsigned long, crash_size, sclp_get_hsa_size()); +		high = crash_base ? crash_base + crash_size : ULONG_MAX; + +		if (crash_base && crash_base < low) { +			pr_info("crashkernel reservation failed: %s\n", +				"crash_base too low"); +			return; +		} +		low = crash_base ?: low; +		crash_base = memblock_find_in_range(low, high, crash_size, +						    KEXEC_CRASH_MEM_ALIGN); +	} + +	if (!crash_base) { +		pr_info("crashkernel reservation failed: %s\n", +			"no suitable area found");  		return;  	} + +	if (register_memory_notifier(&kdump_mem_nb)) +		return; +  	if (!OLDMEM_BASE && MACHINE_IS_VM)  		diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size));  	crashk_res.start = crash_base;  	crashk_res.end = crash_base + crash_size - 1;  	insert_resource(&iomem_resource, &crashk_res); -	create_mem_hole(memory_chunk, crash_base, crash_size); +	memblock_remove(crash_base, crash_size);  	pr_info("Reserving %lluMB of memory at %lluMB "  		"for crashkernel (System RAM: %luMB)\n", -		crash_size >> 20, crash_base >> 20, memory_end >> 20); +		crash_size >> 20, crash_base >> 20, +		(unsigned long)memblock.memory.total_size >> 20);  	os_info_crashkernel_add(crash_base, crash_size);  #endif  } -static void __init setup_memory(void) +/* + * Reserve the initrd from being used by memblock + */ +static void __init reserve_initrd(void)  { -        unsigned long bootmap_size; -	unsigned long start_pfn, end_pfn; -	int i; +#ifdef CONFIG_BLK_DEV_INITRD +	initrd_start = INITRD_START; +	initrd_end = initrd_start + INITRD_SIZE; +	memblock_reserve(INITRD_START, INITRD_SIZE); +#endif +} -	/* -	 * partially used pages are not usable - thus -	 * we are rounding upwards: -	 */ +/* + * Check for initrd being in usable memory + */ +static void __init check_initrd(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD +	if (INITRD_START && INITRD_SIZE && +	    !memblock_is_region_memory(INITRD_START, INITRD_SIZE)) { +		pr_err("initrd does not fit memory.\n"); +		memblock_free(INITRD_START, INITRD_SIZE); +		initrd_start = initrd_end = 0; +	} +#endif +} + +/* + * Reserve all kernel text + */ +static void __init reserve_kernel(void) +{ +	unsigned long start_pfn;  	start_pfn = PFN_UP(__pa(&_end)); -	end_pfn = max_pfn = PFN_DOWN(memory_end); -#ifdef CONFIG_BLK_DEV_INITRD  	/* -	 * Move the initrd in case the bitmap of the bootmem allocater -	 * would overwrite it. +	 * Reserve memory used for lowcore/command line/kernel image.  	 */ +	memblock_reserve(0, (unsigned long)_ehead); +	memblock_reserve((unsigned long)_stext, PFN_PHYS(start_pfn) +			 - (unsigned long)_stext); +} -	if (INITRD_START && INITRD_SIZE) { -		unsigned long bmap_size; -		unsigned long start; - -		bmap_size = bootmem_bootmap_pages(end_pfn - start_pfn + 1); -		bmap_size = PFN_PHYS(bmap_size); - -		if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) { -			start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE; - +static void __init reserve_elfcorehdr(void) +{  #ifdef CONFIG_CRASH_DUMP -			if (OLDMEM_BASE) { -				/* Move initrd behind kdump oldmem */ -				if (start + INITRD_SIZE > OLDMEM_BASE && -				    start < OLDMEM_BASE + OLDMEM_SIZE) -					start = OLDMEM_BASE + OLDMEM_SIZE; -			} -#endif -			if (start + INITRD_SIZE > memory_end) { -				pr_err("initrd extends beyond end of " -				       "memory (0x%08lx > 0x%08lx) " -				       "disabling initrd\n", -				       start + INITRD_SIZE, memory_end); -				INITRD_START = INITRD_SIZE = 0; -			} else { -				pr_info("Moving initrd (0x%08lx -> " -					"0x%08lx, size: %ld)\n", -					INITRD_START, start, INITRD_SIZE); -				memmove((void *) start, (void *) INITRD_START, -					INITRD_SIZE); -				INITRD_START = start; -			} -		} -	} +	if (is_kdump_kernel()) +		memblock_reserve(elfcorehdr_addr - OLDMEM_BASE, +				 PAGE_ALIGN(elfcorehdr_size));  #endif +} -	/* -	 * Initialize the boot-time allocator -	 */ -	bootmap_size = init_bootmem(start_pfn, end_pfn); +static void __init setup_memory(void) +{ +	struct memblock_region *reg;  	/* -	 * Register RAM areas with the bootmem allocator. +	 * Init storage key for present memory  	 */ - -	for (i = 0; i < MEMORY_CHUNKS; i++) { -		unsigned long start_chunk, end_chunk, pfn; - -		if (!memory_chunk[i].size) -			continue; -		start_chunk = PFN_DOWN(memory_chunk[i].addr); -		end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size); -		end_chunk = min(end_chunk, end_pfn); -		if (start_chunk >= end_chunk) -			continue; -		memblock_add_node(PFN_PHYS(start_chunk), -				  PFN_PHYS(end_chunk - start_chunk), 0); -		pfn = max(start_chunk, start_pfn); -		storage_key_init_range(PFN_PHYS(pfn), PFN_PHYS(end_chunk)); +	for_each_memblock(memory, reg) { +		storage_key_init_range(reg->base, reg->base + reg->size);  	} -  	psw_set_key(PAGE_DEFAULT_KEY); -	free_bootmem_with_active_regions(0, max_pfn); - -	/* -	 * Reserve memory used for lowcore/command line/kernel image. -	 */ -	reserve_bootmem(0, (unsigned long)_ehead, BOOTMEM_DEFAULT); -	reserve_bootmem((unsigned long)_stext, -			PFN_PHYS(start_pfn) - (unsigned long)_stext, -			BOOTMEM_DEFAULT); -	/* -	 * Reserve the bootmem bitmap itself as well. We do this in two -	 * steps (first step was init_bootmem()) because this catches -	 * the (very unlikely) case of us accidentally initializing the -	 * bootmem allocator with an invalid RAM area. -	 */ -	reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size, -			BOOTMEM_DEFAULT); - -#ifdef CONFIG_CRASH_DUMP -	if (crashk_res.start) -		reserve_bootmem(crashk_res.start, -				crashk_res.end - crashk_res.start + 1, -				BOOTMEM_DEFAULT); -	if (is_kdump_kernel()) -		reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE, -				PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT); -#endif -#ifdef CONFIG_BLK_DEV_INITRD -	if (INITRD_START && INITRD_SIZE) { -		if (INITRD_START + INITRD_SIZE <= memory_end) { -			reserve_bootmem(INITRD_START, INITRD_SIZE, -					BOOTMEM_DEFAULT); -			initrd_start = INITRD_START; -			initrd_end = initrd_start + INITRD_SIZE; -		} else { -			pr_err("initrd extends beyond end of " -			       "memory (0x%08lx > 0x%08lx) " -			       "disabling initrd\n", -			       initrd_start + INITRD_SIZE, memory_end); -			initrd_start = initrd_end = 0; -		} -	} -#endif +	/* Only cosmetics */ +	memblock_enforce_memory_limit(memblock_end_of_DRAM());  }  /* @@ -1038,29 +839,47 @@ void __init setup_arch(char **cmdline_p)          ROOT_DEV = Root_RAM0; +	/* Is init_mm really needed? */  	init_mm.start_code = PAGE_OFFSET;  	init_mm.end_code = (unsigned long) &_etext;  	init_mm.end_data = (unsigned long) &_edata;  	init_mm.brk = (unsigned long) &_end; -	if (MACHINE_HAS_MVCOS) -		memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess)); -	else -		memcpy(&uaccess, &uaccess_std, sizeof(uaccess)); -  	parse_early_param(); -	detect_memory_layout(memory_chunk, memory_end);  	os_info_init();  	setup_ipl(); + +	/* Do some memory reservations *before* memory is added to memblock */ +	reserve_memory_end();  	reserve_oldmem(); +	reserve_kernel(); +	reserve_initrd(); +	reserve_elfcorehdr(); +	memblock_allow_resize(); + +	/* Get information about *all* installed memory */ +	detect_memory_memblock(); + +	remove_oldmem(); + +	/* +	 * Make sure all chunks are MAX_ORDER aligned so we don't need the +	 * extra checks that HOLES_IN_ZONE would require. +	 * +	 * Is this still required? +	 */ +	memblock_trim_memory(1UL << (MAX_ORDER - 1 + PAGE_SHIFT)); +  	setup_memory_end(); -	setup_addressing_mode(); -	reserve_crashkernel();  	setup_memory(); + +	check_initrd(); +	reserve_crashkernel(); +  	setup_resources();  	setup_vmcoreinfo();  	setup_lowcore(); - +	smp_fill_possible_mask();          cpu_init();  	s390_init_cpu_topology(); @@ -1081,3 +900,35 @@ void __init setup_arch(char **cmdline_p)  	/* Setup zfcpdump support */  	setup_zfcpdump();  } + +#ifdef CONFIG_32BIT +static int no_removal_warning __initdata; + +static int __init parse_no_removal_warning(char *str) +{ +	no_removal_warning = 1; +	return 0; +} +__setup("no_removal_warning", parse_no_removal_warning); + +static int __init removal_warning(void) +{ +	if (no_removal_warning) +		return 0; +	printk(KERN_ALERT "\n\n"); +	printk(KERN_CONT "Warning - you are using a 31 bit kernel!\n\n"); +	printk(KERN_CONT "We plan to remove 31 bit kernel support from the kernel sources in March 2015.\n"); +	printk(KERN_CONT "Currently we assume that nobody is using the 31 bit kernel on old 31 bit\n"); +	printk(KERN_CONT "hardware anymore. If you think that the code should not be removed and also\n"); +	printk(KERN_CONT "future versions of the Linux kernel should be able to run in 31 bit mode\n"); +	printk(KERN_CONT "please let us know. Please write to:\n"); +	printk(KERN_CONT "linux390@de.ibm.com (mail address) and/or\n"); +	printk(KERN_CONT "linux-s390@vger.kernel.org (mailing list).\n\n"); +	printk(KERN_CONT "Thank you!\n\n"); +	printk(KERN_CONT "If this kernel runs on a 64 bit machine you may consider using a 64 bit kernel.\n"); +	printk(KERN_CONT "This message can be disabled with the \"no_removal_warning\" kernel parameter.\n"); +	schedule_timeout_uninterruptible(300 * HZ); +	return 0; +} +early_initcall(removal_warning); +#endif diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index c45becf82e0..42b49f9e19b 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -57,40 +57,48 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)  	/* Copy a 'clean' PSW mask to the user to avoid leaking  	   information about whether PER is currently on.  */ -	user_sregs.regs.psw.mask = psw_user_bits | -		(regs->psw.mask & PSW_MASK_USER); +	user_sregs.regs.psw.mask = PSW_USER_BITS | +		(regs->psw.mask & (PSW_MASK_USER | PSW_MASK_RI));  	user_sregs.regs.psw.addr = regs->psw.addr;  	memcpy(&user_sregs.regs.gprs, ®s->gprs, sizeof(sregs->regs.gprs));  	memcpy(&user_sregs.regs.acrs, current->thread.acrs, -	       sizeof(sregs->regs.acrs)); +	       sizeof(user_sregs.regs.acrs));  	/*   	 * We have to store the fp registers to current->thread.fp_regs  	 * to merge them with the emulated registers.  	 */ -	save_fp_regs(¤t->thread.fp_regs); +	save_fp_ctl(¤t->thread.fp_regs.fpc); +	save_fp_regs(current->thread.fp_regs.fprs);  	memcpy(&user_sregs.fpregs, ¤t->thread.fp_regs, -	       sizeof(s390_fp_regs)); -	return __copy_to_user(sregs, &user_sregs, sizeof(_sigregs)); +	       sizeof(user_sregs.fpregs)); +	if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs))) +		return -EFAULT; +	return 0;  } -/* Returns positive number on error */  static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)  { -	int err;  	_sigregs user_sregs;  	/* Alwys make any pending restarted system call return -EINTR */  	current_thread_info()->restart_block.fn = do_no_restart_syscall; -	err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); -	if (err) -		return err; -	/* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ -	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | -		(user_sregs.regs.psw.mask & PSW_MASK_USER); +	if (__copy_from_user(&user_sregs, sregs, sizeof(user_sregs))) +		return -EFAULT; + +	if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW_MASK_RI)) +		return -EINVAL; + +	/* Loading the floating-point-control word can fail. Do that first. */ +	if (restore_fp_ctl(&user_sregs.fpregs.fpc)) +		return -EINVAL; + +	/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */ +	regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) | +		(user_sregs.regs.psw.mask & (PSW_MASK_USER | PSW_MASK_RI));  	/* Check for invalid user address space control. */ -	if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) -		regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | +	if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME) +		regs->psw.mask = PSW_ASC_PRIMARY |  			(regs->psw.mask & ~PSW_MASK_ASC);  	/* Check for invalid amode */  	if (regs->psw.mask & PSW_MASK_EA) @@ -98,15 +106,14 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)  	regs->psw.addr = user_sregs.regs.psw.addr;  	memcpy(®s->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));  	memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, -	       sizeof(sregs->regs.acrs)); +	       sizeof(current->thread.acrs));  	restore_access_regs(current->thread.acrs);  	memcpy(¤t->thread.fp_regs, &user_sregs.fpregs, -	       sizeof(s390_fp_regs)); -	current->thread.fp_regs.fpc &= FPC_VALID_MASK; +	       sizeof(current->thread.fp_regs)); -	restore_fp_regs(¤t->thread.fp_regs); -	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */ +	restore_fp_regs(current->thread.fp_regs.fprs); +	clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */  	return 0;  } @@ -224,7 +231,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,  	regs->gprs[15] = (unsigned long) frame;  	/* Force default amode and default user address space control. */  	regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | -		(psw_user_bits & PSW_MASK_ASC) | +		(PSW_USER_BITS & PSW_MASK_ASC) |  		(regs->psw.mask & ~PSW_MASK_ASC);  	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; @@ -295,7 +302,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  	regs->gprs[15] = (unsigned long) frame;  	/* Force default amode and default user address space control. */  	regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | -		(psw_user_bits & PSW_MASK_ASC) | +		(PSW_USER_BITS & PSW_MASK_ASC) |  		(regs->psw.mask & ~PSW_MASK_ASC);  	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; @@ -349,7 +356,7 @@ void do_signal(struct pt_regs *regs)  	 * call information.  	 */  	current_thread_info()->system_call = -		test_thread_flag(TIF_SYSCALL) ? regs->int_code : 0; +		test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0;  	signr = get_signal_to_deliver(&info, &ka, regs, NULL);  	if (signr > 0) { @@ -377,7 +384,7 @@ void do_signal(struct pt_regs *regs)  			}  		}  		/* No longer in a system call */ -		clear_thread_flag(TIF_SYSCALL); +		clear_pt_regs_flag(regs, PIF_SYSCALL);  		if (is_compat_task())  			handle_signal32(signr, &ka, &info, oldset, regs); @@ -387,7 +394,7 @@ void do_signal(struct pt_regs *regs)  	}  	/* No handlers present - check for system call restart */ -	clear_thread_flag(TIF_SYSCALL); +	clear_pt_regs_flag(regs, PIF_SYSCALL);  	if (current_thread_info()->system_call) {  		regs->int_code = current_thread_info()->system_call;  		switch (regs->gprs[2]) { @@ -400,9 +407,9 @@ void do_signal(struct pt_regs *regs)  		case -ERESTARTNOINTR:  			/* Restart system call with magic TIF bit. */  			regs->gprs[2] = regs->orig_gpr2; -			set_thread_flag(TIF_SYSCALL); +			set_pt_regs_flag(regs, PIF_SYSCALL);  			if (test_thread_flag(TIF_SINGLE_STEP)) -				set_thread_flag(TIF_PER_TRAP); +				clear_pt_regs_flag(regs, PIF_PER_TRAP);  			break;  		}  	} diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 1a4313a1b60..243c7e51260 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -59,7 +59,7 @@ enum {  };  struct pcpu { -	struct cpu cpu; +	struct cpu *cpu;  	struct _lowcore *lowcore;	/* lowcore page(s) for the cpu */  	unsigned long async_stack;	/* async stack for the cpu */  	unsigned long panic_stack;	/* panic stack for the cpu */ @@ -82,21 +82,6 @@ DEFINE_MUTEX(smp_cpu_state_mutex);  /*   * Signal processor helper functions.   */ -static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status) -{ -	register unsigned int reg1 asm ("1") = parm; -	int cc; - -	asm volatile( -		"	sigp	%1,%2,0(%3)\n" -		"	ipm	%0\n" -		"	srl	%0,28\n" -		: "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc"); -	if (status && cc == 1) -		*status = reg1; -	return cc; -} -  static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)  {  	int cc; @@ -159,9 +144,9 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit)  {  	int order; -	set_bit(ec_bit, &pcpu->ec_mask); -	order = pcpu_running(pcpu) ? -		SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL; +	if (test_and_set_bit(ec_bit, &pcpu->ec_mask)) +		return; +	order = pcpu_running(pcpu) ? SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL;  	pcpu_sigp_retry(pcpu, order, 0);  } @@ -185,6 +170,7 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)  	lc->panic_stack = pcpu->panic_stack + PAGE_SIZE  		- STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);  	lc->cpu_nr = cpu; +	lc->spinlock_lockval = arch_spin_lockval(cpu);  #ifndef CONFIG_64BIT  	if (MACHINE_HAS_IEEE) {  		lc->extended_save_area_addr = get_zeroed_page(GFP_KERNEL); @@ -236,8 +222,12 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)  {  	struct _lowcore *lc = pcpu->lowcore; +	if (MACHINE_HAS_TLB_LC) +		cpumask_set_cpu(cpu, &init_mm.context.cpu_attach_mask); +	cpumask_set_cpu(cpu, mm_cpumask(&init_mm));  	atomic_inc(&init_mm.context.attach_count);  	lc->cpu_nr = cpu; +	lc->spinlock_lockval = arch_spin_lockval(cpu);  	lc->percpu_offset = __per_cpu_offset[cpu];  	lc->kernel_asce = S390_lowcore.kernel_asce;  	lc->machine_flags = S390_lowcore.machine_flags; @@ -283,7 +273,7 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *),  	struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices];  	unsigned long source_cpu = stap(); -	__load_psw_mask(psw_kernel_bits); +	__load_psw_mask(PSW_KERNEL_BITS);  	if (pcpu->address == source_cpu)  		func(data);	/* should not return */  	/* Stop target cpu (if func returns this stops the current cpu). */ @@ -395,7 +385,7 @@ void smp_send_stop(void)  	int cpu;  	/* Disable all interrupts/machine checks */ -	__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT); +	__load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT);  	trace_hardirqs_off();  	debug_set_critical(); @@ -415,15 +405,6 @@ void smp_send_stop(void)  }  /* - * Stop the current cpu. - */ -void smp_stop_cpu(void) -{ -	pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0); -	for (;;) ; -} - -/*   * This is the main routine where commands issued by other   * cpus are handled.   */ @@ -531,10 +512,7 @@ void smp_ctl_clear_bit(int cr, int bit)  }  EXPORT_SYMBOL(smp_ctl_clear_bit); -#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP) - -struct save_area *zfcpdump_save_areas[NR_CPUS + 1]; -EXPORT_SYMBOL_GPL(zfcpdump_save_areas); +#ifdef CONFIG_CRASH_DUMP  static void __init smp_get_save_area(int cpu, u16 address)  { @@ -546,23 +524,15 @@ static void __init smp_get_save_area(int cpu, u16 address)  	if (!OLDMEM_BASE && (address == boot_cpu_address ||  			     ipl_info.type != IPL_TYPE_FCP_DUMP))  		return; -	if (cpu >= NR_CPUS) { -		pr_warning("CPU %i exceeds the maximum %i and is excluded " -			   "from the dump\n", cpu, NR_CPUS - 1); -		return; -	} -	save_area = kmalloc(sizeof(struct save_area), GFP_KERNEL); +	save_area = dump_save_area_create(cpu);  	if (!save_area)  		panic("could not allocate memory for save area\n"); -	zfcpdump_save_areas[cpu] = save_area; -#ifdef CONFIG_CRASH_DUMP  	if (address == boot_cpu_address) {  		/* Copy the registers of the boot cpu. */  		copy_oldmem_page(1, (void *) save_area, sizeof(*save_area),  				 SAVE_AREA_BASE - PAGE_SIZE, 0);  		return;  	} -#endif  	/* Get the registers of a non-boot cpu. */  	__pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL);  	memcpy_real(save_area, lc + SAVE_AREA_BASE, sizeof(*save_area)); @@ -579,11 +549,11 @@ int smp_store_status(int cpu)  	return 0;  } -#else /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ +#else /* CONFIG_CRASH_DUMP */  static inline void smp_get_save_area(int cpu, u16 address) { } -#endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ +#endif /* CONFIG_CRASH_DUMP */  void smp_cpu_set_polarization(int cpu, int val)  { @@ -693,7 +663,7 @@ static void smp_start_secondary(void *cpuvoid)  	S390_lowcore.restart_source = -1UL;  	restore_access_regs(S390_lowcore.access_regs_save_area);  	__ctl_load(S390_lowcore.cregs_save_area, 0, 15); -	__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT); +	__load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT);  	cpu_init();  	preempt_disable();  	init_cpu_timer(); @@ -730,18 +700,14 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)  	return 0;  } -static int __init setup_possible_cpus(char *s) -{ -	int max, cpu; +static unsigned int setup_possible_cpus __initdata; -	if (kstrtoint(s, 0, &max) < 0) -		return 0; -	init_cpu_possible(cpumask_of(0)); -	for (cpu = 1; cpu < max && cpu < nr_cpu_ids; cpu++) -		set_cpu_possible(cpu, true); +static int __init _setup_possible_cpus(char *s) +{ +	get_option(&s, &setup_possible_cpus);  	return 0;  } -early_param("possible_cpus", setup_possible_cpus); +early_param("possible_cpus", _setup_possible_cpus);  #ifdef CONFIG_HOTPLUG_CPU @@ -773,6 +739,9 @@ void __cpu_die(unsigned int cpu)  		cpu_relax();  	pcpu_free_lowcore(pcpu);  	atomic_dec(&init_mm.context.attach_count); +	cpumask_clear_cpu(cpu, mm_cpumask(&init_mm)); +	if (MACHINE_HAS_TLB_LC) +		cpumask_clear_cpu(cpu, &init_mm.context.cpu_attach_mask);  }  void __noreturn cpu_die(void) @@ -784,13 +753,24 @@ void __noreturn cpu_die(void)  #endif /* CONFIG_HOTPLUG_CPU */ +void __init smp_fill_possible_mask(void) +{ +	unsigned int possible, sclp, cpu; + +	sclp = sclp_get_max_cpu() ?: nr_cpu_ids; +	possible = setup_possible_cpus ?: nr_cpu_ids; +	possible = min(possible, sclp); +	for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++) +		set_cpu_possible(cpu, true); +} +  void __init smp_prepare_cpus(unsigned int max_cpus)  {  	/* request the 0x1201 emergency signal external interrupt */ -	if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) +	if (register_external_irq(EXT_IRQ_EMERGENCY_SIG, do_ext_call_interrupt))  		panic("Couldn't request external interrupt 0x1201");  	/* request the 0x1202 external call external interrupt */ -	if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0) +	if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt))  		panic("Couldn't request external interrupt 0x1202");  	smp_detect_cpus();  } @@ -820,6 +800,7 @@ void __init smp_cpus_done(unsigned int max_cpus)  void __init smp_setup_processor_id(void)  {  	S390_lowcore.cpu_nr = 0; +	S390_lowcore.spinlock_lockval = arch_spin_lockval(0);  }  /* @@ -929,7 +910,7 @@ static ssize_t show_idle_count(struct device *dev,  		idle_count = ACCESS_ONCE(idle->idle_count);  		if (ACCESS_ONCE(idle->clock_idle_enter))  			idle_count++; -	} while ((sequence & 1) || (idle->sequence != sequence)); +	} while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));  	return sprintf(buf, "%llu\n", idle_count);  }  static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); @@ -947,7 +928,7 @@ static ssize_t show_idle_time(struct device *dev,  		idle_time = ACCESS_ONCE(idle->idle_time);  		idle_enter = ACCESS_ONCE(idle->clock_idle_enter);  		idle_exit = ACCESS_ONCE(idle->clock_idle_exit); -	} while ((sequence & 1) || (idle->sequence != sequence)); +	} while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));  	idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;  	return sprintf(buf, "%llu\n", idle_time >> 12);  } @@ -967,7 +948,7 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action,  			  void *hcpu)  {  	unsigned int cpu = (unsigned int)(long)hcpu; -	struct cpu *c = &pcpu_devices[cpu].cpu; +	struct cpu *c = pcpu_devices[cpu].cpu;  	struct device *s = &c->dev;  	int err = 0; @@ -984,10 +965,15 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action,  static int smp_add_present_cpu(int cpu)  { -	struct cpu *c = &pcpu_devices[cpu].cpu; -	struct device *s = &c->dev; +	struct device *s; +	struct cpu *c;  	int rc; +	c = kzalloc(sizeof(*c), GFP_KERNEL); +	if (!c) +		return -ENOMEM; +	pcpu_devices[cpu].cpu = c; +	s = &c->dev;  	c->hotpluggable = 1;  	rc = register_cpu(c, cpu);  	if (rc) @@ -1054,19 +1040,24 @@ static DEVICE_ATTR(rescan, 0200, NULL, rescan_store);  static int __init s390_smp_init(void)  { -	int cpu, rc; +	int cpu, rc = 0; -	hotcpu_notifier(smp_cpu_notify, 0);  #ifdef CONFIG_HOTPLUG_CPU  	rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan);  	if (rc)  		return rc;  #endif +	cpu_notifier_register_begin();  	for_each_present_cpu(cpu) {  		rc = smp_add_present_cpu(cpu);  		if (rc) -			return rc; +			goto out;  	} -	return 0; + +	__hotcpu_notifier(smp_cpu_notify, 0); + +out: +	cpu_notifier_register_done(); +	return rc;  }  subsys_initcall(s390_smp_init); diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 913410bd74a..fe5cdf29a00 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -9,347 +9,350 @@  #define NI_SYSCALL SYSCALL(sys_ni_syscall,sys_ni_syscall,sys_ni_syscall)  NI_SYSCALL							/* 0 */ -SYSCALL(sys_exit,sys_exit,sys32_exit_wrapper) +SYSCALL(sys_exit,sys_exit,compat_sys_exit)  SYSCALL(sys_fork,sys_fork,sys_fork) -SYSCALL(sys_read,sys_read,sys32_read_wrapper) -SYSCALL(sys_write,sys_write,sys32_write_wrapper) +SYSCALL(sys_read,sys_read,compat_sys_s390_read) +SYSCALL(sys_write,sys_write,compat_sys_s390_write)  SYSCALL(sys_open,sys_open,compat_sys_open)			/* 5 */ -SYSCALL(sys_close,sys_close,sys32_close_wrapper) +SYSCALL(sys_close,sys_close,compat_sys_close)  SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall) -SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) -SYSCALL(sys_link,sys_link,sys32_link_wrapper) -SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper)		/* 10 */ -SYSCALL(sys_execve,sys_execve,sys32_execve_wrapper) -SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) -SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper)		/* old time syscall */ -SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) -SYSCALL(sys_chmod,sys_chmod,sys32_chmod_wrapper)		/* 15 */ -SYSCALL(sys_lchown16,sys_ni_syscall,sys32_lchown16_wrapper)	/* old lchown16 syscall*/ +SYSCALL(sys_creat,sys_creat,compat_sys_creat) +SYSCALL(sys_link,sys_link,compat_sys_link) +SYSCALL(sys_unlink,sys_unlink,compat_sys_unlink)		/* 10 */ +SYSCALL(sys_execve,sys_execve,compat_sys_execve) +SYSCALL(sys_chdir,sys_chdir,compat_sys_chdir) +SYSCALL(sys_time,sys_ni_syscall,compat_sys_time)		/* old time syscall */ +SYSCALL(sys_mknod,sys_mknod,compat_sys_mknod) +SYSCALL(sys_chmod,sys_chmod,compat_sys_chmod)			/* 15 */ +SYSCALL(sys_lchown16,sys_ni_syscall,compat_sys_s390_lchown16)	/* old lchown16 syscall*/  NI_SYSCALL							/* old break syscall holder */  NI_SYSCALL							/* old stat syscall holder */  SYSCALL(sys_lseek,sys_lseek,compat_sys_lseek)  SYSCALL(sys_getpid,sys_getpid,sys_getpid)			/* 20 */ -SYSCALL(sys_mount,sys_mount,sys32_mount_wrapper) -SYSCALL(sys_oldumount,sys_oldumount,sys32_oldumount_wrapper) -SYSCALL(sys_setuid16,sys_ni_syscall,sys32_setuid16_wrapper)	/* old setuid16 syscall*/ -SYSCALL(sys_getuid16,sys_ni_syscall,sys32_getuid16)		/* old getuid16 syscall*/ -SYSCALL(sys_stime,sys_ni_syscall,sys32_stime_wrapper)		/* 25 old stime syscall */ -SYSCALL(sys_ptrace,sys_ptrace,sys32_ptrace_wrapper) -SYSCALL(sys_alarm,sys_alarm,sys32_alarm_wrapper) +SYSCALL(sys_mount,sys_mount,compat_sys_mount) +SYSCALL(sys_oldumount,sys_oldumount,compat_sys_oldumount) +SYSCALL(sys_setuid16,sys_ni_syscall,compat_sys_s390_setuid16)	/* old setuid16 syscall*/ +SYSCALL(sys_getuid16,sys_ni_syscall,compat_sys_s390_getuid16)	/* old getuid16 syscall*/ +SYSCALL(sys_stime,sys_ni_syscall,compat_sys_stime)		/* 25 old stime syscall */ +SYSCALL(sys_ptrace,sys_ptrace,compat_sys_ptrace) +SYSCALL(sys_alarm,sys_alarm,compat_sys_alarm)  NI_SYSCALL							/* old fstat syscall */  SYSCALL(sys_pause,sys_pause,sys_pause) -SYSCALL(sys_utime,sys_utime,compat_sys_utime_wrapper)		/* 30 */ +SYSCALL(sys_utime,sys_utime,compat_sys_utime)		/* 30 */  NI_SYSCALL							/* old stty syscall */  NI_SYSCALL							/* old gtty syscall */ -SYSCALL(sys_access,sys_access,sys32_access_wrapper) -SYSCALL(sys_nice,sys_nice,sys32_nice_wrapper) +SYSCALL(sys_access,sys_access,compat_sys_access) +SYSCALL(sys_nice,sys_nice,compat_sys_nice)  NI_SYSCALL							/* 35 old ftime syscall */  SYSCALL(sys_sync,sys_sync,sys_sync) -SYSCALL(sys_kill,sys_kill,sys32_kill_wrapper) -SYSCALL(sys_rename,sys_rename,sys32_rename_wrapper) -SYSCALL(sys_mkdir,sys_mkdir,sys32_mkdir_wrapper) -SYSCALL(sys_rmdir,sys_rmdir,sys32_rmdir_wrapper)		/* 40 */ -SYSCALL(sys_dup,sys_dup,sys32_dup_wrapper) -SYSCALL(sys_pipe,sys_pipe,sys32_pipe_wrapper) -SYSCALL(sys_times,sys_times,compat_sys_times_wrapper) +SYSCALL(sys_kill,sys_kill,compat_sys_kill) +SYSCALL(sys_rename,sys_rename,compat_sys_rename) +SYSCALL(sys_mkdir,sys_mkdir,compat_sys_mkdir) +SYSCALL(sys_rmdir,sys_rmdir,compat_sys_rmdir)		/* 40 */ +SYSCALL(sys_dup,sys_dup,compat_sys_dup) +SYSCALL(sys_pipe,sys_pipe,compat_sys_pipe) +SYSCALL(sys_times,sys_times,compat_sys_times)  NI_SYSCALL							/* old prof syscall */ -SYSCALL(sys_brk,sys_brk,sys32_brk_wrapper)			/* 45 */ -SYSCALL(sys_setgid16,sys_ni_syscall,sys32_setgid16_wrapper)	/* old setgid16 syscall*/ -SYSCALL(sys_getgid16,sys_ni_syscall,sys32_getgid16)		/* old getgid16 syscall*/ -SYSCALL(sys_signal,sys_signal,sys32_signal_wrapper) -SYSCALL(sys_geteuid16,sys_ni_syscall,sys32_geteuid16)		/* old geteuid16 syscall */ -SYSCALL(sys_getegid16,sys_ni_syscall,sys32_getegid16)		/* 50 old getegid16 syscall */ -SYSCALL(sys_acct,sys_acct,sys32_acct_wrapper) -SYSCALL(sys_umount,sys_umount,sys32_umount_wrapper) +SYSCALL(sys_brk,sys_brk,compat_sys_brk)				/* 45 */ +SYSCALL(sys_setgid16,sys_ni_syscall,compat_sys_s390_setgid16)	/* old setgid16 syscall*/ +SYSCALL(sys_getgid16,sys_ni_syscall,compat_sys_s390_getgid16)	/* old getgid16 syscall*/ +SYSCALL(sys_signal,sys_signal,compat_sys_signal) +SYSCALL(sys_geteuid16,sys_ni_syscall,compat_sys_s390_geteuid16)	/* old geteuid16 syscall */ +SYSCALL(sys_getegid16,sys_ni_syscall,compat_sys_s390_getegid16)	/* 50 old getegid16 syscall */ +SYSCALL(sys_acct,sys_acct,compat_sys_acct) +SYSCALL(sys_umount,sys_umount,compat_sys_umount)  NI_SYSCALL							/* old lock syscall */ -SYSCALL(sys_ioctl,sys_ioctl,compat_sys_ioctl_wrapper) -SYSCALL(sys_fcntl,sys_fcntl,compat_sys_fcntl_wrapper)		/* 55 */ +SYSCALL(sys_ioctl,sys_ioctl,compat_sys_ioctl) +SYSCALL(sys_fcntl,sys_fcntl,compat_sys_fcntl)		/* 55 */  NI_SYSCALL							/* intel mpx syscall */ -SYSCALL(sys_setpgid,sys_setpgid,sys32_setpgid_wrapper) +SYSCALL(sys_setpgid,sys_setpgid,compat_sys_setpgid)  NI_SYSCALL							/* old ulimit syscall */  NI_SYSCALL							/* old uname syscall */ -SYSCALL(sys_umask,sys_umask,sys32_umask_wrapper)		/* 60 */ -SYSCALL(sys_chroot,sys_chroot,sys32_chroot_wrapper) -SYSCALL(sys_ustat,sys_ustat,sys32_ustat_wrapper) -SYSCALL(sys_dup2,sys_dup2,sys32_dup2_wrapper) +SYSCALL(sys_umask,sys_umask,compat_sys_umask)			/* 60 */ +SYSCALL(sys_chroot,sys_chroot,compat_sys_chroot) +SYSCALL(sys_ustat,sys_ustat,compat_sys_ustat) +SYSCALL(sys_dup2,sys_dup2,compat_sys_dup2)  SYSCALL(sys_getppid,sys_getppid,sys_getppid)  SYSCALL(sys_getpgrp,sys_getpgrp,sys_getpgrp)			/* 65 */  SYSCALL(sys_setsid,sys_setsid,sys_setsid)  SYSCALL(sys_sigaction,sys_sigaction,compat_sys_sigaction)  NI_SYSCALL							/* old sgetmask syscall*/  NI_SYSCALL							/* old ssetmask syscall*/ -SYSCALL(sys_setreuid16,sys_ni_syscall,sys32_setreuid16_wrapper)	/* old setreuid16 syscall */ -SYSCALL(sys_setregid16,sys_ni_syscall,sys32_setregid16_wrapper)	/* old setregid16 syscall */ -SYSCALL(sys_sigsuspend,sys_sigsuspend,sys_sigsuspend_wrapper) -SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending_wrapper) -SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper) -SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper)	/* 75 */ -SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper) +SYSCALL(sys_setreuid16,sys_ni_syscall,compat_sys_s390_setreuid16) /* old setreuid16 syscall */ +SYSCALL(sys_setregid16,sys_ni_syscall,compat_sys_s390_setregid16) /* old setregid16 syscall */ +SYSCALL(sys_sigsuspend,sys_sigsuspend,compat_sys_sigsuspend) +SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending) +SYSCALL(sys_sethostname,sys_sethostname,compat_sys_sethostname) +SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit)	/* 75 */ +SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit)  SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage) -SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday_wrapper) -SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday_wrapper) -SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper)	/* 80 old getgroups16 syscall */ -SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper)	/* old setgroups16 syscall */ +SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday) +SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday) +SYSCALL(sys_getgroups16,sys_ni_syscall,compat_sys_s390_getgroups16)	/* 80 old getgroups16 syscall */ +SYSCALL(sys_setgroups16,sys_ni_syscall,compat_sys_s390_setgroups16)	/* old setgroups16 syscall */  NI_SYSCALL							/* old select syscall */ -SYSCALL(sys_symlink,sys_symlink,sys32_symlink_wrapper) +SYSCALL(sys_symlink,sys_symlink,compat_sys_symlink)  NI_SYSCALL							/* old lstat syscall */ -SYSCALL(sys_readlink,sys_readlink,sys32_readlink_wrapper)	/* 85 */ -SYSCALL(sys_uselib,sys_uselib,sys32_uselib_wrapper) -SYSCALL(sys_swapon,sys_swapon,sys32_swapon_wrapper) -SYSCALL(sys_reboot,sys_reboot,sys32_reboot_wrapper) -SYSCALL(sys_ni_syscall,sys_ni_syscall,old32_readdir_wrapper)	/* old readdir syscall */ -SYSCALL(sys_old_mmap,sys_old_mmap,old32_mmap_wrapper)		/* 90 */ -SYSCALL(sys_munmap,sys_munmap,sys32_munmap_wrapper) +SYSCALL(sys_readlink,sys_readlink,compat_sys_readlink)		/* 85 */ +SYSCALL(sys_uselib,sys_uselib,compat_sys_uselib) +SYSCALL(sys_swapon,sys_swapon,compat_sys_swapon) +SYSCALL(sys_reboot,sys_reboot,compat_sys_reboot) +SYSCALL(sys_ni_syscall,sys_ni_syscall,compat_sys_old_readdir)	/* old readdir syscall */ +SYSCALL(sys_old_mmap,sys_old_mmap,compat_sys_s390_old_mmap)	/* 90 */ +SYSCALL(sys_munmap,sys_munmap,compat_sys_munmap)  SYSCALL(sys_truncate,sys_truncate,compat_sys_truncate)  SYSCALL(sys_ftruncate,sys_ftruncate,compat_sys_ftruncate) -SYSCALL(sys_fchmod,sys_fchmod,sys32_fchmod_wrapper) -SYSCALL(sys_fchown16,sys_ni_syscall,sys32_fchown16_wrapper)	/* 95 old fchown16 syscall*/ -SYSCALL(sys_getpriority,sys_getpriority,sys32_getpriority_wrapper) -SYSCALL(sys_setpriority,sys_setpriority,sys32_setpriority_wrapper) +SYSCALL(sys_fchmod,sys_fchmod,compat_sys_fchmod) +SYSCALL(sys_fchown16,sys_ni_syscall,compat_sys_s390_fchown16)	/* 95 old fchown16 syscall*/ +SYSCALL(sys_getpriority,sys_getpriority,compat_sys_getpriority) +SYSCALL(sys_setpriority,sys_setpriority,compat_sys_setpriority)  NI_SYSCALL							/* old profil syscall */ -SYSCALL(sys_statfs,sys_statfs,compat_sys_statfs_wrapper) -SYSCALL(sys_fstatfs,sys_fstatfs,compat_sys_fstatfs_wrapper)	/* 100 */ +SYSCALL(sys_statfs,sys_statfs,compat_sys_statfs) +SYSCALL(sys_fstatfs,sys_fstatfs,compat_sys_fstatfs)	/* 100 */  NI_SYSCALL							/* ioperm for i386 */ -SYSCALL(sys_socketcall,sys_socketcall,compat_sys_socketcall_wrapper) -SYSCALL(sys_syslog,sys_syslog,sys32_syslog_wrapper) +SYSCALL(sys_socketcall,sys_socketcall,compat_sys_socketcall) +SYSCALL(sys_syslog,sys_syslog,compat_sys_syslog)  SYSCALL(sys_setitimer,sys_setitimer,compat_sys_setitimer)  SYSCALL(sys_getitimer,sys_getitimer,compat_sys_getitimer)	/* 105 */ -SYSCALL(sys_newstat,sys_newstat,compat_sys_newstat_wrapper) -SYSCALL(sys_newlstat,sys_newlstat,compat_sys_newlstat_wrapper) -SYSCALL(sys_newfstat,sys_newfstat,compat_sys_newfstat_wrapper) +SYSCALL(sys_newstat,sys_newstat,compat_sys_newstat) +SYSCALL(sys_newlstat,sys_newlstat,compat_sys_newlstat) +SYSCALL(sys_newfstat,sys_newfstat,compat_sys_newfstat)  NI_SYSCALL							/* old uname syscall */  SYSCALL(sys_lookup_dcookie,sys_lookup_dcookie,compat_sys_lookup_dcookie)	/* 110 */  SYSCALL(sys_vhangup,sys_vhangup,sys_vhangup)  NI_SYSCALL							/* old "idle" system call */  NI_SYSCALL							/* vm86old for i386 */  SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4) -SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper)		/* 115 */ -SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) +SYSCALL(sys_swapoff,sys_swapoff,compat_sys_swapoff)		/* 115 */ +SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo)  SYSCALL(sys_s390_ipc,sys_s390_ipc,compat_sys_s390_ipc) -SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) -SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) -SYSCALL(sys_clone,sys_clone,sys_clone_wrapper)			/* 120 */ -SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) -SYSCALL(sys_newuname,sys_newuname,sys32_newuname_wrapper) +SYSCALL(sys_fsync,sys_fsync,compat_sys_fsync) +SYSCALL(sys_sigreturn,sys_sigreturn,compat_sys_sigreturn) +SYSCALL(sys_clone,sys_clone,compat_sys_clone)			/* 120 */ +SYSCALL(sys_setdomainname,sys_setdomainname,compat_sys_setdomainname) +SYSCALL(sys_newuname,sys_newuname,compat_sys_newuname)  NI_SYSCALL							/* modify_ldt for i386 */ -SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper) -SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper)	/* 125 */ +SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex) +SYSCALL(sys_mprotect,sys_mprotect,compat_sys_mprotect)		/* 125 */  SYSCALL(sys_sigprocmask,sys_sigprocmask,compat_sys_sigprocmask)  NI_SYSCALL							/* old "create module" */ -SYSCALL(sys_init_module,sys_init_module,sys_init_module_wrapper) -SYSCALL(sys_delete_module,sys_delete_module,sys_delete_module_wrapper) +SYSCALL(sys_init_module,sys_init_module,compat_sys_init_module) +SYSCALL(sys_delete_module,sys_delete_module,compat_sys_delete_module)  NI_SYSCALL							/* 130: old get_kernel_syms */ -SYSCALL(sys_quotactl,sys_quotactl,sys32_quotactl_wrapper) -SYSCALL(sys_getpgid,sys_getpgid,sys32_getpgid_wrapper) -SYSCALL(sys_fchdir,sys_fchdir,sys32_fchdir_wrapper) -SYSCALL(sys_bdflush,sys_bdflush,sys32_bdflush_wrapper) -SYSCALL(sys_sysfs,sys_sysfs,sys32_sysfs_wrapper)		/* 135 */ -SYSCALL(sys_personality,sys_s390_personality,sys32_personality_wrapper) +SYSCALL(sys_quotactl,sys_quotactl,compat_sys_quotactl) +SYSCALL(sys_getpgid,sys_getpgid,compat_sys_getpgid) +SYSCALL(sys_fchdir,sys_fchdir,compat_sys_fchdir) +SYSCALL(sys_bdflush,sys_bdflush,compat_sys_bdflush) +SYSCALL(sys_sysfs,sys_sysfs,compat_sys_sysfs)		/* 135 */ +SYSCALL(sys_personality,sys_s390_personality,compat_sys_s390_personality)  NI_SYSCALL							/* for afs_syscall */ -SYSCALL(sys_setfsuid16,sys_ni_syscall,sys32_setfsuid16_wrapper)	/* old setfsuid16 syscall */ -SYSCALL(sys_setfsgid16,sys_ni_syscall,sys32_setfsgid16_wrapper)	/* old setfsgid16 syscall */ -SYSCALL(sys_llseek,sys_llseek,sys32_llseek_wrapper)		/* 140 */ -SYSCALL(sys_getdents,sys_getdents,sys32_getdents_wrapper) -SYSCALL(sys_select,sys_select,compat_sys_select_wrapper) -SYSCALL(sys_flock,sys_flock,sys32_flock_wrapper) -SYSCALL(sys_msync,sys_msync,sys32_msync_wrapper) -SYSCALL(sys_readv,sys_readv,compat_sys_readv_wrapper)		/* 145 */ -SYSCALL(sys_writev,sys_writev,compat_sys_writev_wrapper) -SYSCALL(sys_getsid,sys_getsid,sys32_getsid_wrapper) -SYSCALL(sys_fdatasync,sys_fdatasync,sys32_fdatasync_wrapper) +SYSCALL(sys_setfsuid16,sys_ni_syscall,compat_sys_s390_setfsuid16)	/* old setfsuid16 syscall */ +SYSCALL(sys_setfsgid16,sys_ni_syscall,compat_sys_s390_setfsgid16)	/* old setfsgid16 syscall */ +SYSCALL(sys_llseek,sys_llseek,compat_sys_llseek)		/* 140 */ +SYSCALL(sys_getdents,sys_getdents,compat_sys_getdents) +SYSCALL(sys_select,sys_select,compat_sys_select) +SYSCALL(sys_flock,sys_flock,compat_sys_flock) +SYSCALL(sys_msync,sys_msync,compat_sys_msync) +SYSCALL(sys_readv,sys_readv,compat_sys_readv)		/* 145 */ +SYSCALL(sys_writev,sys_writev,compat_sys_writev) +SYSCALL(sys_getsid,sys_getsid,compat_sys_getsid) +SYSCALL(sys_fdatasync,sys_fdatasync,compat_sys_fdatasync)  SYSCALL(sys_sysctl,sys_sysctl,compat_sys_sysctl) -SYSCALL(sys_mlock,sys_mlock,sys32_mlock_wrapper)		/* 150 */ -SYSCALL(sys_munlock,sys_munlock,sys32_munlock_wrapper) -SYSCALL(sys_mlockall,sys_mlockall,sys32_mlockall_wrapper) +SYSCALL(sys_mlock,sys_mlock,compat_sys_mlock)			/* 150 */ +SYSCALL(sys_munlock,sys_munlock,compat_sys_munlock) +SYSCALL(sys_mlockall,sys_mlockall,compat_sys_mlockall)  SYSCALL(sys_munlockall,sys_munlockall,sys_munlockall) -SYSCALL(sys_sched_setparam,sys_sched_setparam,sys32_sched_setparam_wrapper) -SYSCALL(sys_sched_getparam,sys_sched_getparam,sys32_sched_getparam_wrapper)	/* 155 */ -SYSCALL(sys_sched_setscheduler,sys_sched_setscheduler,sys32_sched_setscheduler_wrapper) -SYSCALL(sys_sched_getscheduler,sys_sched_getscheduler,sys32_sched_getscheduler_wrapper) +SYSCALL(sys_sched_setparam,sys_sched_setparam,compat_sys_sched_setparam) +SYSCALL(sys_sched_getparam,sys_sched_getparam,compat_sys_sched_getparam)	/* 155 */ +SYSCALL(sys_sched_setscheduler,sys_sched_setscheduler,compat_sys_sched_setscheduler) +SYSCALL(sys_sched_getscheduler,sys_sched_getscheduler,compat_sys_sched_getscheduler)  SYSCALL(sys_sched_yield,sys_sched_yield,sys_sched_yield) -SYSCALL(sys_sched_get_priority_max,sys_sched_get_priority_max,sys32_sched_get_priority_max_wrapper) -SYSCALL(sys_sched_get_priority_min,sys_sched_get_priority_min,sys32_sched_get_priority_min_wrapper)	/* 160 */ +SYSCALL(sys_sched_get_priority_max,sys_sched_get_priority_max,compat_sys_sched_get_priority_max) +SYSCALL(sys_sched_get_priority_min,sys_sched_get_priority_min,compat_sys_sched_get_priority_min)	/* 160 */  SYSCALL(sys_sched_rr_get_interval,sys_sched_rr_get_interval,compat_sys_sched_rr_get_interval) -SYSCALL(sys_nanosleep,sys_nanosleep,compat_sys_nanosleep_wrapper) -SYSCALL(sys_mremap,sys_mremap,sys32_mremap_wrapper) -SYSCALL(sys_setresuid16,sys_ni_syscall,sys32_setresuid16_wrapper)	/* old setresuid16 syscall */ -SYSCALL(sys_getresuid16,sys_ni_syscall,sys32_getresuid16_wrapper)	/* 165 old getresuid16 syscall */ +SYSCALL(sys_nanosleep,sys_nanosleep,compat_sys_nanosleep) +SYSCALL(sys_mremap,sys_mremap,compat_sys_mremap) +SYSCALL(sys_setresuid16,sys_ni_syscall,compat_sys_s390_setresuid16)	/* old setresuid16 syscall */ +SYSCALL(sys_getresuid16,sys_ni_syscall,compat_sys_s390_getresuid16)	/* 165 old getresuid16 syscall */  NI_SYSCALL							/* for vm86 */  NI_SYSCALL							/* old sys_query_module */ -SYSCALL(sys_poll,sys_poll,sys32_poll_wrapper) +SYSCALL(sys_poll,sys_poll,compat_sys_poll)  NI_SYSCALL							/* old nfsservctl */ -SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper)	/* 170 old setresgid16 syscall */ -SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper)	/* old getresgid16 syscall */ -SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper) -SYSCALL(sys_rt_sigreturn,sys_rt_sigreturn,sys32_rt_sigreturn) +SYSCALL(sys_setresgid16,sys_ni_syscall,compat_sys_s390_setresgid16)	/* 170 old setresgid16 syscall */ +SYSCALL(sys_getresgid16,sys_ni_syscall,compat_sys_s390_getresgid16)	/* old getresgid16 syscall */ +SYSCALL(sys_prctl,sys_prctl,compat_sys_prctl) +SYSCALL(sys_rt_sigreturn,sys_rt_sigreturn,compat_sys_rt_sigreturn)  SYSCALL(sys_rt_sigaction,sys_rt_sigaction,compat_sys_rt_sigaction)  SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,compat_sys_rt_sigprocmask) /* 175 */  SYSCALL(sys_rt_sigpending,sys_rt_sigpending,compat_sys_rt_sigpending)  SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_sys_rt_sigtimedwait)  SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,compat_sys_rt_sigqueueinfo)  SYSCALL(sys_rt_sigsuspend,sys_rt_sigsuspend,compat_sys_rt_sigsuspend) -SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper)		/* 180 */ -SYSCALL(sys_pwrite64,sys_pwrite64,sys32_pwrite64_wrapper) -SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper)	/* old chown16 syscall */ -SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper) -SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper) -SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper)		/* 185 */ +SYSCALL(sys_pread64,sys_pread64,compat_sys_s390_pread64)		/* 180 */ +SYSCALL(sys_pwrite64,sys_pwrite64,compat_sys_s390_pwrite64) +SYSCALL(sys_chown16,sys_ni_syscall,compat_sys_s390_chown16)	/* old chown16 syscall */ +SYSCALL(sys_getcwd,sys_getcwd,compat_sys_getcwd) +SYSCALL(sys_capget,sys_capget,compat_sys_capget) +SYSCALL(sys_capset,sys_capset,compat_sys_capset)		/* 185 */  SYSCALL(sys_sigaltstack,sys_sigaltstack,compat_sys_sigaltstack)  SYSCALL(sys_sendfile,sys_sendfile64,compat_sys_sendfile)  NI_SYSCALL							/* streams1 */  NI_SYSCALL							/* streams2 */  SYSCALL(sys_vfork,sys_vfork,sys_vfork)				/* 190 */ -SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit_wrapper) -SYSCALL(sys_mmap2,sys_mmap2,sys32_mmap2_wrapper) -SYSCALL(sys_truncate64,sys_ni_syscall,sys32_truncate64_wrapper) -SYSCALL(sys_ftruncate64,sys_ni_syscall,sys32_ftruncate64_wrapper) -SYSCALL(sys_stat64,sys_ni_syscall,sys32_stat64_wrapper)		/* 195 */ -SYSCALL(sys_lstat64,sys_ni_syscall,sys32_lstat64_wrapper) -SYSCALL(sys_fstat64,sys_ni_syscall,sys32_fstat64_wrapper) -SYSCALL(sys_lchown,sys_lchown,sys32_lchown_wrapper) +SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit) +SYSCALL(sys_mmap2,sys_mmap2,compat_sys_s390_mmap2) +SYSCALL(sys_truncate64,sys_ni_syscall,compat_sys_s390_truncate64) +SYSCALL(sys_ftruncate64,sys_ni_syscall,compat_sys_s390_ftruncate64) +SYSCALL(sys_stat64,sys_ni_syscall,compat_sys_s390_stat64)		/* 195 */ +SYSCALL(sys_lstat64,sys_ni_syscall,compat_sys_s390_lstat64) +SYSCALL(sys_fstat64,sys_ni_syscall,compat_sys_s390_fstat64) +SYSCALL(sys_lchown,sys_lchown,compat_sys_lchown)  SYSCALL(sys_getuid,sys_getuid,sys_getuid)  SYSCALL(sys_getgid,sys_getgid,sys_getgid)			/* 200 */  SYSCALL(sys_geteuid,sys_geteuid,sys_geteuid)  SYSCALL(sys_getegid,sys_getegid,sys_getegid) -SYSCALL(sys_setreuid,sys_setreuid,sys32_setreuid_wrapper) -SYSCALL(sys_setregid,sys_setregid,sys32_setregid_wrapper) -SYSCALL(sys_getgroups,sys_getgroups,sys32_getgroups_wrapper)	/* 205 */ -SYSCALL(sys_setgroups,sys_setgroups,sys32_setgroups_wrapper) -SYSCALL(sys_fchown,sys_fchown,sys32_fchown_wrapper) -SYSCALL(sys_setresuid,sys_setresuid,sys32_setresuid_wrapper) -SYSCALL(sys_getresuid,sys_getresuid,sys32_getresuid_wrapper) -SYSCALL(sys_setresgid,sys_setresgid,sys32_setresgid_wrapper)	/* 210 */ -SYSCALL(sys_getresgid,sys_getresgid,sys32_getresgid_wrapper) -SYSCALL(sys_chown,sys_chown,sys32_chown_wrapper) -SYSCALL(sys_setuid,sys_setuid,sys32_setuid_wrapper) -SYSCALL(sys_setgid,sys_setgid,sys32_setgid_wrapper) -SYSCALL(sys_setfsuid,sys_setfsuid,sys32_setfsuid_wrapper)	/* 215 */ -SYSCALL(sys_setfsgid,sys_setfsgid,sys32_setfsgid_wrapper) -SYSCALL(sys_pivot_root,sys_pivot_root,sys32_pivot_root_wrapper) -SYSCALL(sys_mincore,sys_mincore,sys32_mincore_wrapper) -SYSCALL(sys_madvise,sys_madvise,sys32_madvise_wrapper) -SYSCALL(sys_getdents64,sys_getdents64,sys32_getdents64_wrapper)	/* 220 */ -SYSCALL(sys_fcntl64,sys_ni_syscall,compat_sys_fcntl64_wrapper) -SYSCALL(sys_readahead,sys_readahead,sys32_readahead_wrapper) +SYSCALL(sys_setreuid,sys_setreuid,compat_sys_setreuid) +SYSCALL(sys_setregid,sys_setregid,compat_sys_setregid) +SYSCALL(sys_getgroups,sys_getgroups,compat_sys_getgroups)	/* 205 */ +SYSCALL(sys_setgroups,sys_setgroups,compat_sys_setgroups) +SYSCALL(sys_fchown,sys_fchown,compat_sys_fchown) +SYSCALL(sys_setresuid,sys_setresuid,compat_sys_setresuid) +SYSCALL(sys_getresuid,sys_getresuid,compat_sys_getresuid) +SYSCALL(sys_setresgid,sys_setresgid,compat_sys_setresgid)	/* 210 */ +SYSCALL(sys_getresgid,sys_getresgid,compat_sys_getresgid) +SYSCALL(sys_chown,sys_chown,compat_sys_chown) +SYSCALL(sys_setuid,sys_setuid,compat_sys_setuid) +SYSCALL(sys_setgid,sys_setgid,compat_sys_setgid) +SYSCALL(sys_setfsuid,sys_setfsuid,compat_sys_setfsuid)	/* 215 */ +SYSCALL(sys_setfsgid,sys_setfsgid,compat_sys_setfsgid) +SYSCALL(sys_pivot_root,sys_pivot_root,compat_sys_pivot_root) +SYSCALL(sys_mincore,sys_mincore,compat_sys_mincore) +SYSCALL(sys_madvise,sys_madvise,compat_sys_madvise) +SYSCALL(sys_getdents64,sys_getdents64,compat_sys_getdents64)	/* 220 */ +SYSCALL(sys_fcntl64,sys_ni_syscall,compat_sys_fcntl64) +SYSCALL(sys_readahead,sys_readahead,compat_sys_s390_readahead)  SYSCALL(sys_sendfile64,sys_ni_syscall,compat_sys_sendfile64) -SYSCALL(sys_setxattr,sys_setxattr,sys32_setxattr_wrapper) -SYSCALL(sys_lsetxattr,sys_lsetxattr,sys32_lsetxattr_wrapper)	/* 225 */ -SYSCALL(sys_fsetxattr,sys_fsetxattr,sys32_fsetxattr_wrapper) -SYSCALL(sys_getxattr,sys_getxattr,sys32_getxattr_wrapper) -SYSCALL(sys_lgetxattr,sys_lgetxattr,sys32_lgetxattr_wrapper) -SYSCALL(sys_fgetxattr,sys_fgetxattr,sys32_fgetxattr_wrapper) -SYSCALL(sys_listxattr,sys_listxattr,sys32_listxattr_wrapper)	/* 230 */ -SYSCALL(sys_llistxattr,sys_llistxattr,sys32_llistxattr_wrapper) -SYSCALL(sys_flistxattr,sys_flistxattr,sys32_flistxattr_wrapper) -SYSCALL(sys_removexattr,sys_removexattr,sys32_removexattr_wrapper) -SYSCALL(sys_lremovexattr,sys_lremovexattr,sys32_lremovexattr_wrapper) -SYSCALL(sys_fremovexattr,sys_fremovexattr,sys32_fremovexattr_wrapper)	/* 235 */ +SYSCALL(sys_setxattr,sys_setxattr,compat_sys_setxattr) +SYSCALL(sys_lsetxattr,sys_lsetxattr,compat_sys_lsetxattr)	/* 225 */ +SYSCALL(sys_fsetxattr,sys_fsetxattr,compat_sys_fsetxattr) +SYSCALL(sys_getxattr,sys_getxattr,compat_sys_getxattr) +SYSCALL(sys_lgetxattr,sys_lgetxattr,compat_sys_lgetxattr) +SYSCALL(sys_fgetxattr,sys_fgetxattr,compat_sys_fgetxattr) +SYSCALL(sys_listxattr,sys_listxattr,compat_sys_listxattr)	/* 230 */ +SYSCALL(sys_llistxattr,sys_llistxattr,compat_sys_llistxattr) +SYSCALL(sys_flistxattr,sys_flistxattr,compat_sys_flistxattr) +SYSCALL(sys_removexattr,sys_removexattr,compat_sys_removexattr) +SYSCALL(sys_lremovexattr,sys_lremovexattr,compat_sys_lremovexattr) +SYSCALL(sys_fremovexattr,sys_fremovexattr,compat_sys_fremovexattr)	/* 235 */  SYSCALL(sys_gettid,sys_gettid,sys_gettid) -SYSCALL(sys_tkill,sys_tkill,sys_tkill_wrapper) +SYSCALL(sys_tkill,sys_tkill,compat_sys_tkill)  SYSCALL(sys_futex,sys_futex,compat_sys_futex) -SYSCALL(sys_sched_setaffinity,sys_sched_setaffinity,sys32_sched_setaffinity_wrapper) -SYSCALL(sys_sched_getaffinity,sys_sched_getaffinity,sys32_sched_getaffinity_wrapper)	/* 240 */ -SYSCALL(sys_tgkill,sys_tgkill,sys_tgkill_wrapper) +SYSCALL(sys_sched_setaffinity,sys_sched_setaffinity,compat_sys_sched_setaffinity) +SYSCALL(sys_sched_getaffinity,sys_sched_getaffinity,compat_sys_sched_getaffinity)	/* 240 */ +SYSCALL(sys_tgkill,sys_tgkill,compat_sys_tgkill)  NI_SYSCALL							/* reserved for TUX */ -SYSCALL(sys_io_setup,sys_io_setup,sys32_io_setup_wrapper) -SYSCALL(sys_io_destroy,sys_io_destroy,sys32_io_destroy_wrapper) -SYSCALL(sys_io_getevents,sys_io_getevents,sys32_io_getevents_wrapper)	/* 245 */ -SYSCALL(sys_io_submit,sys_io_submit,sys32_io_submit_wrapper) -SYSCALL(sys_io_cancel,sys_io_cancel,sys32_io_cancel_wrapper) -SYSCALL(sys_exit_group,sys_exit_group,sys32_exit_group_wrapper) -SYSCALL(sys_epoll_create,sys_epoll_create,sys_epoll_create_wrapper) -SYSCALL(sys_epoll_ctl,sys_epoll_ctl,sys_epoll_ctl_wrapper)	/* 250 */ -SYSCALL(sys_epoll_wait,sys_epoll_wait,sys_epoll_wait_wrapper) -SYSCALL(sys_set_tid_address,sys_set_tid_address,sys32_set_tid_address_wrapper) -SYSCALL(sys_s390_fadvise64,sys_fadvise64_64,sys32_fadvise64_wrapper) -SYSCALL(sys_timer_create,sys_timer_create,sys32_timer_create_wrapper) -SYSCALL(sys_timer_settime,sys_timer_settime,sys32_timer_settime_wrapper)	/* 255 */ -SYSCALL(sys_timer_gettime,sys_timer_gettime,sys32_timer_gettime_wrapper) -SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun,sys32_timer_getoverrun_wrapper) -SYSCALL(sys_timer_delete,sys_timer_delete,sys32_timer_delete_wrapper) -SYSCALL(sys_clock_settime,sys_clock_settime,sys32_clock_settime_wrapper) -SYSCALL(sys_clock_gettime,sys_clock_gettime,sys32_clock_gettime_wrapper)	/* 260 */ -SYSCALL(sys_clock_getres,sys_clock_getres,sys32_clock_getres_wrapper) -SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys32_clock_nanosleep_wrapper) +SYSCALL(sys_io_setup,sys_io_setup,compat_sys_io_setup) +SYSCALL(sys_io_destroy,sys_io_destroy,compat_sys_io_destroy) +SYSCALL(sys_io_getevents,sys_io_getevents,compat_sys_io_getevents)	/* 245 */ +SYSCALL(sys_io_submit,sys_io_submit,compat_sys_io_submit) +SYSCALL(sys_io_cancel,sys_io_cancel,compat_sys_io_cancel) +SYSCALL(sys_exit_group,sys_exit_group,compat_sys_exit_group) +SYSCALL(sys_epoll_create,sys_epoll_create,compat_sys_epoll_create) +SYSCALL(sys_epoll_ctl,sys_epoll_ctl,compat_sys_epoll_ctl)	/* 250 */ +SYSCALL(sys_epoll_wait,sys_epoll_wait,compat_sys_epoll_wait) +SYSCALL(sys_set_tid_address,sys_set_tid_address,compat_sys_set_tid_address) +SYSCALL(sys_s390_fadvise64,sys_fadvise64_64,compat_sys_s390_fadvise64) +SYSCALL(sys_timer_create,sys_timer_create,compat_sys_timer_create) +SYSCALL(sys_timer_settime,sys_timer_settime,compat_sys_timer_settime)	/* 255 */ +SYSCALL(sys_timer_gettime,sys_timer_gettime,compat_sys_timer_gettime) +SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun,compat_sys_timer_getoverrun) +SYSCALL(sys_timer_delete,sys_timer_delete,compat_sys_timer_delete) +SYSCALL(sys_clock_settime,sys_clock_settime,compat_sys_clock_settime) +SYSCALL(sys_clock_gettime,sys_clock_gettime,compat_sys_clock_gettime)	/* 260 */ +SYSCALL(sys_clock_getres,sys_clock_getres,compat_sys_clock_getres) +SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,compat_sys_clock_nanosleep)  NI_SYSCALL							/* reserved for vserver */ -SYSCALL(sys_s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper) -SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64_wrapper) -SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64_wrapper) -SYSCALL(sys_remap_file_pages,sys_remap_file_pages,sys32_remap_file_pages_wrapper) +SYSCALL(sys_s390_fadvise64_64,sys_ni_syscall,compat_sys_s390_fadvise64_64) +SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64) +SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64) +SYSCALL(sys_remap_file_pages,sys_remap_file_pages,compat_sys_remap_file_pages)  NI_SYSCALL							/* 268 sys_mbind */  NI_SYSCALL							/* 269 sys_get_mempolicy */  NI_SYSCALL							/* 270 sys_set_mempolicy */ -SYSCALL(sys_mq_open,sys_mq_open,compat_sys_mq_open_wrapper) -SYSCALL(sys_mq_unlink,sys_mq_unlink,sys32_mq_unlink_wrapper) -SYSCALL(sys_mq_timedsend,sys_mq_timedsend,compat_sys_mq_timedsend_wrapper) -SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive_wrapper) -SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */ -SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper) -SYSCALL(sys_kexec_load,sys_kexec_load,compat_sys_kexec_load_wrapper) -SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper) -SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper) -SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl_wrapper)		/* 280 */ +SYSCALL(sys_mq_open,sys_mq_open,compat_sys_mq_open) +SYSCALL(sys_mq_unlink,sys_mq_unlink,compat_sys_mq_unlink) +SYSCALL(sys_mq_timedsend,sys_mq_timedsend,compat_sys_mq_timedsend) +SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive) +SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify) /* 275 */ +SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr) +SYSCALL(sys_kexec_load,sys_kexec_load,compat_sys_kexec_load) +SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key) +SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key) +SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl)		/* 280 */  SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid) -SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper) -SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper) +SYSCALL(sys_ioprio_set,sys_ioprio_set,compat_sys_ioprio_set) +SYSCALL(sys_ioprio_get,sys_ioprio_get,compat_sys_ioprio_get)  SYSCALL(sys_inotify_init,sys_inotify_init,sys_inotify_init) -SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper)	/* 285 */ -SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper) +SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,compat_sys_inotify_add_watch)	/* 285 */ +SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,compat_sys_inotify_rm_watch)  NI_SYSCALL							/* 287 sys_migrate_pages */  SYSCALL(sys_openat,sys_openat,compat_sys_openat) -SYSCALL(sys_mkdirat,sys_mkdirat,sys_mkdirat_wrapper) -SYSCALL(sys_mknodat,sys_mknodat,sys_mknodat_wrapper)	/* 290 */ -SYSCALL(sys_fchownat,sys_fchownat,sys_fchownat_wrapper) -SYSCALL(sys_futimesat,sys_futimesat,compat_sys_futimesat_wrapper) -SYSCALL(sys_fstatat64,sys_newfstatat,sys32_fstatat64_wrapper) -SYSCALL(sys_unlinkat,sys_unlinkat,sys_unlinkat_wrapper) -SYSCALL(sys_renameat,sys_renameat,sys_renameat_wrapper)	/* 295 */ -SYSCALL(sys_linkat,sys_linkat,sys_linkat_wrapper) -SYSCALL(sys_symlinkat,sys_symlinkat,sys_symlinkat_wrapper) -SYSCALL(sys_readlinkat,sys_readlinkat,sys_readlinkat_wrapper) -SYSCALL(sys_fchmodat,sys_fchmodat,sys_fchmodat_wrapper) -SYSCALL(sys_faccessat,sys_faccessat,sys_faccessat_wrapper)	/* 300 */ -SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper) -SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper) -SYSCALL(sys_unshare,sys_unshare,sys_unshare_wrapper) +SYSCALL(sys_mkdirat,sys_mkdirat,compat_sys_mkdirat) +SYSCALL(sys_mknodat,sys_mknodat,compat_sys_mknodat)	/* 290 */ +SYSCALL(sys_fchownat,sys_fchownat,compat_sys_fchownat) +SYSCALL(sys_futimesat,sys_futimesat,compat_sys_futimesat) +SYSCALL(sys_fstatat64,sys_newfstatat,compat_sys_s390_fstatat64) +SYSCALL(sys_unlinkat,sys_unlinkat,compat_sys_unlinkat) +SYSCALL(sys_renameat,sys_renameat,compat_sys_renameat)	/* 295 */ +SYSCALL(sys_linkat,sys_linkat,compat_sys_linkat) +SYSCALL(sys_symlinkat,sys_symlinkat,compat_sys_symlinkat) +SYSCALL(sys_readlinkat,sys_readlinkat,compat_sys_readlinkat) +SYSCALL(sys_fchmodat,sys_fchmodat,compat_sys_fchmodat) +SYSCALL(sys_faccessat,sys_faccessat,compat_sys_faccessat)	/* 300 */ +SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6) +SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll) +SYSCALL(sys_unshare,sys_unshare,compat_sys_unshare)  SYSCALL(sys_set_robust_list,sys_set_robust_list,compat_sys_set_robust_list)  SYSCALL(sys_get_robust_list,sys_get_robust_list,compat_sys_get_robust_list) -SYSCALL(sys_splice,sys_splice,sys_splice_wrapper) -SYSCALL(sys_sync_file_range,sys_sync_file_range,sys_sync_file_range_wrapper) -SYSCALL(sys_tee,sys_tee,sys_tee_wrapper) +SYSCALL(sys_splice,sys_splice,compat_sys_splice) +SYSCALL(sys_sync_file_range,sys_sync_file_range,compat_sys_s390_sync_file_range) +SYSCALL(sys_tee,sys_tee,compat_sys_tee)  SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice)  NI_SYSCALL							/* 310 sys_move_pages */ -SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper) +SYSCALL(sys_getcpu,sys_getcpu,compat_sys_getcpu)  SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait) -SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper) -SYSCALL(sys_s390_fallocate,sys_fallocate,sys_fallocate_wrapper) -SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper)	/* 315 */ +SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes) +SYSCALL(sys_s390_fallocate,sys_fallocate,compat_sys_s390_fallocate) +SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat)	/* 315 */  SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd)  NI_SYSCALL						/* 317 old sys_timer_fd */ -SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper) -SYSCALL(sys_timerfd_create,sys_timerfd_create,sys_timerfd_create_wrapper) +SYSCALL(sys_eventfd,sys_eventfd,compat_sys_eventfd) +SYSCALL(sys_timerfd_create,sys_timerfd_create,compat_sys_timerfd_create)  SYSCALL(sys_timerfd_settime,sys_timerfd_settime,compat_sys_timerfd_settime) /* 320 */  SYSCALL(sys_timerfd_gettime,sys_timerfd_gettime,compat_sys_timerfd_gettime)  SYSCALL(sys_signalfd4,sys_signalfd4,compat_sys_signalfd4) -SYSCALL(sys_eventfd2,sys_eventfd2,sys_eventfd2_wrapper) -SYSCALL(sys_inotify_init1,sys_inotify_init1,sys_inotify_init1_wrapper) -SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */ -SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper) -SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper) +SYSCALL(sys_eventfd2,sys_eventfd2,compat_sys_eventfd2) +SYSCALL(sys_inotify_init1,sys_inotify_init1,compat_sys_inotify_init1) +SYSCALL(sys_pipe2,sys_pipe2,compat_sys_pipe2) /* 325 */ +SYSCALL(sys_dup3,sys_dup3,compat_sys_dup3) +SYSCALL(sys_epoll_create1,sys_epoll_create1,compat_sys_epoll_create1)  SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv)  SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev)  SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */ -SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper) -SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper) +SYSCALL(sys_perf_event_open,sys_perf_event_open,compat_sys_perf_event_open) +SYSCALL(sys_fanotify_init,sys_fanotify_init,compat_sys_fanotify_init)  SYSCALL(sys_fanotify_mark,sys_fanotify_mark,compat_sys_fanotify_mark) -SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) -SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */ +SYSCALL(sys_prlimit64,sys_prlimit64,compat_sys_prlimit64) +SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,compat_sys_name_to_handle_at) /* 335 */  SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at) -SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper) -SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper) -SYSCALL(sys_setns,sys_setns,sys_setns_wrapper) -SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */ -SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) -SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) -SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) -SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper) +SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime) +SYSCALL(sys_syncfs,sys_syncfs,compat_sys_syncfs) +SYSCALL(sys_setns,sys_setns,compat_sys_setns) +SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv) /* 340 */ +SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev) +SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,compat_sys_s390_runtime_instr) +SYSCALL(sys_kcmp,sys_kcmp,compat_sys_kcmp) +SYSCALL(sys_finit_module,sys_finit_module,compat_sys_finit_module) +SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */ +SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr) +SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 064c3082ab3..0931b110c82 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -108,20 +108,10 @@ static void fixup_clock_comparator(unsigned long long delta)  	set_clock_comparator(S390_lowcore.clock_comparator);  } -static int s390_next_ktime(ktime_t expires, +static int s390_next_event(unsigned long delta,  			   struct clock_event_device *evt)  { -	struct timespec ts; -	u64 nsecs; - -	ts.tv_sec = ts.tv_nsec = 0; -	monotonic_to_bootbased(&ts); -	nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires)); -	do_div(nsecs, 125); -	S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9); -	/* Program the maximum value if we have an overflow (== year 2042) */ -	if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc)) -		S390_lowcore.clock_comparator = -1ULL; +	S390_lowcore.clock_comparator = get_tod_clock() + delta;  	set_clock_comparator(S390_lowcore.clock_comparator);  	return 0;  } @@ -146,15 +136,14 @@ void init_cpu_timer(void)  	cpu = smp_processor_id();  	cd = &per_cpu(comparators, cpu);  	cd->name		= "comparator"; -	cd->features		= CLOCK_EVT_FEAT_ONESHOT | -				  CLOCK_EVT_FEAT_KTIME; +	cd->features		= CLOCK_EVT_FEAT_ONESHOT;  	cd->mult		= 16777;  	cd->shift		= 12;  	cd->min_delta_ns	= 1;  	cd->max_delta_ns	= LONG_MAX;  	cd->rating		= 400;  	cd->cpumask		= cpumask_of(cpu); -	cd->set_next_ktime	= s390_next_ktime; +	cd->set_next_event	= s390_next_event;  	cd->set_mode		= s390_set_mode;  	clockevents_register_device(cd); @@ -221,21 +210,30 @@ struct clocksource * __init clocksource_default_clock(void)  	return &clocksource_tod;  } -void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm, -			struct clocksource *clock, u32 mult) +void update_vsyscall(struct timekeeper *tk)  { -	if (clock != &clocksource_tod) +	u64 nsecps; + +	if (tk->clock != &clocksource_tod)  		return;  	/* Make userspace gettimeofday spin until we're done. */  	++vdso_data->tb_update_count;  	smp_wmb(); -	vdso_data->xtime_tod_stamp = clock->cycle_last; -	vdso_data->xtime_clock_sec = wall_time->tv_sec; -	vdso_data->xtime_clock_nsec = wall_time->tv_nsec; -	vdso_data->wtom_clock_sec = wtm->tv_sec; -	vdso_data->wtom_clock_nsec = wtm->tv_nsec; -	vdso_data->ntp_mult = mult; +	vdso_data->xtime_tod_stamp = tk->clock->cycle_last; +	vdso_data->xtime_clock_sec = tk->xtime_sec; +	vdso_data->xtime_clock_nsec = tk->xtime_nsec; +	vdso_data->wtom_clock_sec = +		tk->xtime_sec + tk->wall_to_monotonic.tv_sec; +	vdso_data->wtom_clock_nsec = tk->xtime_nsec + +		+ ((u64) tk->wall_to_monotonic.tv_nsec << tk->shift); +	nsecps = (u64) NSEC_PER_SEC << tk->shift; +	while (vdso_data->wtom_clock_nsec >= nsecps) { +		vdso_data->wtom_clock_nsec -= nsecps; +		vdso_data->wtom_clock_sec++; +	} +	vdso_data->tk_mult = tk->mult; +	vdso_data->tk_shift = tk->shift;  	smp_wmb();  	++vdso_data->tb_update_count;  } @@ -264,11 +262,11 @@ void __init time_init(void)  	stp_reset();  	/* request the clock comparator external interrupt */ -	if (register_external_interrupt(0x1004, clock_comparator_interrupt)) -                panic("Couldn't request external interrupt 0x1004"); +	if (register_external_irq(EXT_IRQ_CLK_COMP, clock_comparator_interrupt)) +		panic("Couldn't request external interrupt 0x1004");  	/* request the timing alert external interrupt */ -	if (register_external_interrupt(0x1406, timing_alert_interrupt)) +	if (register_external_irq(EXT_IRQ_TIMING_ALERT, timing_alert_interrupt))  		panic("Couldn't request external interrupt 0x1406");  	if (clocksource_register(&clocksource_tod) != 0) diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 4b2e3e31700..355a16c5570 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -333,7 +333,9 @@ static void __init alloc_masks(struct sysinfo_15_1_x *info,  		nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];  	nr_masks = max(nr_masks, 1);  	for (i = 0; i < nr_masks; i++) { -		mask->next = alloc_bootmem(sizeof(struct mask_info)); +		mask->next = alloc_bootmem_align( +			roundup_pow_of_two(sizeof(struct mask_info)), +			roundup_pow_of_two(sizeof(struct mask_info)));  		mask = mask->next;  	}  } @@ -443,6 +445,23 @@ int topology_cpu_init(struct cpu *cpu)  	return sysfs_create_group(&cpu->dev.kobj, &topology_cpu_attr_group);  } +const struct cpumask *cpu_coregroup_mask(int cpu) +{ +	return &cpu_topology[cpu].core_mask; +} + +static const struct cpumask *cpu_book_mask(int cpu) +{ +	return &cpu_topology[cpu].book_mask; +} + +static struct sched_domain_topology_level s390_topology[] = { +	{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, +	{ cpu_book_mask, SD_INIT_NAME(BOOK) }, +	{ cpu_cpu_mask, SD_INIT_NAME(DIE) }, +	{ NULL, }, +}; +  static int __init topology_init(void)  {  	if (!MACHINE_HAS_TOPOLOGY) { @@ -451,7 +470,9 @@ static int __init topology_init(void)  	}  	set_topology_timer();  out: -	update_cpu_masks(); + +	set_sched_topology(s390_topology); +  	return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);  }  device_initcall(topology_init); diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 05d75c41313..61364909678 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -84,8 +84,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data;   */  static void vdso_init_data(struct vdso_data *vd)  { -	vd->ectg_available = -		s390_user_mode != HOME_SPACE_MODE && test_facility(31); +	vd->ectg_available = test_facility(31);  }  #ifdef CONFIG_64BIT @@ -102,7 +101,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)  	lowcore->vdso_per_cpu_data = __LC_PASTE; -	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) +	if (!vdso_enabled)  		return 0;  	segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER); @@ -126,7 +125,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)  		psal[i] = 0x80000000;  	lowcore->paste[4] = (u32)(addr_t) psal; -	psal[0] = 0x20000000; +	psal[0] = 0x02000000;  	psal[2] = (u32)(addr_t) aste;  	*(unsigned long *) (aste + 2) = segment_table +  		_ASCE_TABLE_LENGTH + _ASCE_USER_BITS + _ASCE_TYPE_SEGMENT; @@ -147,7 +146,7 @@ void vdso_free_per_cpu(struct _lowcore *lowcore)  	unsigned long segment_table, page_table, page_frame;  	u32 *psal, *aste; -	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) +	if (!vdso_enabled)  		return;  	psal = (u32 *)(addr_t) lowcore->paste[4]; @@ -165,7 +164,7 @@ static void vdso_init_cr5(void)  {  	unsigned long cr5; -	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) +	if (!vdso_enabled)  		return;  	cr5 = offsetof(struct _lowcore, paste);  	__ctl_load(cr5, 5, 5); diff --git a/arch/s390/kernel/vdso32/clock_gettime.S b/arch/s390/kernel/vdso32/clock_gettime.S index b2224e0b974..65fc3979c2f 100644 --- a/arch/s390/kernel/vdso32/clock_gettime.S +++ b/arch/s390/kernel/vdso32/clock_gettime.S @@ -38,25 +38,21 @@ __kernel_clock_gettime:  	sl	%r1,__VDSO_XTIME_STAMP+4(%r5)  	brc	3,2f  	ahi	%r0,-1 -2:	ms	%r0,__VDSO_NTP_MULT(%r5)	/* cyc2ns(clock,cycle_delta) */ +2:	ms	%r0,__VDSO_TK_MULT(%r5)		/*  * tk->mult */  	lr	%r2,%r0 -	l	%r0,__VDSO_NTP_MULT(%r5) +	l	%r0,__VDSO_TK_MULT(%r5)  	ltr	%r1,%r1  	mr	%r0,%r0  	jnm	3f -	a	%r0,__VDSO_NTP_MULT(%r5) +	a	%r0,__VDSO_TK_MULT(%r5)  3:	alr	%r0,%r2 -	srdl	%r0,12 -	al	%r0,__VDSO_XTIME_NSEC(%r5)	/*  + xtime */ -	al	%r1,__VDSO_XTIME_NSEC+4(%r5) -	brc	12,4f -	ahi	%r0,1 -4:	l	%r2,__VDSO_XTIME_SEC+4(%r5) -	al	%r0,__VDSO_WTOM_NSEC(%r5)	/*  + wall_to_monotonic */ +	al	%r0,__VDSO_WTOM_NSEC(%r5)  	al	%r1,__VDSO_WTOM_NSEC+4(%r5)  	brc	12,5f  	ahi	%r0,1 -5:	al	%r2,__VDSO_WTOM_SEC+4(%r5) +5:	l	%r2,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */ +	srdl	%r0,0(%r2)			/*  >> tk->shift */ +	l	%r2,__VDSO_WTOM_SEC+4(%r5)  	cl	%r4,__VDSO_UPD_COUNT+4(%r5)	/* check update counter */  	jne	1b  	basr	%r5,0 @@ -86,20 +82,21 @@ __kernel_clock_gettime:  	sl	%r1,__VDSO_XTIME_STAMP+4(%r5)  	brc	3,12f  	ahi	%r0,-1 -12:	ms	%r0,__VDSO_NTP_MULT(%r5)	/* cyc2ns(clock,cycle_delta) */ +12:	ms	%r0,__VDSO_TK_MULT(%r5)		/*  * tk->mult */  	lr	%r2,%r0 -	l	%r0,__VDSO_NTP_MULT(%r5) +	l	%r0,__VDSO_TK_MULT(%r5)  	ltr	%r1,%r1  	mr	%r0,%r0  	jnm	13f -	a	%r0,__VDSO_NTP_MULT(%r5) +	a	%r0,__VDSO_TK_MULT(%r5)  13:	alr	%r0,%r2 -	srdl	%r0,12 -	al	%r0,__VDSO_XTIME_NSEC(%r5)	/*  + xtime */ +	al	%r0,__VDSO_XTIME_NSEC(%r5)	/*  + tk->xtime_nsec */  	al	%r1,__VDSO_XTIME_NSEC+4(%r5)  	brc	12,14f  	ahi	%r0,1 -14:	l	%r2,__VDSO_XTIME_SEC+4(%r5) +14:	l	%r2,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */ +	srdl	%r0,0(%r2)			/*  >> tk->shift */ +	l	%r2,__VDSO_XTIME_SEC+4(%r5)  	cl	%r4,__VDSO_UPD_COUNT+4(%r5)	/* check update counter */  	jne	11b  	basr	%r5,0 diff --git a/arch/s390/kernel/vdso32/gettimeofday.S b/arch/s390/kernel/vdso32/gettimeofday.S index 2d3633175e3..fd621a950f7 100644 --- a/arch/s390/kernel/vdso32/gettimeofday.S +++ b/arch/s390/kernel/vdso32/gettimeofday.S @@ -35,15 +35,14 @@ __kernel_gettimeofday:  	sl	%r1,__VDSO_XTIME_STAMP+4(%r5)  	brc	3,3f  	ahi	%r0,-1 -3:	ms	%r0,__VDSO_NTP_MULT(%r5)	/* cyc2ns(clock,cycle_delta) */ +3:	ms	%r0,__VDSO_TK_MULT(%r5)		/*  * tk->mult */  	st	%r0,24(%r15) -	l	%r0,__VDSO_NTP_MULT(%r5) +	l	%r0,__VDSO_TK_MULT(%r5)  	ltr	%r1,%r1  	mr	%r0,%r0  	jnm	4f -	a	%r0,__VDSO_NTP_MULT(%r5) +	a	%r0,__VDSO_TK_MULT(%r5)  4:	al	%r0,24(%r15) -	srdl	%r0,12  	al	%r0,__VDSO_XTIME_NSEC(%r5)	/*  + xtime */  	al	%r1,__VDSO_XTIME_NSEC+4(%r5)  	brc	12,5f @@ -51,6 +50,8 @@ __kernel_gettimeofday:  5:	mvc	24(4,%r15),__VDSO_XTIME_SEC+4(%r5)  	cl	%r4,__VDSO_UPD_COUNT+4(%r5)	/* check update counter */  	jne	1b +	l	%r4,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */ +	srdl	%r0,0(%r4)			/*  >> tk->shift */  	l	%r4,24(%r15)			/* get tv_sec from stack */  	basr	%r5,0  6:	ltr	%r0,%r0 diff --git a/arch/s390/kernel/vdso64/clock_getres.S b/arch/s390/kernel/vdso64/clock_getres.S index 176e1f75f9a..34deba7c7ed 100644 --- a/arch/s390/kernel/vdso64/clock_getres.S +++ b/arch/s390/kernel/vdso64/clock_getres.S @@ -23,7 +23,9 @@ __kernel_clock_getres:  	je	0f  	cghi	%r2,__CLOCK_MONOTONIC  	je	0f -	cghi	%r2,-2		/* CLOCK_THREAD_CPUTIME_ID for this thread */ +	cghi	%r2,__CLOCK_THREAD_CPUTIME_ID +	je	0f +	cghi	%r2,-2		/* Per-thread CPUCLOCK with PID=0, VIRT=1 */  	jne	2f  	larl	%r5,_vdso_data  	icm	%r0,15,__LC_ECTG_OK(%r5) diff --git a/arch/s390/kernel/vdso64/clock_gettime.S b/arch/s390/kernel/vdso64/clock_gettime.S index d46c95ed5f1..91940ed33a4 100644 --- a/arch/s390/kernel/vdso64/clock_gettime.S +++ b/arch/s390/kernel/vdso64/clock_gettime.S @@ -22,7 +22,9 @@ __kernel_clock_gettime:  	larl	%r5,_vdso_data  	cghi	%r2,__CLOCK_REALTIME  	je	4f -	cghi	%r2,-2		/* CLOCK_THREAD_CPUTIME_ID for this thread */ +	cghi	%r2,__CLOCK_THREAD_CPUTIME_ID +	je	9f +	cghi	%r2,-2		/* Per-thread CPUCLOCK with PID=0, VIRT=1 */  	je	9f  	cghi	%r2,__CLOCK_MONOTONIC  	jne	12f @@ -34,14 +36,13 @@ __kernel_clock_gettime:  	tmll	%r4,0x0001			/* pending update ? loop */  	jnz	0b  	stck	48(%r15)			/* Store TOD clock */ +	lgf	%r2,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */ +	lg	%r0,__VDSO_WTOM_SEC(%r5)  	lg	%r1,48(%r15)  	sg	%r1,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */ -	msgf	%r1,__VDSO_NTP_MULT(%r5)	/*  * NTP adjustment */ -	srlg	%r1,%r1,12			/* cyc2ns(clock,cycle_delta) */ -	alg	%r1,__VDSO_XTIME_NSEC(%r5)	/*  + xtime */ -	lg	%r0,__VDSO_XTIME_SEC(%r5) -	alg	%r1,__VDSO_WTOM_NSEC(%r5)	/*  + wall_to_monotonic */ -	alg	%r0,__VDSO_WTOM_SEC(%r5) +	msgf	%r1,__VDSO_TK_MULT(%r5)		/*  * tk->mult */ +	alg	%r1,__VDSO_WTOM_NSEC(%r5) +	srlg	%r1,%r1,0(%r2)			/*  >> tk->shift */  	clg	%r4,__VDSO_UPD_COUNT(%r5)	/* check update counter */  	jne	0b  	larl	%r5,13f @@ -62,12 +63,13 @@ __kernel_clock_gettime:  	tmll	%r4,0x0001			/* pending update ? loop */  	jnz	5b  	stck	48(%r15)			/* Store TOD clock */ +	lgf	%r2,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */  	lg	%r1,48(%r15)  	sg	%r1,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */ -	msgf	%r1,__VDSO_NTP_MULT(%r5)	/*  * NTP adjustment */ -	srlg	%r1,%r1,12			/* cyc2ns(clock,cycle_delta) */ -	alg	%r1,__VDSO_XTIME_NSEC(%r5)	/*  + xtime */ -	lg	%r0,__VDSO_XTIME_SEC(%r5) +	msgf	%r1,__VDSO_TK_MULT(%r5)		/*  * tk->mult */ +	alg	%r1,__VDSO_XTIME_NSEC(%r5)	/*  + tk->xtime_nsec */ +	srlg	%r1,%r1,0(%r2)			/*  >> tk->shift */ +	lg	%r0,__VDSO_XTIME_SEC(%r5)	/* tk->xtime_sec */  	clg	%r4,__VDSO_UPD_COUNT(%r5)	/* check update counter */  	jne	5b  	larl	%r5,13f diff --git a/arch/s390/kernel/vdso64/gettimeofday.S b/arch/s390/kernel/vdso64/gettimeofday.S index 36ee674722e..d0860d1d0cc 100644 --- a/arch/s390/kernel/vdso64/gettimeofday.S +++ b/arch/s390/kernel/vdso64/gettimeofday.S @@ -31,12 +31,13 @@ __kernel_gettimeofday:  	stck	48(%r15)			/* Store TOD clock */  	lg	%r1,48(%r15)  	sg	%r1,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */ -	msgf	%r1,__VDSO_NTP_MULT(%r5)	/*  * NTP adjustment */ -	srlg	%r1,%r1,12			/* cyc2ns(clock,cycle_delta) */ -	alg	%r1,__VDSO_XTIME_NSEC(%r5)	/*  + xtime.tv_nsec */ -	lg	%r0,__VDSO_XTIME_SEC(%r5)	/* xtime.tv_sec */ +	msgf	%r1,__VDSO_TK_MULT(%r5)		/*  * tk->mult */ +	alg	%r1,__VDSO_XTIME_NSEC(%r5)	/*  + tk->xtime_nsec */ +	lg	%r0,__VDSO_XTIME_SEC(%r5)	/* tk->xtime_sec */  	clg	%r4,__VDSO_UPD_COUNT(%r5)	/* check update counter */  	jne	0b +	lgf	%r5,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */ +	srlg	%r1,%r1,0(%r5)			/*  >> tk->shift */  	larl	%r5,5f  2:	clg	%r1,0(%r5)  	jl	3f diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index abcfab55f99..8c34363d6f1 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -161,7 +161,7 @@ void __kprobes vtime_stop_cpu(void)  	trace_hardirqs_on();  	/* Wait for external, I/O or machine check interrupt. */ -	psw_mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_DAT | +	psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |  		PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;  	idle->nohz_delay = 0; @@ -191,7 +191,7 @@ cputime64_t s390_get_idle_time(int cpu)  		sequence = ACCESS_ONCE(idle->sequence);  		idle_enter = ACCESS_ONCE(idle->clock_idle_enter);  		idle_exit = ACCESS_ONCE(idle->clock_idle_exit); -	} while ((sequence & 1) || (idle->sequence != sequence)); +	} while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));  	return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;  }  | 
