Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a2df3a8 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Martin Schwidefsky
Browse files

[S390] improve irq tracing code in entry[64].S



The system call path in entry[64].S is run with interrupts enabled.
Remove the irq tracing check from the system call exit code. If a
program check interrupted a context enabled for interrupts do a
call to trace_irq_off_caller in the program check handler before
branching to the system call exit code.
Restructure the system call and io interrupt return code to avoid
avoid the lpsw[e] to disable machine checks.

Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 43d399d2
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -459,11 +459,6 @@ extern void (*_machine_power_off)(void);

#define arch_align_stack(x) (x)

#ifdef CONFIG_TRACE_IRQFLAGS
extern psw_t sysc_restore_trace_psw;
extern psw_t io_restore_trace_psw;
#endif

static inline int tprot(unsigned long addr)
{
	int rc = -EFAULT;
+91 −114
Original line number Diff line number Diff line
@@ -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
@@ -273,33 +276,14 @@ 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

#
# There is work to do, but first we need to check if we return to userspace.
#
@@ -310,7 +294,7 @@ sysc_work:
#
# One of the work bits is on. Find out which one.
#
sysc_work_loop:
sysc_work_tif:
	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
	bo	BASED(sysc_mcck_pending)
	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
@@ -330,7 +314,7 @@ sysc_work_loop:
#
sysc_reschedule:
	l	%r1,BASED(.Lschedule)
	la	%r14,BASED(sysc_work_loop)
	la	%r14,BASED(sysc_return)
	br	%r1			# call scheduler

#
@@ -338,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

#
@@ -353,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
@@ -361,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


@@ -384,7 +368,7 @@ sysc_singlestep:
	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_work_loop)	# load adr. of system return
	la	%r14,BASED(sysc_return)	# load adr. of system return
	br	%r1			# branch to do_single_step

#
@@ -456,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
@@ -497,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
@@ -507,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
@@ -535,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)

#
@@ -568,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)

#
@@ -580,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
@@ -600,39 +588,21 @@ 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

#
# 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
@@ -647,19 +617,23 @@ io_work:
	# 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:
	# 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)
	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
	bor	%r1			# call preempt_schedule_irq
#endif
	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
@@ -670,12 +644,13 @@ io_work_user:
	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_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
@@ -690,47 +665,49 @@ io_work_loop:
# _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
	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
@@ -918,14 +895,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_io_return:
	.long	io_return + 0x80000000, io_leave + 0x80000000
cleanup_table_io_leave:
	.long	io_leave + 0x80000000, io_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)
@@ -933,25 +910,25 @@ 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)
	clc	4(4,%r12),BASED(cleanup_table_sysc_tif)
	bl	BASED(0f)
	clc	4(4,%r12),BASED(cleanup_table_sysc_return+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_sysc_leave)
	clc	4(4,%r12),BASED(cleanup_table_sysc_restore)
	bl	BASED(0f)
	clc	4(4,%r12),BASED(cleanup_table_sysc_leave+4)
	bl	BASED(cleanup_sysc_leave)
	clc	4(4,%r12),BASED(cleanup_table_sysc_restore+4)
	bl	BASED(cleanup_sysc_restore)
0:
	clc	4(4,%r12),BASED(cleanup_table_io_return)
	clc	4(4,%r12),BASED(cleanup_table_io_tif)
	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_io_tif+4)
	bl	BASED(cleanup_io_tif)
0:
	clc	4(4,%r12),BASED(cleanup_table_io_leave)
	clc	4(4,%r12),BASED(cleanup_table_io_restore)
	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_restore+4)
	bl	BASED(cleanup_io_restore)
0:
	br	%r14

@@ -998,17 +975,17 @@ 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_ASYNC_ENTER_TIMER
	clc	4(4,%r12),BASED(cleanup_sysc_leave_insn+4)
	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)
@@ -1020,21 +997,21 @@ cleanup_sysc_leave:
	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_leave:
	clc	4(4,%r12),BASED(cleanup_io_leave_insn)
cleanup_io_restore:
	clc	4(4,%r12),BASED(cleanup_io_restore_insn)
	be	BASED(2f)
	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
	clc	4(4,%r12),BASED(cleanup_io_leave_insn+4)
	clc	4(4,%r12),BASED(cleanup_io_restore_insn+4)
	be	BASED(2f)
	mvc	__LC_RETURN_PSW(8),SP_PSW(%r15)
	c	%r12,BASED(.Lmck_old_psw)
@@ -1046,7 +1023,7 @@ cleanup_io_leave:
	l	%r15,SP_R15(%r15)
2:	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

+92 −105
Original line number Diff line number Diff line
@@ -70,19 +70,24 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
	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
@@ -267,29 +272,14 @@ sysc_noemu:
	stg	%r2,SP_R2(%r15) # store return value (change R2 on stack)

sysc_return:
	LOCKDEP_SYS_EXIT
sysc_tif:
	tm	__TI_flags+7(%r9),_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

#
# There is work to do, but first we need to check if we return to userspace.
#
@@ -300,7 +290,7 @@ sysc_work:
#
# One of the work bits is on. Find out which one.
#
sysc_work_loop:
sysc_work_tif:
	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
	jo	sysc_mcck_pending
	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
@@ -319,14 +309,14 @@ sysc_work_loop:
# _TIF_NEED_RESCHED is set, call schedule
#
sysc_reschedule:
	larl	%r14,sysc_work_loop
	jg	schedule		# return point is sysc_work_loop
	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

#
@@ -340,14 +330,14 @@ sysc_sigpending:
	jo	sysc_restart
	tm	__TI_flags+7(%r9),_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

#
@@ -367,7 +357,7 @@ sysc_singlestep:
	ni	__TI_flags+7(%r9),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_work_loop	# load adr. of system return
	larl	%r14,sysc_return	# load adr. of system return
	jg	do_single_step		# branch to do_sigtrap

#
@@ -433,12 +423,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
	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
@@ -474,9 +466,9 @@ 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
	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	mvc	SP_ARGS(8,%r15),__LC_LAST_BREAK
	TRACE_IRQS_OFF
	lgf	%r3,__LC_PGM_ILC	# load program interruption code
	lghi	%r8,0x7f
	ngr	%r8,%r3
@@ -485,8 +477,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
@@ -513,8 +507,8 @@ 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
	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	TRACE_IRQS_OFF
	lg	%r1,__TI_task(%r9)
	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
	jz	kernel_per
@@ -525,7 +519,7 @@ pgm_no_vtime2:
	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

#
@@ -539,14 +533,15 @@ pgm_svcper:
	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
	TRACE_IRQS_OFF
	lg	%r8,__TI_task(%r9)
	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
	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

#
@@ -555,8 +550,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
@@ -579,29 +574,15 @@ io_no_vtime:
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	brasl	%r14,do_IRQ		# call standard irq handler
io_return:
	LOCKDEP_SYS_EXIT
	TRACE_IRQS_ON
io_tif:
	tm	__TI_flags+7(%r9),_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, find out in which context we have been interrupted:
# 1) if we return to user space we can do all _TIF_WORK_INT work
@@ -627,18 +608,22 @@ io_work:
	# check for preemptive scheduling
	icm	%r0,15,__TI_precount(%r9)
	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:
	larl	%r14,io_resume_loop
	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED
	jgo	preempt_schedule_irq
#endif
	# 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
@@ -655,7 +640,7 @@ io_work_user:
# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED
#	       and _TIF_MCCK_PENDING
#
io_work_loop:
io_work_tif:
	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
	jo	io_mcck_pending
	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
@@ -670,43 +655,45 @@ io_work_loop:
# _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
	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
@@ -883,14 +870,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_io_return:
	.quad	io_return, io_leave
cleanup_table_io_leave:
	.quad	io_leave, io_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)
@@ -898,25 +885,25 @@ 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)
	clc	8(8,%r12),BASED(cleanup_table_sysc_tif)
	jl	0f
	clc	8(8,%r12),BASED(cleanup_table_sysc_return+8)
	jl	cleanup_sysc_return
	clc	8(8,%r12),BASED(cleanup_table_sysc_tif+8)
	jl	cleanup_sysc_tif
0:
	clc	8(8,%r12),BASED(cleanup_table_sysc_leave)
	clc	8(8,%r12),BASED(cleanup_table_sysc_restore)
	jl	0f
	clc	8(8,%r12),BASED(cleanup_table_sysc_leave+8)
	jl	cleanup_sysc_leave
	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
	clc	8(8,%r12),BASED(cleanup_table_io_restore+8)
	jl	cleanup_io_restore
0:
	br	%r14

@@ -963,16 +950,16 @@ 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)
cleanup_sysc_restore:
	clc	8(8,%r12),BASED(cleanup_sysc_restore_insn)
	je	3f
	clc	8(8,%r12),BASED(cleanup_sysc_leave_insn+8)
	clc	8(8,%r12),BASED(cleanup_sysc_restore_insn+8)
	jhe	0f
	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
0:	mvc	__LC_RETURN_PSW(16),SP_PSW(%r15)
@@ -985,20 +972,20 @@ cleanup_sysc_leave:
	lg	%r15,SP_R15(%r15)
3:	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:
cleanup_io_tif:
	mvc	__LC_RETURN_PSW(8),0(%r12)
	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_io_return)
	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)
cleanup_io_restore:
	clc	8(8,%r12),BASED(cleanup_io_restore_insn)
	je	3f
	clc	8(8,%r12),BASED(cleanup_io_leave_insn+8)
	clc	8(8,%r12),BASED(cleanup_io_restore_insn+8)
	jhe	0f
	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
0:	mvc	__LC_RETURN_PSW(16),SP_PSW(%r15)
@@ -1011,7 +998,7 @@ cleanup_io_leave:
	lg	%r15,SP_R15(%r15)
3:	la	%r12,__LC_RETURN_PSW
	br	%r14
cleanup_io_leave_insn:
cleanup_io_restore_insn:
	.quad	io_done - 4
	.quad	io_done - 16

+0 −4
Original line number Diff line number Diff line
@@ -369,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