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

Commit 7ae9bda7 authored by Suraj Jitindar Singh's avatar Suraj Jitindar Singh Committed by Paul Mackerras
Browse files

KVM: PPC: Book3S HV: Handle virtual mode in XIVE VCPU push code



The code in book3s_hv_rmhandlers.S that pushes the XIVE virtual CPU
context to the hardware currently assumes it is being called in real
mode, which is usually true.  There is however a path by which it can
be executed in virtual mode, in the case where indep_threads_mode = N.
A virtual CPU executing on an offline secondary thread can take a
hypervisor interrupt in virtual mode and return from the
kvmppc_hv_entry() call after the kvm_secondary_got_guest label.
It is possible for it to be given another vcpu to execute before it
gets to execute the stop instruction.  In that case it will call
kvmppc_hv_entry() for the second VCPU in virtual mode, and the XIVE
vCPU push code will be executed in virtual mode.  The result in that
case will be a host crash due to an unexpected data storage interrupt
caused by executing the stdcix instruction in virtual mode.

This fixes it by adding a code path for virtual mode, which uses the
virtual TIMA pointer and normal load/store instructions.

[paulus@ozlabs.org - wrote patch description]

Signed-off-by: default avatarSuraj Jitindar Singh <sjitindarsingh@gmail.com>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent 1f80ba3d
Loading
Loading
Loading
Loading
+25 −11
Original line number Diff line number Diff line
@@ -969,17 +969,27 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)

#ifdef CONFIG_KVM_XICS
	/* We are entering the guest on that thread, push VCPU to XIVE */
	ld	r10, HSTATE_XIVE_TIMA_PHYS(r13)
	cmpldi	cr0, r10, 0
	beq	no_xive
	ld	r11, VCPU_XIVE_SAVED_STATE(r4)
	li	r9, TM_QW1_OS
	lwz	r8, VCPU_XIVE_CAM_WORD(r4)
	li	r7, TM_QW1_OS + TM_WORD2
	mfmsr	r0
	andi.	r0, r0, MSR_DR		/* in real mode? */
	beq	2f
	ld	r10, HSTATE_XIVE_TIMA_VIRT(r13)
	cmpldi	cr1, r10, 0
	beq     cr1, no_xive
	eieio
	stdx	r11,r9,r10
	stwx	r8,r7,r10
	b	3f
2:	ld	r10, HSTATE_XIVE_TIMA_PHYS(r13)
	cmpldi	cr1, r10, 0
	beq	cr1, no_xive
	eieio
	stdcix	r11,r9,r10
	lwz	r11, VCPU_XIVE_CAM_WORD(r4)
	li	r9, TM_QW1_OS + TM_WORD2
	stwcix	r11,r9,r10
	li	r9, 1
	stwcix	r8,r7,r10
3:	li	r9, 1
	stb	r9, VCPU_XIVE_PUSHED(r4)
	eieio

@@ -998,12 +1008,16 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
	 * on, we mask it.
	 */
	lbz	r0, VCPU_XIVE_ESC_ON(r4)
	cmpwi	r0,0
	beq	1f
	ld	r10, VCPU_XIVE_ESC_RADDR(r4)
	cmpwi	cr1, r0,0
	beq	cr1, 1f
	li	r9, XIVE_ESB_SET_PQ_01
	beq	4f			/* in real mode? */
	ld	r10, VCPU_XIVE_ESC_VADDR(r4)
	ldx	r0, r10, r9
	b	5f
4:	ld	r10, VCPU_XIVE_ESC_RADDR(r4)
	ldcix	r0, r10, r9
	sync
5:	sync

	/* We have a possible subtle race here: The escalation interrupt might
	 * have fired and be on its way to the host queue while we mask it,