diff options
Diffstat (limited to 'arch/s390/kernel')
| -rw-r--r-- | arch/s390/kernel/asm-offsets.c | 6 | ||||
| -rw-r--r-- | arch/s390/kernel/debug.c | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/early.c | 4 | ||||
| -rw-r--r-- | arch/s390/kernel/entry.S | 324 | ||||
| -rw-r--r-- | arch/s390/kernel/entry64.S | 617 | ||||
| -rw-r--r-- | arch/s390/kernel/head.S | 4 | ||||
| -rw-r--r-- | arch/s390/kernel/head31.S | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/head64.S | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/nmi.c | 3 | ||||
| -rw-r--r-- | arch/s390/kernel/processor.c | 37 | ||||
| -rw-r--r-- | arch/s390/kernel/ptrace.c | 73 | ||||
| -rw-r--r-- | arch/s390/kernel/s390_ext.c | 3 | ||||
| -rw-r--r-- | arch/s390/kernel/setup.c | 27 | ||||
| -rw-r--r-- | arch/s390/kernel/signal.c | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/time.c | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/topology.c | 7 | ||||
| -rw-r--r-- | arch/s390/kernel/traps.c | 31 | ||||
| -rw-r--r-- | arch/s390/kernel/vdso.c | 4 | ||||
| -rw-r--r-- | arch/s390/kernel/vtime.c | 15 | 
19 files changed, 584 insertions, 579 deletions
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index a09408952ed..d9b490a2716 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -39,6 +39,7 @@ int main(void)  	DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));  	DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer));  	DEFINE(__TI_system_timer, offsetof(struct thread_info, system_timer)); +	DEFINE(__TI_last_break, offsetof(struct thread_info, last_break));  	BLANK();  	DEFINE(__PT_ARGS, offsetof(struct pt_regs, args));  	DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); @@ -112,6 +113,7 @@ int main(void)  	DEFINE(__LC_RETURN_MCCK_PSW, offsetof(struct _lowcore, return_mcck_psw));  	DEFINE(__LC_SYNC_ENTER_TIMER, offsetof(struct _lowcore, sync_enter_timer));  	DEFINE(__LC_ASYNC_ENTER_TIMER, offsetof(struct _lowcore, async_enter_timer)); +	DEFINE(__LC_MCCK_ENTER_TIMER, offsetof(struct _lowcore, mcck_enter_timer));  	DEFINE(__LC_EXIT_TIMER, offsetof(struct _lowcore, exit_timer));  	DEFINE(__LC_USER_TIMER, offsetof(struct _lowcore, user_timer));  	DEFINE(__LC_SYSTEM_TIMER, offsetof(struct _lowcore, system_timer)); @@ -126,10 +128,12 @@ int main(void)  	DEFINE(__LC_KERNEL_ASCE, offsetof(struct _lowcore, kernel_asce));  	DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));  	DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce)); -	DEFINE(__LC_CPUID, offsetof(struct _lowcore, cpu_id));  	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_SIE_HOOK, offsetof(struct _lowcore, sie_hook)); +	DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp));  	DEFINE(__LC_IRB, offsetof(struct _lowcore, irb));  	DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area));  	DEFINE(__LC_CLOCK_COMP_SAVE_AREA, offsetof(struct _lowcore, clock_comp_save_area)); diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 0168472b2fd..98192261491 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -655,6 +655,7 @@ found:  	p_info->act_entry_offset = 0;  	file->private_data = p_info;  	debug_info_get(debug_info); +	nonseekable_open(inode, file);  out:  	mutex_unlock(&debug_mutex);  	return rc; diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 2d92c2cf92d..c00856ad4e5 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -356,6 +356,7 @@ static __init void detect_machine_facilities(void)  {  #ifdef CONFIG_64BIT  	unsigned int facilities; +	unsigned long long facility_bits;  	facilities = stfl();  	if (facilities & (1 << 28)) @@ -364,6 +365,9 @@ static __init void detect_machine_facilities(void)  		S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF;  	if (facilities & (1 << 4))  		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; +	if ((stfle(&facility_bits, 1) > 0) && +	    (facility_bits & (1ULL << (63 - 40)))) +		S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;  #endif  } diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 6af7045280a..d5e3e600744 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -73,21 +73,24 @@ STACK_SIZE  = 1 << STACK_SHIFT  	basr	%r14,%r1  	.endm -	.macro	TRACE_IRQS_CHECK -	basr	%r2,%r0 +	.macro	TRACE_IRQS_CHECK_ON  	tm	SP_PSW(%r15),0x03	# irqs enabled? -	jz	0f -	l	%r1,BASED(.Ltrace_irq_on_caller) -	basr	%r14,%r1 -	j	1f -0:	l	%r1,BASED(.Ltrace_irq_off_caller) -	basr	%r14,%r1 -1: +	bz	BASED(0f) +	TRACE_IRQS_ON +0: +	.endm + +	.macro	TRACE_IRQS_CHECK_OFF +	tm	SP_PSW(%r15),0x03	# irqs enabled? +	bz	BASED(0f) +	TRACE_IRQS_OFF +0:  	.endm  #else  #define TRACE_IRQS_ON  #define TRACE_IRQS_OFF -#define TRACE_IRQS_CHECK +#define TRACE_IRQS_CHECK_ON +#define TRACE_IRQS_CHECK_OFF  #endif  #ifdef CONFIG_LOCKDEP @@ -177,9 +180,9 @@ STACK_SIZE  = 1 << STACK_SHIFT  	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw  	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack  	st	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2 -	icm	%r12,3,__LC_SVC_ILC +	icm	%r12,12,__LC_SVC_ILC  	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack -	st	%r12,SP_SVCNR(%r15) +	st	%r12,SP_ILC(%r15)  	mvc	SP_R12(16,%r15),\savearea # move %r12-%r15 to stack  	la	%r12,0  	st	%r12,__SF_BACKCHAIN(%r15)	# clear back chain @@ -273,66 +276,45 @@ sysc_do_restart:  	st	%r2,SP_R2(%r15)   # store return value (change R2 on stack)  sysc_return: +	LOCKDEP_SYS_EXIT +sysc_tif:  	tm	__TI_flags+3(%r9),_TIF_WORK_SVC  	bnz	BASED(sysc_work)  # there is work to do (signals etc.)  sysc_restore: -#ifdef CONFIG_TRACE_IRQFLAGS -	la	%r1,BASED(sysc_restore_trace_psw_addr) -	l	%r1,0(%r1) -	lpsw	0(%r1) -sysc_restore_trace: -	TRACE_IRQS_CHECK -	LOCKDEP_SYS_EXIT -#endif -sysc_leave:  	RESTORE_ALL __LC_RETURN_PSW,1  sysc_done: -#ifdef CONFIG_TRACE_IRQFLAGS -sysc_restore_trace_psw_addr: -	.long sysc_restore_trace_psw - -	.section .data,"aw",@progbits -	.align	8 -	.globl	sysc_restore_trace_psw -sysc_restore_trace_psw: -	.long	0, sysc_restore_trace + 0x80000000 -	.previous -#endif - -# -# recheck if there is more work to do  # -sysc_work_loop: -	tm	__TI_flags+3(%r9),_TIF_WORK_SVC -	bz	BASED(sysc_restore)	# there is no work to do -# -# One of the work bits is on. Find out which one. +# There is work to do, but first we need to check if we return to userspace.  #  sysc_work:  	tm	SP_PSW+1(%r15),0x01	# returning to user ?  	bno	BASED(sysc_restore) + +# +# One of the work bits is on. Find out which one. +# +sysc_work_tif:  	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING  	bo	BASED(sysc_mcck_pending)  	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED  	bo	BASED(sysc_reschedule)  	tm	__TI_flags+3(%r9),_TIF_SIGPENDING -	bnz	BASED(sysc_sigpending) +	bo	BASED(sysc_sigpending)  	tm	__TI_flags+3(%r9),_TIF_NOTIFY_RESUME -	bnz	BASED(sysc_notify_resume) +	bo	BASED(sysc_notify_resume)  	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC  	bo	BASED(sysc_restart)  	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP  	bo	BASED(sysc_singlestep) -	b	BASED(sysc_restore) -sysc_work_done: +	b	BASED(sysc_return)	# beware of critical section cleanup  #  # _TIF_NEED_RESCHED is set, call schedule  #  sysc_reschedule:  	l	%r1,BASED(.Lschedule) -	la	%r14,BASED(sysc_work_loop) +	la	%r14,BASED(sysc_return)  	br	%r1			# call scheduler  # @@ -340,7 +322,7 @@ sysc_reschedule:  #  sysc_mcck_pending:  	l	%r1,BASED(.Ls390_handle_mcck) -	la	%r14,BASED(sysc_work_loop) +	la	%r14,BASED(sysc_return)  	br	%r1			# TIF bit will be cleared by handler  # @@ -355,7 +337,7 @@ sysc_sigpending:  	bo	BASED(sysc_restart)  	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP  	bo	BASED(sysc_singlestep) -	b	BASED(sysc_work_loop) +	b	BASED(sysc_return)  #  # _TIF_NOTIFY_RESUME is set, call do_notify_resume @@ -363,7 +345,7 @@ sysc_sigpending:  sysc_notify_resume:  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	l	%r1,BASED(.Ldo_notify_resume) -	la	%r14,BASED(sysc_work_loop) +	la	%r14,BASED(sysc_return)  	br	%r1			# call do_notify_resume @@ -458,11 +440,13 @@ kernel_execve:  	br	%r14  	# execve succeeded.  0:	stnsm	__SF_EMPTY(%r15),0xfc	# disable interrupts +	TRACE_IRQS_OFF  	l	%r15,__LC_KERNEL_STACK	# load ksp  	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw  	l	%r9,__LC_THREAD_INFO  	mvc	SP_PTREGS(__PT_SIZE,%r15),0(%r12)	# copy pt_regs  	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) +	TRACE_IRQS_ON  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts  	l	%r1,BASED(.Lexecve_tail)  	basr	%r14,%r1 @@ -499,8 +483,8 @@ pgm_check_handler:  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER  pgm_no_vtime: +	TRACE_IRQS_CHECK_OFF  	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct -	TRACE_IRQS_OFF  	l	%r3,__LC_PGM_ILC	# load program interruption code  	la	%r8,0x7f  	nr	%r8,%r3 @@ -509,8 +493,10 @@ pgm_do_call:  	sll	%r8,2  	l	%r7,0(%r8,%r7)		# load address of handler routine  	la	%r2,SP_PTREGS(%r15)	# address of register-save area -	la	%r14,BASED(sysc_return) -	br	%r7			# branch to interrupt-handler +	basr	%r14,%r7		# branch to interrupt-handler +pgm_exit: +	TRACE_IRQS_CHECK_ON +	b	BASED(sysc_return)  #  # handle per exception @@ -537,19 +523,19 @@ pgm_per_std:  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER  pgm_no_vtime2: +	TRACE_IRQS_CHECK_OFF  	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct -	TRACE_IRQS_OFF  	l	%r1,__TI_task(%r9) +	tm	SP_PSW+1(%r15),0x01	# kernel per event ? +	bz	BASED(kernel_per)  	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID  	mvc	__THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS  	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID  	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP -	tm	SP_PSW+1(%r15),0x01	# kernel per event ? -	bz	BASED(kernel_per)  	l	%r3,__LC_PGM_ILC	# load program interruption code  	la	%r8,0x7f  	nr	%r8,%r3 		# clear per-event-bit and ilc -	be	BASED(sysc_return)	# only per or per+check ? +	be	BASED(pgm_exit)		# only per or per+check ?  	b	BASED(pgm_do_call)  # @@ -570,8 +556,8 @@ pgm_svcper:  	mvc	__THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID  	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP  	TRACE_IRQS_ON -	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts +	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments  	b	BASED(sysc_do_svc)  # @@ -582,8 +568,8 @@ kernel_per:  	mvi	SP_SVCNR+1(%r15),0xff  	la	%r2,SP_PTREGS(%r15)	# address of register-save area  	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler -	la	%r14,BASED(sysc_restore)# load adr. of system return -	br	%r1			# branch to do_single_step +	basr	%r14,%r1		# branch to do_single_step +	b	BASED(pgm_exit)  /*   * IO interrupt handler routine @@ -602,134 +588,126 @@ io_int_handler:  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER  io_no_vtime: -	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct  	TRACE_IRQS_OFF +	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct  	l	%r1,BASED(.Ldo_IRQ)	# load address of do_IRQ  	la	%r2,SP_PTREGS(%r15)	# address of register-save area  	basr	%r14,%r1		# branch to standard irq handler  io_return: +	LOCKDEP_SYS_EXIT +	TRACE_IRQS_ON +io_tif:  	tm	__TI_flags+3(%r9),_TIF_WORK_INT  	bnz	BASED(io_work)		# there is work to do (signals etc.)  io_restore: -#ifdef CONFIG_TRACE_IRQFLAGS -	la	%r1,BASED(io_restore_trace_psw_addr) -	l	%r1,0(%r1) -	lpsw	0(%r1) -io_restore_trace: -	TRACE_IRQS_CHECK -	LOCKDEP_SYS_EXIT -#endif -io_leave:  	RESTORE_ALL __LC_RETURN_PSW,0  io_done: -#ifdef CONFIG_TRACE_IRQFLAGS -io_restore_trace_psw_addr: -	.long io_restore_trace_psw - -	.section .data,"aw",@progbits -	.align	8 -	.globl	io_restore_trace_psw -io_restore_trace_psw: -	.long	0, io_restore_trace + 0x80000000 -	.previous -#endif -  # -# switch to kernel stack, then check the TIF bits +# 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 +# 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.  #  io_work:  	tm	SP_PSW+1(%r15),0x01	# returning to user ? -#ifndef CONFIG_PREEMPT -	bno	BASED(io_restore)	# no-> skip resched & signal -#else -	bnz	BASED(io_work_user)	# no -> check for preemptive scheduling +	bo	BASED(io_work_user)	# yes -> do resched & signal +#ifdef CONFIG_PREEMPT  	# check for preemptive scheduling  	icm	%r0,15,__TI_precount(%r9)  	bnz	BASED(io_restore)	# preemption disabled +	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED +	bno	BASED(io_restore) +	# switch to kernel stack  	l	%r1,SP_R15(%r15)  	s	%r1,BASED(.Lc_spsize)  	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)  	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain  	lr	%r15,%r1 -io_resume_loop: -	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED -	bno	BASED(io_restore) +	# TRACE_IRQS_ON already done at io_return, call +	# TRACE_IRQS_OFF to keep things symmetrical +	TRACE_IRQS_OFF  	l	%r1,BASED(.Lpreempt_schedule_irq) -	la	%r14,BASED(io_resume_loop) -	br	%r1			# call schedule +	basr	%r14,%r1		# call preempt_schedule_irq +	b	BASED(io_return) +#else +	b	BASED(io_restore)  #endif +# +# Need to do work before returning to userspace, switch to kernel stack +#  io_work_user:  	l	%r1,__LC_KERNEL_STACK  	s	%r1,BASED(.Lc_spsize)  	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)  	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain  	lr	%r15,%r1 +  #  # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED +# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED  #		and _TIF_MCCK_PENDING  # -io_work_loop: +io_work_tif:  	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING  	bo	BASED(io_mcck_pending)  	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED  	bo	BASED(io_reschedule)  	tm	__TI_flags+3(%r9),_TIF_SIGPENDING -	bnz	BASED(io_sigpending) +	bo	BASED(io_sigpending)  	tm	__TI_flags+3(%r9),_TIF_NOTIFY_RESUME -	bnz	BASED(io_notify_resume) -	b	BASED(io_restore) -io_work_done: +	bo	BASED(io_notify_resume) +	b	BASED(io_return)	# beware of critical section cleanup  #  # _TIF_MCCK_PENDING is set, call handler  #  io_mcck_pending: +	# TRACE_IRQS_ON already done at io_return  	l	%r1,BASED(.Ls390_handle_mcck)  	basr	%r14,%r1		# TIF bit will be cleared by handler -	b	BASED(io_work_loop) +	TRACE_IRQS_OFF +	b	BASED(io_return)  #  # _TIF_NEED_RESCHED is set, call schedule  #  io_reschedule: -	TRACE_IRQS_ON +	# TRACE_IRQS_ON already done at io_return  	l	%r1,BASED(.Lschedule)  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts  	basr	%r14,%r1		# call scheduler  	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts  	TRACE_IRQS_OFF -	tm	__TI_flags+3(%r9),_TIF_WORK_INT -	bz	BASED(io_restore)	# there is no work to do -	b	BASED(io_work_loop) +	b	BASED(io_return)  #  # _TIF_SIGPENDING is set, call do_signal  #  io_sigpending: -	TRACE_IRQS_ON +	# TRACE_IRQS_ON already done at io_return  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	l	%r1,BASED(.Ldo_signal)  	basr	%r14,%r1		# call do_signal  	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts  	TRACE_IRQS_OFF -	b	BASED(io_work_loop) +	b	BASED(io_return)  #  # _TIF_SIGPENDING is set, call do_signal  #  io_notify_resume: -	TRACE_IRQS_ON +	# TRACE_IRQS_ON already done at io_return  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	l	%r1,BASED(.Ldo_notify_resume)  	basr	%r14,%r1		# call do_signal  	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts  	TRACE_IRQS_OFF -	b	BASED(io_work_loop) +	b	BASED(io_return)  /*   * External interrupt handler routine @@ -764,15 +742,14 @@ __critical_end:  	.globl mcck_int_handler  mcck_int_handler: -	stck	__LC_INT_CLOCK +	stck	__LC_MCCK_CLOCK  	spt	__LC_CPU_TIMER_SAVE_AREA	# revalidate cpu timer  	lm	%r0,%r15,__LC_GPREGS_SAVE_AREA	# revalidate gprs  	SAVE_ALL_BASE __LC_SAVE_AREA+32  	la	%r12,__LC_MCK_OLD_PSW  	tm	__LC_MCCK_CODE,0x80	# system damage?  	bo	BASED(mcck_int_main)	# yes -> rest of mcck code invalid -	mvc	__LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER -	mvc	__LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA +	mvc	__LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA  	tm	__LC_MCCK_CODE+5,0x02	# stored cpu timer value valid?  	bo	BASED(1f)  	la	%r14,__LC_SYNC_ENTER_TIMER @@ -786,7 +763,7 @@ mcck_int_handler:  	bl	BASED(0f)  	la	%r14,__LC_LAST_UPDATE_TIMER  0:	spt	0(%r14) -	mvc	__LC_ASYNC_ENTER_TIMER(8),0(%r14) +	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)  1:	tm	__LC_MCCK_CODE+2,0x09	# mwp + ia of old psw valid?  	bno	BASED(mcck_int_main)	# no -> skip cleanup critical  	tm	__LC_MCK_OLD_PSW+1,0x01	# test problem state bit @@ -808,9 +785,9 @@ mcck_int_main:  	bno	BASED(mcck_no_vtime)	# no -> skip cleanup critical  	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?  	bz	BASED(mcck_no_vtime) -	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER +	UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER -	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER  mcck_no_vtime:  	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct  	la	%r2,SP_PTREGS(%r15)	# load pt_regs @@ -833,7 +810,6 @@ mcck_no_vtime:  mcck_return:  	mvc	__LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW  	ni	__LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit -	mvc	__LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52  	tm	__LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?  	bno	BASED(0f)  	lm	%r0,%r15,SP_R0(%r15)	# load gprs 0-15 @@ -917,18 +893,14 @@ stack_overflow:  cleanup_table_system_call:  	.long	system_call + 0x80000000, sysc_do_svc + 0x80000000 -cleanup_table_sysc_return: -	.long	sysc_return + 0x80000000, sysc_leave + 0x80000000 -cleanup_table_sysc_leave: -	.long	sysc_leave + 0x80000000, sysc_done + 0x80000000 -cleanup_table_sysc_work_loop: -	.long	sysc_work_loop + 0x80000000, sysc_work_done + 0x80000000 -cleanup_table_io_return: -	.long	io_return + 0x80000000, io_leave + 0x80000000 -cleanup_table_io_leave: -	.long	io_leave + 0x80000000, io_done + 0x80000000 -cleanup_table_io_work_loop: -	.long	io_work_loop + 0x80000000, io_work_done + 0x80000000 +cleanup_table_sysc_tif: +	.long	sysc_tif + 0x80000000, sysc_restore + 0x80000000 +cleanup_table_sysc_restore: +	.long	sysc_restore + 0x80000000, sysc_done + 0x80000000 +cleanup_table_io_tif: +	.long	io_tif + 0x80000000, io_restore + 0x80000000 +cleanup_table_io_restore: +	.long	io_restore + 0x80000000, io_done + 0x80000000  cleanup_critical:  	clc	4(4,%r12),BASED(cleanup_table_system_call) @@ -936,49 +908,40 @@ cleanup_critical:  	clc	4(4,%r12),BASED(cleanup_table_system_call+4)  	bl	BASED(cleanup_system_call)  0: -	clc	4(4,%r12),BASED(cleanup_table_sysc_return) -	bl	BASED(0f) -	clc	4(4,%r12),BASED(cleanup_table_sysc_return+4) -	bl	BASED(cleanup_sysc_return) -0: -	clc	4(4,%r12),BASED(cleanup_table_sysc_leave) -	bl	BASED(0f) -	clc	4(4,%r12),BASED(cleanup_table_sysc_leave+4) -	bl	BASED(cleanup_sysc_leave) -0: -	clc	4(4,%r12),BASED(cleanup_table_sysc_work_loop) +	clc	4(4,%r12),BASED(cleanup_table_sysc_tif)  	bl	BASED(0f) -	clc	4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) -	bl	BASED(cleanup_sysc_return) +	clc	4(4,%r12),BASED(cleanup_table_sysc_tif+4) +	bl	BASED(cleanup_sysc_tif)  0: -	clc	4(4,%r12),BASED(cleanup_table_io_return) +	clc	4(4,%r12),BASED(cleanup_table_sysc_restore)  	bl	BASED(0f) -	clc	4(4,%r12),BASED(cleanup_table_io_return+4) -	bl	BASED(cleanup_io_return) +	clc	4(4,%r12),BASED(cleanup_table_sysc_restore+4) +	bl	BASED(cleanup_sysc_restore)  0: -	clc	4(4,%r12),BASED(cleanup_table_io_leave) +	clc	4(4,%r12),BASED(cleanup_table_io_tif)  	bl	BASED(0f) -	clc	4(4,%r12),BASED(cleanup_table_io_leave+4) -	bl	BASED(cleanup_io_leave) +	clc	4(4,%r12),BASED(cleanup_table_io_tif+4) +	bl	BASED(cleanup_io_tif)  0: -	clc	4(4,%r12),BASED(cleanup_table_io_work_loop) +	clc	4(4,%r12),BASED(cleanup_table_io_restore)  	bl	BASED(0f) -	clc	4(4,%r12),BASED(cleanup_table_io_work_loop+4) -	bl	BASED(cleanup_io_work_loop) +	clc	4(4,%r12),BASED(cleanup_table_io_restore+4) +	bl	BASED(cleanup_io_restore)  0:  	br	%r14  cleanup_system_call:  	mvc	__LC_RETURN_PSW(8),0(%r12) -	c	%r12,BASED(.Lmck_old_psw) -	be	BASED(0f) -	la	%r12,__LC_SAVE_AREA+16 -	b	BASED(1f) -0:	la	%r12,__LC_SAVE_AREA+32 -1:  	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4)  	bh	BASED(0f) +	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER +	c	%r12,BASED(.Lmck_old_psw) +	be	BASED(0f)  	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER +0:	c	%r12,BASED(.Lmck_old_psw) +	la	%r12,__LC_SAVE_AREA+32 +	be	BASED(0f) +	la	%r12,__LC_SAVE_AREA+16  0:	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8)  	bhe	BASED(cleanup_vtime)  	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) @@ -1011,61 +974,54 @@ cleanup_system_call_insn:  	.long	sysc_stime + 0x80000000  	.long	sysc_update + 0x80000000 -cleanup_sysc_return: +cleanup_sysc_tif:  	mvc	__LC_RETURN_PSW(4),0(%r12) -	mvc	__LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_return) +	mvc	__LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_tif)  	la	%r12,__LC_RETURN_PSW  	br	%r14 -cleanup_sysc_leave: -	clc	4(4,%r12),BASED(cleanup_sysc_leave_insn) +cleanup_sysc_restore: +	clc	4(4,%r12),BASED(cleanup_sysc_restore_insn)  	be	BASED(2f) +	mvc	__LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER +	c	%r12,BASED(.Lmck_old_psw) +	be	BASED(0f)  	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER -	clc	4(4,%r12),BASED(cleanup_sysc_leave_insn+4) +0:	clc	4(4,%r12),BASED(cleanup_sysc_restore_insn+4)  	be	BASED(2f)  	mvc	__LC_RETURN_PSW(8),SP_PSW(%r15)  	c	%r12,BASED(.Lmck_old_psw) -	bne	BASED(0f) -	mvc	__LC_SAVE_AREA+32(16),SP_R12(%r15) -	b	BASED(1f) -0:	mvc	__LC_SAVE_AREA+16(16),SP_R12(%r15) -1:	lm	%r0,%r11,SP_R0(%r15) +	la	%r12,__LC_SAVE_AREA+32 +	be	BASED(1f) +	la	%r12,__LC_SAVE_AREA+16 +1:	mvc	0(16,%r12),SP_R12(%r15) +	lm	%r0,%r11,SP_R0(%r15)  	l	%r15,SP_R15(%r15)  2:	la	%r12,__LC_RETURN_PSW  	br	%r14 -cleanup_sysc_leave_insn: +cleanup_sysc_restore_insn:  	.long	sysc_done - 4 + 0x80000000  	.long	sysc_done - 8 + 0x80000000 -cleanup_io_return: +cleanup_io_tif:  	mvc	__LC_RETURN_PSW(4),0(%r12) -	mvc	__LC_RETURN_PSW+4(4),BASED(cleanup_table_io_return) +	mvc	__LC_RETURN_PSW+4(4),BASED(cleanup_table_io_tif)  	la	%r12,__LC_RETURN_PSW  	br	%r14 -cleanup_io_work_loop: -	mvc	__LC_RETURN_PSW(4),0(%r12) -	mvc	__LC_RETURN_PSW+4(4),BASED(cleanup_table_io_work_loop) -	la	%r12,__LC_RETURN_PSW -	br	%r14 - -cleanup_io_leave: -	clc	4(4,%r12),BASED(cleanup_io_leave_insn) -	be	BASED(2f) -	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER -	clc	4(4,%r12),BASED(cleanup_io_leave_insn+4) -	be	BASED(2f) +cleanup_io_restore: +	clc	4(4,%r12),BASED(cleanup_io_restore_insn) +	be	BASED(1f) +	mvc	__LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER +	clc	4(4,%r12),BASED(cleanup_io_restore_insn+4) +	be	BASED(1f)  	mvc	__LC_RETURN_PSW(8),SP_PSW(%r15) -	c	%r12,BASED(.Lmck_old_psw) -	bne	BASED(0f)  	mvc	__LC_SAVE_AREA+32(16),SP_R12(%r15) -	b	BASED(1f) -0:	mvc	__LC_SAVE_AREA+16(16),SP_R12(%r15) -1:	lm	%r0,%r11,SP_R0(%r15) +	lm	%r0,%r11,SP_R0(%r15)  	l	%r15,SP_R15(%r15) -2:	la	%r12,__LC_RETURN_PSW +1:	la	%r12,__LC_RETURN_PSW  	br	%r14 -cleanup_io_leave_insn: +cleanup_io_restore_insn:  	.long	io_done - 4 + 0x80000000  	.long	io_done - 8 + 0x80000000 diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 52106d53271..178d92536d9 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -2,7 +2,7 @@   *  arch/s390/kernel/entry64.S   *    S390 low-level entry points.   * - *    Copyright (C) IBM Corp. 1999,2006 + *    Copyright (C) IBM Corp. 1999,2010   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),   *		 Hartmut Penner (hp@de.ibm.com),   *		 Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), @@ -59,30 +59,45 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \  #define BASED(name) name-system_call(%r13) +	.macro	HANDLE_SIE_INTERCEPT +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +	lg	%r3,__LC_SIE_HOOK +	ltgr	%r3,%r3 +	jz	0f +	basr	%r14,%r3 +	0: +#endif +	.endm +  #ifdef CONFIG_TRACE_IRQFLAGS  	.macro	TRACE_IRQS_ON -	 basr	%r2,%r0 -	 brasl	%r14,trace_hardirqs_on_caller +	basr	%r2,%r0 +	brasl	%r14,trace_hardirqs_on_caller  	.endm  	.macro	TRACE_IRQS_OFF -	 basr	%r2,%r0 -	 brasl	%r14,trace_hardirqs_off_caller +	basr	%r2,%r0 +	brasl	%r14,trace_hardirqs_off_caller  	.endm -	.macro TRACE_IRQS_CHECK -	basr	%r2,%r0 +	.macro TRACE_IRQS_CHECK_ON  	tm	SP_PSW(%r15),0x03	# irqs enabled?  	jz	0f -	brasl	%r14,trace_hardirqs_on_caller -	j	1f -0:	brasl	%r14,trace_hardirqs_off_caller -1: +	TRACE_IRQS_ON +0: +	.endm + +	.macro TRACE_IRQS_CHECK_OFF +	tm	SP_PSW(%r15),0x03	# irqs enabled? +	jz	0f +	TRACE_IRQS_OFF +0:  	.endm  #else  #define TRACE_IRQS_ON  #define TRACE_IRQS_OFF -#define TRACE_IRQS_CHECK +#define TRACE_IRQS_CHECK_ON +#define TRACE_IRQS_CHECK_OFF  #endif  #ifdef CONFIG_LOCKDEP @@ -111,31 +126,35 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \   *    R15 - kernel stack pointer   */ -	.macro	SAVE_ALL_BASE savearea -	stmg	%r12,%r15,\savearea -	larl	%r13,system_call -	.endm -  	.macro	SAVE_ALL_SVC psworg,savearea -	la	%r12,\psworg +	stmg	%r11,%r15,\savearea  	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp +	aghi	%r15,-SP_SIZE		# make room for registers & psw +	lg	%r11,__LC_LAST_BREAK  	.endm -	.macro	SAVE_ALL_SYNC psworg,savearea -	la	%r12,\psworg +	.macro	SAVE_ALL_PGM psworg,savearea +	stmg	%r11,%r15,\savearea  	tm	\psworg+1,0x01		# test problem state bit -	jz	2f			# skip stack setup save -	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp  #ifdef CONFIG_CHECK_STACK -	j	3f -2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD -	jz	stack_overflow -3: +	jnz	1f +	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD +	jnz	2f +	la	%r12,\psworg +	j	stack_overflow +#else +	jz	2f  #endif -2: +1:	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp +2:	aghi	%r15,-SP_SIZE		# make room for registers & psw +	larl	%r13,system_call +	lg	%r11,__LC_LAST_BREAK  	.endm  	.macro	SAVE_ALL_ASYNC psworg,savearea +	stmg	%r11,%r15,\savearea +	larl	%r13,system_call +	lg	%r11,__LC_LAST_BREAK  	la	%r12,\psworg  	tm	\psworg+1,0x01		# test problem state bit  	jnz	1f			# from user -> load kernel stack @@ -149,27 +168,23 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \  0:	lg	%r14,__LC_ASYNC_STACK	# are we already on the async. stack ?  	slgr	%r14,%r15  	srag	%r14,%r14,STACK_SHIFT -	jz	2f -1:	lg	%r15,__LC_ASYNC_STACK	# load async stack  #ifdef CONFIG_CHECK_STACK -	j	3f -2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD -	jz	stack_overflow -3: +	jnz	1f +	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD +	jnz	2f +	j	stack_overflow +#else +	jz	2f  #endif -2: +1:	lg	%r15,__LC_ASYNC_STACK	# load async stack +2:	aghi	%r15,-SP_SIZE		# make room for registers & psw  	.endm -	.macro	CREATE_STACK_FRAME psworg,savearea -	aghi	%r15,-SP_SIZE		# make room for registers & psw -	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack +	.macro	CREATE_STACK_FRAME savearea +	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)  	stg	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2 -	icm	%r12,3,__LC_SVC_ILC -	stmg	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack -	st	%r12,SP_SVCNR(%r15) -	mvc	SP_R12(32,%r15),\savearea # move %r12-%r15 to stack -	la	%r12,0 -	stg	%r12,__SF_BACKCHAIN(%r15) +	mvc	SP_R11(40,%r15),\savearea # move %r11-%r15 to stack +	stmg	%r0,%r10,SP_R0(%r15)	# store gprs %r0-%r10 to kernel stack  	.endm  	.macro	RESTORE_ALL psworg,sync @@ -185,6 +200,13 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \  	lpswe	\psworg			# back to caller  	.endm +	.macro	LAST_BREAK +	srag	%r10,%r11,23 +	jz	0f +	stg	%r11,__TI_last_break(%r12) +0: +	.endm +  /*   * Scheduler resume function, called by switch_to   *  gpr2 = (task_struct *) prev @@ -230,143 +252,129 @@ __critical_start:  system_call:  	stpt	__LC_SYNC_ENTER_TIMER  sysc_saveall: -	SAVE_ALL_BASE __LC_SAVE_AREA  	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA -	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA -	llgh	%r7,__LC_SVC_INT_CODE	# get svc number from lowcore +	CREATE_STACK_FRAME __LC_SAVE_AREA +	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW +	mvc	SP_ILC(4,%r15),__LC_SVC_ILC +	stg	%r7,SP_ARGS(%r15) +	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct  sysc_vtime:  	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER  sysc_stime:  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  sysc_update:  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +	LAST_BREAK  sysc_do_svc: -	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct -	ltgr	%r7,%r7		# test for svc 0 +	llgh	%r7,SP_SVCNR(%r15) +	slag	%r7,%r7,2	# shift and test for svc 0  	jnz	sysc_nr_ok  	# svc 0: system call number in %r1 -	cl	%r1,BASED(.Lnr_syscalls) +	llgfr	%r1,%r1		# clear high word in r1 +	cghi	%r1,NR_syscalls  	jnl	sysc_nr_ok -	lgfr	%r7,%r1 	# clear high word in r1 +	sth	%r1,SP_SVCNR(%r15) +	slag	%r7,%r1,2	# shift and test for svc 0  sysc_nr_ok: -	mvc	SP_ARGS(8,%r15),SP_R7(%r15) -sysc_do_restart: -	sth	%r7,SP_SVCNR(%r15) -	sllg	%r7,%r7,2	# svc number * 4  	larl	%r10,sys_call_table  #ifdef CONFIG_COMPAT -	tm	__TI_flags+5(%r9),(_TIF_31BIT>>16)  # running in 31 bit mode ? +	tm	__TI_flags+5(%r12),(_TIF_31BIT>>16)  # running in 31 bit mode ?  	jno	sysc_noemu  	larl	%r10,sys_call_table_emu  # use 31 bit emulation system calls  sysc_noemu:  #endif -	tm	__TI_flags+6(%r9),_TIF_SYSCALL +	tm	__TI_flags+6(%r12),_TIF_SYSCALL  	lgf	%r8,0(%r7,%r10) # load address of system call routine  	jnz	sysc_tracesys  	basr	%r14,%r8	# call sys_xxxx  	stg	%r2,SP_R2(%r15) # store return value (change R2 on stack)  sysc_return: -	tm	__TI_flags+7(%r9),_TIF_WORK_SVC +	LOCKDEP_SYS_EXIT +sysc_tif: +	tm	__TI_flags+7(%r12),_TIF_WORK_SVC  	jnz	sysc_work	# there is work to do (signals etc.)  sysc_restore: -#ifdef CONFIG_TRACE_IRQFLAGS -	larl	%r1,sysc_restore_trace_psw -	lpswe	0(%r1) -sysc_restore_trace: -	TRACE_IRQS_CHECK -	LOCKDEP_SYS_EXIT -#endif -sysc_leave:  	RESTORE_ALL __LC_RETURN_PSW,1  sysc_done: -#ifdef CONFIG_TRACE_IRQFLAGS -	.section .data,"aw",@progbits -	.align	8 -	.globl sysc_restore_trace_psw -sysc_restore_trace_psw: -	.quad	0, sysc_restore_trace -	.previous -#endif - -# -# recheck if there is more work to do  # -sysc_work_loop: -	tm	__TI_flags+7(%r9),_TIF_WORK_SVC -	jz	sysc_restore	  # there is no work to do -# -# One of the work bits is on. Find out which one. +# There is work to do, but first we need to check if we return to userspace.  #  sysc_work:  	tm	SP_PSW+1(%r15),0x01	# returning to user ?  	jno	sysc_restore -	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING + +# +# One of the work bits is on. Find out which one. +# +sysc_work_tif: +	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING  	jo	sysc_mcck_pending -	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED +	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED  	jo	sysc_reschedule -	tm	__TI_flags+7(%r9),_TIF_SIGPENDING -	jnz	sysc_sigpending -	tm	__TI_flags+7(%r9),_TIF_NOTIFY_RESUME -	jnz	sysc_notify_resume -	tm	__TI_flags+7(%r9),_TIF_RESTART_SVC +	tm	__TI_flags+7(%r12),_TIF_SIGPENDING +	jo	sysc_sigpending +	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME +	jo	sysc_notify_resume +	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC  	jo	sysc_restart -	tm	__TI_flags+7(%r9),_TIF_SINGLE_STEP +	tm	__TI_flags+7(%r12),_TIF_SINGLE_STEP  	jo	sysc_singlestep -	j	sysc_restore -sysc_work_done: +	j	sysc_return		# beware of critical section cleanup  #  # _TIF_NEED_RESCHED is set, call schedule  #  sysc_reschedule: -	larl	%r14,sysc_work_loop -	jg	schedule	# return point is sysc_return +	larl	%r14,sysc_return +	jg	schedule		# return point is sysc_return  #  # _TIF_MCCK_PENDING is set, call handler  #  sysc_mcck_pending: -	larl	%r14,sysc_work_loop +	larl	%r14,sysc_return  	jg	s390_handle_mcck	# TIF bit will be cleared by handler  #  # _TIF_SIGPENDING is set, call do_signal  #  sysc_sigpending: -	ni	__TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP +	ni	__TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	brasl	%r14,do_signal		# call do_signal -	tm	__TI_flags+7(%r9),_TIF_RESTART_SVC +	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC  	jo	sysc_restart -	tm	__TI_flags+7(%r9),_TIF_SINGLE_STEP +	tm	__TI_flags+7(%r12),_TIF_SINGLE_STEP  	jo	sysc_singlestep -	j	sysc_work_loop +	j	sysc_return  #  # _TIF_NOTIFY_RESUME is set, call do_notify_resume  #  sysc_notify_resume:  	la	%r2,SP_PTREGS(%r15)	# load pt_regs -	larl	%r14,sysc_work_loop +	larl	%r14,sysc_return  	jg	do_notify_resume	# call do_notify_resume  #  # _TIF_RESTART_SVC is set, set up registers and restart svc  #  sysc_restart: -	ni	__TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC +	ni	__TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC  	lg	%r7,SP_R2(%r15)		# load new svc number  	mvc	SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument  	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments -	j	sysc_do_restart 	# restart svc +	sth	%r7,SP_SVCNR(%r15) +	slag	%r7,%r7,2 +	j	sysc_nr_ok		# restart svc  #  # _TIF_SINGLE_STEP is set, call do_single_step  #  sysc_singlestep: -	ni	__TI_flags+7(%r9),255-_TIF_SINGLE_STEP	# clear TIF_SINGLE_STEP +	ni	__TI_flags+7(%r12),255-_TIF_SINGLE_STEP	# clear TIF_SINGLE_STEP  	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number  	la	%r2,SP_PTREGS(%r15)	# address of register-save area  	larl	%r14,sysc_return	# load adr. of system return @@ -379,8 +387,8 @@ sysc_singlestep:  sysc_tracesys:  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	la	%r3,0 -	srl	%r7,2 -	stg	%r7,SP_R2(%r15) +	llgh	%r0,SP_SVCNR(%r15) +	stg	%r0,SP_R2(%r15)  	brasl	%r14,do_syscall_trace_enter  	lghi	%r0,NR_syscalls  	clgr	%r0,%r2 @@ -393,7 +401,7 @@ sysc_tracego:  	basr	%r14,%r8		# call sys_xxx  	stg	%r2,SP_R2(%r15)		# store return value  sysc_tracenogo: -	tm	__TI_flags+6(%r9),_TIF_SYSCALL +	tm	__TI_flags+6(%r12),_TIF_SYSCALL  	jz	sysc_return  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	larl	%r14,sysc_return	# return point is sysc_return @@ -405,7 +413,7 @@ sysc_tracenogo:  	.globl	ret_from_fork  ret_from_fork:  	lg	%r13,__LC_SVC_NEW_PSW+8 -	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct +	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct  	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?  	jo	0f  	stg	%r15,SP_R15(%r15)	# store stack pointer for new kthread @@ -435,12 +443,14 @@ kernel_execve:  	br	%r14  	# execve succeeded.  0:	stnsm	__SF_EMPTY(%r15),0xfc	# disable interrupts +#	TRACE_IRQS_OFF  	lg	%r15,__LC_KERNEL_STACK	# load ksp  	aghi	%r15,-SP_SIZE		# make room for registers & psw  	lg	%r13,__LC_SVC_NEW_PSW+8 -	lg	%r9,__LC_THREAD_INFO  	mvc	SP_PTREGS(__PT_SIZE,%r15),0(%r12)	# copy pt_regs +	lg	%r12,__LC_THREAD_INFO  	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) +#	TRACE_IRQS_ON  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts  	brasl	%r14,execve_tail  	j	sysc_return @@ -465,20 +475,23 @@ pgm_check_handler:   * for LPSW?).   */  	stpt	__LC_SYNC_ENTER_TIMER -	SAVE_ALL_BASE __LC_SAVE_AREA  	tm	__LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception  	jnz	pgm_per 		 # got per exception -> special case -	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA -	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA +	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA +	CREATE_STACK_FRAME __LC_SAVE_AREA +	xc	SP_ILC(4,%r15),SP_ILC(%r15) +	mvc	SP_PSW(16,%r15),__LC_PGM_OLD_PSW +	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct  	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?  	jz	pgm_no_vtime  	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +	LAST_BREAK  pgm_no_vtime: -	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct -	mvc	SP_ARGS(8,%r15),__LC_LAST_BREAK -	TRACE_IRQS_OFF +	HANDLE_SIE_INTERCEPT +	TRACE_IRQS_CHECK_OFF +	stg	%r11,SP_ARGS(%r15)  	lgf	%r3,__LC_PGM_ILC	# load program interruption code  	lghi	%r8,0x7f  	ngr	%r8,%r3 @@ -487,8 +500,10 @@ pgm_do_call:  	larl	%r1,pgm_check_table  	lg	%r1,0(%r8,%r1)		# load address of handler routine  	la	%r2,SP_PTREGS(%r15)	# address of register-save area -	larl	%r14,sysc_return -	br	%r1			# branch to interrupt-handler +	basr	%r14,%r1		# branch to interrupt-handler +pgm_exit: +	TRACE_IRQS_CHECK_ON +	j	sysc_return  #  # handle per exception @@ -500,55 +515,60 @@ pgm_per:  	clc	__LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW  	je	pgm_svcper  # no interesting special case, ignore PER event -	lmg	%r12,%r15,__LC_SAVE_AREA  	lpswe	__LC_PGM_OLD_PSW  #  # Normal per exception  #  pgm_per_std: -	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA -	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA +	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA +	CREATE_STACK_FRAME __LC_SAVE_AREA +	mvc	SP_PSW(16,%r15),__LC_PGM_OLD_PSW +	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct  	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?  	jz	pgm_no_vtime2  	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +	LAST_BREAK  pgm_no_vtime2: -	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct -	TRACE_IRQS_OFF -	lg	%r1,__TI_task(%r9) +	HANDLE_SIE_INTERCEPT +	TRACE_IRQS_CHECK_OFF +	lg	%r1,__TI_task(%r12)  	tm	SP_PSW+1(%r15),0x01	# kernel per event ?  	jz	kernel_per  	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID  	mvc	__THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS  	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID -	oi	__TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP +	oi	__TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP  	lgf	%r3,__LC_PGM_ILC	# load program interruption code  	lghi	%r8,0x7f  	ngr	%r8,%r3			# clear per-event-bit and ilc -	je	sysc_return +	je	pgm_exit  	j	pgm_do_call  #  # it was a single stepped SVC that is causing all the trouble  #  pgm_svcper: -	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA -	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA +	SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA +	CREATE_STACK_FRAME __LC_SAVE_AREA +	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW +	mvc	SP_ILC(4,%r15),__LC_SVC_ILC +	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct  	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER -	llgh	%r7,__LC_SVC_INT_CODE	# get svc number from lowcore -	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct -	lg	%r8,__TI_task(%r9) +	LAST_BREAK +	TRACE_IRQS_OFF +	lg	%r8,__TI_task(%r12)  	mvc	__THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID  	mvc	__THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS  	mvc	__THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID -	oi	__TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP +	oi	__TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP  	TRACE_IRQS_ON -	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts +	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments  	j	sysc_do_svc  # @@ -557,8 +577,8 @@ pgm_svcper:  kernel_per:  	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)	# clear svc number  	la	%r2,SP_PTREGS(%r15)	# address of register-save area -	larl	%r14,sysc_restore	# load adr. of system ret, no work -	jg	do_single_step		# branch to do_single_step +	brasl	%r14,do_single_step +	j	pgm_exit  /*   * IO interrupt handler routine @@ -567,162 +587,133 @@ kernel_per:  io_int_handler:  	stck	__LC_INT_CLOCK  	stpt	__LC_ASYNC_ENTER_TIMER -	SAVE_ALL_BASE __LC_SAVE_AREA+32 -	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 -	CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 +	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+40 +	CREATE_STACK_FRAME __LC_SAVE_AREA+40 +	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack +	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct  	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?  	jz	io_no_vtime  	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +	LAST_BREAK  io_no_vtime: -	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct +	HANDLE_SIE_INTERCEPT  	TRACE_IRQS_OFF  	la	%r2,SP_PTREGS(%r15)	# address of register-save area  	brasl	%r14,do_IRQ		# call standard irq handler  io_return: -	tm	__TI_flags+7(%r9),_TIF_WORK_INT +	LOCKDEP_SYS_EXIT +	TRACE_IRQS_ON +io_tif: +	tm	__TI_flags+7(%r12),_TIF_WORK_INT  	jnz	io_work 		# there is work to do (signals etc.)  io_restore: -#ifdef CONFIG_TRACE_IRQFLAGS -	larl	%r1,io_restore_trace_psw -	lpswe	0(%r1) -io_restore_trace: -	TRACE_IRQS_CHECK -	LOCKDEP_SYS_EXIT -#endif -io_leave:  	RESTORE_ALL __LC_RETURN_PSW,0  io_done: -#ifdef CONFIG_TRACE_IRQFLAGS -	.section .data,"aw",@progbits -	.align	8 -	.globl io_restore_trace_psw -io_restore_trace_psw: -	.quad	0, io_restore_trace -	.previous -#endif -  # -# There is work todo, we need to check if we return to userspace, then -# check, if we are in SIE, if yes leave it +# 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 +# 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 +#    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.  #  io_work:  	tm	SP_PSW+1(%r15),0x01	# returning to user ? -#ifndef CONFIG_PREEMPT -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) -	jnz	io_work_user		# yes -> no need to check for SIE -	la	%r1, BASED(sie_opcode)	# we return to kernel here -	lg	%r2, SP_PSW+8(%r15) -	clc	0(2,%r1), 0(%r2)	# is current instruction = SIE? -	jne	io_restore		# no-> return to kernel -	lg	%r1, SP_PSW+8(%r15)	# yes-> add 4 bytes to leave SIE -	aghi	%r1, 4 -	stg	%r1, SP_PSW+8(%r15) -	j	io_restore		# return to kernel -#else -	jno	io_restore		# no-> skip resched & signal -#endif -#else -	jnz	io_work_user		# yes -> do resched & signal -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) -	la	%r1, BASED(sie_opcode) -	lg	%r2, SP_PSW+8(%r15) -	clc	0(2,%r1), 0(%r2)	# is current instruction = SIE? -	jne	0f			# no -> leave PSW alone -	lg	%r1, SP_PSW+8(%r15)	# yes-> add 4 bytes to leave SIE -	aghi	%r1, 4 -	stg	%r1, SP_PSW+8(%r15) -0: -#endif +	jo	io_work_user		# yes -> do resched & signal +#ifdef CONFIG_PREEMPT  	# check for preemptive scheduling -	icm	%r0,15,__TI_precount(%r9) +	icm	%r0,15,__TI_precount(%r12)  	jnz	io_restore		# preemption is disabled +	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED +	jno	io_restore  	# switch to kernel stack  	lg	%r1,SP_R15(%r15)  	aghi	%r1,-SP_SIZE  	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)  	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain  	lgr	%r15,%r1 -io_resume_loop: -	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED -	jno	io_restore -	larl	%r14,io_resume_loop -	jg	preempt_schedule_irq +	# TRACE_IRQS_ON already done at io_return, call +	# TRACE_IRQS_OFF to keep things symmetrical +	TRACE_IRQS_OFF +	brasl	%r14,preempt_schedule_irq +	j	io_return +#else +	j	io_restore  #endif +# +# Need to do work before returning to userspace, switch to kernel stack +#  io_work_user:  	lg	%r1,__LC_KERNEL_STACK  	aghi	%r1,-SP_SIZE  	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)  	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain  	lgr	%r15,%r1 +  #  # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGPENDING, _TIF_NEED_RESCHED +# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED  #	       and _TIF_MCCK_PENDING  # -io_work_loop: -	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING +io_work_tif: +	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING  	jo	io_mcck_pending -	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED +	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED  	jo	io_reschedule -	tm	__TI_flags+7(%r9),_TIF_SIGPENDING -	jnz	io_sigpending -	tm	__TI_flags+7(%r9),_TIF_NOTIFY_RESUME -	jnz	io_notify_resume -	j	io_restore -io_work_done: - -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) -sie_opcode: -	.long 0xb2140000 -#endif +	tm	__TI_flags+7(%r12),_TIF_SIGPENDING +	jo	io_sigpending +	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME +	jo	io_notify_resume +	j	io_return		# beware of critical section cleanup  #  # _TIF_MCCK_PENDING is set, call handler  #  io_mcck_pending: +	# TRACE_IRQS_ON already done at io_return  	brasl	%r14,s390_handle_mcck	# TIF bit will be cleared by handler -	j	io_work_loop +	TRACE_IRQS_OFF +	j	io_return  #  # _TIF_NEED_RESCHED is set, call schedule  #  io_reschedule: -	TRACE_IRQS_ON +	# TRACE_IRQS_ON already done at io_return  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts  	brasl	%r14,schedule		# call scheduler  	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts  	TRACE_IRQS_OFF -	tm	__TI_flags+7(%r9),_TIF_WORK_INT -	jz	io_restore		# there is no work to do -	j	io_work_loop +	j	io_return  #  # _TIF_SIGPENDING or is set, call do_signal  #  io_sigpending: -	TRACE_IRQS_ON +	# TRACE_IRQS_ON already done at io_return  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	brasl	%r14,do_signal		# call do_signal  	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts  	TRACE_IRQS_OFF -	j	io_work_loop +	j	io_return  #  # _TIF_NOTIFY_RESUME or is set, call do_notify_resume  #  io_notify_resume: -	TRACE_IRQS_ON +	# TRACE_IRQS_ON already done at io_return  	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	brasl	%r14,do_notify_resume	# call do_notify_resume  	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts  	TRACE_IRQS_OFF -	j	io_work_loop +	j	io_return  /*   * External interrupt handler routine @@ -731,16 +722,18 @@ io_notify_resume:  ext_int_handler:  	stck	__LC_INT_CLOCK  	stpt	__LC_ASYNC_ENTER_TIMER -	SAVE_ALL_BASE __LC_SAVE_AREA+32 -	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 -	CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 +	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+40 +	CREATE_STACK_FRAME __LC_SAVE_AREA+40 +	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack +	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct  	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?  	jz	ext_no_vtime  	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +	LAST_BREAK  ext_no_vtime: -	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct +	HANDLE_SIE_INTERCEPT  	TRACE_IRQS_OFF  	la	%r2,SP_PTREGS(%r15)	# address of register-save area  	llgh	%r3,__LC_EXT_INT_CODE	# get interruption code @@ -754,17 +747,18 @@ __critical_end:   */  	.globl mcck_int_handler  mcck_int_handler: -	stck	__LC_INT_CLOCK +	stck	__LC_MCCK_CLOCK  	la	%r1,4095		# revalidate r1  	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer  	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs -	SAVE_ALL_BASE __LC_SAVE_AREA+64 +	stmg	%r11,%r15,__LC_SAVE_AREA+80 +	larl	%r13,system_call +	lg	%r11,__LC_LAST_BREAK  	la	%r12,__LC_MCK_OLD_PSW  	tm	__LC_MCCK_CODE,0x80	# system damage?  	jo	mcck_int_main		# yes -> rest of mcck code invalid  	la	%r14,4095 -	mvc	__LC_SAVE_AREA+104(8),__LC_ASYNC_ENTER_TIMER -	mvc	__LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) +	mvc	__LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14)  	tm	__LC_MCCK_CODE+5,0x02	# stored cpu timer value valid?  	jo	1f  	la	%r14,__LC_SYNC_ENTER_TIMER @@ -778,7 +772,7 @@ mcck_int_handler:  	jl	0f  	la	%r14,__LC_LAST_UPDATE_TIMER  0:	spt	0(%r14) -	mvc	__LC_ASYNC_ENTER_TIMER(8),0(%r14) +	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)  1:	tm	__LC_MCCK_CODE+2,0x09	# mwp + ia of old psw valid?  	jno	mcck_int_main		# no -> skip cleanup critical  	tm	__LC_MCK_OLD_PSW+1,0x01 # test problem state bit @@ -794,16 +788,19 @@ mcck_int_main:  	srag	%r14,%r14,PAGE_SHIFT  	jz	0f  	lg	%r15,__LC_PANIC_STACK	# load panic stack -0:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 +0:	aghi	%r15,-SP_SIZE		# make room for registers & psw +	CREATE_STACK_FRAME __LC_SAVE_AREA+80 +	mvc	SP_PSW(16,%r15),0(%r12) +	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct  	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?  	jno	mcck_no_vtime		# no -> no timer update  	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?  	jz	mcck_no_vtime -	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER +	UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER -	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER +	LAST_BREAK  mcck_no_vtime: -	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct  	la	%r2,SP_PTREGS(%r15)	# load pt_regs  	brasl	%r14,s390_do_machine_check  	tm	SP_PSW+1(%r15),0x01	# returning to user ? @@ -814,8 +811,9 @@ mcck_no_vtime:  	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain  	lgr	%r15,%r1  	stosm	__SF_EMPTY(%r15),0x04	# turn dat on -	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING +	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING  	jno	mcck_return +	HANDLE_SIE_INTERCEPT  	TRACE_IRQS_OFF  	brasl	%r14,s390_handle_mcck  	TRACE_IRQS_ON @@ -823,11 +821,11 @@ mcck_return:  	mvc	__LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW  	ni	__LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit  	lmg	%r0,%r15,SP_R0(%r15)	# load gprs 0-15 -	mvc	__LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+104  	tm	__LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?  	jno	0f  	stpt	__LC_EXIT_TIMER  0:	lpswe	__LC_RETURN_MCCK_PSW	# back to caller +mcck_done:  /*   * Restart interruption handler, kick starter for additional CPUs @@ -883,14 +881,14 @@ stack_overflow:  	lg	%r15,__LC_PANIC_STACK	# change to panic stack  	aghi	%r15,-SP_SIZE  	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack -	stmg	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack +	stmg	%r0,%r10,SP_R0(%r15)	# store gprs %r0-%r10 to kernel stack  	la	%r1,__LC_SAVE_AREA  	chi	%r12,__LC_SVC_OLD_PSW  	je	0f  	chi	%r12,__LC_PGM_OLD_PSW  	je	0f -	la	%r1,__LC_SAVE_AREA+32 -0:	mvc	SP_R12(32,%r15),0(%r1)	# move %r12-%r15 to stack +	la	%r1,__LC_SAVE_AREA+40 +0:	mvc	SP_R11(40,%r15),0(%r1)	# move %r11-%r15 to stack  	mvc	SP_ARGS(8,%r15),__LC_LAST_BREAK  	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain  	la	%r2,SP_PTREGS(%r15)	# load pt_regs @@ -899,18 +897,14 @@ stack_overflow:  cleanup_table_system_call:  	.quad	system_call, sysc_do_svc -cleanup_table_sysc_return: -	.quad	sysc_return, sysc_leave -cleanup_table_sysc_leave: -	.quad	sysc_leave, sysc_done -cleanup_table_sysc_work_loop: -	.quad	sysc_work_loop, sysc_work_done -cleanup_table_io_return: -	.quad	io_return, io_leave -cleanup_table_io_leave: -	.quad	io_leave, io_done -cleanup_table_io_work_loop: -	.quad	io_work_loop, io_work_done +cleanup_table_sysc_tif: +	.quad	sysc_tif, sysc_restore +cleanup_table_sysc_restore: +	.quad	sysc_restore, sysc_done +cleanup_table_io_tif: +	.quad	io_tif, io_restore +cleanup_table_io_restore: +	.quad	io_restore, io_done  cleanup_critical:  	clc	8(8,%r12),BASED(cleanup_table_system_call) @@ -918,61 +912,54 @@ cleanup_critical:  	clc	8(8,%r12),BASED(cleanup_table_system_call+8)  	jl	cleanup_system_call  0: -	clc	8(8,%r12),BASED(cleanup_table_sysc_return) -	jl	0f -	clc	8(8,%r12),BASED(cleanup_table_sysc_return+8) -	jl	cleanup_sysc_return -0: -	clc	8(8,%r12),BASED(cleanup_table_sysc_leave) +	clc	8(8,%r12),BASED(cleanup_table_sysc_tif)  	jl	0f -	clc	8(8,%r12),BASED(cleanup_table_sysc_leave+8) -	jl	cleanup_sysc_leave +	clc	8(8,%r12),BASED(cleanup_table_sysc_tif+8) +	jl	cleanup_sysc_tif  0: -	clc	8(8,%r12),BASED(cleanup_table_sysc_work_loop) +	clc	8(8,%r12),BASED(cleanup_table_sysc_restore)  	jl	0f -	clc	8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) -	jl	cleanup_sysc_return +	clc	8(8,%r12),BASED(cleanup_table_sysc_restore+8) +	jl	cleanup_sysc_restore  0: -	clc	8(8,%r12),BASED(cleanup_table_io_return) +	clc	8(8,%r12),BASED(cleanup_table_io_tif)  	jl	0f -	clc	8(8,%r12),BASED(cleanup_table_io_return+8) -	jl	cleanup_io_return +	clc	8(8,%r12),BASED(cleanup_table_io_tif+8) +	jl	cleanup_io_tif  0: -	clc	8(8,%r12),BASED(cleanup_table_io_leave) +	clc	8(8,%r12),BASED(cleanup_table_io_restore)  	jl	0f -	clc	8(8,%r12),BASED(cleanup_table_io_leave+8) -	jl	cleanup_io_leave -0: -	clc	8(8,%r12),BASED(cleanup_table_io_work_loop) -	jl	0f -	clc	8(8,%r12),BASED(cleanup_table_io_work_loop+8) -	jl	cleanup_io_work_loop +	clc	8(8,%r12),BASED(cleanup_table_io_restore+8) +	jl	cleanup_io_restore  0:  	br	%r14  cleanup_system_call:  	mvc	__LC_RETURN_PSW(16),0(%r12) -	cghi	%r12,__LC_MCK_OLD_PSW -	je	0f -	la	%r12,__LC_SAVE_AREA+32 -	j	1f -0:	la	%r12,__LC_SAVE_AREA+64 -1:  	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8)  	jh	0f +	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER +	cghi	%r12,__LC_MCK_OLD_PSW +	je	0f  	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER +0:	cghi	%r12,__LC_MCK_OLD_PSW +	la	%r12,__LC_SAVE_AREA+80 +	je	0f +	la	%r12,__LC_SAVE_AREA+40  0:	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16)  	jhe	cleanup_vtime  	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn)  	jh	0f -	mvc	__LC_SAVE_AREA(32),0(%r12) -0:	stg	%r13,8(%r12) -	stg	%r12,__LC_SAVE_AREA+96	# argh -	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA -	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA -	lg	%r12,__LC_SAVE_AREA+96	# argh -	stg	%r15,24(%r12) -	llgh	%r7,__LC_SVC_INT_CODE +	mvc	__LC_SAVE_AREA(40),0(%r12) +0:	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp +	aghi	%r15,-SP_SIZE		# make room for registers & psw +	stg	%r15,32(%r12) +	stg	%r11,0(%r12) +	CREATE_STACK_FRAME __LC_SAVE_AREA +	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW +	mvc	SP_ILC(4,%r15),__LC_SVC_ILC +	stg	%r7,SP_ARGS(%r15) +	mvc	8(8,%r12),__LC_THREAD_INFO  cleanup_vtime:  	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)  	jhe	cleanup_stime @@ -983,7 +970,11 @@ cleanup_stime:  	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER  cleanup_update:  	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER -	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) +	srag	%r12,%r11,23 +	lg	%r12,__LC_THREAD_INFO +	jz	0f +	stg	%r11,__TI_last_break(%r12) +0:	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8)  	la	%r12,__LC_RETURN_PSW  	br	%r14  cleanup_system_call_insn: @@ -993,61 +984,54 @@ cleanup_system_call_insn:  	.quad	sysc_stime  	.quad	sysc_update -cleanup_sysc_return: +cleanup_sysc_tif:  	mvc	__LC_RETURN_PSW(8),0(%r12) -	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_return) +	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_tif)  	la	%r12,__LC_RETURN_PSW  	br	%r14 -cleanup_sysc_leave: -	clc	8(8,%r12),BASED(cleanup_sysc_leave_insn) -	je	3f -	clc	8(8,%r12),BASED(cleanup_sysc_leave_insn+8) +cleanup_sysc_restore: +	clc	8(8,%r12),BASED(cleanup_sysc_restore_insn) +	je	2f +	clc	8(8,%r12),BASED(cleanup_sysc_restore_insn+8)  	jhe	0f +	mvc	__LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER +	cghi	%r12,__LC_MCK_OLD_PSW +	je	0f  	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER  0:	mvc	__LC_RETURN_PSW(16),SP_PSW(%r15)  	cghi	%r12,__LC_MCK_OLD_PSW -	jne	1f -	mvc	__LC_SAVE_AREA+64(32),SP_R12(%r15) -	j	2f -1:	mvc	__LC_SAVE_AREA+32(32),SP_R12(%r15) -2:	lmg	%r0,%r11,SP_R0(%r15) +	la	%r12,__LC_SAVE_AREA+80 +	je	1f +	la	%r12,__LC_SAVE_AREA+40 +1:	mvc	0(40,%r12),SP_R11(%r15) +	lmg	%r0,%r10,SP_R0(%r15)  	lg	%r15,SP_R15(%r15) -3:	la	%r12,__LC_RETURN_PSW +2:	la	%r12,__LC_RETURN_PSW  	br	%r14 -cleanup_sysc_leave_insn: +cleanup_sysc_restore_insn:  	.quad	sysc_done - 4  	.quad	sysc_done - 16 -cleanup_io_return: -	mvc	__LC_RETURN_PSW(8),0(%r12) -	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_io_return) -	la	%r12,__LC_RETURN_PSW -	br	%r14 - -cleanup_io_work_loop: +cleanup_io_tif:  	mvc	__LC_RETURN_PSW(8),0(%r12) -	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_io_work_loop) +	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_io_tif)  	la	%r12,__LC_RETURN_PSW  	br	%r14 -cleanup_io_leave: -	clc	8(8,%r12),BASED(cleanup_io_leave_insn) -	je	3f -	clc	8(8,%r12),BASED(cleanup_io_leave_insn+8) +cleanup_io_restore: +	clc	8(8,%r12),BASED(cleanup_io_restore_insn) +	je	1f +	clc	8(8,%r12),BASED(cleanup_io_restore_insn+8)  	jhe	0f -	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER +	mvc	__LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER  0:	mvc	__LC_RETURN_PSW(16),SP_PSW(%r15) -	cghi	%r12,__LC_MCK_OLD_PSW -	jne	1f -	mvc	__LC_SAVE_AREA+64(32),SP_R12(%r15) -	j	2f -1:	mvc	__LC_SAVE_AREA+32(32),SP_R12(%r15) -2:	lmg	%r0,%r11,SP_R0(%r15) +	mvc	__LC_SAVE_AREA+80(40),SP_R11(%r15) +	lmg	%r0,%r10,SP_R0(%r15)  	lg	%r15,SP_R15(%r15) -3:	la	%r12,__LC_RETURN_PSW +1:	la	%r12,__LC_RETURN_PSW  	br	%r14 -cleanup_io_leave_insn: +cleanup_io_restore_insn:  	.quad	io_done - 4  	.quad	io_done - 16 @@ -1055,13 +1039,6 @@ cleanup_io_leave_insn:   * Integer constants   */  		.align	4 -.Lconst: -.Lnr_syscalls:	.long	NR_syscalls -.L0x0130:	.short	0x130 -.L0x0140:	.short	0x140 -.L0x0150:	.short	0x150 -.L0x0160:	.short	0x160 -.L0x0170:	.short	0x170  .Lcritical_start:  		.quad	__critical_start  .Lcritical_end: diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 9d1f76702d4..51838ad42d5 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -328,8 +328,8 @@ iplstart:  #  # reset files in VM reader  # -	stidp	__LC_CPUID		# store cpuid -	tm	__LC_CPUID,0xff 	# running VM ? +	stidp	__LC_SAVE_AREA		# store cpuid +	tm	__LC_SAVE_AREA,0xff	# running VM ?  	bno	.Lnoreset  	la	%r2,.Lreset  	lhi	%r3,26 diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index 1bbcc499d45..b8f8dc12610 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -82,7 +82,7 @@ startup_continue:  _ehead:  #ifdef CONFIG_SHARED_KERNEL -	.org	0x100000 +	.org	0x100000 - 0x11000	# head.o ends at 0x11000  #endif  # diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 1f70970de0a..cdef6871741 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -80,7 +80,7 @@ startup_continue:  _ehead:  #ifdef CONFIG_SHARED_KERNEL -	.org	0x100000 +	.org	0x100000 - 0x11000	# head.o ends at 0x11000  #endif  # diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 015e27da40e..ac151399ef3 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -255,7 +255,8 @@ void notrace s390_do_machine_check(struct pt_regs *regs)  	int umode;  	nmi_enter(); -	s390_idle_check(); +	s390_idle_check(regs, S390_lowcore.mcck_clock, +			S390_lowcore.mcck_enter_timer);  	mci = (struct mci *) &S390_lowcore.mcck_interruption_code;  	mcck = &__get_cpu_var(cpu_mcck); diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 0729f36c2fe..ecb2d02b02e 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -18,24 +18,42 @@  #include <asm/lowcore.h>  #include <asm/param.h> +static DEFINE_PER_CPU(struct cpuid, cpu_id); + +/* + * cpu_init - initializes state that is per-CPU. + */ +void __cpuinit cpu_init(void) +{ +	struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); + +	get_cpu_id(id); +	atomic_inc(&init_mm.mm_count); +	current->active_mm = &init_mm; +	BUG_ON(current->mm); +	enter_lazy_tlb(&init_mm, current); +} + +/* + * print_cpu_info - print basic information about a cpu + */  void __cpuinit print_cpu_info(void)  { +	struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); +  	pr_info("Processor %d started, address %d, identification %06X\n", -		S390_lowcore.cpu_nr, S390_lowcore.cpu_addr, -		S390_lowcore.cpu_id.ident); +		S390_lowcore.cpu_nr, S390_lowcore.cpu_addr, id->ident);  }  /*   * show_cpuinfo - Get information on one CPU for use by procfs.   */ -  static int show_cpuinfo(struct seq_file *m, void *v)  {  	static const char *hwcap_str[10] = {  		"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",  		"edat", "etf3eh", "highgprs"  	}; -	struct _lowcore *lc;  	unsigned long n = (unsigned long) v - 1;  	int i; @@ -55,19 +73,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)  	}  	if (cpu_online(n)) { -#ifdef CONFIG_SMP -		lc = (smp_processor_id() == n) ? -			&S390_lowcore : lowcore_ptr[n]; -#else -		lc = &S390_lowcore; -#endif +		struct cpuid *id = &per_cpu(cpu_id, n);  		seq_printf(m, "processor %li: "  			   "version = %02X,  "  			   "identification = %06X,  "  			   "machine = %04X\n", -			   n, lc->cpu_id.version, -			   lc->cpu_id.ident, -			   lc->cpu_id.machine); +			   n, id->version, id->ident, id->machine);  	}  	preempt_enable();  	return 0; diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 33fdc5a7976..83339d33c4b 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -57,6 +57,7 @@  enum s390_regset {  	REGSET_GENERAL,  	REGSET_FP, +	REGSET_LAST_BREAK,  	REGSET_GENERAL_EXTENDED,  }; @@ -381,6 +382,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)  			copied += sizeof(unsigned long);  		}  		return 0; +	case PTRACE_GET_LAST_BREAK: +		put_user(task_thread_info(child)->last_break, +			 (unsigned long __user *) data); +		return 0;  	default:  		/* Removing high order bit from addr (only for 31 bit). */  		addr &= PSW_ADDR_INSN; @@ -633,6 +638,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,  			copied += sizeof(unsigned int);  		}  		return 0; +	case PTRACE_GET_LAST_BREAK: +		put_user(task_thread_info(child)->last_break, +			 (unsigned int __user *) data); +		return 0;  	}  	return compat_ptrace_request(child, request, addr, data);  } @@ -640,7 +649,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,  asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)  { -	long ret; +	long ret = 0;  	/* Do the secure computing check first. */  	secure_computing(regs->gprs[2]); @@ -649,7 +658,6 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)  	 * The sysc_tracesys code in entry.S stored the system  	 * call number to gprs[2].  	 */ -	ret = regs->gprs[2];  	if (test_thread_flag(TIF_SYSCALL_TRACE) &&  	    (tracehook_report_syscall_entry(regs) ||  	     regs->gprs[2] >= NR_syscalls)) { @@ -671,7 +679,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)  				    regs->gprs[2], regs->orig_gpr2,  				    regs->gprs[3], regs->gprs[4],  				    regs->gprs[5]); -	return ret; +	return ret ?: regs->gprs[2];  }  asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) @@ -798,6 +806,28 @@ static int s390_fpregs_set(struct task_struct *target,  	return rc;  } +#ifdef CONFIG_64BIT + +static int s390_last_break_get(struct task_struct *target, +			       const struct user_regset *regset, +			       unsigned int pos, unsigned int count, +			       void *kbuf, void __user *ubuf) +{ +	if (count > 0) { +		if (kbuf) { +			unsigned long *k = kbuf; +			*k = task_thread_info(target)->last_break; +		} else { +			unsigned long  __user *u = ubuf; +			if (__put_user(task_thread_info(target)->last_break, u)) +				return -EFAULT; +		} +	} +	return 0; +} + +#endif +  static const struct user_regset s390_regsets[] = {  	[REGSET_GENERAL] = {  		.core_note_type = NT_PRSTATUS, @@ -815,6 +845,15 @@ static const struct user_regset s390_regsets[] = {  		.get = s390_fpregs_get,  		.set = s390_fpregs_set,  	}, +#ifdef CONFIG_64BIT +	[REGSET_LAST_BREAK] = { +		.core_note_type = NT_S390_LAST_BREAK, +		.n = 1, +		.size = sizeof(long), +		.align = sizeof(long), +		.get = s390_last_break_get, +	}, +#endif  };  static const struct user_regset_view user_s390_view = { @@ -949,6 +988,27 @@ static int s390_compat_regs_high_set(struct task_struct *target,  	return rc;  } +static int s390_compat_last_break_get(struct task_struct *target, +				      const struct user_regset *regset, +				      unsigned int pos, unsigned int count, +				      void *kbuf, void __user *ubuf) +{ +	compat_ulong_t last_break; + +	if (count > 0) { +		last_break = task_thread_info(target)->last_break; +		if (kbuf) { +			unsigned long *k = kbuf; +			*k = last_break; +		} else { +			unsigned long  __user *u = ubuf; +			if (__put_user(last_break, u)) +				return -EFAULT; +		} +	} +	return 0; +} +  static const struct user_regset s390_compat_regsets[] = {  	[REGSET_GENERAL] = {  		.core_note_type = NT_PRSTATUS, @@ -966,6 +1026,13 @@ static const struct user_regset s390_compat_regsets[] = {  		.get = s390_fpregs_get,  		.set = s390_fpregs_set,  	}, +	[REGSET_LAST_BREAK] = { +		.core_note_type = NT_S390_LAST_BREAK, +		.n = 1, +		.size = sizeof(long), +		.align = sizeof(long), +		.get = s390_compat_last_break_get, +	},  	[REGSET_GENERAL_EXTENDED] = {  		.core_note_type = NT_S390_HIGH_GPRS,  		.n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t), diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c index 59618bcd99b..9ce641b5291 100644 --- a/arch/s390/kernel/s390_ext.c +++ b/arch/s390/kernel/s390_ext.c @@ -120,7 +120,8 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)  	struct pt_regs *old_regs;  	old_regs = set_irq_regs(regs); -	s390_idle_check(); +	s390_idle_check(regs, S390_lowcore.int_clock, +			S390_lowcore.async_enter_timer);  	irq_enter();  	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)  		/* Serve timer interrupts first. */ diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 91625f759cc..7d893248d26 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -2,7 +2,7 @@   *  arch/s390/kernel/setup.c   *   *  S390 version - *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright (C) IBM Corp. 1999,2010   *    Author(s): Hartmut Penner (hp@de.ibm.com),   *               Martin Schwidefsky (schwidefsky@de.ibm.com)   * @@ -113,22 +113,6 @@ static struct resource data_resource = {  };  /* - * cpu_init() initializes state that is per-CPU. - */ -void __cpuinit cpu_init(void) -{ -        /* -         * Store processor id in lowcore (used e.g. in timer_interrupt) -         */ -	get_cpu_id(&S390_lowcore.cpu_id); - -	atomic_inc(&init_mm.mm_count); -	current->active_mm = &init_mm; -	BUG_ON(current->mm); -        enter_lazy_tlb(&init_mm, current); -} - -/*   * condev= and conmode= setup parameter.   */ @@ -385,10 +369,6 @@ static void setup_addressing_mode(void)  			pr_info("Address spaces switched, "  				"mvcos not available\n");  	} -#ifdef CONFIG_TRACE_IRQFLAGS -	sysc_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; -	io_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; -#endif  }  static void __init @@ -421,6 +401,7 @@ setup_lowcore(void)  	lc->io_new_psw.mask = psw_kernel_bits;  	lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;  	lc->clock_comparator = -1ULL; +	lc->cmf_hpp = -1ULL;  	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;  	lc->async_stack = (unsigned long)  		__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; @@ -695,6 +676,7 @@ static void __init setup_hwcaps(void)  	static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };  	unsigned long long facility_list_extended;  	unsigned int facility_list; +	struct cpuid cpu_id;  	int i;  	facility_list = stfl(); @@ -756,7 +738,8 @@ static void __init setup_hwcaps(void)  	 */  	elf_hwcap |= HWCAP_S390_HIGH_GPRS; -	switch (S390_lowcore.cpu_id.machine) { +	get_cpu_id(&cpu_id); +	switch (cpu_id.machine) {  	case 0x9672:  #if !defined(CONFIG_64BIT)  	default:	/* Use "g5" as default for 31 bit kernels. */ diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 6289945562b..ee7ac8b1178 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -313,6 +313,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,  	   To avoid breaking binary compatibility, they are passed as args. */  	regs->gprs[4] = current->thread.trap_no;  	regs->gprs[5] = current->thread.prot_addr; +	regs->gprs[6] = task_thread_info(current)->last_break;  	/* Place signal number on stack to allow backtrace from handler.  */  	if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) @@ -376,6 +377,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  	regs->gprs[2] = map_signal(sig);  	regs->gprs[3] = (unsigned long) &frame->info;  	regs->gprs[4] = (unsigned long) &frame->uc; +	regs->gprs[5] = task_thread_info(current)->last_break;  	return 0;  give_sigsegv: diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index d906bf19c14..a2163c95eb9 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -391,7 +391,6 @@ static void __init time_init_wq(void)  	if (time_sync_wq)  		return;  	time_sync_wq = create_singlethread_workqueue("timesync"); -	stop_machine_create();  }  /* diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 247b4c2d1e5..bcef00766a6 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -37,7 +37,8 @@ struct tl_cpu {  };  struct tl_container { -	unsigned char reserved[8]; +	unsigned char reserved[7]; +	unsigned char id;  };  union tl_entry { @@ -58,6 +59,7 @@ struct tl_info {  struct core_info {  	struct core_info *next; +	unsigned char id;  	cpumask_t mask;  }; @@ -73,6 +75,7 @@ static DECLARE_WORK(topology_work, topology_work_fn);  static DEFINE_SPINLOCK(topology_lock);  cpumask_t cpu_core_map[NR_CPUS]; +unsigned char cpu_core_id[NR_CPUS];  static cpumask_t cpu_coregroup_map(unsigned int cpu)  { @@ -116,6 +119,7 @@ static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)  		for_each_present_cpu(lcpu) {  			if (cpu_logical_map(lcpu) == rcpu) {  				cpu_set(lcpu, core->mask); +				cpu_core_id[lcpu] = core->id;  				smp_cpu_polarization[lcpu] = tl_cpu->pp;  			}  		} @@ -158,6 +162,7 @@ static void tl_to_cores(struct tl_info *info)  			break;  		case 1:  			core = core->next; +			core->id = tle->container.id;  			break;  		case 0:  			add_cpus_to_core(&tle->cpu, core); diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 6e7ad63854c..5d8f0f3d025 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -46,13 +46,7 @@  pgm_check_handler_t *pgm_check_table[128]; -#ifdef CONFIG_SYSCTL -#ifdef CONFIG_PROCESS_DEBUG -int sysctl_userprocess_debug = 1; -#else -int sysctl_userprocess_debug = 0; -#endif -#endif +int show_unhandled_signals;  extern pgm_check_handler_t do_protection_exception;  extern pgm_check_handler_t do_dat_exception; @@ -315,18 +309,19 @@ void die(const char * str, struct pt_regs * regs, long err)  	do_exit(SIGSEGV);  } -static void inline -report_user_fault(long interruption_code, struct pt_regs *regs) +static void inline report_user_fault(struct pt_regs *regs, long int_code, +				     int signr)  { -#if defined(CONFIG_SYSCTL) -	if (!sysctl_userprocess_debug) +	if ((task_pid_nr(current) > 1) && !show_unhandled_signals)  		return; -#endif -#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) -	printk("User process fault: interruption code 0x%lX\n", -	       interruption_code); +	if (!unhandled_signal(current, signr)) +		return; +	if (!printk_ratelimit()) +		return; +	printk("User process fault: interruption code 0x%lX ", int_code); +	print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN); +	printk("\n");  	show_regs(regs); -#endif  }  int is_valid_bugaddr(unsigned long addr) @@ -354,7 +349,7 @@ static void __kprobes inline do_trap(long interruption_code, int signr,                  tsk->thread.trap_no = interruption_code & 0xffff;  		force_sig_info(signr, info, tsk); -		report_user_fault(interruption_code, regs); +		report_user_fault(regs, interruption_code, signr);          } else {                  const struct exception_table_entry *fixup;                  fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); @@ -390,8 +385,8 @@ static void default_trap_handler(struct pt_regs * regs, long interruption_code)  {          if (regs->psw.mask & PSW_MASK_PSTATE) {  		local_irq_enable(); +		report_user_fault(regs, interruption_code, SIGSEGV);  		do_exit(SIGSEGV); -		report_user_fault(interruption_code, regs);  	} else  		die("Unknown program exception", regs, interruption_code);  } diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 6bc9c197aa9..6b83870507d 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -102,11 +102,7 @@ static void vdso_init_per_cpu_data(int cpu, struct vdso_per_cpu_data *vpcd)  /*   * Allocate/free per cpu vdso data.   */ -#ifdef CONFIG_64BIT  #define SEGMENT_ORDER	2 -#else -#define SEGMENT_ORDER	1 -#endif  int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore)  { diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index b59a812a010..3479f1b0d4e 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -121,32 +121,35 @@ void account_system_vtime(struct task_struct *tsk)  }  EXPORT_SYMBOL_GPL(account_system_vtime); -void vtime_start_cpu(void) +void vtime_start_cpu(__u64 int_clock, __u64 enter_timer)  {  	struct s390_idle_data *idle = &__get_cpu_var(s390_idle);  	struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);  	__u64 idle_time, expires; +	if (idle->idle_enter == 0ULL) +		return; +  	/* Account time spent with enabled wait psw loaded as idle time. */ -	idle_time = S390_lowcore.int_clock - idle->idle_enter; +	idle_time = int_clock - idle->idle_enter;  	account_idle_time(idle_time);  	S390_lowcore.steal_timer +=  		idle->idle_enter - S390_lowcore.last_update_clock; -	S390_lowcore.last_update_clock = S390_lowcore.int_clock; +	S390_lowcore.last_update_clock = int_clock;  	/* Account system time spent going idle. */  	S390_lowcore.system_timer += S390_lowcore.last_update_timer - vq->idle; -	S390_lowcore.last_update_timer = S390_lowcore.async_enter_timer; +	S390_lowcore.last_update_timer = enter_timer;  	/* Restart vtime CPU timer */  	if (vq->do_spt) {  		/* Program old expire value but first save progress. */ -		expires = vq->idle - S390_lowcore.async_enter_timer; +		expires = vq->idle - enter_timer;  		expires += get_vtimer();  		set_vtimer(expires);  	} else {  		/* Don't account the CPU timer delta while the cpu was idle. */ -		vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; +		vq->elapsed -= vq->idle - enter_timer;  	}  	idle->sequence++;  |