Эх сурвалжийг харах

s390/kvm: Mark if a cpu is in SIE

Lets track in a private bit if the sie control block is active.
We want to track this as closely as possible, so we also have to
instrument the interrupt and program check handler. Lets use the
existing HANDLE_SIE_INTERCEPT macro.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Christian Borntraeger 12 жил өмнө
parent
commit
95d38fd0bc

+ 4 - 1
arch/s390/include/asm/kvm_host.h

@@ -68,7 +68,10 @@ struct sca_block {
 struct kvm_s390_sie_block {
 struct kvm_s390_sie_block {
 	atomic_t cpuflags;		/* 0x0000 */
 	atomic_t cpuflags;		/* 0x0000 */
 	__u32	prefix;			/* 0x0004 */
 	__u32	prefix;			/* 0x0004 */
-	__u8	reserved8[32];		/* 0x0008 */
+	__u8	reserved08[4];		/* 0x0008 */
+#define PROG_IN_SIE (1<<0)
+	__u32	prog0c;			/* 0x000c */
+	__u8	reserved10[24];		/* 0x0010 */
 	__u64	cputm;			/* 0x0028 */
 	__u64	cputm;			/* 0x0028 */
 	__u64	ckc;			/* 0x0030 */
 	__u64	ckc;			/* 0x0030 */
 	__u64	epoch;			/* 0x0038 */
 	__u64	epoch;			/* 0x0038 */

+ 2 - 0
arch/s390/kernel/asm-offsets.c

@@ -7,6 +7,7 @@
 #define ASM_OFFSETS_C
 #define ASM_OFFSETS_C
 
 
 #include <linux/kbuild.h>
 #include <linux/kbuild.h>
+#include <linux/kvm_host.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <asm/cputime.h>
 #include <asm/cputime.h>
 #include <asm/vdso.h>
 #include <asm/vdso.h>
@@ -161,6 +162,7 @@ int main(void)
 	DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb));
 	DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb));
 	DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb));
 	DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb));
 	DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce));
 	DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce));
+	DEFINE(__SIE_PROG0C, offsetof(struct kvm_s390_sie_block, prog0c));
 #endif /* CONFIG_32BIT */
 #endif /* CONFIG_32BIT */
 	return 0;
 	return 0;
 }
 }

+ 7 - 3
arch/s390/kernel/entry64.S

@@ -84,7 +84,7 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 	.macro	HANDLE_SIE_INTERCEPT scratch,pgmcheck
 	.macro	HANDLE_SIE_INTERCEPT scratch,pgmcheck
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
 	tmhh	%r8,0x0001		# interrupting from user ?
 	tmhh	%r8,0x0001		# interrupting from user ?
-	jnz	.+42
+	jnz	.+52
 	lgr	\scratch,%r9
 	lgr	\scratch,%r9
 	slg	\scratch,BASED(.Lsie_loop)
 	slg	\scratch,BASED(.Lsie_loop)
 	clg	\scratch,BASED(.Lsie_length)
 	clg	\scratch,BASED(.Lsie_length)
@@ -92,12 +92,14 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 	# Some program interrupts are suppressing (e.g. protection).
 	# Some program interrupts are suppressing (e.g. protection).
 	# We must also check the instruction after SIE in that case.
 	# We must also check the instruction after SIE in that case.
 	# do_protection_exception will rewind to rewind_pad
 	# do_protection_exception will rewind to rewind_pad
-	jh	.+22
+	jh	.+32
 	.else
 	.else
-	jhe	.+22
+	jhe	.+32
 	.endif
 	.endif
 	lg	%r9,BASED(.Lsie_loop)
 	lg	%r9,BASED(.Lsie_loop)
 	LPP	BASED(.Lhost_id)	# set host id
 	LPP	BASED(.Lhost_id)	# set host id
+	lg	%r14,__SF_EMPTY(%r15)	# get control block pointer
+	ni	__SIE_PROG0C+3(%r14),0xfe	# no longer in SIE
 #endif
 #endif
 	.endm
 	.endm
 
 
@@ -956,10 +958,12 @@ sie_loop:
 	lctlg	%c1,%c1,__GMAP_ASCE(%r14)	# load primary asce
 	lctlg	%c1,%c1,__GMAP_ASCE(%r14)	# load primary asce
 sie_gmap:
 sie_gmap:
 	lg	%r14,__SF_EMPTY(%r15)		# get control block pointer
 	lg	%r14,__SF_EMPTY(%r15)		# get control block pointer
+	oi	__SIE_PROG0C+3(%r14),1		# we are in SIE now
 	LPP	__SF_EMPTY(%r15)		# set guest id
 	LPP	__SF_EMPTY(%r15)		# set guest id
 	sie	0(%r14)
 	sie	0(%r14)
 sie_done:
 sie_done:
 	LPP	__SF_EMPTY+16(%r15)		# set host id
 	LPP	__SF_EMPTY+16(%r15)		# set host id
+	ni	__SIE_PROG0C+3(%r14),0xfe	# no longer in SIE
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 sie_exit:
 sie_exit:
 	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
 	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce