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

Commit 603d1a50 authored by Martin Schwidefsky's avatar Martin Schwidefsky
Browse files

[S390] move sie code to entry.S



The entry to / exit from sie has subtle dependencies to the first level
interrupt handler. Move the sie assembler code to entry64.S and replace
the SIE_HOOK callback with a test and the new _TIF_SIE bit.
In addition this patch fixes several problems in regard to the check for
the_TIF_EXIT_SIE bits. The old code checked the TIF bits before executing
the interrupt handler and it only modified the instruction address if it
pointed directly to the sie instruction. In both cases it could miss
a TIF bit that normally would cause an exit from the guest and would
reenter the guest context.

Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent bb25b9ba
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */
#define TIF_SECCOMP		10	/* secure computing */
#define TIF_SYSCALL_TRACEPOINT	11	/* syscall tracepoint instrumentation */
#define TIF_SIE			12	/* guest execution active */
#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling
					   TIF_NEED_RESCHED */
#define TIF_31BIT		17	/* 32bit process */
@@ -113,6 +114,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
#define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_SIE		(1<<TIF_SIE)
#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
#define _TIF_31BIT		(1<<TIF_31BIT)
#define _TIF_SINGLE_STEP	(1<<TIF_FREEZE)
+72 −8
Original line number Diff line number Diff line
@@ -56,15 +56,28 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
		 _TIF_MCCK_PENDING)
_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
		_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)

#define BASED(name) name-system_call(%r13)

	.macro SPP newpp
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
	tm	__LC_MACHINE_FLAGS+6,0x20	# MACHINE_FLAG_SPP
	jz	.+8
	.insn	s,0xb2800000,\newpp
#endif
	.endm

	.macro	HANDLE_SIE_INTERCEPT
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
	lg	%r3,__LC_SIE_HOOK
	ltgr	%r3,%r3
	tm	__TI_flags+6(%r12),_TIF_SIE>>8
	jz	0f
	basr	%r14,%r3
	SPP	__LC_CMF_HPP			# set host id
	clc	SP_PSW+8(8,%r15),BASED(.Lsie_loop)
	jl	0f
	clc	SP_PSW+8(8,%r15),BASED(.Lsie_done)
	jhe	0f
	mvc	SP_PSW+8(8,%r15),BASED(.Lsie_loop)
0:
#endif
	.endm
@@ -465,6 +478,7 @@ pgm_check_handler:
	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
	HANDLE_SIE_INTERCEPT
	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
@@ -472,7 +486,6 @@ pgm_check_handler:
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
	LAST_BREAK
pgm_no_vtime:
	HANDLE_SIE_INTERCEPT
	stg	%r11,SP_ARGS(%r15)
	lgf	%r3,__LC_PGM_ILC	# load program interruption code
	lg	%r4,__LC_TRANS_EXC_CODE
@@ -507,6 +520,7 @@ pgm_per_std:
	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
	HANDLE_SIE_INTERCEPT
	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
@@ -514,7 +528,6 @@ pgm_per_std:
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
	LAST_BREAK
pgm_no_vtime2:
	HANDLE_SIE_INTERCEPT
	lg	%r1,__TI_task(%r12)
	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
	jz	kernel_per
@@ -579,6 +592,7 @@ io_int_handler:
	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
	HANDLE_SIE_INTERCEPT
	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
@@ -586,7 +600,6 @@ io_int_handler:
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
	LAST_BREAK
io_no_vtime:
	HANDLE_SIE_INTERCEPT
	TRACE_IRQS_OFF
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	brasl	%r14,do_IRQ		# call standard irq handler
@@ -714,6 +727,7 @@ ext_int_handler:
	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
	HANDLE_SIE_INTERCEPT
	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
@@ -721,7 +735,6 @@ ext_int_handler:
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
	LAST_BREAK
ext_no_vtime:
	HANDLE_SIE_INTERCEPT
	TRACE_IRQS_OFF
	lghi	%r1,4096
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
@@ -785,6 +798,7 @@ mcck_int_main:
	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
	HANDLE_SIE_INTERCEPT
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	jz	mcck_no_vtime
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
@@ -804,7 +818,6 @@ mcck_no_vtime:
	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
	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
@@ -1036,6 +1049,57 @@ cleanup_io_restore_insn:
.Lcritical_end:
		.quad	__critical_end

#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
/*
 * sie64a calling convention:
 * %r2 pointer to sie control block
 * %r3 guest register save area
 */
	.globl	sie64a
sie64a:
	stmg	%r6,%r14,__SF_GPRS(%r15)	# save kernel registers
	stg	%r2,__SF_EMPTY(%r15)		# save control block pointer
	stg	%r3,__SF_EMPTY+8(%r15)		# save guest register save area
	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
	oi	__TI_flags+6(%r14),_TIF_SIE>>8
sie_loop:
	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
	tm	__TI_flags+7(%r14),_TIF_EXIT_SIE
	jnz	sie_exit
	lg	%r14,__SF_EMPTY(%r15)		# get control block pointer
	SPP	__SF_EMPTY(%r15)		# set guest id
	sie	0(%r14)
sie_done:
	SPP	__LC_CMF_HPP			# set host id
	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
sie_exit:
	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
	lghi	%r2,0
	br	%r14
sie_fault:
	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
	lghi	%r2,-EFAULT
	br	%r14

	.align	8
.Lsie_loop:
	.quad	sie_loop
.Lsie_done:
	.quad	sie_done

	.section __ex_table,"a"
	.quad	sie_loop,sie_fault
	.previous
#endif

		.section .rodata, "a"
#define SYSCALL(esa,esame,emu)	.long esame
	.globl	sys_call_table
+4 −0
Original line number Diff line number Diff line
#include <linux/module.h>
#include <linux/kvm_host.h>
#include <asm/ftrace.h>

#ifdef CONFIG_FUNCTION_TRACER
EXPORT_SYMBOL(_mcount);
#endif
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
EXPORT_SYMBOL(sie64a);
#endif
+1 −1
Original line number Diff line number Diff line
@@ -10,5 +10,5 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)

ccflags-y := -Ivirt/kvm -Iarch/s390/kvm

kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o diag.o
obj-$(CONFIG_KVM) += kvm.o

arch/s390/kvm/sie64a.S

deleted100644 → 0
+0 −98
Original line number Diff line number Diff line
/*
 * sie64a.S - low level sie call
 *
 * Copyright IBM Corp. 2008,2010
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (version 2 only)
 * as published by the Free Software Foundation.
 *
 *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
 *		 Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
 */

#include <linux/errno.h>
#include <asm/asm-offsets.h>
#include <asm/setup.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>

_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)

/*
 * offsets into stackframe
 * SP_	= offsets into stack sie64 is called with
 * SPI_ = offsets into irq stack
 */
SP_GREGS = __SF_EMPTY
SP_HOOK  = __SF_EMPTY+8
SP_GPP	 = __SF_EMPTY+16
SPI_PSW  = STACK_FRAME_OVERHEAD + __PT_PSW


	.macro SPP newpp
	tm	__LC_MACHINE_FLAGS+6,0x20	# MACHINE_FLAG_SPP
	jz	0f
	.insn	s,0xb2800000,\newpp
0:
	.endm

sie_irq_handler:
	SPP	__LC_CMF_HPP			# set host id
	larl	%r2,sie_inst
	clg	%r2,SPI_PSW+8(0,%r15)		# intercepted sie
	jne	1f
	xc	__LC_SIE_HOOK(8),__LC_SIE_HOOK
	lg	%r2,__LC_THREAD_INFO		# pointer thread_info struct
	tm	__TI_flags+7(%r2),_TIF_EXIT_SIE
	jz	0f
	larl	%r2,sie_exit			# work pending, leave sie
	stg	%r2,SPI_PSW+8(0,%r15)
	br	%r14
0:	larl	%r2,sie_reenter			# re-enter with guest id
	stg	%r2,SPI_PSW+8(0,%r15)
1:	br	%r14

/*
 * sie64a calling convention:
 * %r2 pointer to sie control block
 * %r3 guest register save area
 */
	.globl	sie64a
sie64a:
	stg	%r3,SP_GREGS(%r15)		# save guest register save area
	stmg	%r6,%r14,__SF_GPRS(%r15)	# save registers on entry
	lgr	%r14,%r2			# pointer to sie control block
	larl	%r5,sie_irq_handler
	stg	%r2,SP_GPP(%r15)
	stg	%r5,SP_HOOK(%r15)		# save hook target
	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
sie_reenter:
	mvc	__LC_SIE_HOOK(8),SP_HOOK(%r15)
	SPP	SP_GPP(%r15)			# set guest id
sie_inst:
	sie	0(%r14)
	xc	__LC_SIE_HOOK(8),__LC_SIE_HOOK
	SPP	__LC_CMF_HPP			# set host id
sie_exit:
	lg	%r14,SP_GREGS(%r15)
	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
	lghi	%r2,0
	lmg	%r6,%r14,__SF_GPRS(%r15)
	br	%r14

sie_err:
	xc	__LC_SIE_HOOK(8),__LC_SIE_HOOK
	SPP	__LC_CMF_HPP			# set host id
	lg	%r14,SP_GREGS(%r15)
	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
	lghi	%r2,-EFAULT
	lmg	%r6,%r14,__SF_GPRS(%r15)
	br	%r14

	.section __ex_table,"a"
	.quad	sie_inst,sie_err
	.quad	sie_exit,sie_err
	.quad	sie_reenter,sie_err
	.previous