Commit d0139059 authored by Heiko Carstens's avatar Heiko Carstens Committed by Janosch Frank
Browse files

KVM: s390: Enable and disable interrupts in entry code



Move enabling and disabling of interrupts around the SIE instruction to
entry code. Enabling interrupts only after the __TI_sie flag has been set
guarantees that the SIE instruction is not executed if an interrupt happens
between enabling interrupts and the execution of the SIE instruction.
Interrupt handlers and machine check handler forward the PSW to the
sie_exit label in such cases.

This is a prerequisite for VIRT_XFER_TO_GUEST_WORK to prevent that guest
context is entered when e.g. a scheduler IPI, indicating that a reschedule
is required, happens right before the SIE instruction, which could lead to
long delays.

Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Tested-by: default avatarAndrew Donnellan <ajd@linux.ibm.com>
Signed-off-by: default avatarAndrew Donnellan <ajd@linux.ibm.com>
Reviewed-by: default avatarJanosch Frank <frankja@linux.ibm.com>
Signed-off-by: default avatarJanosch Frank <frankja@linux.ibm.com>
parent c067847c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ struct stack_frame {
			unsigned long sie_flags;
			unsigned long sie_control_block_phys;
			unsigned long sie_guest_asce;
			unsigned long sie_irq;
		};
	};
	unsigned long gprs[10];
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ int main(void)
	OFFSET(__SF_SIE_FLAGS, stack_frame, sie_flags);
	OFFSET(__SF_SIE_CONTROL_PHYS, stack_frame, sie_control_block_phys);
	OFFSET(__SF_SIE_GUEST_ASCE, stack_frame, sie_guest_asce);
	OFFSET(__SF_SIE_IRQ, stack_frame, sie_irq);
	DEFINE(STACK_FRAME_OVERHEAD, sizeof(struct stack_frame));
	BLANK();
	OFFSET(__SFUSER_BACKCHAIN, stack_frame_user, back_chain);
+2 −0
Original line number Diff line number Diff line
@@ -189,6 +189,7 @@ SYM_FUNC_START(__sie64a)
	mvc	__SF_SIE_FLAGS(8,%r15),__TI_flags(%r14) # copy thread flags
	lmg	%r0,%r13,0(%r4)			# load guest gprs 0-13
	mvi	__TI_sie(%r14),1
	stosm	__SF_SIE_IRQ(%r15),0x03		# enable interrupts
	lctlg	%c1,%c1,__SF_SIE_GUEST_ASCE(%r15) # load primary asce
	lg	%r14,__SF_SIE_CONTROL(%r15)	# get control block pointer
	oi	__SIE_PROG0C+3(%r14),1		# we are going into SIE now
@@ -212,6 +213,7 @@ SYM_FUNC_START(__sie64a)
	lg	%r14,__LC_CURRENT(%r14)
	mvi	__TI_sie(%r14),0
SYM_INNER_LABEL(sie_exit, SYM_L_GLOBAL)
	stnsm	__SF_SIE_IRQ(%r15),0xfc		# disable interrupts
	lg	%r14,__SF_SIE_SAVEAREA(%r15)	# load guest register save area
	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
	xgr	%r0,%r0				# clear guest registers to
+0 −5
Original line number Diff line number Diff line
@@ -4962,13 +4962,8 @@ int noinstr kvm_s390_enter_exit_sie(struct kvm_s390_sie_block *scb,
	 * The guest_state_{enter,exit}_irqoff() functions inform lockdep and
	 * tracing that entry to the guest will enable host IRQs, and exit from
	 * the guest will disable host IRQs.
	 *
	 * We must not use lockdep/tracing/RCU in this critical section, so we
	 * use the low-level arch_local_irq_*() helpers to enable/disable IRQs.
	 */
	arch_local_irq_enable();
	ret = sie64a(scb, gprs, gasce);
	arch_local_irq_disable();

	guest_state_exit_irqoff();