xref: /OK3568_Linux_fs/kernel/arch/powerpc/kvm/book3s_hv_rmhandlers.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun/*
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Derived from book3s_rmhandlers.S and other files, which are:
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copyright SUSE Linux Products GmbH 2009
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Authors: Alexander Graf <agraf@suse.de>
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun#include <asm/ppc_asm.h>
14*4882a593Smuzhiyun#include <asm/code-patching-asm.h>
15*4882a593Smuzhiyun#include <asm/kvm_asm.h>
16*4882a593Smuzhiyun#include <asm/reg.h>
17*4882a593Smuzhiyun#include <asm/mmu.h>
18*4882a593Smuzhiyun#include <asm/page.h>
19*4882a593Smuzhiyun#include <asm/ptrace.h>
20*4882a593Smuzhiyun#include <asm/hvcall.h>
21*4882a593Smuzhiyun#include <asm/asm-offsets.h>
22*4882a593Smuzhiyun#include <asm/exception-64s.h>
23*4882a593Smuzhiyun#include <asm/kvm_book3s_asm.h>
24*4882a593Smuzhiyun#include <asm/book3s/64/mmu-hash.h>
25*4882a593Smuzhiyun#include <asm/export.h>
26*4882a593Smuzhiyun#include <asm/tm.h>
27*4882a593Smuzhiyun#include <asm/opal.h>
28*4882a593Smuzhiyun#include <asm/xive-regs.h>
29*4882a593Smuzhiyun#include <asm/thread_info.h>
30*4882a593Smuzhiyun#include <asm/asm-compat.h>
31*4882a593Smuzhiyun#include <asm/feature-fixups.h>
32*4882a593Smuzhiyun#include <asm/cpuidle.h>
33*4882a593Smuzhiyun#include <asm/ultravisor-api.h>
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun/* Sign-extend HDEC if not on POWER9 */
36*4882a593Smuzhiyun#define EXTEND_HDEC(reg)			\
37*4882a593SmuzhiyunBEGIN_FTR_SECTION;				\
38*4882a593Smuzhiyun	extsw	reg, reg;			\
39*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun/* Values in HSTATE_NAPPING(r13) */
42*4882a593Smuzhiyun#define NAPPING_CEDE	1
43*4882a593Smuzhiyun#define NAPPING_NOVCPU	2
44*4882a593Smuzhiyun#define NAPPING_UNSPLIT	3
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun/* Stack frame offsets for kvmppc_hv_entry */
47*4882a593Smuzhiyun#define SFS			208
48*4882a593Smuzhiyun#define STACK_SLOT_TRAP		(SFS-4)
49*4882a593Smuzhiyun#define STACK_SLOT_SHORT_PATH	(SFS-8)
50*4882a593Smuzhiyun#define STACK_SLOT_TID		(SFS-16)
51*4882a593Smuzhiyun#define STACK_SLOT_PSSCR	(SFS-24)
52*4882a593Smuzhiyun#define STACK_SLOT_PID		(SFS-32)
53*4882a593Smuzhiyun#define STACK_SLOT_IAMR		(SFS-40)
54*4882a593Smuzhiyun#define STACK_SLOT_CIABR	(SFS-48)
55*4882a593Smuzhiyun#define STACK_SLOT_DAWR		(SFS-56)
56*4882a593Smuzhiyun#define STACK_SLOT_DAWRX	(SFS-64)
57*4882a593Smuzhiyun#define STACK_SLOT_HFSCR	(SFS-72)
58*4882a593Smuzhiyun#define STACK_SLOT_AMR		(SFS-80)
59*4882a593Smuzhiyun#define STACK_SLOT_UAMOR	(SFS-88)
60*4882a593Smuzhiyun/* the following is used by the P9 short path */
61*4882a593Smuzhiyun#define STACK_SLOT_NVGPRS	(SFS-152)	/* 18 gprs */
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun/*
64*4882a593Smuzhiyun * Call kvmppc_hv_entry in real mode.
65*4882a593Smuzhiyun * Must be called with interrupts hard-disabled.
66*4882a593Smuzhiyun *
67*4882a593Smuzhiyun * Input Registers:
68*4882a593Smuzhiyun *
69*4882a593Smuzhiyun * LR = return address to continue at after eventually re-enabling MMU
70*4882a593Smuzhiyun */
71*4882a593Smuzhiyun_GLOBAL_TOC(kvmppc_hv_entry_trampoline)
72*4882a593Smuzhiyun	mflr	r0
73*4882a593Smuzhiyun	std	r0, PPC_LR_STKOFF(r1)
74*4882a593Smuzhiyun	stdu	r1, -112(r1)
75*4882a593Smuzhiyun	mfmsr	r10
76*4882a593Smuzhiyun	std	r10, HSTATE_HOST_MSR(r13)
77*4882a593Smuzhiyun	LOAD_REG_ADDR(r5, kvmppc_call_hv_entry)
78*4882a593Smuzhiyun	li	r0,MSR_RI
79*4882a593Smuzhiyun	andc	r0,r10,r0
80*4882a593Smuzhiyun	li	r6,MSR_IR | MSR_DR
81*4882a593Smuzhiyun	andc	r6,r10,r6
82*4882a593Smuzhiyun	mtmsrd	r0,1		/* clear RI in MSR */
83*4882a593Smuzhiyun	mtsrr0	r5
84*4882a593Smuzhiyun	mtsrr1	r6
85*4882a593Smuzhiyun	RFI_TO_KERNEL
86*4882a593Smuzhiyun
87*4882a593Smuzhiyunkvmppc_call_hv_entry:
88*4882a593SmuzhiyunBEGIN_FTR_SECTION
89*4882a593Smuzhiyun	/* On P9, do LPCR setting, if necessary */
90*4882a593Smuzhiyun	ld	r3, HSTATE_SPLIT_MODE(r13)
91*4882a593Smuzhiyun	cmpdi	r3, 0
92*4882a593Smuzhiyun	beq	46f
93*4882a593Smuzhiyun	lwz	r4, KVM_SPLIT_DO_SET(r3)
94*4882a593Smuzhiyun	cmpwi	r4, 0
95*4882a593Smuzhiyun	beq	46f
96*4882a593Smuzhiyun	bl	kvmhv_p9_set_lpcr
97*4882a593Smuzhiyun	nop
98*4882a593Smuzhiyun46:
99*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
102*4882a593Smuzhiyun	bl	kvmppc_hv_entry
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun	/* Back from guest - restore host state and return to caller */
105*4882a593Smuzhiyun
106*4882a593SmuzhiyunBEGIN_FTR_SECTION
107*4882a593Smuzhiyun	/* Restore host DABR and DABRX */
108*4882a593Smuzhiyun	ld	r5,HSTATE_DABR(r13)
109*4882a593Smuzhiyun	li	r6,7
110*4882a593Smuzhiyun	mtspr	SPRN_DABR,r5
111*4882a593Smuzhiyun	mtspr	SPRN_DABRX,r6
112*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun	/* Restore SPRG3 */
115*4882a593Smuzhiyun	ld	r3,PACA_SPRG_VDSO(r13)
116*4882a593Smuzhiyun	mtspr	SPRN_SPRG_VDSO_WRITE,r3
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun	/* Reload the host's PMU registers */
119*4882a593Smuzhiyun	bl	kvmhv_load_host_pmu
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun	/*
122*4882a593Smuzhiyun	 * Reload DEC.  HDEC interrupts were disabled when
123*4882a593Smuzhiyun	 * we reloaded the host's LPCR value.
124*4882a593Smuzhiyun	 */
125*4882a593Smuzhiyun	ld	r3, HSTATE_DECEXP(r13)
126*4882a593Smuzhiyun	mftb	r4
127*4882a593Smuzhiyun	subf	r4, r4, r3
128*4882a593Smuzhiyun	mtspr	SPRN_DEC, r4
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun	/* hwthread_req may have got set by cede or no vcpu, so clear it */
131*4882a593Smuzhiyun	li	r0, 0
132*4882a593Smuzhiyun	stb	r0, HSTATE_HWTHREAD_REQ(r13)
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun	/*
135*4882a593Smuzhiyun	 * For external interrupts we need to call the Linux
136*4882a593Smuzhiyun	 * handler to process the interrupt. We do that by jumping
137*4882a593Smuzhiyun	 * to absolute address 0x500 for external interrupts.
138*4882a593Smuzhiyun	 * The [h]rfid at the end of the handler will return to
139*4882a593Smuzhiyun	 * the book3s_hv_interrupts.S code. For other interrupts
140*4882a593Smuzhiyun	 * we do the rfid to get back to the book3s_hv_interrupts.S
141*4882a593Smuzhiyun	 * code here.
142*4882a593Smuzhiyun	 */
143*4882a593Smuzhiyun	ld	r8, 112+PPC_LR_STKOFF(r1)
144*4882a593Smuzhiyun	addi	r1, r1, 112
145*4882a593Smuzhiyun	ld	r7, HSTATE_HOST_MSR(r13)
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun	/* Return the trap number on this thread as the return value */
148*4882a593Smuzhiyun	mr	r3, r12
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun	/*
151*4882a593Smuzhiyun	 * If we came back from the guest via a relocation-on interrupt,
152*4882a593Smuzhiyun	 * we will be in virtual mode at this point, which makes it a
153*4882a593Smuzhiyun	 * little easier to get back to the caller.
154*4882a593Smuzhiyun	 */
155*4882a593Smuzhiyun	mfmsr	r0
156*4882a593Smuzhiyun	andi.	r0, r0, MSR_IR		/* in real mode? */
157*4882a593Smuzhiyun	bne	.Lvirt_return
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun	/* RFI into the highmem handler */
160*4882a593Smuzhiyun	mfmsr	r6
161*4882a593Smuzhiyun	li	r0, MSR_RI
162*4882a593Smuzhiyun	andc	r6, r6, r0
163*4882a593Smuzhiyun	mtmsrd	r6, 1			/* Clear RI in MSR */
164*4882a593Smuzhiyun	mtsrr0	r8
165*4882a593Smuzhiyun	mtsrr1	r7
166*4882a593Smuzhiyun	RFI_TO_KERNEL
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun	/* Virtual-mode return */
169*4882a593Smuzhiyun.Lvirt_return:
170*4882a593Smuzhiyun	mtlr	r8
171*4882a593Smuzhiyun	blr
172*4882a593Smuzhiyun
173*4882a593Smuzhiyunkvmppc_primary_no_guest:
174*4882a593Smuzhiyun	/* We handle this much like a ceded vcpu */
175*4882a593Smuzhiyun	/* put the HDEC into the DEC, since HDEC interrupts don't wake us */
176*4882a593Smuzhiyun	/* HDEC may be larger than DEC for arch >= v3.00, but since the */
177*4882a593Smuzhiyun	/* HDEC value came from DEC in the first place, it will fit */
178*4882a593Smuzhiyun	mfspr	r3, SPRN_HDEC
179*4882a593Smuzhiyun	mtspr	SPRN_DEC, r3
180*4882a593Smuzhiyun	/*
181*4882a593Smuzhiyun	 * Make sure the primary has finished the MMU switch.
182*4882a593Smuzhiyun	 * We should never get here on a secondary thread, but
183*4882a593Smuzhiyun	 * check it for robustness' sake.
184*4882a593Smuzhiyun	 */
185*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
186*4882a593Smuzhiyun65:	lbz	r0, VCORE_IN_GUEST(r5)
187*4882a593Smuzhiyun	cmpwi	r0, 0
188*4882a593Smuzhiyun	beq	65b
189*4882a593Smuzhiyun	/* Set LPCR. */
190*4882a593Smuzhiyun	ld	r8,VCORE_LPCR(r5)
191*4882a593Smuzhiyun	mtspr	SPRN_LPCR,r8
192*4882a593Smuzhiyun	isync
193*4882a593Smuzhiyun	/* set our bit in napping_threads */
194*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
195*4882a593Smuzhiyun	lbz	r7, HSTATE_PTID(r13)
196*4882a593Smuzhiyun	li	r0, 1
197*4882a593Smuzhiyun	sld	r0, r0, r7
198*4882a593Smuzhiyun	addi	r6, r5, VCORE_NAPPING_THREADS
199*4882a593Smuzhiyun1:	lwarx	r3, 0, r6
200*4882a593Smuzhiyun	or	r3, r3, r0
201*4882a593Smuzhiyun	stwcx.	r3, 0, r6
202*4882a593Smuzhiyun	bne	1b
203*4882a593Smuzhiyun	/* order napping_threads update vs testing entry_exit_map */
204*4882a593Smuzhiyun	isync
205*4882a593Smuzhiyun	li	r12, 0
206*4882a593Smuzhiyun	lwz	r7, VCORE_ENTRY_EXIT(r5)
207*4882a593Smuzhiyun	cmpwi	r7, 0x100
208*4882a593Smuzhiyun	bge	kvm_novcpu_exit	/* another thread already exiting */
209*4882a593Smuzhiyun	li	r3, NAPPING_NOVCPU
210*4882a593Smuzhiyun	stb	r3, HSTATE_NAPPING(r13)
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun	li	r3, 0		/* Don't wake on privileged (OS) doorbell */
213*4882a593Smuzhiyun	b	kvm_do_nap
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun/*
216*4882a593Smuzhiyun * kvm_novcpu_wakeup
217*4882a593Smuzhiyun *	Entered from kvm_start_guest if kvm_hstate.napping is set
218*4882a593Smuzhiyun *	to NAPPING_NOVCPU
219*4882a593Smuzhiyun *		r2 = kernel TOC
220*4882a593Smuzhiyun *		r13 = paca
221*4882a593Smuzhiyun */
222*4882a593Smuzhiyunkvm_novcpu_wakeup:
223*4882a593Smuzhiyun	ld	r1, HSTATE_HOST_R1(r13)
224*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
225*4882a593Smuzhiyun	li	r0, 0
226*4882a593Smuzhiyun	stb	r0, HSTATE_NAPPING(r13)
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun	/* check the wake reason */
229*4882a593Smuzhiyun	bl	kvmppc_check_wake_reason
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun	/*
232*4882a593Smuzhiyun	 * Restore volatile registers since we could have called
233*4882a593Smuzhiyun	 * a C routine in kvmppc_check_wake_reason.
234*4882a593Smuzhiyun	 *	r5 = VCORE
235*4882a593Smuzhiyun	 */
236*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun	/* see if any other thread is already exiting */
239*4882a593Smuzhiyun	lwz	r0, VCORE_ENTRY_EXIT(r5)
240*4882a593Smuzhiyun	cmpwi	r0, 0x100
241*4882a593Smuzhiyun	bge	kvm_novcpu_exit
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun	/* clear our bit in napping_threads */
244*4882a593Smuzhiyun	lbz	r7, HSTATE_PTID(r13)
245*4882a593Smuzhiyun	li	r0, 1
246*4882a593Smuzhiyun	sld	r0, r0, r7
247*4882a593Smuzhiyun	addi	r6, r5, VCORE_NAPPING_THREADS
248*4882a593Smuzhiyun4:	lwarx	r7, 0, r6
249*4882a593Smuzhiyun	andc	r7, r7, r0
250*4882a593Smuzhiyun	stwcx.	r7, 0, r6
251*4882a593Smuzhiyun	bne	4b
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun	/* See if the wake reason means we need to exit */
254*4882a593Smuzhiyun	cmpdi	r3, 0
255*4882a593Smuzhiyun	bge	kvm_novcpu_exit
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun	/* See if our timeslice has expired (HDEC is negative) */
258*4882a593Smuzhiyun	mfspr	r0, SPRN_HDEC
259*4882a593Smuzhiyun	EXTEND_HDEC(r0)
260*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_HV_DECREMENTER
261*4882a593Smuzhiyun	cmpdi	r0, 0
262*4882a593Smuzhiyun	blt	kvm_novcpu_exit
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun	/* Got an IPI but other vcpus aren't yet exiting, must be a latecomer */
265*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
266*4882a593Smuzhiyun	cmpdi	r4, 0
267*4882a593Smuzhiyun	beq	kvmppc_primary_no_guest
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
270*4882a593Smuzhiyun	addi	r3, r4, VCPU_TB_RMENTRY
271*4882a593Smuzhiyun	bl	kvmhv_start_timing
272*4882a593Smuzhiyun#endif
273*4882a593Smuzhiyun	b	kvmppc_got_guest
274*4882a593Smuzhiyun
275*4882a593Smuzhiyunkvm_novcpu_exit:
276*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
277*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
278*4882a593Smuzhiyun	cmpdi	r4, 0
279*4882a593Smuzhiyun	beq	13f
280*4882a593Smuzhiyun	addi	r3, r4, VCPU_TB_RMEXIT
281*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
282*4882a593Smuzhiyun#endif
283*4882a593Smuzhiyun13:	mr	r3, r12
284*4882a593Smuzhiyun	stw	r12, STACK_SLOT_TRAP(r1)
285*4882a593Smuzhiyun	bl	kvmhv_commence_exit
286*4882a593Smuzhiyun	nop
287*4882a593Smuzhiyun	b	kvmhv_switch_to_host
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun/*
290*4882a593Smuzhiyun * We come in here when wakened from Linux offline idle code.
291*4882a593Smuzhiyun * Relocation is off
292*4882a593Smuzhiyun * r3 contains the SRR1 wakeup value, SRR1 is trashed.
293*4882a593Smuzhiyun */
294*4882a593Smuzhiyun_GLOBAL(idle_kvm_start_guest)
295*4882a593Smuzhiyun	mfcr	r5
296*4882a593Smuzhiyun	mflr	r0
297*4882a593Smuzhiyun	std	r5, 8(r1)	// Save CR in caller's frame
298*4882a593Smuzhiyun	std	r0, 16(r1)	// Save LR in caller's frame
299*4882a593Smuzhiyun	// Create frame on emergency stack
300*4882a593Smuzhiyun	ld	r4, PACAEMERGSP(r13)
301*4882a593Smuzhiyun	stdu	r1, -SWITCH_FRAME_SIZE(r4)
302*4882a593Smuzhiyun	// Switch to new frame on emergency stack
303*4882a593Smuzhiyun	mr	r1, r4
304*4882a593Smuzhiyun	std	r3, 32(r1)	// Save SRR1 wakeup value
305*4882a593Smuzhiyun	SAVE_NVGPRS(r1)
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun	/*
308*4882a593Smuzhiyun	 * Could avoid this and pass it through in r3. For now,
309*4882a593Smuzhiyun	 * code expects it to be in SRR1.
310*4882a593Smuzhiyun	 */
311*4882a593Smuzhiyun	mtspr	SPRN_SRR1,r3
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun	li	r0,0
314*4882a593Smuzhiyun	stb	r0,PACA_FTRACE_ENABLED(r13)
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun	li	r0,KVM_HWTHREAD_IN_KVM
317*4882a593Smuzhiyun	stb	r0,HSTATE_HWTHREAD_STATE(r13)
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun	/* kvm cede / napping does not come through here */
320*4882a593Smuzhiyun	lbz	r0,HSTATE_NAPPING(r13)
321*4882a593Smuzhiyun	twnei	r0,0
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun	b	1f
324*4882a593Smuzhiyun
325*4882a593Smuzhiyunkvm_unsplit_wakeup:
326*4882a593Smuzhiyun	li	r0, 0
327*4882a593Smuzhiyun	stb	r0, HSTATE_NAPPING(r13)
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun1:
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun	/*
332*4882a593Smuzhiyun	 * We weren't napping due to cede, so this must be a secondary
333*4882a593Smuzhiyun	 * thread being woken up to run a guest, or being woken up due
334*4882a593Smuzhiyun	 * to a stray IPI.  (Or due to some machine check or hypervisor
335*4882a593Smuzhiyun	 * maintenance interrupt while the core is in KVM.)
336*4882a593Smuzhiyun	 */
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun	/* Check the wake reason in SRR1 to see why we got here */
339*4882a593Smuzhiyun	bl	kvmppc_check_wake_reason
340*4882a593Smuzhiyun	/*
341*4882a593Smuzhiyun	 * kvmppc_check_wake_reason could invoke a C routine, but we
342*4882a593Smuzhiyun	 * have no volatile registers to restore when we return.
343*4882a593Smuzhiyun	 */
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun	cmpdi	r3, 0
346*4882a593Smuzhiyun	bge	kvm_no_guest
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun	/* get vcore pointer, NULL if we have nothing to run */
349*4882a593Smuzhiyun	ld	r5,HSTATE_KVM_VCORE(r13)
350*4882a593Smuzhiyun	cmpdi	r5,0
351*4882a593Smuzhiyun	/* if we have no vcore to run, go back to sleep */
352*4882a593Smuzhiyun	beq	kvm_no_guest
353*4882a593Smuzhiyun
354*4882a593Smuzhiyunkvm_secondary_got_guest:
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun	// About to go to guest, clear saved SRR1
357*4882a593Smuzhiyun	li	r0, 0
358*4882a593Smuzhiyun	std	r0, 32(r1)
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun	/* Set HSTATE_DSCR(r13) to something sensible */
361*4882a593Smuzhiyun	ld	r6, PACA_DSCR_DEFAULT(r13)
362*4882a593Smuzhiyun	std	r6, HSTATE_DSCR(r13)
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun	/* On thread 0 of a subcore, set HDEC to max */
365*4882a593Smuzhiyun	lbz	r4, HSTATE_PTID(r13)
366*4882a593Smuzhiyun	cmpwi	r4, 0
367*4882a593Smuzhiyun	bne	63f
368*4882a593Smuzhiyun	LOAD_REG_ADDR(r6, decrementer_max)
369*4882a593Smuzhiyun	ld	r6, 0(r6)
370*4882a593Smuzhiyun	mtspr	SPRN_HDEC, r6
371*4882a593Smuzhiyun	/* and set per-LPAR registers, if doing dynamic micro-threading */
372*4882a593Smuzhiyun	ld	r6, HSTATE_SPLIT_MODE(r13)
373*4882a593Smuzhiyun	cmpdi	r6, 0
374*4882a593Smuzhiyun	beq	63f
375*4882a593SmuzhiyunBEGIN_FTR_SECTION
376*4882a593Smuzhiyun	ld	r0, KVM_SPLIT_RPR(r6)
377*4882a593Smuzhiyun	mtspr	SPRN_RPR, r0
378*4882a593Smuzhiyun	ld	r0, KVM_SPLIT_PMMAR(r6)
379*4882a593Smuzhiyun	mtspr	SPRN_PMMAR, r0
380*4882a593Smuzhiyun	ld	r0, KVM_SPLIT_LDBAR(r6)
381*4882a593Smuzhiyun	mtspr	SPRN_LDBAR, r0
382*4882a593Smuzhiyun	isync
383*4882a593SmuzhiyunFTR_SECTION_ELSE
384*4882a593Smuzhiyun	/* On P9 we use the split_info for coordinating LPCR changes */
385*4882a593Smuzhiyun	lwz	r4, KVM_SPLIT_DO_SET(r6)
386*4882a593Smuzhiyun	cmpwi	r4, 0
387*4882a593Smuzhiyun	beq	1f
388*4882a593Smuzhiyun	mr	r3, r6
389*4882a593Smuzhiyun	bl	kvmhv_p9_set_lpcr
390*4882a593Smuzhiyun	nop
391*4882a593Smuzhiyun1:
392*4882a593SmuzhiyunALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
393*4882a593Smuzhiyun63:
394*4882a593Smuzhiyun	/* Order load of vcpu after load of vcore */
395*4882a593Smuzhiyun	lwsync
396*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
397*4882a593Smuzhiyun	bl	kvmppc_hv_entry
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun	/* Back from the guest, go back to nap */
400*4882a593Smuzhiyun	/* Clear our vcpu and vcore pointers so we don't come back in early */
401*4882a593Smuzhiyun	li	r0, 0
402*4882a593Smuzhiyun	std	r0, HSTATE_KVM_VCPU(r13)
403*4882a593Smuzhiyun	/*
404*4882a593Smuzhiyun	 * Once we clear HSTATE_KVM_VCORE(r13), the code in
405*4882a593Smuzhiyun	 * kvmppc_run_core() is going to assume that all our vcpu
406*4882a593Smuzhiyun	 * state is visible in memory.  This lwsync makes sure
407*4882a593Smuzhiyun	 * that that is true.
408*4882a593Smuzhiyun	 */
409*4882a593Smuzhiyun	lwsync
410*4882a593Smuzhiyun	std	r0, HSTATE_KVM_VCORE(r13)
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun	/*
413*4882a593Smuzhiyun	 * All secondaries exiting guest will fall through this path.
414*4882a593Smuzhiyun	 * Before proceeding, just check for HMI interrupt and
415*4882a593Smuzhiyun	 * invoke opal hmi handler. By now we are sure that the
416*4882a593Smuzhiyun	 * primary thread on this core/subcore has already made partition
417*4882a593Smuzhiyun	 * switch/TB resync and we are good to call opal hmi handler.
418*4882a593Smuzhiyun	 */
419*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_HMI
420*4882a593Smuzhiyun	bne	kvm_no_guest
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun	li	r3,0			/* NULL argument */
423*4882a593Smuzhiyun	bl	hmi_exception_realmode
424*4882a593Smuzhiyun/*
425*4882a593Smuzhiyun * At this point we have finished executing in the guest.
426*4882a593Smuzhiyun * We need to wait for hwthread_req to become zero, since
427*4882a593Smuzhiyun * we may not turn on the MMU while hwthread_req is non-zero.
428*4882a593Smuzhiyun * While waiting we also need to check if we get given a vcpu to run.
429*4882a593Smuzhiyun */
430*4882a593Smuzhiyunkvm_no_guest:
431*4882a593Smuzhiyun	lbz	r3, HSTATE_HWTHREAD_REQ(r13)
432*4882a593Smuzhiyun	cmpwi	r3, 0
433*4882a593Smuzhiyun	bne	53f
434*4882a593Smuzhiyun	HMT_MEDIUM
435*4882a593Smuzhiyun	li	r0, KVM_HWTHREAD_IN_KERNEL
436*4882a593Smuzhiyun	stb	r0, HSTATE_HWTHREAD_STATE(r13)
437*4882a593Smuzhiyun	/* need to recheck hwthread_req after a barrier, to avoid race */
438*4882a593Smuzhiyun	sync
439*4882a593Smuzhiyun	lbz	r3, HSTATE_HWTHREAD_REQ(r13)
440*4882a593Smuzhiyun	cmpwi	r3, 0
441*4882a593Smuzhiyun	bne	54f
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun	/*
444*4882a593Smuzhiyun	 * Jump to idle_return_gpr_loss, which returns to the
445*4882a593Smuzhiyun	 * idle_kvm_start_guest caller.
446*4882a593Smuzhiyun	 */
447*4882a593Smuzhiyun	li	r3, LPCR_PECE0
448*4882a593Smuzhiyun	mfspr	r4, SPRN_LPCR
449*4882a593Smuzhiyun	rlwimi	r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
450*4882a593Smuzhiyun	mtspr	SPRN_LPCR, r4
451*4882a593Smuzhiyun	// Return SRR1 wakeup value, or 0 if we went into the guest
452*4882a593Smuzhiyun	ld	r3, 32(r1)
453*4882a593Smuzhiyun	REST_NVGPRS(r1)
454*4882a593Smuzhiyun	ld	r1, 0(r1)	// Switch back to caller stack
455*4882a593Smuzhiyun	ld	r0, 16(r1)	// Reload LR
456*4882a593Smuzhiyun	ld	r5, 8(r1)	// Reload CR
457*4882a593Smuzhiyun	mtlr	r0
458*4882a593Smuzhiyun	mtcr	r5
459*4882a593Smuzhiyun	blr
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun53:	HMT_LOW
462*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
463*4882a593Smuzhiyun	cmpdi	r5, 0
464*4882a593Smuzhiyun	bne	60f
465*4882a593Smuzhiyun	ld	r3, HSTATE_SPLIT_MODE(r13)
466*4882a593Smuzhiyun	cmpdi	r3, 0
467*4882a593Smuzhiyun	beq	kvm_no_guest
468*4882a593Smuzhiyun	lwz	r0, KVM_SPLIT_DO_SET(r3)
469*4882a593Smuzhiyun	cmpwi	r0, 0
470*4882a593Smuzhiyun	bne	kvmhv_do_set
471*4882a593Smuzhiyun	lwz	r0, KVM_SPLIT_DO_RESTORE(r3)
472*4882a593Smuzhiyun	cmpwi	r0, 0
473*4882a593Smuzhiyun	bne	kvmhv_do_restore
474*4882a593Smuzhiyun	lbz	r0, KVM_SPLIT_DO_NAP(r3)
475*4882a593Smuzhiyun	cmpwi	r0, 0
476*4882a593Smuzhiyun	beq	kvm_no_guest
477*4882a593Smuzhiyun	HMT_MEDIUM
478*4882a593Smuzhiyun	b	kvm_unsplit_nap
479*4882a593Smuzhiyun60:	HMT_MEDIUM
480*4882a593Smuzhiyun	b	kvm_secondary_got_guest
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun54:	li	r0, KVM_HWTHREAD_IN_KVM
483*4882a593Smuzhiyun	stb	r0, HSTATE_HWTHREAD_STATE(r13)
484*4882a593Smuzhiyun	b	kvm_no_guest
485*4882a593Smuzhiyun
486*4882a593Smuzhiyunkvmhv_do_set:
487*4882a593Smuzhiyun	/* Set LPCR, LPIDR etc. on P9 */
488*4882a593Smuzhiyun	HMT_MEDIUM
489*4882a593Smuzhiyun	bl	kvmhv_p9_set_lpcr
490*4882a593Smuzhiyun	nop
491*4882a593Smuzhiyun	b	kvm_no_guest
492*4882a593Smuzhiyun
493*4882a593Smuzhiyunkvmhv_do_restore:
494*4882a593Smuzhiyun	HMT_MEDIUM
495*4882a593Smuzhiyun	bl	kvmhv_p9_restore_lpcr
496*4882a593Smuzhiyun	nop
497*4882a593Smuzhiyun	b	kvm_no_guest
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun/*
500*4882a593Smuzhiyun * Here the primary thread is trying to return the core to
501*4882a593Smuzhiyun * whole-core mode, so we need to nap.
502*4882a593Smuzhiyun */
503*4882a593Smuzhiyunkvm_unsplit_nap:
504*4882a593Smuzhiyun	/*
505*4882a593Smuzhiyun	 * When secondaries are napping in kvm_unsplit_nap() with
506*4882a593Smuzhiyun	 * hwthread_req = 1, HMI goes ignored even though subcores are
507*4882a593Smuzhiyun	 * already exited the guest. Hence HMI keeps waking up secondaries
508*4882a593Smuzhiyun	 * from nap in a loop and secondaries always go back to nap since
509*4882a593Smuzhiyun	 * no vcore is assigned to them. This makes impossible for primary
510*4882a593Smuzhiyun	 * thread to get hold of secondary threads resulting into a soft
511*4882a593Smuzhiyun	 * lockup in KVM path.
512*4882a593Smuzhiyun	 *
513*4882a593Smuzhiyun	 * Let us check if HMI is pending and handle it before we go to nap.
514*4882a593Smuzhiyun	 */
515*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_HMI
516*4882a593Smuzhiyun	bne	55f
517*4882a593Smuzhiyun	li	r3, 0			/* NULL argument */
518*4882a593Smuzhiyun	bl	hmi_exception_realmode
519*4882a593Smuzhiyun55:
520*4882a593Smuzhiyun	/*
521*4882a593Smuzhiyun	 * Ensure that secondary doesn't nap when it has
522*4882a593Smuzhiyun	 * its vcore pointer set.
523*4882a593Smuzhiyun	 */
524*4882a593Smuzhiyun	sync		/* matches smp_mb() before setting split_info.do_nap */
525*4882a593Smuzhiyun	ld	r0, HSTATE_KVM_VCORE(r13)
526*4882a593Smuzhiyun	cmpdi	r0, 0
527*4882a593Smuzhiyun	bne	kvm_no_guest
528*4882a593Smuzhiyun	/* clear any pending message */
529*4882a593SmuzhiyunBEGIN_FTR_SECTION
530*4882a593Smuzhiyun	lis	r6, (PPC_DBELL_SERVER << (63-36))@h
531*4882a593Smuzhiyun	PPC_MSGCLR(6)
532*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
533*4882a593Smuzhiyun	/* Set kvm_split_mode.napped[tid] = 1 */
534*4882a593Smuzhiyun	ld	r3, HSTATE_SPLIT_MODE(r13)
535*4882a593Smuzhiyun	li	r0, 1
536*4882a593Smuzhiyun	lbz	r4, HSTATE_TID(r13)
537*4882a593Smuzhiyun	addi	r4, r4, KVM_SPLIT_NAPPED
538*4882a593Smuzhiyun	stbx	r0, r3, r4
539*4882a593Smuzhiyun	/* Check the do_nap flag again after setting napped[] */
540*4882a593Smuzhiyun	sync
541*4882a593Smuzhiyun	lbz	r0, KVM_SPLIT_DO_NAP(r3)
542*4882a593Smuzhiyun	cmpwi	r0, 0
543*4882a593Smuzhiyun	beq	57f
544*4882a593Smuzhiyun	li	r3, NAPPING_UNSPLIT
545*4882a593Smuzhiyun	stb	r3, HSTATE_NAPPING(r13)
546*4882a593Smuzhiyun	li	r3, (LPCR_PECEDH | LPCR_PECE0) >> 4
547*4882a593Smuzhiyun	mfspr	r5, SPRN_LPCR
548*4882a593Smuzhiyun	rlwimi	r5, r3, 4, (LPCR_PECEDP | LPCR_PECEDH | LPCR_PECE0 | LPCR_PECE1)
549*4882a593Smuzhiyun	b	kvm_nap_sequence
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun57:	li	r0, 0
552*4882a593Smuzhiyun	stbx	r0, r3, r4
553*4882a593Smuzhiyun	b	kvm_no_guest
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun/******************************************************************************
556*4882a593Smuzhiyun *                                                                            *
557*4882a593Smuzhiyun *                               Entry code                                   *
558*4882a593Smuzhiyun *                                                                            *
559*4882a593Smuzhiyun *****************************************************************************/
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun.global kvmppc_hv_entry
562*4882a593Smuzhiyunkvmppc_hv_entry:
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun	/* Required state:
565*4882a593Smuzhiyun	 *
566*4882a593Smuzhiyun	 * R4 = vcpu pointer (or NULL)
567*4882a593Smuzhiyun	 * MSR = ~IR|DR
568*4882a593Smuzhiyun	 * R13 = PACA
569*4882a593Smuzhiyun	 * R1 = host R1
570*4882a593Smuzhiyun	 * R2 = TOC
571*4882a593Smuzhiyun	 * all other volatile GPRS = free
572*4882a593Smuzhiyun	 * Does not preserve non-volatile GPRs or CR fields
573*4882a593Smuzhiyun	 */
574*4882a593Smuzhiyun	mflr	r0
575*4882a593Smuzhiyun	std	r0, PPC_LR_STKOFF(r1)
576*4882a593Smuzhiyun	stdu	r1, -SFS(r1)
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun	/* Save R1 in the PACA */
579*4882a593Smuzhiyun	std	r1, HSTATE_HOST_R1(r13)
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun	li	r6, KVM_GUEST_MODE_HOST_HV
582*4882a593Smuzhiyun	stb	r6, HSTATE_IN_GUEST(r13)
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
585*4882a593Smuzhiyun	/* Store initial timestamp */
586*4882a593Smuzhiyun	cmpdi	r4, 0
587*4882a593Smuzhiyun	beq	1f
588*4882a593Smuzhiyun	addi	r3, r4, VCPU_TB_RMENTRY
589*4882a593Smuzhiyun	bl	kvmhv_start_timing
590*4882a593Smuzhiyun1:
591*4882a593Smuzhiyun#endif
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
594*4882a593Smuzhiyun	ld	r9, VCORE_KVM(r5)	/* pointer to struct kvm */
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun	/*
597*4882a593Smuzhiyun	 * POWER7/POWER8 host -> guest partition switch code.
598*4882a593Smuzhiyun	 * We don't have to lock against concurrent tlbies,
599*4882a593Smuzhiyun	 * but we do have to coordinate across hardware threads.
600*4882a593Smuzhiyun	 */
601*4882a593Smuzhiyun	/* Set bit in entry map iff exit map is zero. */
602*4882a593Smuzhiyun	li	r7, 1
603*4882a593Smuzhiyun	lbz	r6, HSTATE_PTID(r13)
604*4882a593Smuzhiyun	sld	r7, r7, r6
605*4882a593Smuzhiyun	addi	r8, r5, VCORE_ENTRY_EXIT
606*4882a593Smuzhiyun21:	lwarx	r3, 0, r8
607*4882a593Smuzhiyun	cmpwi	r3, 0x100		/* any threads starting to exit? */
608*4882a593Smuzhiyun	bge	secondary_too_late	/* if so we're too late to the party */
609*4882a593Smuzhiyun	or	r3, r3, r7
610*4882a593Smuzhiyun	stwcx.	r3, 0, r8
611*4882a593Smuzhiyun	bne	21b
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun	/* Primary thread switches to guest partition. */
614*4882a593Smuzhiyun	cmpwi	r6,0
615*4882a593Smuzhiyun	bne	10f
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun	lwz	r7,KVM_LPID(r9)
618*4882a593SmuzhiyunBEGIN_FTR_SECTION
619*4882a593Smuzhiyun	ld	r6,KVM_SDR1(r9)
620*4882a593Smuzhiyun	li	r0,LPID_RSVD		/* switch to reserved LPID */
621*4882a593Smuzhiyun	mtspr	SPRN_LPID,r0
622*4882a593Smuzhiyun	ptesync
623*4882a593Smuzhiyun	mtspr	SPRN_SDR1,r6		/* switch to partition page table */
624*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
625*4882a593Smuzhiyun	mtspr	SPRN_LPID,r7
626*4882a593Smuzhiyun	isync
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun	/* See if we need to flush the TLB. */
629*4882a593Smuzhiyun	mr	r3, r9			/* kvm pointer */
630*4882a593Smuzhiyun	lhz	r4, PACAPACAINDEX(r13)	/* physical cpu number */
631*4882a593Smuzhiyun	li	r5, 0			/* nested vcpu pointer */
632*4882a593Smuzhiyun	bl	kvmppc_check_need_tlb_flush
633*4882a593Smuzhiyun	nop
634*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun	/* Add timebase offset onto timebase */
637*4882a593Smuzhiyun22:	ld	r8,VCORE_TB_OFFSET(r5)
638*4882a593Smuzhiyun	cmpdi	r8,0
639*4882a593Smuzhiyun	beq	37f
640*4882a593Smuzhiyun	std	r8, VCORE_TB_OFFSET_APPL(r5)
641*4882a593Smuzhiyun	mftb	r6		/* current host timebase */
642*4882a593Smuzhiyun	add	r8,r8,r6
643*4882a593Smuzhiyun	mtspr	SPRN_TBU40,r8	/* update upper 40 bits */
644*4882a593Smuzhiyun	mftb	r7		/* check if lower 24 bits overflowed */
645*4882a593Smuzhiyun	clrldi	r6,r6,40
646*4882a593Smuzhiyun	clrldi	r7,r7,40
647*4882a593Smuzhiyun	cmpld	r7,r6
648*4882a593Smuzhiyun	bge	37f
649*4882a593Smuzhiyun	addis	r8,r8,0x100	/* if so, increment upper 40 bits */
650*4882a593Smuzhiyun	mtspr	SPRN_TBU40,r8
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun	/* Load guest PCR value to select appropriate compat mode */
653*4882a593Smuzhiyun37:	ld	r7, VCORE_PCR(r5)
654*4882a593Smuzhiyun	LOAD_REG_IMMEDIATE(r6, PCR_MASK)
655*4882a593Smuzhiyun	cmpld	r7, r6
656*4882a593Smuzhiyun	beq	38f
657*4882a593Smuzhiyun	or	r7, r7, r6
658*4882a593Smuzhiyun	mtspr	SPRN_PCR, r7
659*4882a593Smuzhiyun38:
660*4882a593Smuzhiyun
661*4882a593SmuzhiyunBEGIN_FTR_SECTION
662*4882a593Smuzhiyun	/* DPDES and VTB are shared between threads */
663*4882a593Smuzhiyun	ld	r8, VCORE_DPDES(r5)
664*4882a593Smuzhiyun	ld	r7, VCORE_VTB(r5)
665*4882a593Smuzhiyun	mtspr	SPRN_DPDES, r8
666*4882a593Smuzhiyun	mtspr	SPRN_VTB, r7
667*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun	/* Mark the subcore state as inside guest */
670*4882a593Smuzhiyun	bl	kvmppc_subcore_enter_guest
671*4882a593Smuzhiyun	nop
672*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
673*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
674*4882a593Smuzhiyun	li	r0,1
675*4882a593Smuzhiyun	stb	r0,VCORE_IN_GUEST(r5)	/* signal secondaries to continue */
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun	/* Do we have a guest vcpu to run? */
678*4882a593Smuzhiyun10:	cmpdi	r4, 0
679*4882a593Smuzhiyun	beq	kvmppc_primary_no_guest
680*4882a593Smuzhiyunkvmppc_got_guest:
681*4882a593Smuzhiyun	/* Increment yield count if they have a VPA */
682*4882a593Smuzhiyun	ld	r3, VCPU_VPA(r4)
683*4882a593Smuzhiyun	cmpdi	r3, 0
684*4882a593Smuzhiyun	beq	25f
685*4882a593Smuzhiyun	li	r6, LPPACA_YIELDCOUNT
686*4882a593Smuzhiyun	LWZX_BE	r5, r3, r6
687*4882a593Smuzhiyun	addi	r5, r5, 1
688*4882a593Smuzhiyun	STWX_BE	r5, r3, r6
689*4882a593Smuzhiyun	li	r6, 1
690*4882a593Smuzhiyun	stb	r6, VCPU_VPA_DIRTY(r4)
691*4882a593Smuzhiyun25:
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun	/* Save purr/spurr */
694*4882a593Smuzhiyun	mfspr	r5,SPRN_PURR
695*4882a593Smuzhiyun	mfspr	r6,SPRN_SPURR
696*4882a593Smuzhiyun	std	r5,HSTATE_PURR(r13)
697*4882a593Smuzhiyun	std	r6,HSTATE_SPURR(r13)
698*4882a593Smuzhiyun	ld	r7,VCPU_PURR(r4)
699*4882a593Smuzhiyun	ld	r8,VCPU_SPURR(r4)
700*4882a593Smuzhiyun	mtspr	SPRN_PURR,r7
701*4882a593Smuzhiyun	mtspr	SPRN_SPURR,r8
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun	/* Save host values of some registers */
704*4882a593SmuzhiyunBEGIN_FTR_SECTION
705*4882a593Smuzhiyun	mfspr	r5, SPRN_TIDR
706*4882a593Smuzhiyun	mfspr	r6, SPRN_PSSCR
707*4882a593Smuzhiyun	mfspr	r7, SPRN_PID
708*4882a593Smuzhiyun	std	r5, STACK_SLOT_TID(r1)
709*4882a593Smuzhiyun	std	r6, STACK_SLOT_PSSCR(r1)
710*4882a593Smuzhiyun	std	r7, STACK_SLOT_PID(r1)
711*4882a593Smuzhiyun	mfspr	r5, SPRN_HFSCR
712*4882a593Smuzhiyun	std	r5, STACK_SLOT_HFSCR(r1)
713*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
714*4882a593SmuzhiyunBEGIN_FTR_SECTION
715*4882a593Smuzhiyun	mfspr	r5, SPRN_CIABR
716*4882a593Smuzhiyun	mfspr	r6, SPRN_DAWR0
717*4882a593Smuzhiyun	mfspr	r7, SPRN_DAWRX0
718*4882a593Smuzhiyun	mfspr	r8, SPRN_IAMR
719*4882a593Smuzhiyun	std	r5, STACK_SLOT_CIABR(r1)
720*4882a593Smuzhiyun	std	r6, STACK_SLOT_DAWR(r1)
721*4882a593Smuzhiyun	std	r7, STACK_SLOT_DAWRX(r1)
722*4882a593Smuzhiyun	std	r8, STACK_SLOT_IAMR(r1)
723*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun	mfspr	r5, SPRN_AMR
726*4882a593Smuzhiyun	std	r5, STACK_SLOT_AMR(r1)
727*4882a593Smuzhiyun	mfspr	r6, SPRN_UAMOR
728*4882a593Smuzhiyun	std	r6, STACK_SLOT_UAMOR(r1)
729*4882a593Smuzhiyun
730*4882a593SmuzhiyunBEGIN_FTR_SECTION
731*4882a593Smuzhiyun	/* Set partition DABR */
732*4882a593Smuzhiyun	/* Do this before re-enabling PMU to avoid P7 DABR corruption bug */
733*4882a593Smuzhiyun	lwz	r5,VCPU_DABRX(r4)
734*4882a593Smuzhiyun	ld	r6,VCPU_DABR(r4)
735*4882a593Smuzhiyun	mtspr	SPRN_DABRX,r5
736*4882a593Smuzhiyun	mtspr	SPRN_DABR,r6
737*4882a593Smuzhiyun	isync
738*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
741*4882a593Smuzhiyun/*
742*4882a593Smuzhiyun * Branch around the call if both CPU_FTR_TM and
743*4882a593Smuzhiyun * CPU_FTR_P9_TM_HV_ASSIST are off.
744*4882a593Smuzhiyun */
745*4882a593SmuzhiyunBEGIN_FTR_SECTION
746*4882a593Smuzhiyun	b	91f
747*4882a593SmuzhiyunEND_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
748*4882a593Smuzhiyun	/*
749*4882a593Smuzhiyun	 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS (but not CR)
750*4882a593Smuzhiyun	 */
751*4882a593Smuzhiyun	mr      r3, r4
752*4882a593Smuzhiyun	ld      r4, VCPU_MSR(r3)
753*4882a593Smuzhiyun	li	r5, 0			/* don't preserve non-vol regs */
754*4882a593Smuzhiyun	bl	kvmppc_restore_tm_hv
755*4882a593Smuzhiyun	nop
756*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
757*4882a593Smuzhiyun91:
758*4882a593Smuzhiyun#endif
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun	/* Load guest PMU registers; r4 = vcpu pointer here */
761*4882a593Smuzhiyun	mr	r3, r4
762*4882a593Smuzhiyun	bl	kvmhv_load_guest_pmu
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun	/* Load up FP, VMX and VSX registers */
765*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
766*4882a593Smuzhiyun	bl	kvmppc_load_fp
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun	ld	r14, VCPU_GPR(R14)(r4)
769*4882a593Smuzhiyun	ld	r15, VCPU_GPR(R15)(r4)
770*4882a593Smuzhiyun	ld	r16, VCPU_GPR(R16)(r4)
771*4882a593Smuzhiyun	ld	r17, VCPU_GPR(R17)(r4)
772*4882a593Smuzhiyun	ld	r18, VCPU_GPR(R18)(r4)
773*4882a593Smuzhiyun	ld	r19, VCPU_GPR(R19)(r4)
774*4882a593Smuzhiyun	ld	r20, VCPU_GPR(R20)(r4)
775*4882a593Smuzhiyun	ld	r21, VCPU_GPR(R21)(r4)
776*4882a593Smuzhiyun	ld	r22, VCPU_GPR(R22)(r4)
777*4882a593Smuzhiyun	ld	r23, VCPU_GPR(R23)(r4)
778*4882a593Smuzhiyun	ld	r24, VCPU_GPR(R24)(r4)
779*4882a593Smuzhiyun	ld	r25, VCPU_GPR(R25)(r4)
780*4882a593Smuzhiyun	ld	r26, VCPU_GPR(R26)(r4)
781*4882a593Smuzhiyun	ld	r27, VCPU_GPR(R27)(r4)
782*4882a593Smuzhiyun	ld	r28, VCPU_GPR(R28)(r4)
783*4882a593Smuzhiyun	ld	r29, VCPU_GPR(R29)(r4)
784*4882a593Smuzhiyun	ld	r30, VCPU_GPR(R30)(r4)
785*4882a593Smuzhiyun	ld	r31, VCPU_GPR(R31)(r4)
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun	/* Switch DSCR to guest value */
788*4882a593Smuzhiyun	ld	r5, VCPU_DSCR(r4)
789*4882a593Smuzhiyun	mtspr	SPRN_DSCR, r5
790*4882a593Smuzhiyun
791*4882a593SmuzhiyunBEGIN_FTR_SECTION
792*4882a593Smuzhiyun	/* Skip next section on POWER7 */
793*4882a593Smuzhiyun	b	8f
794*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
795*4882a593Smuzhiyun	/* Load up POWER8-specific registers */
796*4882a593Smuzhiyun	ld	r5, VCPU_IAMR(r4)
797*4882a593Smuzhiyun	lwz	r6, VCPU_PSPB(r4)
798*4882a593Smuzhiyun	ld	r7, VCPU_FSCR(r4)
799*4882a593Smuzhiyun	mtspr	SPRN_IAMR, r5
800*4882a593Smuzhiyun	mtspr	SPRN_PSPB, r6
801*4882a593Smuzhiyun	mtspr	SPRN_FSCR, r7
802*4882a593Smuzhiyun	/*
803*4882a593Smuzhiyun	 * Handle broken DAWR case by not writing it. This means we
804*4882a593Smuzhiyun	 * can still store the DAWR register for migration.
805*4882a593Smuzhiyun	 */
806*4882a593Smuzhiyun	LOAD_REG_ADDR(r5, dawr_force_enable)
807*4882a593Smuzhiyun	lbz	r5, 0(r5)
808*4882a593Smuzhiyun	cmpdi	r5, 0
809*4882a593Smuzhiyun	beq	1f
810*4882a593Smuzhiyun	ld	r5, VCPU_DAWR(r4)
811*4882a593Smuzhiyun	ld	r6, VCPU_DAWRX(r4)
812*4882a593Smuzhiyun	mtspr	SPRN_DAWR0, r5
813*4882a593Smuzhiyun	mtspr	SPRN_DAWRX0, r6
814*4882a593Smuzhiyun1:
815*4882a593Smuzhiyun	ld	r7, VCPU_CIABR(r4)
816*4882a593Smuzhiyun	ld	r8, VCPU_TAR(r4)
817*4882a593Smuzhiyun	mtspr	SPRN_CIABR, r7
818*4882a593Smuzhiyun	mtspr	SPRN_TAR, r8
819*4882a593Smuzhiyun	ld	r5, VCPU_IC(r4)
820*4882a593Smuzhiyun	ld	r8, VCPU_EBBHR(r4)
821*4882a593Smuzhiyun	mtspr	SPRN_IC, r5
822*4882a593Smuzhiyun	mtspr	SPRN_EBBHR, r8
823*4882a593Smuzhiyun	ld	r5, VCPU_EBBRR(r4)
824*4882a593Smuzhiyun	ld	r6, VCPU_BESCR(r4)
825*4882a593Smuzhiyun	lwz	r7, VCPU_GUEST_PID(r4)
826*4882a593Smuzhiyun	ld	r8, VCPU_WORT(r4)
827*4882a593Smuzhiyun	mtspr	SPRN_EBBRR, r5
828*4882a593Smuzhiyun	mtspr	SPRN_BESCR, r6
829*4882a593Smuzhiyun	mtspr	SPRN_PID, r7
830*4882a593Smuzhiyun	mtspr	SPRN_WORT, r8
831*4882a593SmuzhiyunBEGIN_FTR_SECTION
832*4882a593Smuzhiyun	/* POWER8-only registers */
833*4882a593Smuzhiyun	ld	r5, VCPU_TCSCR(r4)
834*4882a593Smuzhiyun	ld	r6, VCPU_ACOP(r4)
835*4882a593Smuzhiyun	ld	r7, VCPU_CSIGR(r4)
836*4882a593Smuzhiyun	ld	r8, VCPU_TACR(r4)
837*4882a593Smuzhiyun	mtspr	SPRN_TCSCR, r5
838*4882a593Smuzhiyun	mtspr	SPRN_ACOP, r6
839*4882a593Smuzhiyun	mtspr	SPRN_CSIGR, r7
840*4882a593Smuzhiyun	mtspr	SPRN_TACR, r8
841*4882a593Smuzhiyun	nop
842*4882a593SmuzhiyunFTR_SECTION_ELSE
843*4882a593Smuzhiyun	/* POWER9-only registers */
844*4882a593Smuzhiyun	ld	r5, VCPU_TID(r4)
845*4882a593Smuzhiyun	ld	r6, VCPU_PSSCR(r4)
846*4882a593Smuzhiyun	lbz	r8, HSTATE_FAKE_SUSPEND(r13)
847*4882a593Smuzhiyun	oris	r6, r6, PSSCR_EC@h	/* This makes stop trap to HV */
848*4882a593Smuzhiyun	rldimi	r6, r8, PSSCR_FAKE_SUSPEND_LG, 63 - PSSCR_FAKE_SUSPEND_LG
849*4882a593Smuzhiyun	ld	r7, VCPU_HFSCR(r4)
850*4882a593Smuzhiyun	mtspr	SPRN_TIDR, r5
851*4882a593Smuzhiyun	mtspr	SPRN_PSSCR, r6
852*4882a593Smuzhiyun	mtspr	SPRN_HFSCR, r7
853*4882a593SmuzhiyunALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
854*4882a593Smuzhiyun8:
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun	ld	r5, VCPU_SPRG0(r4)
857*4882a593Smuzhiyun	ld	r6, VCPU_SPRG1(r4)
858*4882a593Smuzhiyun	ld	r7, VCPU_SPRG2(r4)
859*4882a593Smuzhiyun	ld	r8, VCPU_SPRG3(r4)
860*4882a593Smuzhiyun	mtspr	SPRN_SPRG0, r5
861*4882a593Smuzhiyun	mtspr	SPRN_SPRG1, r6
862*4882a593Smuzhiyun	mtspr	SPRN_SPRG2, r7
863*4882a593Smuzhiyun	mtspr	SPRN_SPRG3, r8
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun	/* Load up DAR and DSISR */
866*4882a593Smuzhiyun	ld	r5, VCPU_DAR(r4)
867*4882a593Smuzhiyun	lwz	r6, VCPU_DSISR(r4)
868*4882a593Smuzhiyun	mtspr	SPRN_DAR, r5
869*4882a593Smuzhiyun	mtspr	SPRN_DSISR, r6
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun	/* Restore AMR and UAMOR, set AMOR to all 1s */
872*4882a593Smuzhiyun	ld	r5,VCPU_AMR(r4)
873*4882a593Smuzhiyun	ld	r6,VCPU_UAMOR(r4)
874*4882a593Smuzhiyun	li	r7,-1
875*4882a593Smuzhiyun	mtspr	SPRN_AMR,r5
876*4882a593Smuzhiyun	mtspr	SPRN_UAMOR,r6
877*4882a593Smuzhiyun	mtspr	SPRN_AMOR,r7
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun	/* Restore state of CTRL run bit; assume 1 on entry */
880*4882a593Smuzhiyun	lwz	r5,VCPU_CTRL(r4)
881*4882a593Smuzhiyun	andi.	r5,r5,1
882*4882a593Smuzhiyun	bne	4f
883*4882a593Smuzhiyun	mfspr	r6,SPRN_CTRLF
884*4882a593Smuzhiyun	clrrdi	r6,r6,1
885*4882a593Smuzhiyun	mtspr	SPRN_CTRLT,r6
886*4882a593Smuzhiyun4:
887*4882a593Smuzhiyun	/* Secondary threads wait for primary to have done partition switch */
888*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
889*4882a593Smuzhiyun	lbz	r6, HSTATE_PTID(r13)
890*4882a593Smuzhiyun	cmpwi	r6, 0
891*4882a593Smuzhiyun	beq	21f
892*4882a593Smuzhiyun	lbz	r0, VCORE_IN_GUEST(r5)
893*4882a593Smuzhiyun	cmpwi	r0, 0
894*4882a593Smuzhiyun	bne	21f
895*4882a593Smuzhiyun	HMT_LOW
896*4882a593Smuzhiyun20:	lwz	r3, VCORE_ENTRY_EXIT(r5)
897*4882a593Smuzhiyun	cmpwi	r3, 0x100
898*4882a593Smuzhiyun	bge	no_switch_exit
899*4882a593Smuzhiyun	lbz	r0, VCORE_IN_GUEST(r5)
900*4882a593Smuzhiyun	cmpwi	r0, 0
901*4882a593Smuzhiyun	beq	20b
902*4882a593Smuzhiyun	HMT_MEDIUM
903*4882a593Smuzhiyun21:
904*4882a593Smuzhiyun	/* Set LPCR. */
905*4882a593Smuzhiyun	ld	r8,VCORE_LPCR(r5)
906*4882a593Smuzhiyun	mtspr	SPRN_LPCR,r8
907*4882a593Smuzhiyun	isync
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun	/*
910*4882a593Smuzhiyun	 * Set the decrementer to the guest decrementer.
911*4882a593Smuzhiyun	 */
912*4882a593Smuzhiyun	ld	r8,VCPU_DEC_EXPIRES(r4)
913*4882a593Smuzhiyun	/* r8 is a host timebase value here, convert to guest TB */
914*4882a593Smuzhiyun	ld	r5,HSTATE_KVM_VCORE(r13)
915*4882a593Smuzhiyun	ld	r6,VCORE_TB_OFFSET_APPL(r5)
916*4882a593Smuzhiyun	add	r8,r8,r6
917*4882a593Smuzhiyun	mftb	r7
918*4882a593Smuzhiyun	subf	r3,r7,r8
919*4882a593Smuzhiyun	mtspr	SPRN_DEC,r3
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun	/* Check if HDEC expires soon */
922*4882a593Smuzhiyun	mfspr	r3, SPRN_HDEC
923*4882a593Smuzhiyun	EXTEND_HDEC(r3)
924*4882a593Smuzhiyun	cmpdi	r3, 512		/* 1 microsecond */
925*4882a593Smuzhiyun	blt	hdec_soon
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun	/* For hash guest, clear out and reload the SLB */
928*4882a593Smuzhiyun	ld	r6, VCPU_KVM(r4)
929*4882a593Smuzhiyun	lbz	r0, KVM_RADIX(r6)
930*4882a593Smuzhiyun	cmpwi	r0, 0
931*4882a593Smuzhiyun	bne	9f
932*4882a593Smuzhiyun	li	r6, 0
933*4882a593Smuzhiyun	slbmte	r6, r6
934*4882a593Smuzhiyun	slbia
935*4882a593Smuzhiyun	ptesync
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun	/* Load up guest SLB entries (N.B. slb_max will be 0 for radix) */
938*4882a593Smuzhiyun	lwz	r5,VCPU_SLB_MAX(r4)
939*4882a593Smuzhiyun	cmpwi	r5,0
940*4882a593Smuzhiyun	beq	9f
941*4882a593Smuzhiyun	mtctr	r5
942*4882a593Smuzhiyun	addi	r6,r4,VCPU_SLB
943*4882a593Smuzhiyun1:	ld	r8,VCPU_SLB_E(r6)
944*4882a593Smuzhiyun	ld	r9,VCPU_SLB_V(r6)
945*4882a593Smuzhiyun	slbmte	r9,r8
946*4882a593Smuzhiyun	addi	r6,r6,VCPU_SLB_SIZE
947*4882a593Smuzhiyun	bdnz	1b
948*4882a593Smuzhiyun9:
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun#ifdef CONFIG_KVM_XICS
951*4882a593Smuzhiyun	/* We are entering the guest on that thread, push VCPU to XIVE */
952*4882a593Smuzhiyun	ld	r11, VCPU_XIVE_SAVED_STATE(r4)
953*4882a593Smuzhiyun	li	r9, TM_QW1_OS
954*4882a593Smuzhiyun	lwz	r8, VCPU_XIVE_CAM_WORD(r4)
955*4882a593Smuzhiyun	cmpwi	r8, 0
956*4882a593Smuzhiyun	beq	no_xive
957*4882a593Smuzhiyun	li	r7, TM_QW1_OS + TM_WORD2
958*4882a593Smuzhiyun	mfmsr	r0
959*4882a593Smuzhiyun	andi.	r0, r0, MSR_DR		/* in real mode? */
960*4882a593Smuzhiyun	beq	2f
961*4882a593Smuzhiyun	ld	r10, HSTATE_XIVE_TIMA_VIRT(r13)
962*4882a593Smuzhiyun	cmpldi	cr1, r10, 0
963*4882a593Smuzhiyun	beq     cr1, no_xive
964*4882a593Smuzhiyun	eieio
965*4882a593Smuzhiyun	stdx	r11,r9,r10
966*4882a593Smuzhiyun	stwx	r8,r7,r10
967*4882a593Smuzhiyun	b	3f
968*4882a593Smuzhiyun2:	ld	r10, HSTATE_XIVE_TIMA_PHYS(r13)
969*4882a593Smuzhiyun	cmpldi	cr1, r10, 0
970*4882a593Smuzhiyun	beq	cr1, no_xive
971*4882a593Smuzhiyun	eieio
972*4882a593Smuzhiyun	stdcix	r11,r9,r10
973*4882a593Smuzhiyun	stwcix	r8,r7,r10
974*4882a593Smuzhiyun3:	li	r9, 1
975*4882a593Smuzhiyun	stb	r9, VCPU_XIVE_PUSHED(r4)
976*4882a593Smuzhiyun	eieio
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun	/*
979*4882a593Smuzhiyun	 * We clear the irq_pending flag. There is a small chance of a
980*4882a593Smuzhiyun	 * race vs. the escalation interrupt happening on another
981*4882a593Smuzhiyun	 * processor setting it again, but the only consequence is to
982*4882a593Smuzhiyun	 * cause a spurrious wakeup on the next H_CEDE which is not an
983*4882a593Smuzhiyun	 * issue.
984*4882a593Smuzhiyun	 */
985*4882a593Smuzhiyun	li	r0,0
986*4882a593Smuzhiyun	stb	r0, VCPU_IRQ_PENDING(r4)
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun	/*
989*4882a593Smuzhiyun	 * In single escalation mode, if the escalation interrupt is
990*4882a593Smuzhiyun	 * on, we mask it.
991*4882a593Smuzhiyun	 */
992*4882a593Smuzhiyun	lbz	r0, VCPU_XIVE_ESC_ON(r4)
993*4882a593Smuzhiyun	cmpwi	cr1, r0,0
994*4882a593Smuzhiyun	beq	cr1, 1f
995*4882a593Smuzhiyun	li	r9, XIVE_ESB_SET_PQ_01
996*4882a593Smuzhiyun	beq	4f			/* in real mode? */
997*4882a593Smuzhiyun	ld	r10, VCPU_XIVE_ESC_VADDR(r4)
998*4882a593Smuzhiyun	ldx	r0, r10, r9
999*4882a593Smuzhiyun	b	5f
1000*4882a593Smuzhiyun4:	ld	r10, VCPU_XIVE_ESC_RADDR(r4)
1001*4882a593Smuzhiyun	ldcix	r0, r10, r9
1002*4882a593Smuzhiyun5:	sync
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun	/* We have a possible subtle race here: The escalation interrupt might
1005*4882a593Smuzhiyun	 * have fired and be on its way to the host queue while we mask it,
1006*4882a593Smuzhiyun	 * and if we unmask it early enough (re-cede right away), there is
1007*4882a593Smuzhiyun	 * a theorical possibility that it fires again, thus landing in the
1008*4882a593Smuzhiyun	 * target queue more than once which is a big no-no.
1009*4882a593Smuzhiyun	 *
1010*4882a593Smuzhiyun	 * Fortunately, solving this is rather easy. If the above load setting
1011*4882a593Smuzhiyun	 * PQ to 01 returns a previous value where P is set, then we know the
1012*4882a593Smuzhiyun	 * escalation interrupt is somewhere on its way to the host. In that
1013*4882a593Smuzhiyun	 * case we simply don't clear the xive_esc_on flag below. It will be
1014*4882a593Smuzhiyun	 * eventually cleared by the handler for the escalation interrupt.
1015*4882a593Smuzhiyun	 *
1016*4882a593Smuzhiyun	 * Then, when doing a cede, we check that flag again before re-enabling
1017*4882a593Smuzhiyun	 * the escalation interrupt, and if set, we abort the cede.
1018*4882a593Smuzhiyun	 */
1019*4882a593Smuzhiyun	andi.	r0, r0, XIVE_ESB_VAL_P
1020*4882a593Smuzhiyun	bne-	1f
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun	/* Now P is 0, we can clear the flag */
1023*4882a593Smuzhiyun	li	r0, 0
1024*4882a593Smuzhiyun	stb	r0, VCPU_XIVE_ESC_ON(r4)
1025*4882a593Smuzhiyun1:
1026*4882a593Smuzhiyunno_xive:
1027*4882a593Smuzhiyun#endif /* CONFIG_KVM_XICS */
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun	li	r0, 0
1030*4882a593Smuzhiyun	stw	r0, STACK_SLOT_SHORT_PATH(r1)
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyundeliver_guest_interrupt:	/* r4 = vcpu, r13 = paca */
1033*4882a593Smuzhiyun	/* Check if we can deliver an external or decrementer interrupt now */
1034*4882a593Smuzhiyun	ld	r0, VCPU_PENDING_EXC(r4)
1035*4882a593SmuzhiyunBEGIN_FTR_SECTION
1036*4882a593Smuzhiyun	/* On POWER9, also check for emulated doorbell interrupt */
1037*4882a593Smuzhiyun	lbz	r3, VCPU_DBELL_REQ(r4)
1038*4882a593Smuzhiyun	or	r0, r0, r3
1039*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
1040*4882a593Smuzhiyun	cmpdi	r0, 0
1041*4882a593Smuzhiyun	beq	71f
1042*4882a593Smuzhiyun	mr	r3, r4
1043*4882a593Smuzhiyun	bl	kvmppc_guest_entry_inject_int
1044*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
1045*4882a593Smuzhiyun71:
1046*4882a593Smuzhiyun	ld	r6, VCPU_SRR0(r4)
1047*4882a593Smuzhiyun	ld	r7, VCPU_SRR1(r4)
1048*4882a593Smuzhiyun	mtspr	SPRN_SRR0, r6
1049*4882a593Smuzhiyun	mtspr	SPRN_SRR1, r7
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyunfast_guest_entry_c:
1052*4882a593Smuzhiyun	ld	r10, VCPU_PC(r4)
1053*4882a593Smuzhiyun	ld	r11, VCPU_MSR(r4)
1054*4882a593Smuzhiyun	/* r11 = vcpu->arch.msr & ~MSR_HV */
1055*4882a593Smuzhiyun	rldicl	r11, r11, 63 - MSR_HV_LG, 1
1056*4882a593Smuzhiyun	rotldi	r11, r11, 1 + MSR_HV_LG
1057*4882a593Smuzhiyun	ori	r11, r11, MSR_ME
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun	ld	r6, VCPU_CTR(r4)
1060*4882a593Smuzhiyun	ld	r7, VCPU_XER(r4)
1061*4882a593Smuzhiyun	mtctr	r6
1062*4882a593Smuzhiyun	mtxer	r7
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun/*
1065*4882a593Smuzhiyun * Required state:
1066*4882a593Smuzhiyun * R4 = vcpu
1067*4882a593Smuzhiyun * R10: value for HSRR0
1068*4882a593Smuzhiyun * R11: value for HSRR1
1069*4882a593Smuzhiyun * R13 = PACA
1070*4882a593Smuzhiyun */
1071*4882a593Smuzhiyunfast_guest_return:
1072*4882a593Smuzhiyun	li	r0,0
1073*4882a593Smuzhiyun	stb	r0,VCPU_CEDED(r4)	/* cancel cede */
1074*4882a593Smuzhiyun	mtspr	SPRN_HSRR0,r10
1075*4882a593Smuzhiyun	mtspr	SPRN_HSRR1,r11
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun	/* Activate guest mode, so faults get handled by KVM */
1078*4882a593Smuzhiyun	li	r9, KVM_GUEST_MODE_GUEST_HV
1079*4882a593Smuzhiyun	stb	r9, HSTATE_IN_GUEST(r13)
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
1082*4882a593Smuzhiyun	/* Accumulate timing */
1083*4882a593Smuzhiyun	addi	r3, r4, VCPU_TB_GUEST
1084*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
1085*4882a593Smuzhiyun#endif
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun	/* Enter guest */
1088*4882a593Smuzhiyun
1089*4882a593SmuzhiyunBEGIN_FTR_SECTION
1090*4882a593Smuzhiyun	ld	r5, VCPU_CFAR(r4)
1091*4882a593Smuzhiyun	mtspr	SPRN_CFAR, r5
1092*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_CFAR)
1093*4882a593SmuzhiyunBEGIN_FTR_SECTION
1094*4882a593Smuzhiyun	ld	r0, VCPU_PPR(r4)
1095*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun	ld	r5, VCPU_LR(r4)
1098*4882a593Smuzhiyun	mtlr	r5
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun	ld	r1, VCPU_GPR(R1)(r4)
1101*4882a593Smuzhiyun	ld	r5, VCPU_GPR(R5)(r4)
1102*4882a593Smuzhiyun	ld	r8, VCPU_GPR(R8)(r4)
1103*4882a593Smuzhiyun	ld	r9, VCPU_GPR(R9)(r4)
1104*4882a593Smuzhiyun	ld	r10, VCPU_GPR(R10)(r4)
1105*4882a593Smuzhiyun	ld	r11, VCPU_GPR(R11)(r4)
1106*4882a593Smuzhiyun	ld	r12, VCPU_GPR(R12)(r4)
1107*4882a593Smuzhiyun	ld	r13, VCPU_GPR(R13)(r4)
1108*4882a593Smuzhiyun
1109*4882a593SmuzhiyunBEGIN_FTR_SECTION
1110*4882a593Smuzhiyun	mtspr	SPRN_PPR, r0
1111*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun/* Move canary into DSISR to check for later */
1114*4882a593SmuzhiyunBEGIN_FTR_SECTION
1115*4882a593Smuzhiyun	li	r0, 0x7fff
1116*4882a593Smuzhiyun	mtspr	SPRN_HDSISR, r0
1117*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun	ld	r6, VCPU_KVM(r4)
1120*4882a593Smuzhiyun	lbz	r7, KVM_SECURE_GUEST(r6)
1121*4882a593Smuzhiyun	cmpdi	r7, 0
1122*4882a593Smuzhiyun	ld	r6, VCPU_GPR(R6)(r4)
1123*4882a593Smuzhiyun	ld	r7, VCPU_GPR(R7)(r4)
1124*4882a593Smuzhiyun	bne	ret_to_ultra
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun	ld	r0, VCPU_CR(r4)
1127*4882a593Smuzhiyun	mtcr	r0
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun	ld	r0, VCPU_GPR(R0)(r4)
1130*4882a593Smuzhiyun	ld	r2, VCPU_GPR(R2)(r4)
1131*4882a593Smuzhiyun	ld	r3, VCPU_GPR(R3)(r4)
1132*4882a593Smuzhiyun	ld	r4, VCPU_GPR(R4)(r4)
1133*4882a593Smuzhiyun	HRFI_TO_GUEST
1134*4882a593Smuzhiyun	b	.
1135*4882a593Smuzhiyun/*
1136*4882a593Smuzhiyun * Use UV_RETURN ultracall to return control back to the Ultravisor after
1137*4882a593Smuzhiyun * processing an hypercall or interrupt that was forwarded (a.k.a. reflected)
1138*4882a593Smuzhiyun * to the Hypervisor.
1139*4882a593Smuzhiyun *
1140*4882a593Smuzhiyun * All registers have already been loaded, except:
1141*4882a593Smuzhiyun *   R0 = hcall result
1142*4882a593Smuzhiyun *   R2 = SRR1, so UV can detect a synthesized interrupt (if any)
1143*4882a593Smuzhiyun *   R3 = UV_RETURN
1144*4882a593Smuzhiyun */
1145*4882a593Smuzhiyunret_to_ultra:
1146*4882a593Smuzhiyun	ld	r0, VCPU_CR(r4)
1147*4882a593Smuzhiyun	mtcr	r0
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun	ld	r0, VCPU_GPR(R3)(r4)
1150*4882a593Smuzhiyun	mfspr	r2, SPRN_SRR1
1151*4882a593Smuzhiyun	li	r3, 0
1152*4882a593Smuzhiyun	ori	r3, r3, UV_RETURN
1153*4882a593Smuzhiyun	ld	r4, VCPU_GPR(R4)(r4)
1154*4882a593Smuzhiyun	sc	2
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun/*
1157*4882a593Smuzhiyun * Enter the guest on a P9 or later system where we have exactly
1158*4882a593Smuzhiyun * one vcpu per vcore and we don't need to go to real mode
1159*4882a593Smuzhiyun * (which implies that host and guest are both using radix MMU mode).
1160*4882a593Smuzhiyun * r3 = vcpu pointer
1161*4882a593Smuzhiyun * Most SPRs and all the VSRs have been loaded already.
1162*4882a593Smuzhiyun */
1163*4882a593Smuzhiyun_GLOBAL(__kvmhv_vcpu_entry_p9)
1164*4882a593SmuzhiyunEXPORT_SYMBOL_GPL(__kvmhv_vcpu_entry_p9)
1165*4882a593Smuzhiyun	mflr	r0
1166*4882a593Smuzhiyun	std	r0, PPC_LR_STKOFF(r1)
1167*4882a593Smuzhiyun	stdu	r1, -SFS(r1)
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun	li	r0, 1
1170*4882a593Smuzhiyun	stw	r0, STACK_SLOT_SHORT_PATH(r1)
1171*4882a593Smuzhiyun
1172*4882a593Smuzhiyun	std	r3, HSTATE_KVM_VCPU(r13)
1173*4882a593Smuzhiyun	mfcr	r4
1174*4882a593Smuzhiyun	stw	r4, SFS+8(r1)
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun	std	r1, HSTATE_HOST_R1(r13)
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun	reg = 14
1179*4882a593Smuzhiyun	.rept	18
1180*4882a593Smuzhiyun	std	reg, STACK_SLOT_NVGPRS + ((reg - 14) * 8)(r1)
1181*4882a593Smuzhiyun	reg = reg + 1
1182*4882a593Smuzhiyun	.endr
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun	reg = 14
1185*4882a593Smuzhiyun	.rept	18
1186*4882a593Smuzhiyun	ld	reg, __VCPU_GPR(reg)(r3)
1187*4882a593Smuzhiyun	reg = reg + 1
1188*4882a593Smuzhiyun	.endr
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun	mfmsr	r10
1191*4882a593Smuzhiyun	std	r10, HSTATE_HOST_MSR(r13)
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun	mr	r4, r3
1194*4882a593Smuzhiyun	b	fast_guest_entry_c
1195*4882a593Smuzhiyunguest_exit_short_path:
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun	li	r0, KVM_GUEST_MODE_NONE
1198*4882a593Smuzhiyun	stb	r0, HSTATE_IN_GUEST(r13)
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun	reg = 14
1201*4882a593Smuzhiyun	.rept	18
1202*4882a593Smuzhiyun	std	reg, __VCPU_GPR(reg)(r9)
1203*4882a593Smuzhiyun	reg = reg + 1
1204*4882a593Smuzhiyun	.endr
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun	reg = 14
1207*4882a593Smuzhiyun	.rept	18
1208*4882a593Smuzhiyun	ld	reg, STACK_SLOT_NVGPRS + ((reg - 14) * 8)(r1)
1209*4882a593Smuzhiyun	reg = reg + 1
1210*4882a593Smuzhiyun	.endr
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun	lwz	r4, SFS+8(r1)
1213*4882a593Smuzhiyun	mtcr	r4
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun	mr	r3, r12		/* trap number */
1216*4882a593Smuzhiyun
1217*4882a593Smuzhiyun	addi	r1, r1, SFS
1218*4882a593Smuzhiyun	ld	r0, PPC_LR_STKOFF(r1)
1219*4882a593Smuzhiyun	mtlr	r0
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun	/* If we are in real mode, do a rfid to get back to the caller */
1222*4882a593Smuzhiyun	mfmsr	r4
1223*4882a593Smuzhiyun	andi.	r5, r4, MSR_IR
1224*4882a593Smuzhiyun	bnelr
1225*4882a593Smuzhiyun	rldicl	r5, r4, 64 - MSR_TS_S_LG, 62	/* extract TS field */
1226*4882a593Smuzhiyun	mtspr	SPRN_SRR0, r0
1227*4882a593Smuzhiyun	ld	r10, HSTATE_HOST_MSR(r13)
1228*4882a593Smuzhiyun	rldimi	r10, r5, MSR_TS_S_LG, 63 - MSR_TS_T_LG
1229*4882a593Smuzhiyun	mtspr	SPRN_SRR1, r10
1230*4882a593Smuzhiyun	RFI_TO_KERNEL
1231*4882a593Smuzhiyun	b	.
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyunsecondary_too_late:
1234*4882a593Smuzhiyun	li	r12, 0
1235*4882a593Smuzhiyun	stw	r12, STACK_SLOT_TRAP(r1)
1236*4882a593Smuzhiyun	cmpdi	r4, 0
1237*4882a593Smuzhiyun	beq	11f
1238*4882a593Smuzhiyun	stw	r12, VCPU_TRAP(r4)
1239*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
1240*4882a593Smuzhiyun	addi	r3, r4, VCPU_TB_RMEXIT
1241*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
1242*4882a593Smuzhiyun#endif
1243*4882a593Smuzhiyun11:	b	kvmhv_switch_to_host
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyunno_switch_exit:
1246*4882a593Smuzhiyun	HMT_MEDIUM
1247*4882a593Smuzhiyun	li	r12, 0
1248*4882a593Smuzhiyun	b	12f
1249*4882a593Smuzhiyunhdec_soon:
1250*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_HV_DECREMENTER
1251*4882a593Smuzhiyun12:	stw	r12, VCPU_TRAP(r4)
1252*4882a593Smuzhiyun	mr	r9, r4
1253*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
1254*4882a593Smuzhiyun	addi	r3, r4, VCPU_TB_RMEXIT
1255*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
1256*4882a593Smuzhiyun#endif
1257*4882a593Smuzhiyun	b	guest_bypass
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun/******************************************************************************
1260*4882a593Smuzhiyun *                                                                            *
1261*4882a593Smuzhiyun *                               Exit code                                    *
1262*4882a593Smuzhiyun *                                                                            *
1263*4882a593Smuzhiyun *****************************************************************************/
1264*4882a593Smuzhiyun
1265*4882a593Smuzhiyun/*
1266*4882a593Smuzhiyun * We come here from the first-level interrupt handlers.
1267*4882a593Smuzhiyun */
1268*4882a593Smuzhiyun	.globl	kvmppc_interrupt_hv
1269*4882a593Smuzhiyunkvmppc_interrupt_hv:
1270*4882a593Smuzhiyun	/*
1271*4882a593Smuzhiyun	 * Register contents:
1272*4882a593Smuzhiyun	 * R12		= (guest CR << 32) | interrupt vector
1273*4882a593Smuzhiyun	 * R13		= PACA
1274*4882a593Smuzhiyun	 * guest R12 saved in shadow VCPU SCRATCH0
1275*4882a593Smuzhiyun	 * guest R13 saved in SPRN_SCRATCH0
1276*4882a593Smuzhiyun	 */
1277*4882a593Smuzhiyun	std	r9, HSTATE_SCRATCH2(r13)
1278*4882a593Smuzhiyun	lbz	r9, HSTATE_IN_GUEST(r13)
1279*4882a593Smuzhiyun	cmpwi	r9, KVM_GUEST_MODE_HOST_HV
1280*4882a593Smuzhiyun	beq	kvmppc_bad_host_intr
1281*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
1282*4882a593Smuzhiyun	cmpwi	r9, KVM_GUEST_MODE_GUEST
1283*4882a593Smuzhiyun	ld	r9, HSTATE_SCRATCH2(r13)
1284*4882a593Smuzhiyun	beq	kvmppc_interrupt_pr
1285*4882a593Smuzhiyun#endif
1286*4882a593Smuzhiyun	/* We're now back in the host but in guest MMU context */
1287*4882a593Smuzhiyun	li	r9, KVM_GUEST_MODE_HOST_HV
1288*4882a593Smuzhiyun	stb	r9, HSTATE_IN_GUEST(r13)
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
1291*4882a593Smuzhiyun
1292*4882a593Smuzhiyun	/* Save registers */
1293*4882a593Smuzhiyun
1294*4882a593Smuzhiyun	std	r0, VCPU_GPR(R0)(r9)
1295*4882a593Smuzhiyun	std	r1, VCPU_GPR(R1)(r9)
1296*4882a593Smuzhiyun	std	r2, VCPU_GPR(R2)(r9)
1297*4882a593Smuzhiyun	std	r3, VCPU_GPR(R3)(r9)
1298*4882a593Smuzhiyun	std	r4, VCPU_GPR(R4)(r9)
1299*4882a593Smuzhiyun	std	r5, VCPU_GPR(R5)(r9)
1300*4882a593Smuzhiyun	std	r6, VCPU_GPR(R6)(r9)
1301*4882a593Smuzhiyun	std	r7, VCPU_GPR(R7)(r9)
1302*4882a593Smuzhiyun	std	r8, VCPU_GPR(R8)(r9)
1303*4882a593Smuzhiyun	ld	r0, HSTATE_SCRATCH2(r13)
1304*4882a593Smuzhiyun	std	r0, VCPU_GPR(R9)(r9)
1305*4882a593Smuzhiyun	std	r10, VCPU_GPR(R10)(r9)
1306*4882a593Smuzhiyun	std	r11, VCPU_GPR(R11)(r9)
1307*4882a593Smuzhiyun	ld	r3, HSTATE_SCRATCH0(r13)
1308*4882a593Smuzhiyun	std	r3, VCPU_GPR(R12)(r9)
1309*4882a593Smuzhiyun	/* CR is in the high half of r12 */
1310*4882a593Smuzhiyun	srdi	r4, r12, 32
1311*4882a593Smuzhiyun	std	r4, VCPU_CR(r9)
1312*4882a593SmuzhiyunBEGIN_FTR_SECTION
1313*4882a593Smuzhiyun	ld	r3, HSTATE_CFAR(r13)
1314*4882a593Smuzhiyun	std	r3, VCPU_CFAR(r9)
1315*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_CFAR)
1316*4882a593SmuzhiyunBEGIN_FTR_SECTION
1317*4882a593Smuzhiyun	ld	r4, HSTATE_PPR(r13)
1318*4882a593Smuzhiyun	std	r4, VCPU_PPR(r9)
1319*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun	/* Restore R1/R2 so we can handle faults */
1322*4882a593Smuzhiyun	ld	r1, HSTATE_HOST_R1(r13)
1323*4882a593Smuzhiyun	ld	r2, PACATOC(r13)
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun	mfspr	r10, SPRN_SRR0
1326*4882a593Smuzhiyun	mfspr	r11, SPRN_SRR1
1327*4882a593Smuzhiyun	std	r10, VCPU_SRR0(r9)
1328*4882a593Smuzhiyun	std	r11, VCPU_SRR1(r9)
1329*4882a593Smuzhiyun	/* trap is in the low half of r12, clear CR from the high half */
1330*4882a593Smuzhiyun	clrldi	r12, r12, 32
1331*4882a593Smuzhiyun	andi.	r0, r12, 2		/* need to read HSRR0/1? */
1332*4882a593Smuzhiyun	beq	1f
1333*4882a593Smuzhiyun	mfspr	r10, SPRN_HSRR0
1334*4882a593Smuzhiyun	mfspr	r11, SPRN_HSRR1
1335*4882a593Smuzhiyun	clrrdi	r12, r12, 2
1336*4882a593Smuzhiyun1:	std	r10, VCPU_PC(r9)
1337*4882a593Smuzhiyun	std	r11, VCPU_MSR(r9)
1338*4882a593Smuzhiyun
1339*4882a593Smuzhiyun	GET_SCRATCH0(r3)
1340*4882a593Smuzhiyun	mflr	r4
1341*4882a593Smuzhiyun	std	r3, VCPU_GPR(R13)(r9)
1342*4882a593Smuzhiyun	std	r4, VCPU_LR(r9)
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun	stw	r12,VCPU_TRAP(r9)
1345*4882a593Smuzhiyun
1346*4882a593Smuzhiyun	/*
1347*4882a593Smuzhiyun	 * Now that we have saved away SRR0/1 and HSRR0/1,
1348*4882a593Smuzhiyun	 * interrupts are recoverable in principle, so set MSR_RI.
1349*4882a593Smuzhiyun	 * This becomes important for relocation-on interrupts from
1350*4882a593Smuzhiyun	 * the guest, which we can get in radix mode on POWER9.
1351*4882a593Smuzhiyun	 */
1352*4882a593Smuzhiyun	li	r0, MSR_RI
1353*4882a593Smuzhiyun	mtmsrd	r0, 1
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
1356*4882a593Smuzhiyun	addi	r3, r9, VCPU_TB_RMINTR
1357*4882a593Smuzhiyun	mr	r4, r9
1358*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
1359*4882a593Smuzhiyun	ld	r5, VCPU_GPR(R5)(r9)
1360*4882a593Smuzhiyun	ld	r6, VCPU_GPR(R6)(r9)
1361*4882a593Smuzhiyun	ld	r7, VCPU_GPR(R7)(r9)
1362*4882a593Smuzhiyun	ld	r8, VCPU_GPR(R8)(r9)
1363*4882a593Smuzhiyun#endif
1364*4882a593Smuzhiyun
1365*4882a593Smuzhiyun	/* Save HEIR (HV emulation assist reg) in emul_inst
1366*4882a593Smuzhiyun	   if this is an HEI (HV emulation interrupt, e40) */
1367*4882a593Smuzhiyun	li	r3,KVM_INST_FETCH_FAILED
1368*4882a593Smuzhiyun	stw	r3,VCPU_LAST_INST(r9)
1369*4882a593Smuzhiyun	cmpwi	r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
1370*4882a593Smuzhiyun	bne	11f
1371*4882a593Smuzhiyun	mfspr	r3,SPRN_HEIR
1372*4882a593Smuzhiyun11:	stw	r3,VCPU_HEIR(r9)
1373*4882a593Smuzhiyun
1374*4882a593Smuzhiyun	/* these are volatile across C function calls */
1375*4882a593Smuzhiyun	mfctr	r3
1376*4882a593Smuzhiyun	mfxer	r4
1377*4882a593Smuzhiyun	std	r3, VCPU_CTR(r9)
1378*4882a593Smuzhiyun	std	r4, VCPU_XER(r9)
1379*4882a593Smuzhiyun
1380*4882a593Smuzhiyun	/* Save more register state  */
1381*4882a593Smuzhiyun	mfdar	r3
1382*4882a593Smuzhiyun	mfdsisr	r4
1383*4882a593Smuzhiyun	std	r3, VCPU_DAR(r9)
1384*4882a593Smuzhiyun	stw	r4, VCPU_DSISR(r9)
1385*4882a593Smuzhiyun
1386*4882a593Smuzhiyun	/* If this is a page table miss then see if it's theirs or ours */
1387*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
1388*4882a593Smuzhiyun	beq	kvmppc_hdsi
1389*4882a593Smuzhiyun	std	r3, VCPU_FAULT_DAR(r9)
1390*4882a593Smuzhiyun	stw	r4, VCPU_FAULT_DSISR(r9)
1391*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_H_INST_STORAGE
1392*4882a593Smuzhiyun	beq	kvmppc_hisi
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1395*4882a593Smuzhiyun	/* For softpatch interrupt, go off and do TM instruction emulation */
1396*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
1397*4882a593Smuzhiyun	beq	kvmppc_tm_emul
1398*4882a593Smuzhiyun#endif
1399*4882a593Smuzhiyun
1400*4882a593Smuzhiyun	/* See if this is a leftover HDEC interrupt */
1401*4882a593Smuzhiyun	cmpwi	r12,BOOK3S_INTERRUPT_HV_DECREMENTER
1402*4882a593Smuzhiyun	bne	2f
1403*4882a593Smuzhiyun	mfspr	r3,SPRN_HDEC
1404*4882a593Smuzhiyun	EXTEND_HDEC(r3)
1405*4882a593Smuzhiyun	cmpdi	r3,0
1406*4882a593Smuzhiyun	mr	r4,r9
1407*4882a593Smuzhiyun	bge	fast_guest_return
1408*4882a593Smuzhiyun2:
1409*4882a593Smuzhiyun	/* See if this is an hcall we can handle in real mode */
1410*4882a593Smuzhiyun	cmpwi	r12,BOOK3S_INTERRUPT_SYSCALL
1411*4882a593Smuzhiyun	beq	hcall_try_real_mode
1412*4882a593Smuzhiyun
1413*4882a593Smuzhiyun	/* Hypervisor doorbell - exit only if host IPI flag set */
1414*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_H_DOORBELL
1415*4882a593Smuzhiyun	bne	3f
1416*4882a593SmuzhiyunBEGIN_FTR_SECTION
1417*4882a593Smuzhiyun	PPC_MSGSYNC
1418*4882a593Smuzhiyun	lwsync
1419*4882a593Smuzhiyun	/* always exit if we're running a nested guest */
1420*4882a593Smuzhiyun	ld	r0, VCPU_NESTED(r9)
1421*4882a593Smuzhiyun	cmpdi	r0, 0
1422*4882a593Smuzhiyun	bne	guest_exit_cont
1423*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
1424*4882a593Smuzhiyun	lbz	r0, HSTATE_HOST_IPI(r13)
1425*4882a593Smuzhiyun	cmpwi	r0, 0
1426*4882a593Smuzhiyun	beq	maybe_reenter_guest
1427*4882a593Smuzhiyun	b	guest_exit_cont
1428*4882a593Smuzhiyun3:
1429*4882a593Smuzhiyun	/* If it's a hypervisor facility unavailable interrupt, save HFSCR */
1430*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_H_FAC_UNAVAIL
1431*4882a593Smuzhiyun	bne	14f
1432*4882a593Smuzhiyun	mfspr	r3, SPRN_HFSCR
1433*4882a593Smuzhiyun	std	r3, VCPU_HFSCR(r9)
1434*4882a593Smuzhiyun	b	guest_exit_cont
1435*4882a593Smuzhiyun14:
1436*4882a593Smuzhiyun	/* External interrupt ? */
1437*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
1438*4882a593Smuzhiyun	beq	kvmppc_guest_external
1439*4882a593Smuzhiyun	/* See if it is a machine check */
1440*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_MACHINE_CHECK
1441*4882a593Smuzhiyun	beq	machine_check_realmode
1442*4882a593Smuzhiyun	/* Or a hypervisor maintenance interrupt */
1443*4882a593Smuzhiyun	cmpwi	r12, BOOK3S_INTERRUPT_HMI
1444*4882a593Smuzhiyun	beq	hmi_realmode
1445*4882a593Smuzhiyun
1446*4882a593Smuzhiyunguest_exit_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
1449*4882a593Smuzhiyun	addi	r3, r9, VCPU_TB_RMEXIT
1450*4882a593Smuzhiyun	mr	r4, r9
1451*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
1452*4882a593Smuzhiyun#endif
1453*4882a593Smuzhiyun#ifdef CONFIG_KVM_XICS
1454*4882a593Smuzhiyun	/* We are exiting, pull the VP from the XIVE */
1455*4882a593Smuzhiyun	lbz	r0, VCPU_XIVE_PUSHED(r9)
1456*4882a593Smuzhiyun	cmpwi	cr0, r0, 0
1457*4882a593Smuzhiyun	beq	1f
1458*4882a593Smuzhiyun	li	r7, TM_SPC_PULL_OS_CTX
1459*4882a593Smuzhiyun	li	r6, TM_QW1_OS
1460*4882a593Smuzhiyun	mfmsr	r0
1461*4882a593Smuzhiyun	andi.	r0, r0, MSR_DR		/* in real mode? */
1462*4882a593Smuzhiyun	beq	2f
1463*4882a593Smuzhiyun	ld	r10, HSTATE_XIVE_TIMA_VIRT(r13)
1464*4882a593Smuzhiyun	cmpldi	cr0, r10, 0
1465*4882a593Smuzhiyun	beq	1f
1466*4882a593Smuzhiyun	/* First load to pull the context, we ignore the value */
1467*4882a593Smuzhiyun	eieio
1468*4882a593Smuzhiyun	lwzx	r11, r7, r10
1469*4882a593Smuzhiyun	/* Second load to recover the context state (Words 0 and 1) */
1470*4882a593Smuzhiyun	ldx	r11, r6, r10
1471*4882a593Smuzhiyun	b	3f
1472*4882a593Smuzhiyun2:	ld	r10, HSTATE_XIVE_TIMA_PHYS(r13)
1473*4882a593Smuzhiyun	cmpldi	cr0, r10, 0
1474*4882a593Smuzhiyun	beq	1f
1475*4882a593Smuzhiyun	/* First load to pull the context, we ignore the value */
1476*4882a593Smuzhiyun	eieio
1477*4882a593Smuzhiyun	lwzcix	r11, r7, r10
1478*4882a593Smuzhiyun	/* Second load to recover the context state (Words 0 and 1) */
1479*4882a593Smuzhiyun	ldcix	r11, r6, r10
1480*4882a593Smuzhiyun3:	std	r11, VCPU_XIVE_SAVED_STATE(r9)
1481*4882a593Smuzhiyun	/* Fixup some of the state for the next load */
1482*4882a593Smuzhiyun	li	r10, 0
1483*4882a593Smuzhiyun	li	r0, 0xff
1484*4882a593Smuzhiyun	stb	r10, VCPU_XIVE_PUSHED(r9)
1485*4882a593Smuzhiyun	stb	r10, (VCPU_XIVE_SAVED_STATE+3)(r9)
1486*4882a593Smuzhiyun	stb	r0, (VCPU_XIVE_SAVED_STATE+4)(r9)
1487*4882a593Smuzhiyun	eieio
1488*4882a593Smuzhiyun1:
1489*4882a593Smuzhiyun#endif /* CONFIG_KVM_XICS */
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun	/*
1492*4882a593Smuzhiyun	 * Possibly flush the link stack here, before we do a blr in
1493*4882a593Smuzhiyun	 * guest_exit_short_path.
1494*4882a593Smuzhiyun	 */
1495*4882a593Smuzhiyun1:	nop
1496*4882a593Smuzhiyun	patch_site 1b patch__call_kvm_flush_link_stack
1497*4882a593Smuzhiyun
1498*4882a593Smuzhiyun	/* If we came in through the P9 short path, go back out to C now */
1499*4882a593Smuzhiyun	lwz	r0, STACK_SLOT_SHORT_PATH(r1)
1500*4882a593Smuzhiyun	cmpwi	r0, 0
1501*4882a593Smuzhiyun	bne	guest_exit_short_path
1502*4882a593Smuzhiyun
1503*4882a593Smuzhiyun	/* For hash guest, read the guest SLB and save it away */
1504*4882a593Smuzhiyun	ld	r5, VCPU_KVM(r9)
1505*4882a593Smuzhiyun	lbz	r0, KVM_RADIX(r5)
1506*4882a593Smuzhiyun	li	r5, 0
1507*4882a593Smuzhiyun	cmpwi	r0, 0
1508*4882a593Smuzhiyun	bne	3f			/* for radix, save 0 entries */
1509*4882a593Smuzhiyun	lwz	r0,VCPU_SLB_NR(r9)	/* number of entries in SLB */
1510*4882a593Smuzhiyun	mtctr	r0
1511*4882a593Smuzhiyun	li	r6,0
1512*4882a593Smuzhiyun	addi	r7,r9,VCPU_SLB
1513*4882a593Smuzhiyun1:	slbmfee	r8,r6
1514*4882a593Smuzhiyun	andis.	r0,r8,SLB_ESID_V@h
1515*4882a593Smuzhiyun	beq	2f
1516*4882a593Smuzhiyun	add	r8,r8,r6		/* put index in */
1517*4882a593Smuzhiyun	slbmfev	r3,r6
1518*4882a593Smuzhiyun	std	r8,VCPU_SLB_E(r7)
1519*4882a593Smuzhiyun	std	r3,VCPU_SLB_V(r7)
1520*4882a593Smuzhiyun	addi	r7,r7,VCPU_SLB_SIZE
1521*4882a593Smuzhiyun	addi	r5,r5,1
1522*4882a593Smuzhiyun2:	addi	r6,r6,1
1523*4882a593Smuzhiyun	bdnz	1b
1524*4882a593Smuzhiyun	/* Finally clear out the SLB */
1525*4882a593Smuzhiyun	li	r0,0
1526*4882a593Smuzhiyun	slbmte	r0,r0
1527*4882a593Smuzhiyun	slbia
1528*4882a593Smuzhiyun	ptesync
1529*4882a593Smuzhiyun3:	stw	r5,VCPU_SLB_MAX(r9)
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun	/* load host SLB entries */
1532*4882a593SmuzhiyunBEGIN_MMU_FTR_SECTION
1533*4882a593Smuzhiyun	b	0f
1534*4882a593SmuzhiyunEND_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
1535*4882a593Smuzhiyun	ld	r8,PACA_SLBSHADOWPTR(r13)
1536*4882a593Smuzhiyun
1537*4882a593Smuzhiyun	.rept	SLB_NUM_BOLTED
1538*4882a593Smuzhiyun	li	r3, SLBSHADOW_SAVEAREA
1539*4882a593Smuzhiyun	LDX_BE	r5, r8, r3
1540*4882a593Smuzhiyun	addi	r3, r3, 8
1541*4882a593Smuzhiyun	LDX_BE	r6, r8, r3
1542*4882a593Smuzhiyun	andis.	r7,r5,SLB_ESID_V@h
1543*4882a593Smuzhiyun	beq	1f
1544*4882a593Smuzhiyun	slbmte	r6,r5
1545*4882a593Smuzhiyun1:	addi	r8,r8,16
1546*4882a593Smuzhiyun	.endr
1547*4882a593Smuzhiyun0:
1548*4882a593Smuzhiyun
1549*4882a593Smuzhiyunguest_bypass:
1550*4882a593Smuzhiyun	stw	r12, STACK_SLOT_TRAP(r1)
1551*4882a593Smuzhiyun
1552*4882a593Smuzhiyun	/* Save DEC */
1553*4882a593Smuzhiyun	/* Do this before kvmhv_commence_exit so we know TB is guest TB */
1554*4882a593Smuzhiyun	ld	r3, HSTATE_KVM_VCORE(r13)
1555*4882a593Smuzhiyun	mfspr	r5,SPRN_DEC
1556*4882a593Smuzhiyun	mftb	r6
1557*4882a593Smuzhiyun	/* On P9, if the guest has large decr enabled, don't sign extend */
1558*4882a593SmuzhiyunBEGIN_FTR_SECTION
1559*4882a593Smuzhiyun	ld	r4, VCORE_LPCR(r3)
1560*4882a593Smuzhiyun	andis.	r4, r4, LPCR_LD@h
1561*4882a593Smuzhiyun	bne	16f
1562*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
1563*4882a593Smuzhiyun	extsw	r5,r5
1564*4882a593Smuzhiyun16:	add	r5,r5,r6
1565*4882a593Smuzhiyun	/* r5 is a guest timebase value here, convert to host TB */
1566*4882a593Smuzhiyun	ld	r4,VCORE_TB_OFFSET_APPL(r3)
1567*4882a593Smuzhiyun	subf	r5,r4,r5
1568*4882a593Smuzhiyun	std	r5,VCPU_DEC_EXPIRES(r9)
1569*4882a593Smuzhiyun
1570*4882a593Smuzhiyun	/* Increment exit count, poke other threads to exit */
1571*4882a593Smuzhiyun	mr 	r3, r12
1572*4882a593Smuzhiyun	bl	kvmhv_commence_exit
1573*4882a593Smuzhiyun	nop
1574*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
1575*4882a593Smuzhiyun
1576*4882a593Smuzhiyun	/* Stop others sending VCPU interrupts to this physical CPU */
1577*4882a593Smuzhiyun	li	r0, -1
1578*4882a593Smuzhiyun	stw	r0, VCPU_CPU(r9)
1579*4882a593Smuzhiyun	stw	r0, VCPU_THREAD_CPU(r9)
1580*4882a593Smuzhiyun
1581*4882a593Smuzhiyun	/* Save guest CTRL register, set runlatch to 1 */
1582*4882a593Smuzhiyun	mfspr	r6,SPRN_CTRLF
1583*4882a593Smuzhiyun	stw	r6,VCPU_CTRL(r9)
1584*4882a593Smuzhiyun	andi.	r0,r6,1
1585*4882a593Smuzhiyun	bne	4f
1586*4882a593Smuzhiyun	ori	r6,r6,1
1587*4882a593Smuzhiyun	mtspr	SPRN_CTRLT,r6
1588*4882a593Smuzhiyun4:
1589*4882a593Smuzhiyun	/*
1590*4882a593Smuzhiyun	 * Save the guest PURR/SPURR
1591*4882a593Smuzhiyun	 */
1592*4882a593Smuzhiyun	mfspr	r5,SPRN_PURR
1593*4882a593Smuzhiyun	mfspr	r6,SPRN_SPURR
1594*4882a593Smuzhiyun	ld	r7,VCPU_PURR(r9)
1595*4882a593Smuzhiyun	ld	r8,VCPU_SPURR(r9)
1596*4882a593Smuzhiyun	std	r5,VCPU_PURR(r9)
1597*4882a593Smuzhiyun	std	r6,VCPU_SPURR(r9)
1598*4882a593Smuzhiyun	subf	r5,r7,r5
1599*4882a593Smuzhiyun	subf	r6,r8,r6
1600*4882a593Smuzhiyun
1601*4882a593Smuzhiyun	/*
1602*4882a593Smuzhiyun	 * Restore host PURR/SPURR and add guest times
1603*4882a593Smuzhiyun	 * so that the time in the guest gets accounted.
1604*4882a593Smuzhiyun	 */
1605*4882a593Smuzhiyun	ld	r3,HSTATE_PURR(r13)
1606*4882a593Smuzhiyun	ld	r4,HSTATE_SPURR(r13)
1607*4882a593Smuzhiyun	add	r3,r3,r5
1608*4882a593Smuzhiyun	add	r4,r4,r6
1609*4882a593Smuzhiyun	mtspr	SPRN_PURR,r3
1610*4882a593Smuzhiyun	mtspr	SPRN_SPURR,r4
1611*4882a593Smuzhiyun
1612*4882a593SmuzhiyunBEGIN_FTR_SECTION
1613*4882a593Smuzhiyun	b	8f
1614*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
1615*4882a593Smuzhiyun	/* Save POWER8-specific registers */
1616*4882a593Smuzhiyun	mfspr	r5, SPRN_IAMR
1617*4882a593Smuzhiyun	mfspr	r6, SPRN_PSPB
1618*4882a593Smuzhiyun	mfspr	r7, SPRN_FSCR
1619*4882a593Smuzhiyun	std	r5, VCPU_IAMR(r9)
1620*4882a593Smuzhiyun	stw	r6, VCPU_PSPB(r9)
1621*4882a593Smuzhiyun	std	r7, VCPU_FSCR(r9)
1622*4882a593Smuzhiyun	mfspr	r5, SPRN_IC
1623*4882a593Smuzhiyun	mfspr	r7, SPRN_TAR
1624*4882a593Smuzhiyun	std	r5, VCPU_IC(r9)
1625*4882a593Smuzhiyun	std	r7, VCPU_TAR(r9)
1626*4882a593Smuzhiyun	mfspr	r8, SPRN_EBBHR
1627*4882a593Smuzhiyun	std	r8, VCPU_EBBHR(r9)
1628*4882a593Smuzhiyun	mfspr	r5, SPRN_EBBRR
1629*4882a593Smuzhiyun	mfspr	r6, SPRN_BESCR
1630*4882a593Smuzhiyun	mfspr	r7, SPRN_PID
1631*4882a593Smuzhiyun	mfspr	r8, SPRN_WORT
1632*4882a593Smuzhiyun	std	r5, VCPU_EBBRR(r9)
1633*4882a593Smuzhiyun	std	r6, VCPU_BESCR(r9)
1634*4882a593Smuzhiyun	stw	r7, VCPU_GUEST_PID(r9)
1635*4882a593Smuzhiyun	std	r8, VCPU_WORT(r9)
1636*4882a593SmuzhiyunBEGIN_FTR_SECTION
1637*4882a593Smuzhiyun	mfspr	r5, SPRN_TCSCR
1638*4882a593Smuzhiyun	mfspr	r6, SPRN_ACOP
1639*4882a593Smuzhiyun	mfspr	r7, SPRN_CSIGR
1640*4882a593Smuzhiyun	mfspr	r8, SPRN_TACR
1641*4882a593Smuzhiyun	std	r5, VCPU_TCSCR(r9)
1642*4882a593Smuzhiyun	std	r6, VCPU_ACOP(r9)
1643*4882a593Smuzhiyun	std	r7, VCPU_CSIGR(r9)
1644*4882a593Smuzhiyun	std	r8, VCPU_TACR(r9)
1645*4882a593SmuzhiyunFTR_SECTION_ELSE
1646*4882a593Smuzhiyun	mfspr	r5, SPRN_TIDR
1647*4882a593Smuzhiyun	mfspr	r6, SPRN_PSSCR
1648*4882a593Smuzhiyun	std	r5, VCPU_TID(r9)
1649*4882a593Smuzhiyun	rldicl	r6, r6, 4, 50		/* r6 &= PSSCR_GUEST_VIS */
1650*4882a593Smuzhiyun	rotldi	r6, r6, 60
1651*4882a593Smuzhiyun	std	r6, VCPU_PSSCR(r9)
1652*4882a593Smuzhiyun	/* Restore host HFSCR value */
1653*4882a593Smuzhiyun	ld	r7, STACK_SLOT_HFSCR(r1)
1654*4882a593Smuzhiyun	mtspr	SPRN_HFSCR, r7
1655*4882a593SmuzhiyunALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
1656*4882a593Smuzhiyun	/*
1657*4882a593Smuzhiyun	 * Restore various registers to 0, where non-zero values
1658*4882a593Smuzhiyun	 * set by the guest could disrupt the host.
1659*4882a593Smuzhiyun	 */
1660*4882a593Smuzhiyun	li	r0, 0
1661*4882a593Smuzhiyun	mtspr	SPRN_PSPB, r0
1662*4882a593Smuzhiyun	mtspr	SPRN_WORT, r0
1663*4882a593SmuzhiyunBEGIN_FTR_SECTION
1664*4882a593Smuzhiyun	mtspr	SPRN_TCSCR, r0
1665*4882a593Smuzhiyun	/* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
1666*4882a593Smuzhiyun	li	r0, 1
1667*4882a593Smuzhiyun	sldi	r0, r0, 31
1668*4882a593Smuzhiyun	mtspr	SPRN_MMCRS, r0
1669*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
1670*4882a593Smuzhiyun
1671*4882a593Smuzhiyun	/* Save and restore AMR, IAMR and UAMOR before turning on the MMU */
1672*4882a593Smuzhiyun	ld	r8, STACK_SLOT_IAMR(r1)
1673*4882a593Smuzhiyun	mtspr	SPRN_IAMR, r8
1674*4882a593Smuzhiyun
1675*4882a593Smuzhiyun8:	/* Power7 jumps back in here */
1676*4882a593Smuzhiyun	mfspr	r5,SPRN_AMR
1677*4882a593Smuzhiyun	mfspr	r6,SPRN_UAMOR
1678*4882a593Smuzhiyun	std	r5,VCPU_AMR(r9)
1679*4882a593Smuzhiyun	std	r6,VCPU_UAMOR(r9)
1680*4882a593Smuzhiyun	ld	r5,STACK_SLOT_AMR(r1)
1681*4882a593Smuzhiyun	ld	r6,STACK_SLOT_UAMOR(r1)
1682*4882a593Smuzhiyun	mtspr	SPRN_AMR, r5
1683*4882a593Smuzhiyun	mtspr	SPRN_UAMOR, r6
1684*4882a593Smuzhiyun
1685*4882a593Smuzhiyun	/* Switch DSCR back to host value */
1686*4882a593Smuzhiyun	mfspr	r8, SPRN_DSCR
1687*4882a593Smuzhiyun	ld	r7, HSTATE_DSCR(r13)
1688*4882a593Smuzhiyun	std	r8, VCPU_DSCR(r9)
1689*4882a593Smuzhiyun	mtspr	SPRN_DSCR, r7
1690*4882a593Smuzhiyun
1691*4882a593Smuzhiyun	/* Save non-volatile GPRs */
1692*4882a593Smuzhiyun	std	r14, VCPU_GPR(R14)(r9)
1693*4882a593Smuzhiyun	std	r15, VCPU_GPR(R15)(r9)
1694*4882a593Smuzhiyun	std	r16, VCPU_GPR(R16)(r9)
1695*4882a593Smuzhiyun	std	r17, VCPU_GPR(R17)(r9)
1696*4882a593Smuzhiyun	std	r18, VCPU_GPR(R18)(r9)
1697*4882a593Smuzhiyun	std	r19, VCPU_GPR(R19)(r9)
1698*4882a593Smuzhiyun	std	r20, VCPU_GPR(R20)(r9)
1699*4882a593Smuzhiyun	std	r21, VCPU_GPR(R21)(r9)
1700*4882a593Smuzhiyun	std	r22, VCPU_GPR(R22)(r9)
1701*4882a593Smuzhiyun	std	r23, VCPU_GPR(R23)(r9)
1702*4882a593Smuzhiyun	std	r24, VCPU_GPR(R24)(r9)
1703*4882a593Smuzhiyun	std	r25, VCPU_GPR(R25)(r9)
1704*4882a593Smuzhiyun	std	r26, VCPU_GPR(R26)(r9)
1705*4882a593Smuzhiyun	std	r27, VCPU_GPR(R27)(r9)
1706*4882a593Smuzhiyun	std	r28, VCPU_GPR(R28)(r9)
1707*4882a593Smuzhiyun	std	r29, VCPU_GPR(R29)(r9)
1708*4882a593Smuzhiyun	std	r30, VCPU_GPR(R30)(r9)
1709*4882a593Smuzhiyun	std	r31, VCPU_GPR(R31)(r9)
1710*4882a593Smuzhiyun
1711*4882a593Smuzhiyun	/* Save SPRGs */
1712*4882a593Smuzhiyun	mfspr	r3, SPRN_SPRG0
1713*4882a593Smuzhiyun	mfspr	r4, SPRN_SPRG1
1714*4882a593Smuzhiyun	mfspr	r5, SPRN_SPRG2
1715*4882a593Smuzhiyun	mfspr	r6, SPRN_SPRG3
1716*4882a593Smuzhiyun	std	r3, VCPU_SPRG0(r9)
1717*4882a593Smuzhiyun	std	r4, VCPU_SPRG1(r9)
1718*4882a593Smuzhiyun	std	r5, VCPU_SPRG2(r9)
1719*4882a593Smuzhiyun	std	r6, VCPU_SPRG3(r9)
1720*4882a593Smuzhiyun
1721*4882a593Smuzhiyun	/* save FP state */
1722*4882a593Smuzhiyun	mr	r3, r9
1723*4882a593Smuzhiyun	bl	kvmppc_save_fp
1724*4882a593Smuzhiyun
1725*4882a593Smuzhiyun#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1726*4882a593Smuzhiyun/*
1727*4882a593Smuzhiyun * Branch around the call if both CPU_FTR_TM and
1728*4882a593Smuzhiyun * CPU_FTR_P9_TM_HV_ASSIST are off.
1729*4882a593Smuzhiyun */
1730*4882a593SmuzhiyunBEGIN_FTR_SECTION
1731*4882a593Smuzhiyun	b	91f
1732*4882a593SmuzhiyunEND_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
1733*4882a593Smuzhiyun	/*
1734*4882a593Smuzhiyun	 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS (but not CR)
1735*4882a593Smuzhiyun	 */
1736*4882a593Smuzhiyun	mr      r3, r9
1737*4882a593Smuzhiyun	ld      r4, VCPU_MSR(r3)
1738*4882a593Smuzhiyun	li	r5, 0			/* don't preserve non-vol regs */
1739*4882a593Smuzhiyun	bl	kvmppc_save_tm_hv
1740*4882a593Smuzhiyun	nop
1741*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
1742*4882a593Smuzhiyun91:
1743*4882a593Smuzhiyun#endif
1744*4882a593Smuzhiyun
1745*4882a593Smuzhiyun	/* Increment yield count if they have a VPA */
1746*4882a593Smuzhiyun	ld	r8, VCPU_VPA(r9)	/* do they have a VPA? */
1747*4882a593Smuzhiyun	cmpdi	r8, 0
1748*4882a593Smuzhiyun	beq	25f
1749*4882a593Smuzhiyun	li	r4, LPPACA_YIELDCOUNT
1750*4882a593Smuzhiyun	LWZX_BE	r3, r8, r4
1751*4882a593Smuzhiyun	addi	r3, r3, 1
1752*4882a593Smuzhiyun	STWX_BE	r3, r8, r4
1753*4882a593Smuzhiyun	li	r3, 1
1754*4882a593Smuzhiyun	stb	r3, VCPU_VPA_DIRTY(r9)
1755*4882a593Smuzhiyun25:
1756*4882a593Smuzhiyun	/* Save PMU registers if requested */
1757*4882a593Smuzhiyun	/* r8 and cr0.eq are live here */
1758*4882a593Smuzhiyun	mr	r3, r9
1759*4882a593Smuzhiyun	li	r4, 1
1760*4882a593Smuzhiyun	beq	21f			/* if no VPA, save PMU stuff anyway */
1761*4882a593Smuzhiyun	lbz	r4, LPPACA_PMCINUSE(r8)
1762*4882a593Smuzhiyun21:	bl	kvmhv_save_guest_pmu
1763*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
1764*4882a593Smuzhiyun
1765*4882a593Smuzhiyun	/* Restore host values of some registers */
1766*4882a593SmuzhiyunBEGIN_FTR_SECTION
1767*4882a593Smuzhiyun	ld	r5, STACK_SLOT_CIABR(r1)
1768*4882a593Smuzhiyun	ld	r6, STACK_SLOT_DAWR(r1)
1769*4882a593Smuzhiyun	ld	r7, STACK_SLOT_DAWRX(r1)
1770*4882a593Smuzhiyun	mtspr	SPRN_CIABR, r5
1771*4882a593Smuzhiyun	/*
1772*4882a593Smuzhiyun	 * If the DAWR doesn't work, it's ok to write these here as
1773*4882a593Smuzhiyun	 * this value should always be zero
1774*4882a593Smuzhiyun	*/
1775*4882a593Smuzhiyun	mtspr	SPRN_DAWR0, r6
1776*4882a593Smuzhiyun	mtspr	SPRN_DAWRX0, r7
1777*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
1778*4882a593SmuzhiyunBEGIN_FTR_SECTION
1779*4882a593Smuzhiyun	ld	r5, STACK_SLOT_TID(r1)
1780*4882a593Smuzhiyun	ld	r6, STACK_SLOT_PSSCR(r1)
1781*4882a593Smuzhiyun	ld	r7, STACK_SLOT_PID(r1)
1782*4882a593Smuzhiyun	mtspr	SPRN_TIDR, r5
1783*4882a593Smuzhiyun	mtspr	SPRN_PSSCR, r6
1784*4882a593Smuzhiyun	mtspr	SPRN_PID, r7
1785*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
1786*4882a593Smuzhiyun
1787*4882a593Smuzhiyun#ifdef CONFIG_PPC_RADIX_MMU
1788*4882a593Smuzhiyun	/*
1789*4882a593Smuzhiyun	 * Are we running hash or radix ?
1790*4882a593Smuzhiyun	 */
1791*4882a593Smuzhiyun	ld	r5, VCPU_KVM(r9)
1792*4882a593Smuzhiyun	lbz	r0, KVM_RADIX(r5)
1793*4882a593Smuzhiyun	cmpwi	cr2, r0, 0
1794*4882a593Smuzhiyun	beq	cr2, 2f
1795*4882a593Smuzhiyun
1796*4882a593Smuzhiyun	/*
1797*4882a593Smuzhiyun	 * Radix: do eieio; tlbsync; ptesync sequence in case we
1798*4882a593Smuzhiyun	 * interrupted the guest between a tlbie and a ptesync.
1799*4882a593Smuzhiyun	 */
1800*4882a593Smuzhiyun	eieio
1801*4882a593Smuzhiyun	tlbsync
1802*4882a593Smuzhiyun	ptesync
1803*4882a593Smuzhiyun
1804*4882a593SmuzhiyunBEGIN_FTR_SECTION
1805*4882a593Smuzhiyun	/* Radix: Handle the case where the guest used an illegal PID */
1806*4882a593Smuzhiyun	LOAD_REG_ADDR(r4, mmu_base_pid)
1807*4882a593Smuzhiyun	lwz	r3, VCPU_GUEST_PID(r9)
1808*4882a593Smuzhiyun	lwz	r5, 0(r4)
1809*4882a593Smuzhiyun	cmpw	cr0,r3,r5
1810*4882a593Smuzhiyun	blt	2f
1811*4882a593Smuzhiyun
1812*4882a593Smuzhiyun	/*
1813*4882a593Smuzhiyun	 * Illegal PID, the HW might have prefetched and cached in the TLB
1814*4882a593Smuzhiyun	 * some translations for the  LPID 0 / guest PID combination which
1815*4882a593Smuzhiyun	 * Linux doesn't know about, so we need to flush that PID out of
1816*4882a593Smuzhiyun	 * the TLB. First we need to set LPIDR to 0 so tlbiel applies to
1817*4882a593Smuzhiyun	 * the right context.
1818*4882a593Smuzhiyun	*/
1819*4882a593Smuzhiyun	li	r0,0
1820*4882a593Smuzhiyun	mtspr	SPRN_LPID,r0
1821*4882a593Smuzhiyun	isync
1822*4882a593Smuzhiyun
1823*4882a593Smuzhiyun	/* Then do a congruence class local flush */
1824*4882a593Smuzhiyun	ld	r6,VCPU_KVM(r9)
1825*4882a593Smuzhiyun	lwz	r0,KVM_TLB_SETS(r6)
1826*4882a593Smuzhiyun	mtctr	r0
1827*4882a593Smuzhiyun	li	r7,0x400		/* IS field = 0b01 */
1828*4882a593Smuzhiyun	ptesync
1829*4882a593Smuzhiyun	sldi	r0,r3,32		/* RS has PID */
1830*4882a593Smuzhiyun1:	PPC_TLBIEL(7,0,2,1,1)		/* RIC=2, PRS=1, R=1 */
1831*4882a593Smuzhiyun	addi	r7,r7,0x1000
1832*4882a593Smuzhiyun	bdnz	1b
1833*4882a593Smuzhiyun	ptesync
1834*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_P9_RADIX_PREFETCH_BUG)
1835*4882a593Smuzhiyun
1836*4882a593Smuzhiyun2:
1837*4882a593Smuzhiyun#endif /* CONFIG_PPC_RADIX_MMU */
1838*4882a593Smuzhiyun
1839*4882a593Smuzhiyun	/*
1840*4882a593Smuzhiyun	 * cp_abort is required if the processor supports local copy-paste
1841*4882a593Smuzhiyun	 * to clear the copy buffer that was under control of the guest.
1842*4882a593Smuzhiyun	 */
1843*4882a593SmuzhiyunBEGIN_FTR_SECTION
1844*4882a593Smuzhiyun	PPC_CP_ABORT
1845*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_31)
1846*4882a593Smuzhiyun
1847*4882a593Smuzhiyun	/*
1848*4882a593Smuzhiyun	 * POWER7/POWER8 guest -> host partition switch code.
1849*4882a593Smuzhiyun	 * We don't have to lock against tlbies but we do
1850*4882a593Smuzhiyun	 * have to coordinate the hardware threads.
1851*4882a593Smuzhiyun	 * Here STACK_SLOT_TRAP(r1) contains the trap number.
1852*4882a593Smuzhiyun	 */
1853*4882a593Smuzhiyunkvmhv_switch_to_host:
1854*4882a593Smuzhiyun	/* Secondary threads wait for primary to do partition switch */
1855*4882a593Smuzhiyun	ld	r5,HSTATE_KVM_VCORE(r13)
1856*4882a593Smuzhiyun	ld	r4,VCORE_KVM(r5)	/* pointer to struct kvm */
1857*4882a593Smuzhiyun	lbz	r3,HSTATE_PTID(r13)
1858*4882a593Smuzhiyun	cmpwi	r3,0
1859*4882a593Smuzhiyun	beq	15f
1860*4882a593Smuzhiyun	HMT_LOW
1861*4882a593Smuzhiyun13:	lbz	r3,VCORE_IN_GUEST(r5)
1862*4882a593Smuzhiyun	cmpwi	r3,0
1863*4882a593Smuzhiyun	bne	13b
1864*4882a593Smuzhiyun	HMT_MEDIUM
1865*4882a593Smuzhiyun	b	16f
1866*4882a593Smuzhiyun
1867*4882a593Smuzhiyun	/* Primary thread waits for all the secondaries to exit guest */
1868*4882a593Smuzhiyun15:	lwz	r3,VCORE_ENTRY_EXIT(r5)
1869*4882a593Smuzhiyun	rlwinm	r0,r3,32-8,0xff
1870*4882a593Smuzhiyun	clrldi	r3,r3,56
1871*4882a593Smuzhiyun	cmpw	r3,r0
1872*4882a593Smuzhiyun	bne	15b
1873*4882a593Smuzhiyun	isync
1874*4882a593Smuzhiyun
1875*4882a593Smuzhiyun	/* Did we actually switch to the guest at all? */
1876*4882a593Smuzhiyun	lbz	r6, VCORE_IN_GUEST(r5)
1877*4882a593Smuzhiyun	cmpwi	r6, 0
1878*4882a593Smuzhiyun	beq	19f
1879*4882a593Smuzhiyun
1880*4882a593Smuzhiyun	/* Primary thread switches back to host partition */
1881*4882a593Smuzhiyun	lwz	r7,KVM_HOST_LPID(r4)
1882*4882a593SmuzhiyunBEGIN_FTR_SECTION
1883*4882a593Smuzhiyun	ld	r6,KVM_HOST_SDR1(r4)
1884*4882a593Smuzhiyun	li	r8,LPID_RSVD		/* switch to reserved LPID */
1885*4882a593Smuzhiyun	mtspr	SPRN_LPID,r8
1886*4882a593Smuzhiyun	ptesync
1887*4882a593Smuzhiyun	mtspr	SPRN_SDR1,r6		/* switch to host page table */
1888*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
1889*4882a593Smuzhiyun	mtspr	SPRN_LPID,r7
1890*4882a593Smuzhiyun	isync
1891*4882a593Smuzhiyun
1892*4882a593SmuzhiyunBEGIN_FTR_SECTION
1893*4882a593Smuzhiyun	/* DPDES and VTB are shared between threads */
1894*4882a593Smuzhiyun	mfspr	r7, SPRN_DPDES
1895*4882a593Smuzhiyun	mfspr	r8, SPRN_VTB
1896*4882a593Smuzhiyun	std	r7, VCORE_DPDES(r5)
1897*4882a593Smuzhiyun	std	r8, VCORE_VTB(r5)
1898*4882a593Smuzhiyun	/* clear DPDES so we don't get guest doorbells in the host */
1899*4882a593Smuzhiyun	li	r8, 0
1900*4882a593Smuzhiyun	mtspr	SPRN_DPDES, r8
1901*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
1902*4882a593Smuzhiyun
1903*4882a593Smuzhiyun	/* Subtract timebase offset from timebase */
1904*4882a593Smuzhiyun	ld	r8, VCORE_TB_OFFSET_APPL(r5)
1905*4882a593Smuzhiyun	cmpdi	r8,0
1906*4882a593Smuzhiyun	beq	17f
1907*4882a593Smuzhiyun	li	r0, 0
1908*4882a593Smuzhiyun	std	r0, VCORE_TB_OFFSET_APPL(r5)
1909*4882a593Smuzhiyun	mftb	r6			/* current guest timebase */
1910*4882a593Smuzhiyun	subf	r8,r8,r6
1911*4882a593Smuzhiyun	mtspr	SPRN_TBU40,r8		/* update upper 40 bits */
1912*4882a593Smuzhiyun	mftb	r7			/* check if lower 24 bits overflowed */
1913*4882a593Smuzhiyun	clrldi	r6,r6,40
1914*4882a593Smuzhiyun	clrldi	r7,r7,40
1915*4882a593Smuzhiyun	cmpld	r7,r6
1916*4882a593Smuzhiyun	bge	17f
1917*4882a593Smuzhiyun	addis	r8,r8,0x100		/* if so, increment upper 40 bits */
1918*4882a593Smuzhiyun	mtspr	SPRN_TBU40,r8
1919*4882a593Smuzhiyun
1920*4882a593Smuzhiyun17:
1921*4882a593Smuzhiyun	/*
1922*4882a593Smuzhiyun	 * If this is an HMI, we called kvmppc_realmode_hmi_handler
1923*4882a593Smuzhiyun	 * above, which may or may not have already called
1924*4882a593Smuzhiyun	 * kvmppc_subcore_exit_guest.  Fortunately, all that
1925*4882a593Smuzhiyun	 * kvmppc_subcore_exit_guest does is clear a flag, so calling
1926*4882a593Smuzhiyun	 * it again here is benign even if kvmppc_realmode_hmi_handler
1927*4882a593Smuzhiyun	 * has already called it.
1928*4882a593Smuzhiyun	 */
1929*4882a593Smuzhiyun	bl	kvmppc_subcore_exit_guest
1930*4882a593Smuzhiyun	nop
1931*4882a593Smuzhiyun30:	ld	r5,HSTATE_KVM_VCORE(r13)
1932*4882a593Smuzhiyun	ld	r4,VCORE_KVM(r5)	/* pointer to struct kvm */
1933*4882a593Smuzhiyun
1934*4882a593Smuzhiyun	/* Reset PCR */
1935*4882a593Smuzhiyun	ld	r0, VCORE_PCR(r5)
1936*4882a593Smuzhiyun	LOAD_REG_IMMEDIATE(r6, PCR_MASK)
1937*4882a593Smuzhiyun	cmpld	r0, r6
1938*4882a593Smuzhiyun	beq	18f
1939*4882a593Smuzhiyun	mtspr	SPRN_PCR, r6
1940*4882a593Smuzhiyun18:
1941*4882a593Smuzhiyun	/* Signal secondary CPUs to continue */
1942*4882a593Smuzhiyun	li	r0, 0
1943*4882a593Smuzhiyun	stb	r0,VCORE_IN_GUEST(r5)
1944*4882a593Smuzhiyun19:	lis	r8,0x7fff		/* MAX_INT@h */
1945*4882a593Smuzhiyun	mtspr	SPRN_HDEC,r8
1946*4882a593Smuzhiyun
1947*4882a593Smuzhiyun16:
1948*4882a593SmuzhiyunBEGIN_FTR_SECTION
1949*4882a593Smuzhiyun	/* On POWER9 with HPT-on-radix we need to wait for all other threads */
1950*4882a593Smuzhiyun	ld	r3, HSTATE_SPLIT_MODE(r13)
1951*4882a593Smuzhiyun	cmpdi	r3, 0
1952*4882a593Smuzhiyun	beq	47f
1953*4882a593Smuzhiyun	lwz	r8, KVM_SPLIT_DO_RESTORE(r3)
1954*4882a593Smuzhiyun	cmpwi	r8, 0
1955*4882a593Smuzhiyun	beq	47f
1956*4882a593Smuzhiyun	bl	kvmhv_p9_restore_lpcr
1957*4882a593Smuzhiyun	nop
1958*4882a593Smuzhiyun	b	48f
1959*4882a593Smuzhiyun47:
1960*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
1961*4882a593Smuzhiyun	ld	r8,KVM_HOST_LPCR(r4)
1962*4882a593Smuzhiyun	mtspr	SPRN_LPCR,r8
1963*4882a593Smuzhiyun	isync
1964*4882a593Smuzhiyun48:
1965*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
1966*4882a593Smuzhiyun	/* Finish timing, if we have a vcpu */
1967*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
1968*4882a593Smuzhiyun	cmpdi	r4, 0
1969*4882a593Smuzhiyun	li	r3, 0
1970*4882a593Smuzhiyun	beq	2f
1971*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
1972*4882a593Smuzhiyun2:
1973*4882a593Smuzhiyun#endif
1974*4882a593Smuzhiyun	/* Unset guest mode */
1975*4882a593Smuzhiyun	li	r0, KVM_GUEST_MODE_NONE
1976*4882a593Smuzhiyun	stb	r0, HSTATE_IN_GUEST(r13)
1977*4882a593Smuzhiyun
1978*4882a593Smuzhiyun	lwz	r12, STACK_SLOT_TRAP(r1)	/* return trap # in r12 */
1979*4882a593Smuzhiyun	ld	r0, SFS+PPC_LR_STKOFF(r1)
1980*4882a593Smuzhiyun	addi	r1, r1, SFS
1981*4882a593Smuzhiyun	mtlr	r0
1982*4882a593Smuzhiyun	blr
1983*4882a593Smuzhiyun
1984*4882a593Smuzhiyun.balign 32
1985*4882a593Smuzhiyun.global kvm_flush_link_stack
1986*4882a593Smuzhiyunkvm_flush_link_stack:
1987*4882a593Smuzhiyun	/* Save LR into r0 */
1988*4882a593Smuzhiyun	mflr	r0
1989*4882a593Smuzhiyun
1990*4882a593Smuzhiyun	/* Flush the link stack. On Power8 it's up to 32 entries in size. */
1991*4882a593Smuzhiyun	.rept 32
1992*4882a593Smuzhiyun	bl	.+4
1993*4882a593Smuzhiyun	.endr
1994*4882a593Smuzhiyun
1995*4882a593Smuzhiyun	/* And on Power9 it's up to 64. */
1996*4882a593SmuzhiyunBEGIN_FTR_SECTION
1997*4882a593Smuzhiyun	.rept 32
1998*4882a593Smuzhiyun	bl	.+4
1999*4882a593Smuzhiyun	.endr
2000*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
2001*4882a593Smuzhiyun
2002*4882a593Smuzhiyun	/* Restore LR */
2003*4882a593Smuzhiyun	mtlr	r0
2004*4882a593Smuzhiyun	blr
2005*4882a593Smuzhiyun
2006*4882a593Smuzhiyunkvmppc_guest_external:
2007*4882a593Smuzhiyun	/* External interrupt, first check for host_ipi. If this is
2008*4882a593Smuzhiyun	 * set, we know the host wants us out so let's do it now
2009*4882a593Smuzhiyun	 */
2010*4882a593Smuzhiyun	bl	kvmppc_read_intr
2011*4882a593Smuzhiyun
2012*4882a593Smuzhiyun	/*
2013*4882a593Smuzhiyun	 * Restore the active volatile registers after returning from
2014*4882a593Smuzhiyun	 * a C function.
2015*4882a593Smuzhiyun	 */
2016*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
2017*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_EXTERNAL
2018*4882a593Smuzhiyun
2019*4882a593Smuzhiyun	/*
2020*4882a593Smuzhiyun	 * kvmppc_read_intr return codes:
2021*4882a593Smuzhiyun	 *
2022*4882a593Smuzhiyun	 * Exit to host (r3 > 0)
2023*4882a593Smuzhiyun	 *   1 An interrupt is pending that needs to be handled by the host
2024*4882a593Smuzhiyun	 *     Exit guest and return to host by branching to guest_exit_cont
2025*4882a593Smuzhiyun	 *
2026*4882a593Smuzhiyun	 *   2 Passthrough that needs completion in the host
2027*4882a593Smuzhiyun	 *     Exit guest and return to host by branching to guest_exit_cont
2028*4882a593Smuzhiyun	 *     However, we also set r12 to BOOK3S_INTERRUPT_HV_RM_HARD
2029*4882a593Smuzhiyun	 *     to indicate to the host to complete handling the interrupt
2030*4882a593Smuzhiyun	 *
2031*4882a593Smuzhiyun	 * Before returning to guest, we check if any CPU is heading out
2032*4882a593Smuzhiyun	 * to the host and if so, we head out also. If no CPUs are heading
2033*4882a593Smuzhiyun	 * check return values <= 0.
2034*4882a593Smuzhiyun	 *
2035*4882a593Smuzhiyun	 * Return to guest (r3 <= 0)
2036*4882a593Smuzhiyun	 *  0 No external interrupt is pending
2037*4882a593Smuzhiyun	 * -1 A guest wakeup IPI (which has now been cleared)
2038*4882a593Smuzhiyun	 *    In either case, we return to guest to deliver any pending
2039*4882a593Smuzhiyun	 *    guest interrupts.
2040*4882a593Smuzhiyun	 *
2041*4882a593Smuzhiyun	 * -2 A PCI passthrough external interrupt was handled
2042*4882a593Smuzhiyun	 *    (interrupt was delivered directly to guest)
2043*4882a593Smuzhiyun	 *    Return to guest to deliver any pending guest interrupts.
2044*4882a593Smuzhiyun	 */
2045*4882a593Smuzhiyun
2046*4882a593Smuzhiyun	cmpdi	r3, 1
2047*4882a593Smuzhiyun	ble	1f
2048*4882a593Smuzhiyun
2049*4882a593Smuzhiyun	/* Return code = 2 */
2050*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_HV_RM_HARD
2051*4882a593Smuzhiyun	stw	r12, VCPU_TRAP(r9)
2052*4882a593Smuzhiyun	b	guest_exit_cont
2053*4882a593Smuzhiyun
2054*4882a593Smuzhiyun1:	/* Return code <= 1 */
2055*4882a593Smuzhiyun	cmpdi	r3, 0
2056*4882a593Smuzhiyun	bgt	guest_exit_cont
2057*4882a593Smuzhiyun
2058*4882a593Smuzhiyun	/* Return code <= 0 */
2059*4882a593Smuzhiyunmaybe_reenter_guest:
2060*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
2061*4882a593Smuzhiyun	lwz	r0, VCORE_ENTRY_EXIT(r5)
2062*4882a593Smuzhiyun	cmpwi	r0, 0x100
2063*4882a593Smuzhiyun	mr	r4, r9
2064*4882a593Smuzhiyun	blt	deliver_guest_interrupt
2065*4882a593Smuzhiyun	b	guest_exit_cont
2066*4882a593Smuzhiyun
2067*4882a593Smuzhiyun#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2068*4882a593Smuzhiyun/*
2069*4882a593Smuzhiyun * Softpatch interrupt for transactional memory emulation cases
2070*4882a593Smuzhiyun * on POWER9 DD2.2.  This is early in the guest exit path - we
2071*4882a593Smuzhiyun * haven't saved registers or done a treclaim yet.
2072*4882a593Smuzhiyun */
2073*4882a593Smuzhiyunkvmppc_tm_emul:
2074*4882a593Smuzhiyun	/* Save instruction image in HEIR */
2075*4882a593Smuzhiyun	mfspr	r3, SPRN_HEIR
2076*4882a593Smuzhiyun	stw	r3, VCPU_HEIR(r9)
2077*4882a593Smuzhiyun
2078*4882a593Smuzhiyun	/*
2079*4882a593Smuzhiyun	 * The cases we want to handle here are those where the guest
2080*4882a593Smuzhiyun	 * is in real suspend mode and is trying to transition to
2081*4882a593Smuzhiyun	 * transactional mode.
2082*4882a593Smuzhiyun	 */
2083*4882a593Smuzhiyun	lbz	r0, HSTATE_FAKE_SUSPEND(r13)
2084*4882a593Smuzhiyun	cmpwi	r0, 0		/* keep exiting guest if in fake suspend */
2085*4882a593Smuzhiyun	bne	guest_exit_cont
2086*4882a593Smuzhiyun	rldicl	r3, r11, 64 - MSR_TS_S_LG, 62
2087*4882a593Smuzhiyun	cmpwi	r3, 1		/* or if not in suspend state */
2088*4882a593Smuzhiyun	bne	guest_exit_cont
2089*4882a593Smuzhiyun
2090*4882a593Smuzhiyun	/* Call C code to do the emulation */
2091*4882a593Smuzhiyun	mr	r3, r9
2092*4882a593Smuzhiyun	bl	kvmhv_p9_tm_emulation_early
2093*4882a593Smuzhiyun	nop
2094*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
2095*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
2096*4882a593Smuzhiyun	cmpwi	r3, 0
2097*4882a593Smuzhiyun	beq	guest_exit_cont		/* continue exiting if not handled */
2098*4882a593Smuzhiyun	ld	r10, VCPU_PC(r9)
2099*4882a593Smuzhiyun	ld	r11, VCPU_MSR(r9)
2100*4882a593Smuzhiyun	b	fast_interrupt_c_return	/* go back to guest if handled */
2101*4882a593Smuzhiyun#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
2102*4882a593Smuzhiyun
2103*4882a593Smuzhiyun/*
2104*4882a593Smuzhiyun * Check whether an HDSI is an HPTE not found fault or something else.
2105*4882a593Smuzhiyun * If it is an HPTE not found fault that is due to the guest accessing
2106*4882a593Smuzhiyun * a page that they have mapped but which we have paged out, then
2107*4882a593Smuzhiyun * we continue on with the guest exit path.  In all other cases,
2108*4882a593Smuzhiyun * reflect the HDSI to the guest as a DSI.
2109*4882a593Smuzhiyun */
2110*4882a593Smuzhiyunkvmppc_hdsi:
2111*4882a593Smuzhiyun	ld	r3, VCPU_KVM(r9)
2112*4882a593Smuzhiyun	lbz	r0, KVM_RADIX(r3)
2113*4882a593Smuzhiyun	mfspr	r4, SPRN_HDAR
2114*4882a593Smuzhiyun	mfspr	r6, SPRN_HDSISR
2115*4882a593SmuzhiyunBEGIN_FTR_SECTION
2116*4882a593Smuzhiyun	/* Look for DSISR canary. If we find it, retry instruction */
2117*4882a593Smuzhiyun	cmpdi	r6, 0x7fff
2118*4882a593Smuzhiyun	beq	6f
2119*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
2120*4882a593Smuzhiyun	cmpwi	r0, 0
2121*4882a593Smuzhiyun	bne	.Lradix_hdsi		/* on radix, just save DAR/DSISR/ASDR */
2122*4882a593Smuzhiyun	/* HPTE not found fault or protection fault? */
2123*4882a593Smuzhiyun	andis.	r0, r6, (DSISR_NOHPTE | DSISR_PROTFAULT)@h
2124*4882a593Smuzhiyun	beq	1f			/* if not, send it to the guest */
2125*4882a593Smuzhiyun	andi.	r0, r11, MSR_DR		/* data relocation enabled? */
2126*4882a593Smuzhiyun	beq	3f
2127*4882a593SmuzhiyunBEGIN_FTR_SECTION
2128*4882a593Smuzhiyun	mfspr	r5, SPRN_ASDR		/* on POWER9, use ASDR to get VSID */
2129*4882a593Smuzhiyun	b	4f
2130*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
2131*4882a593Smuzhiyun	clrrdi	r0, r4, 28
2132*4882a593Smuzhiyun	PPC_SLBFEE_DOT(R5, R0)		/* if so, look up SLB */
2133*4882a593Smuzhiyun	li	r0, BOOK3S_INTERRUPT_DATA_SEGMENT
2134*4882a593Smuzhiyun	bne	7f			/* if no SLB entry found */
2135*4882a593Smuzhiyun4:	std	r4, VCPU_FAULT_DAR(r9)
2136*4882a593Smuzhiyun	stw	r6, VCPU_FAULT_DSISR(r9)
2137*4882a593Smuzhiyun
2138*4882a593Smuzhiyun	/* Search the hash table. */
2139*4882a593Smuzhiyun	mr	r3, r9			/* vcpu pointer */
2140*4882a593Smuzhiyun	li	r7, 1			/* data fault */
2141*4882a593Smuzhiyun	bl	kvmppc_hpte_hv_fault
2142*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
2143*4882a593Smuzhiyun	ld	r10, VCPU_PC(r9)
2144*4882a593Smuzhiyun	ld	r11, VCPU_MSR(r9)
2145*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
2146*4882a593Smuzhiyun	cmpdi	r3, 0			/* retry the instruction */
2147*4882a593Smuzhiyun	beq	6f
2148*4882a593Smuzhiyun	cmpdi	r3, -1			/* handle in kernel mode */
2149*4882a593Smuzhiyun	beq	guest_exit_cont
2150*4882a593Smuzhiyun	cmpdi	r3, -2			/* MMIO emulation; need instr word */
2151*4882a593Smuzhiyun	beq	2f
2152*4882a593Smuzhiyun
2153*4882a593Smuzhiyun	/* Synthesize a DSI (or DSegI) for the guest */
2154*4882a593Smuzhiyun	ld	r4, VCPU_FAULT_DAR(r9)
2155*4882a593Smuzhiyun	mr	r6, r3
2156*4882a593Smuzhiyun1:	li	r0, BOOK3S_INTERRUPT_DATA_STORAGE
2157*4882a593Smuzhiyun	mtspr	SPRN_DSISR, r6
2158*4882a593Smuzhiyun7:	mtspr	SPRN_DAR, r4
2159*4882a593Smuzhiyun	mtspr	SPRN_SRR0, r10
2160*4882a593Smuzhiyun	mtspr	SPRN_SRR1, r11
2161*4882a593Smuzhiyun	mr	r10, r0
2162*4882a593Smuzhiyun	bl	kvmppc_msr_interrupt
2163*4882a593Smuzhiyunfast_interrupt_c_return:
2164*4882a593Smuzhiyun6:	ld	r7, VCPU_CTR(r9)
2165*4882a593Smuzhiyun	ld	r8, VCPU_XER(r9)
2166*4882a593Smuzhiyun	mtctr	r7
2167*4882a593Smuzhiyun	mtxer	r8
2168*4882a593Smuzhiyun	mr	r4, r9
2169*4882a593Smuzhiyun	b	fast_guest_return
2170*4882a593Smuzhiyun
2171*4882a593Smuzhiyun3:	ld	r5, VCPU_KVM(r9)	/* not relocated, use VRMA */
2172*4882a593Smuzhiyun	ld	r5, KVM_VRMA_SLB_V(r5)
2173*4882a593Smuzhiyun	b	4b
2174*4882a593Smuzhiyun
2175*4882a593Smuzhiyun	/* If this is for emulated MMIO, load the instruction word */
2176*4882a593Smuzhiyun2:	li	r8, KVM_INST_FETCH_FAILED	/* In case lwz faults */
2177*4882a593Smuzhiyun
2178*4882a593Smuzhiyun	/* Set guest mode to 'jump over instruction' so if lwz faults
2179*4882a593Smuzhiyun	 * we'll just continue at the next IP. */
2180*4882a593Smuzhiyun	li	r0, KVM_GUEST_MODE_SKIP
2181*4882a593Smuzhiyun	stb	r0, HSTATE_IN_GUEST(r13)
2182*4882a593Smuzhiyun
2183*4882a593Smuzhiyun	/* Do the access with MSR:DR enabled */
2184*4882a593Smuzhiyun	mfmsr	r3
2185*4882a593Smuzhiyun	ori	r4, r3, MSR_DR		/* Enable paging for data */
2186*4882a593Smuzhiyun	mtmsrd	r4
2187*4882a593Smuzhiyun	lwz	r8, 0(r10)
2188*4882a593Smuzhiyun	mtmsrd	r3
2189*4882a593Smuzhiyun
2190*4882a593Smuzhiyun	/* Store the result */
2191*4882a593Smuzhiyun	stw	r8, VCPU_LAST_INST(r9)
2192*4882a593Smuzhiyun
2193*4882a593Smuzhiyun	/* Unset guest mode. */
2194*4882a593Smuzhiyun	li	r0, KVM_GUEST_MODE_HOST_HV
2195*4882a593Smuzhiyun	stb	r0, HSTATE_IN_GUEST(r13)
2196*4882a593Smuzhiyun	b	guest_exit_cont
2197*4882a593Smuzhiyun
2198*4882a593Smuzhiyun.Lradix_hdsi:
2199*4882a593Smuzhiyun	std	r4, VCPU_FAULT_DAR(r9)
2200*4882a593Smuzhiyun	stw	r6, VCPU_FAULT_DSISR(r9)
2201*4882a593Smuzhiyun.Lradix_hisi:
2202*4882a593Smuzhiyun	mfspr	r5, SPRN_ASDR
2203*4882a593Smuzhiyun	std	r5, VCPU_FAULT_GPA(r9)
2204*4882a593Smuzhiyun	b	guest_exit_cont
2205*4882a593Smuzhiyun
2206*4882a593Smuzhiyun/*
2207*4882a593Smuzhiyun * Similarly for an HISI, reflect it to the guest as an ISI unless
2208*4882a593Smuzhiyun * it is an HPTE not found fault for a page that we have paged out.
2209*4882a593Smuzhiyun */
2210*4882a593Smuzhiyunkvmppc_hisi:
2211*4882a593Smuzhiyun	ld	r3, VCPU_KVM(r9)
2212*4882a593Smuzhiyun	lbz	r0, KVM_RADIX(r3)
2213*4882a593Smuzhiyun	cmpwi	r0, 0
2214*4882a593Smuzhiyun	bne	.Lradix_hisi		/* for radix, just save ASDR */
2215*4882a593Smuzhiyun	andis.	r0, r11, SRR1_ISI_NOPT@h
2216*4882a593Smuzhiyun	beq	1f
2217*4882a593Smuzhiyun	andi.	r0, r11, MSR_IR		/* instruction relocation enabled? */
2218*4882a593Smuzhiyun	beq	3f
2219*4882a593SmuzhiyunBEGIN_FTR_SECTION
2220*4882a593Smuzhiyun	mfspr	r5, SPRN_ASDR		/* on POWER9, use ASDR to get VSID */
2221*4882a593Smuzhiyun	b	4f
2222*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
2223*4882a593Smuzhiyun	clrrdi	r0, r10, 28
2224*4882a593Smuzhiyun	PPC_SLBFEE_DOT(R5, R0)		/* if so, look up SLB */
2225*4882a593Smuzhiyun	li	r0, BOOK3S_INTERRUPT_INST_SEGMENT
2226*4882a593Smuzhiyun	bne	7f			/* if no SLB entry found */
2227*4882a593Smuzhiyun4:
2228*4882a593Smuzhiyun	/* Search the hash table. */
2229*4882a593Smuzhiyun	mr	r3, r9			/* vcpu pointer */
2230*4882a593Smuzhiyun	mr	r4, r10
2231*4882a593Smuzhiyun	mr	r6, r11
2232*4882a593Smuzhiyun	li	r7, 0			/* instruction fault */
2233*4882a593Smuzhiyun	bl	kvmppc_hpte_hv_fault
2234*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
2235*4882a593Smuzhiyun	ld	r10, VCPU_PC(r9)
2236*4882a593Smuzhiyun	ld	r11, VCPU_MSR(r9)
2237*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_H_INST_STORAGE
2238*4882a593Smuzhiyun	cmpdi	r3, 0			/* retry the instruction */
2239*4882a593Smuzhiyun	beq	fast_interrupt_c_return
2240*4882a593Smuzhiyun	cmpdi	r3, -1			/* handle in kernel mode */
2241*4882a593Smuzhiyun	beq	guest_exit_cont
2242*4882a593Smuzhiyun
2243*4882a593Smuzhiyun	/* Synthesize an ISI (or ISegI) for the guest */
2244*4882a593Smuzhiyun	mr	r11, r3
2245*4882a593Smuzhiyun1:	li	r0, BOOK3S_INTERRUPT_INST_STORAGE
2246*4882a593Smuzhiyun7:	mtspr	SPRN_SRR0, r10
2247*4882a593Smuzhiyun	mtspr	SPRN_SRR1, r11
2248*4882a593Smuzhiyun	mr	r10, r0
2249*4882a593Smuzhiyun	bl	kvmppc_msr_interrupt
2250*4882a593Smuzhiyun	b	fast_interrupt_c_return
2251*4882a593Smuzhiyun
2252*4882a593Smuzhiyun3:	ld	r6, VCPU_KVM(r9)	/* not relocated, use VRMA */
2253*4882a593Smuzhiyun	ld	r5, KVM_VRMA_SLB_V(r6)
2254*4882a593Smuzhiyun	b	4b
2255*4882a593Smuzhiyun
2256*4882a593Smuzhiyun/*
2257*4882a593Smuzhiyun * Try to handle an hcall in real mode.
2258*4882a593Smuzhiyun * Returns to the guest if we handle it, or continues on up to
2259*4882a593Smuzhiyun * the kernel if we can't (i.e. if we don't have a handler for
2260*4882a593Smuzhiyun * it, or if the handler returns H_TOO_HARD).
2261*4882a593Smuzhiyun *
2262*4882a593Smuzhiyun * r5 - r8 contain hcall args,
2263*4882a593Smuzhiyun * r9 = vcpu, r10 = pc, r11 = msr, r12 = trap, r13 = paca
2264*4882a593Smuzhiyun */
2265*4882a593Smuzhiyunhcall_try_real_mode:
2266*4882a593Smuzhiyun	ld	r3,VCPU_GPR(R3)(r9)
2267*4882a593Smuzhiyun	andi.	r0,r11,MSR_PR
2268*4882a593Smuzhiyun	/* sc 1 from userspace - reflect to guest syscall */
2269*4882a593Smuzhiyun	bne	sc_1_fast_return
2270*4882a593Smuzhiyun	/* sc 1 from nested guest - give it to L1 to handle */
2271*4882a593Smuzhiyun	ld	r0, VCPU_NESTED(r9)
2272*4882a593Smuzhiyun	cmpdi	r0, 0
2273*4882a593Smuzhiyun	bne	guest_exit_cont
2274*4882a593Smuzhiyun	clrrdi	r3,r3,2
2275*4882a593Smuzhiyun	cmpldi	r3,hcall_real_table_end - hcall_real_table
2276*4882a593Smuzhiyun	bge	guest_exit_cont
2277*4882a593Smuzhiyun	/* See if this hcall is enabled for in-kernel handling */
2278*4882a593Smuzhiyun	ld	r4, VCPU_KVM(r9)
2279*4882a593Smuzhiyun	srdi	r0, r3, 8	/* r0 = (r3 / 4) >> 6 */
2280*4882a593Smuzhiyun	sldi	r0, r0, 3	/* index into kvm->arch.enabled_hcalls[] */
2281*4882a593Smuzhiyun	add	r4, r4, r0
2282*4882a593Smuzhiyun	ld	r0, KVM_ENABLED_HCALLS(r4)
2283*4882a593Smuzhiyun	rlwinm	r4, r3, 32-2, 0x3f	/* r4 = (r3 / 4) & 0x3f */
2284*4882a593Smuzhiyun	srd	r0, r0, r4
2285*4882a593Smuzhiyun	andi.	r0, r0, 1
2286*4882a593Smuzhiyun	beq	guest_exit_cont
2287*4882a593Smuzhiyun	/* Get pointer to handler, if any, and call it */
2288*4882a593Smuzhiyun	LOAD_REG_ADDR(r4, hcall_real_table)
2289*4882a593Smuzhiyun	lwax	r3,r3,r4
2290*4882a593Smuzhiyun	cmpwi	r3,0
2291*4882a593Smuzhiyun	beq	guest_exit_cont
2292*4882a593Smuzhiyun	add	r12,r3,r4
2293*4882a593Smuzhiyun	mtctr	r12
2294*4882a593Smuzhiyun	mr	r3,r9		/* get vcpu pointer */
2295*4882a593Smuzhiyun	ld	r4,VCPU_GPR(R4)(r9)
2296*4882a593Smuzhiyun	bctrl
2297*4882a593Smuzhiyun	cmpdi	r3,H_TOO_HARD
2298*4882a593Smuzhiyun	beq	hcall_real_fallback
2299*4882a593Smuzhiyun	ld	r4,HSTATE_KVM_VCPU(r13)
2300*4882a593Smuzhiyun	std	r3,VCPU_GPR(R3)(r4)
2301*4882a593Smuzhiyun	ld	r10,VCPU_PC(r4)
2302*4882a593Smuzhiyun	ld	r11,VCPU_MSR(r4)
2303*4882a593Smuzhiyun	b	fast_guest_return
2304*4882a593Smuzhiyun
2305*4882a593Smuzhiyunsc_1_fast_return:
2306*4882a593Smuzhiyun	mtspr	SPRN_SRR0,r10
2307*4882a593Smuzhiyun	mtspr	SPRN_SRR1,r11
2308*4882a593Smuzhiyun	li	r10, BOOK3S_INTERRUPT_SYSCALL
2309*4882a593Smuzhiyun	bl	kvmppc_msr_interrupt
2310*4882a593Smuzhiyun	mr	r4,r9
2311*4882a593Smuzhiyun	b	fast_guest_return
2312*4882a593Smuzhiyun
2313*4882a593Smuzhiyun	/* We've attempted a real mode hcall, but it's punted it back
2314*4882a593Smuzhiyun	 * to userspace.  We need to restore some clobbered volatiles
2315*4882a593Smuzhiyun	 * before resuming the pass-it-to-qemu path */
2316*4882a593Smuzhiyunhcall_real_fallback:
2317*4882a593Smuzhiyun	li	r12,BOOK3S_INTERRUPT_SYSCALL
2318*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
2319*4882a593Smuzhiyun
2320*4882a593Smuzhiyun	b	guest_exit_cont
2321*4882a593Smuzhiyun
2322*4882a593Smuzhiyun	.globl	hcall_real_table
2323*4882a593Smuzhiyunhcall_real_table:
2324*4882a593Smuzhiyun	.long	0		/* 0 - unused */
2325*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_remove) - hcall_real_table
2326*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_enter) - hcall_real_table
2327*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_read) - hcall_real_table
2328*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_clear_mod) - hcall_real_table
2329*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_clear_ref) - hcall_real_table
2330*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_protect) - hcall_real_table
2331*4882a593Smuzhiyun#ifdef CONFIG_SPAPR_TCE_IOMMU
2332*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_get_tce) - hcall_real_table
2333*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_put_tce) - hcall_real_table
2334*4882a593Smuzhiyun#else
2335*4882a593Smuzhiyun	.long	0		/* 0x1c */
2336*4882a593Smuzhiyun	.long	0		/* 0x20 */
2337*4882a593Smuzhiyun#endif
2338*4882a593Smuzhiyun	.long	0		/* 0x24 - H_SET_SPRG0 */
2339*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_set_dabr) - hcall_real_table
2340*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_page_init) - hcall_real_table
2341*4882a593Smuzhiyun	.long	0		/* 0x30 */
2342*4882a593Smuzhiyun	.long	0		/* 0x34 */
2343*4882a593Smuzhiyun	.long	0		/* 0x38 */
2344*4882a593Smuzhiyun	.long	0		/* 0x3c */
2345*4882a593Smuzhiyun	.long	0		/* 0x40 */
2346*4882a593Smuzhiyun	.long	0		/* 0x44 */
2347*4882a593Smuzhiyun	.long	0		/* 0x48 */
2348*4882a593Smuzhiyun	.long	0		/* 0x4c */
2349*4882a593Smuzhiyun	.long	0		/* 0x50 */
2350*4882a593Smuzhiyun	.long	0		/* 0x54 */
2351*4882a593Smuzhiyun	.long	0		/* 0x58 */
2352*4882a593Smuzhiyun	.long	0		/* 0x5c */
2353*4882a593Smuzhiyun	.long	0		/* 0x60 */
2354*4882a593Smuzhiyun#ifdef CONFIG_KVM_XICS
2355*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_eoi) - hcall_real_table
2356*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_cppr) - hcall_real_table
2357*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_ipi) - hcall_real_table
2358*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_ipoll) - hcall_real_table
2359*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_xirr) - hcall_real_table
2360*4882a593Smuzhiyun#else
2361*4882a593Smuzhiyun	.long	0		/* 0x64 - H_EOI */
2362*4882a593Smuzhiyun	.long	0		/* 0x68 - H_CPPR */
2363*4882a593Smuzhiyun	.long	0		/* 0x6c - H_IPI */
2364*4882a593Smuzhiyun	.long	0		/* 0x70 - H_IPOLL */
2365*4882a593Smuzhiyun	.long	0		/* 0x74 - H_XIRR */
2366*4882a593Smuzhiyun#endif
2367*4882a593Smuzhiyun	.long	0		/* 0x78 */
2368*4882a593Smuzhiyun	.long	0		/* 0x7c */
2369*4882a593Smuzhiyun	.long	0		/* 0x80 */
2370*4882a593Smuzhiyun	.long	0		/* 0x84 */
2371*4882a593Smuzhiyun	.long	0		/* 0x88 */
2372*4882a593Smuzhiyun	.long	0		/* 0x8c */
2373*4882a593Smuzhiyun	.long	0		/* 0x90 */
2374*4882a593Smuzhiyun	.long	0		/* 0x94 */
2375*4882a593Smuzhiyun	.long	0		/* 0x98 */
2376*4882a593Smuzhiyun	.long	0		/* 0x9c */
2377*4882a593Smuzhiyun	.long	0		/* 0xa0 */
2378*4882a593Smuzhiyun	.long	0		/* 0xa4 */
2379*4882a593Smuzhiyun	.long	0		/* 0xa8 */
2380*4882a593Smuzhiyun	.long	0		/* 0xac */
2381*4882a593Smuzhiyun	.long	0		/* 0xb0 */
2382*4882a593Smuzhiyun	.long	0		/* 0xb4 */
2383*4882a593Smuzhiyun	.long	0		/* 0xb8 */
2384*4882a593Smuzhiyun	.long	0		/* 0xbc */
2385*4882a593Smuzhiyun	.long	0		/* 0xc0 */
2386*4882a593Smuzhiyun	.long	0		/* 0xc4 */
2387*4882a593Smuzhiyun	.long	0		/* 0xc8 */
2388*4882a593Smuzhiyun	.long	0		/* 0xcc */
2389*4882a593Smuzhiyun	.long	0		/* 0xd0 */
2390*4882a593Smuzhiyun	.long	0		/* 0xd4 */
2391*4882a593Smuzhiyun	.long	0		/* 0xd8 */
2392*4882a593Smuzhiyun	.long	0		/* 0xdc */
2393*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_cede) - hcall_real_table
2394*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_confer) - hcall_real_table
2395*4882a593Smuzhiyun	.long	0		/* 0xe8 */
2396*4882a593Smuzhiyun	.long	0		/* 0xec */
2397*4882a593Smuzhiyun	.long	0		/* 0xf0 */
2398*4882a593Smuzhiyun	.long	0		/* 0xf4 */
2399*4882a593Smuzhiyun	.long	0		/* 0xf8 */
2400*4882a593Smuzhiyun	.long	0		/* 0xfc */
2401*4882a593Smuzhiyun	.long	0		/* 0x100 */
2402*4882a593Smuzhiyun	.long	0		/* 0x104 */
2403*4882a593Smuzhiyun	.long	0		/* 0x108 */
2404*4882a593Smuzhiyun	.long	0		/* 0x10c */
2405*4882a593Smuzhiyun	.long	0		/* 0x110 */
2406*4882a593Smuzhiyun	.long	0		/* 0x114 */
2407*4882a593Smuzhiyun	.long	0		/* 0x118 */
2408*4882a593Smuzhiyun	.long	0		/* 0x11c */
2409*4882a593Smuzhiyun	.long	0		/* 0x120 */
2410*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_bulk_remove) - hcall_real_table
2411*4882a593Smuzhiyun	.long	0		/* 0x128 */
2412*4882a593Smuzhiyun	.long	0		/* 0x12c */
2413*4882a593Smuzhiyun	.long	0		/* 0x130 */
2414*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table
2415*4882a593Smuzhiyun#ifdef CONFIG_SPAPR_TCE_IOMMU
2416*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_stuff_tce) - hcall_real_table
2417*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_put_tce_indirect) - hcall_real_table
2418*4882a593Smuzhiyun#else
2419*4882a593Smuzhiyun	.long	0		/* 0x138 */
2420*4882a593Smuzhiyun	.long	0		/* 0x13c */
2421*4882a593Smuzhiyun#endif
2422*4882a593Smuzhiyun	.long	0		/* 0x140 */
2423*4882a593Smuzhiyun	.long	0		/* 0x144 */
2424*4882a593Smuzhiyun	.long	0		/* 0x148 */
2425*4882a593Smuzhiyun	.long	0		/* 0x14c */
2426*4882a593Smuzhiyun	.long	0		/* 0x150 */
2427*4882a593Smuzhiyun	.long	0		/* 0x154 */
2428*4882a593Smuzhiyun	.long	0		/* 0x158 */
2429*4882a593Smuzhiyun	.long	0		/* 0x15c */
2430*4882a593Smuzhiyun	.long	0		/* 0x160 */
2431*4882a593Smuzhiyun	.long	0		/* 0x164 */
2432*4882a593Smuzhiyun	.long	0		/* 0x168 */
2433*4882a593Smuzhiyun	.long	0		/* 0x16c */
2434*4882a593Smuzhiyun	.long	0		/* 0x170 */
2435*4882a593Smuzhiyun	.long	0		/* 0x174 */
2436*4882a593Smuzhiyun	.long	0		/* 0x178 */
2437*4882a593Smuzhiyun	.long	0		/* 0x17c */
2438*4882a593Smuzhiyun	.long	0		/* 0x180 */
2439*4882a593Smuzhiyun	.long	0		/* 0x184 */
2440*4882a593Smuzhiyun	.long	0		/* 0x188 */
2441*4882a593Smuzhiyun	.long	0		/* 0x18c */
2442*4882a593Smuzhiyun	.long	0		/* 0x190 */
2443*4882a593Smuzhiyun	.long	0		/* 0x194 */
2444*4882a593Smuzhiyun	.long	0		/* 0x198 */
2445*4882a593Smuzhiyun	.long	0		/* 0x19c */
2446*4882a593Smuzhiyun	.long	0		/* 0x1a0 */
2447*4882a593Smuzhiyun	.long	0		/* 0x1a4 */
2448*4882a593Smuzhiyun	.long	0		/* 0x1a8 */
2449*4882a593Smuzhiyun	.long	0		/* 0x1ac */
2450*4882a593Smuzhiyun	.long	0		/* 0x1b0 */
2451*4882a593Smuzhiyun	.long	0		/* 0x1b4 */
2452*4882a593Smuzhiyun	.long	0		/* 0x1b8 */
2453*4882a593Smuzhiyun	.long	0		/* 0x1bc */
2454*4882a593Smuzhiyun	.long	0		/* 0x1c0 */
2455*4882a593Smuzhiyun	.long	0		/* 0x1c4 */
2456*4882a593Smuzhiyun	.long	0		/* 0x1c8 */
2457*4882a593Smuzhiyun	.long	0		/* 0x1cc */
2458*4882a593Smuzhiyun	.long	0		/* 0x1d0 */
2459*4882a593Smuzhiyun	.long	0		/* 0x1d4 */
2460*4882a593Smuzhiyun	.long	0		/* 0x1d8 */
2461*4882a593Smuzhiyun	.long	0		/* 0x1dc */
2462*4882a593Smuzhiyun	.long	0		/* 0x1e0 */
2463*4882a593Smuzhiyun	.long	0		/* 0x1e4 */
2464*4882a593Smuzhiyun	.long	0		/* 0x1e8 */
2465*4882a593Smuzhiyun	.long	0		/* 0x1ec */
2466*4882a593Smuzhiyun	.long	0		/* 0x1f0 */
2467*4882a593Smuzhiyun	.long	0		/* 0x1f4 */
2468*4882a593Smuzhiyun	.long	0		/* 0x1f8 */
2469*4882a593Smuzhiyun	.long	0		/* 0x1fc */
2470*4882a593Smuzhiyun	.long	0		/* 0x200 */
2471*4882a593Smuzhiyun	.long	0		/* 0x204 */
2472*4882a593Smuzhiyun	.long	0		/* 0x208 */
2473*4882a593Smuzhiyun	.long	0		/* 0x20c */
2474*4882a593Smuzhiyun	.long	0		/* 0x210 */
2475*4882a593Smuzhiyun	.long	0		/* 0x214 */
2476*4882a593Smuzhiyun	.long	0		/* 0x218 */
2477*4882a593Smuzhiyun	.long	0		/* 0x21c */
2478*4882a593Smuzhiyun	.long	0		/* 0x220 */
2479*4882a593Smuzhiyun	.long	0		/* 0x224 */
2480*4882a593Smuzhiyun	.long	0		/* 0x228 */
2481*4882a593Smuzhiyun	.long	0		/* 0x22c */
2482*4882a593Smuzhiyun	.long	0		/* 0x230 */
2483*4882a593Smuzhiyun	.long	0		/* 0x234 */
2484*4882a593Smuzhiyun	.long	0		/* 0x238 */
2485*4882a593Smuzhiyun	.long	0		/* 0x23c */
2486*4882a593Smuzhiyun	.long	0		/* 0x240 */
2487*4882a593Smuzhiyun	.long	0		/* 0x244 */
2488*4882a593Smuzhiyun	.long	0		/* 0x248 */
2489*4882a593Smuzhiyun	.long	0		/* 0x24c */
2490*4882a593Smuzhiyun	.long	0		/* 0x250 */
2491*4882a593Smuzhiyun	.long	0		/* 0x254 */
2492*4882a593Smuzhiyun	.long	0		/* 0x258 */
2493*4882a593Smuzhiyun	.long	0		/* 0x25c */
2494*4882a593Smuzhiyun	.long	0		/* 0x260 */
2495*4882a593Smuzhiyun	.long	0		/* 0x264 */
2496*4882a593Smuzhiyun	.long	0		/* 0x268 */
2497*4882a593Smuzhiyun	.long	0		/* 0x26c */
2498*4882a593Smuzhiyun	.long	0		/* 0x270 */
2499*4882a593Smuzhiyun	.long	0		/* 0x274 */
2500*4882a593Smuzhiyun	.long	0		/* 0x278 */
2501*4882a593Smuzhiyun	.long	0		/* 0x27c */
2502*4882a593Smuzhiyun	.long	0		/* 0x280 */
2503*4882a593Smuzhiyun	.long	0		/* 0x284 */
2504*4882a593Smuzhiyun	.long	0		/* 0x288 */
2505*4882a593Smuzhiyun	.long	0		/* 0x28c */
2506*4882a593Smuzhiyun	.long	0		/* 0x290 */
2507*4882a593Smuzhiyun	.long	0		/* 0x294 */
2508*4882a593Smuzhiyun	.long	0		/* 0x298 */
2509*4882a593Smuzhiyun	.long	0		/* 0x29c */
2510*4882a593Smuzhiyun	.long	0		/* 0x2a0 */
2511*4882a593Smuzhiyun	.long	0		/* 0x2a4 */
2512*4882a593Smuzhiyun	.long	0		/* 0x2a8 */
2513*4882a593Smuzhiyun	.long	0		/* 0x2ac */
2514*4882a593Smuzhiyun	.long	0		/* 0x2b0 */
2515*4882a593Smuzhiyun	.long	0		/* 0x2b4 */
2516*4882a593Smuzhiyun	.long	0		/* 0x2b8 */
2517*4882a593Smuzhiyun	.long	0		/* 0x2bc */
2518*4882a593Smuzhiyun	.long	0		/* 0x2c0 */
2519*4882a593Smuzhiyun	.long	0		/* 0x2c4 */
2520*4882a593Smuzhiyun	.long	0		/* 0x2c8 */
2521*4882a593Smuzhiyun	.long	0		/* 0x2cc */
2522*4882a593Smuzhiyun	.long	0		/* 0x2d0 */
2523*4882a593Smuzhiyun	.long	0		/* 0x2d4 */
2524*4882a593Smuzhiyun	.long	0		/* 0x2d8 */
2525*4882a593Smuzhiyun	.long	0		/* 0x2dc */
2526*4882a593Smuzhiyun	.long	0		/* 0x2e0 */
2527*4882a593Smuzhiyun	.long	0		/* 0x2e4 */
2528*4882a593Smuzhiyun	.long	0		/* 0x2e8 */
2529*4882a593Smuzhiyun	.long	0		/* 0x2ec */
2530*4882a593Smuzhiyun	.long	0		/* 0x2f0 */
2531*4882a593Smuzhiyun	.long	0		/* 0x2f4 */
2532*4882a593Smuzhiyun	.long	0		/* 0x2f8 */
2533*4882a593Smuzhiyun#ifdef CONFIG_KVM_XICS
2534*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_rm_h_xirr_x) - hcall_real_table
2535*4882a593Smuzhiyun#else
2536*4882a593Smuzhiyun	.long	0		/* 0x2fc - H_XIRR_X*/
2537*4882a593Smuzhiyun#endif
2538*4882a593Smuzhiyun	.long	DOTSYM(kvmppc_h_random) - hcall_real_table
2539*4882a593Smuzhiyun	.globl	hcall_real_table_end
2540*4882a593Smuzhiyunhcall_real_table_end:
2541*4882a593Smuzhiyun
2542*4882a593Smuzhiyun_GLOBAL_TOC(kvmppc_h_set_xdabr)
2543*4882a593SmuzhiyunEXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr)
2544*4882a593Smuzhiyun	andi.	r0, r5, DABRX_USER | DABRX_KERNEL
2545*4882a593Smuzhiyun	beq	6f
2546*4882a593Smuzhiyun	li	r0, DABRX_USER | DABRX_KERNEL | DABRX_BTI
2547*4882a593Smuzhiyun	andc.	r0, r5, r0
2548*4882a593Smuzhiyun	beq	3f
2549*4882a593Smuzhiyun6:	li	r3, H_PARAMETER
2550*4882a593Smuzhiyun	blr
2551*4882a593Smuzhiyun
2552*4882a593Smuzhiyun_GLOBAL_TOC(kvmppc_h_set_dabr)
2553*4882a593SmuzhiyunEXPORT_SYMBOL_GPL(kvmppc_h_set_dabr)
2554*4882a593Smuzhiyun	li	r5, DABRX_USER | DABRX_KERNEL
2555*4882a593Smuzhiyun3:
2556*4882a593SmuzhiyunBEGIN_FTR_SECTION
2557*4882a593Smuzhiyun	b	2f
2558*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
2559*4882a593Smuzhiyun	std	r4,VCPU_DABR(r3)
2560*4882a593Smuzhiyun	stw	r5, VCPU_DABRX(r3)
2561*4882a593Smuzhiyun	mtspr	SPRN_DABRX, r5
2562*4882a593Smuzhiyun	/* Work around P7 bug where DABR can get corrupted on mtspr */
2563*4882a593Smuzhiyun1:	mtspr	SPRN_DABR,r4
2564*4882a593Smuzhiyun	mfspr	r5, SPRN_DABR
2565*4882a593Smuzhiyun	cmpd	r4, r5
2566*4882a593Smuzhiyun	bne	1b
2567*4882a593Smuzhiyun	isync
2568*4882a593Smuzhiyun	li	r3,0
2569*4882a593Smuzhiyun	blr
2570*4882a593Smuzhiyun
2571*4882a593Smuzhiyun2:
2572*4882a593Smuzhiyun	LOAD_REG_ADDR(r11, dawr_force_enable)
2573*4882a593Smuzhiyun	lbz	r11, 0(r11)
2574*4882a593Smuzhiyun	cmpdi	r11, 0
2575*4882a593Smuzhiyun	bne	3f
2576*4882a593Smuzhiyun	li	r3, H_HARDWARE
2577*4882a593Smuzhiyun	blr
2578*4882a593Smuzhiyun3:
2579*4882a593Smuzhiyun	/* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */
2580*4882a593Smuzhiyun	rlwimi	r5, r4, 5, DAWRX_DR | DAWRX_DW
2581*4882a593Smuzhiyun	rlwimi	r5, r4, 2, DAWRX_WT
2582*4882a593Smuzhiyun	clrrdi	r4, r4, 3
2583*4882a593Smuzhiyun	std	r4, VCPU_DAWR(r3)
2584*4882a593Smuzhiyun	std	r5, VCPU_DAWRX(r3)
2585*4882a593Smuzhiyun	/*
2586*4882a593Smuzhiyun	 * If came in through the real mode hcall handler then it is necessary
2587*4882a593Smuzhiyun	 * to write the registers since the return path won't. Otherwise it is
2588*4882a593Smuzhiyun	 * sufficient to store then in the vcpu struct as they will be loaded
2589*4882a593Smuzhiyun	 * next time the vcpu is run.
2590*4882a593Smuzhiyun	 */
2591*4882a593Smuzhiyun	mfmsr	r6
2592*4882a593Smuzhiyun	andi.	r6, r6, MSR_DR		/* in real mode? */
2593*4882a593Smuzhiyun	bne	4f
2594*4882a593Smuzhiyun	mtspr	SPRN_DAWR0, r4
2595*4882a593Smuzhiyun	mtspr	SPRN_DAWRX0, r5
2596*4882a593Smuzhiyun4:	li	r3, 0
2597*4882a593Smuzhiyun	blr
2598*4882a593Smuzhiyun
2599*4882a593Smuzhiyun_GLOBAL(kvmppc_h_cede)		/* r3 = vcpu pointer, r11 = msr, r13 = paca */
2600*4882a593Smuzhiyun	ori	r11,r11,MSR_EE
2601*4882a593Smuzhiyun	std	r11,VCPU_MSR(r3)
2602*4882a593Smuzhiyun	li	r0,1
2603*4882a593Smuzhiyun	stb	r0,VCPU_CEDED(r3)
2604*4882a593Smuzhiyun	sync			/* order setting ceded vs. testing prodded */
2605*4882a593Smuzhiyun	lbz	r5,VCPU_PRODDED(r3)
2606*4882a593Smuzhiyun	cmpwi	r5,0
2607*4882a593Smuzhiyun	bne	kvm_cede_prodded
2608*4882a593Smuzhiyun	li	r12,0		/* set trap to 0 to say hcall is handled */
2609*4882a593Smuzhiyun	stw	r12,VCPU_TRAP(r3)
2610*4882a593Smuzhiyun	li	r0,H_SUCCESS
2611*4882a593Smuzhiyun	std	r0,VCPU_GPR(R3)(r3)
2612*4882a593Smuzhiyun
2613*4882a593Smuzhiyun	/*
2614*4882a593Smuzhiyun	 * Set our bit in the bitmask of napping threads unless all the
2615*4882a593Smuzhiyun	 * other threads are already napping, in which case we send this
2616*4882a593Smuzhiyun	 * up to the host.
2617*4882a593Smuzhiyun	 */
2618*4882a593Smuzhiyun	ld	r5,HSTATE_KVM_VCORE(r13)
2619*4882a593Smuzhiyun	lbz	r6,HSTATE_PTID(r13)
2620*4882a593Smuzhiyun	lwz	r8,VCORE_ENTRY_EXIT(r5)
2621*4882a593Smuzhiyun	clrldi	r8,r8,56
2622*4882a593Smuzhiyun	li	r0,1
2623*4882a593Smuzhiyun	sld	r0,r0,r6
2624*4882a593Smuzhiyun	addi	r6,r5,VCORE_NAPPING_THREADS
2625*4882a593Smuzhiyun31:	lwarx	r4,0,r6
2626*4882a593Smuzhiyun	or	r4,r4,r0
2627*4882a593Smuzhiyun	cmpw	r4,r8
2628*4882a593Smuzhiyun	beq	kvm_cede_exit
2629*4882a593Smuzhiyun	stwcx.	r4,0,r6
2630*4882a593Smuzhiyun	bne	31b
2631*4882a593Smuzhiyun	/* order napping_threads update vs testing entry_exit_map */
2632*4882a593Smuzhiyun	isync
2633*4882a593Smuzhiyun	li	r0,NAPPING_CEDE
2634*4882a593Smuzhiyun	stb	r0,HSTATE_NAPPING(r13)
2635*4882a593Smuzhiyun	lwz	r7,VCORE_ENTRY_EXIT(r5)
2636*4882a593Smuzhiyun	cmpwi	r7,0x100
2637*4882a593Smuzhiyun	bge	33f		/* another thread already exiting */
2638*4882a593Smuzhiyun
2639*4882a593Smuzhiyun/*
2640*4882a593Smuzhiyun * Although not specifically required by the architecture, POWER7
2641*4882a593Smuzhiyun * preserves the following registers in nap mode, even if an SMT mode
2642*4882a593Smuzhiyun * switch occurs: SLB entries, PURR, SPURR, AMOR, UAMOR, AMR, SPRG0-3,
2643*4882a593Smuzhiyun * DAR, DSISR, DABR, DABRX, DSCR, PMCx, MMCRx, SIAR, SDAR.
2644*4882a593Smuzhiyun */
2645*4882a593Smuzhiyun	/* Save non-volatile GPRs */
2646*4882a593Smuzhiyun	std	r14, VCPU_GPR(R14)(r3)
2647*4882a593Smuzhiyun	std	r15, VCPU_GPR(R15)(r3)
2648*4882a593Smuzhiyun	std	r16, VCPU_GPR(R16)(r3)
2649*4882a593Smuzhiyun	std	r17, VCPU_GPR(R17)(r3)
2650*4882a593Smuzhiyun	std	r18, VCPU_GPR(R18)(r3)
2651*4882a593Smuzhiyun	std	r19, VCPU_GPR(R19)(r3)
2652*4882a593Smuzhiyun	std	r20, VCPU_GPR(R20)(r3)
2653*4882a593Smuzhiyun	std	r21, VCPU_GPR(R21)(r3)
2654*4882a593Smuzhiyun	std	r22, VCPU_GPR(R22)(r3)
2655*4882a593Smuzhiyun	std	r23, VCPU_GPR(R23)(r3)
2656*4882a593Smuzhiyun	std	r24, VCPU_GPR(R24)(r3)
2657*4882a593Smuzhiyun	std	r25, VCPU_GPR(R25)(r3)
2658*4882a593Smuzhiyun	std	r26, VCPU_GPR(R26)(r3)
2659*4882a593Smuzhiyun	std	r27, VCPU_GPR(R27)(r3)
2660*4882a593Smuzhiyun	std	r28, VCPU_GPR(R28)(r3)
2661*4882a593Smuzhiyun	std	r29, VCPU_GPR(R29)(r3)
2662*4882a593Smuzhiyun	std	r30, VCPU_GPR(R30)(r3)
2663*4882a593Smuzhiyun	std	r31, VCPU_GPR(R31)(r3)
2664*4882a593Smuzhiyun
2665*4882a593Smuzhiyun	/* save FP state */
2666*4882a593Smuzhiyun	bl	kvmppc_save_fp
2667*4882a593Smuzhiyun
2668*4882a593Smuzhiyun#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2669*4882a593Smuzhiyun/*
2670*4882a593Smuzhiyun * Branch around the call if both CPU_FTR_TM and
2671*4882a593Smuzhiyun * CPU_FTR_P9_TM_HV_ASSIST are off.
2672*4882a593Smuzhiyun */
2673*4882a593SmuzhiyunBEGIN_FTR_SECTION
2674*4882a593Smuzhiyun	b	91f
2675*4882a593SmuzhiyunEND_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
2676*4882a593Smuzhiyun	/*
2677*4882a593Smuzhiyun	 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS (but not CR)
2678*4882a593Smuzhiyun	 */
2679*4882a593Smuzhiyun	ld	r3, HSTATE_KVM_VCPU(r13)
2680*4882a593Smuzhiyun	ld      r4, VCPU_MSR(r3)
2681*4882a593Smuzhiyun	li	r5, 0			/* don't preserve non-vol regs */
2682*4882a593Smuzhiyun	bl	kvmppc_save_tm_hv
2683*4882a593Smuzhiyun	nop
2684*4882a593Smuzhiyun91:
2685*4882a593Smuzhiyun#endif
2686*4882a593Smuzhiyun
2687*4882a593Smuzhiyun	/*
2688*4882a593Smuzhiyun	 * Set DEC to the smaller of DEC and HDEC, so that we wake
2689*4882a593Smuzhiyun	 * no later than the end of our timeslice (HDEC interrupts
2690*4882a593Smuzhiyun	 * don't wake us from nap).
2691*4882a593Smuzhiyun	 */
2692*4882a593Smuzhiyun	mfspr	r3, SPRN_DEC
2693*4882a593Smuzhiyun	mfspr	r4, SPRN_HDEC
2694*4882a593Smuzhiyun	mftb	r5
2695*4882a593SmuzhiyunBEGIN_FTR_SECTION
2696*4882a593Smuzhiyun	/* On P9 check whether the guest has large decrementer mode enabled */
2697*4882a593Smuzhiyun	ld	r6, HSTATE_KVM_VCORE(r13)
2698*4882a593Smuzhiyun	ld	r6, VCORE_LPCR(r6)
2699*4882a593Smuzhiyun	andis.	r6, r6, LPCR_LD@h
2700*4882a593Smuzhiyun	bne	68f
2701*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
2702*4882a593Smuzhiyun	extsw	r3, r3
2703*4882a593Smuzhiyun68:	EXTEND_HDEC(r4)
2704*4882a593Smuzhiyun	cmpd	r3, r4
2705*4882a593Smuzhiyun	ble	67f
2706*4882a593Smuzhiyun	mtspr	SPRN_DEC, r4
2707*4882a593Smuzhiyun67:
2708*4882a593Smuzhiyun	/* save expiry time of guest decrementer */
2709*4882a593Smuzhiyun	add	r3, r3, r5
2710*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
2711*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
2712*4882a593Smuzhiyun	ld	r6, VCORE_TB_OFFSET_APPL(r5)
2713*4882a593Smuzhiyun	subf	r3, r6, r3	/* convert to host TB value */
2714*4882a593Smuzhiyun	std	r3, VCPU_DEC_EXPIRES(r4)
2715*4882a593Smuzhiyun
2716*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
2717*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
2718*4882a593Smuzhiyun	addi	r3, r4, VCPU_TB_CEDE
2719*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
2720*4882a593Smuzhiyun#endif
2721*4882a593Smuzhiyun
2722*4882a593Smuzhiyun	lis	r3, LPCR_PECEDP@h	/* Do wake on privileged doorbell */
2723*4882a593Smuzhiyun
2724*4882a593Smuzhiyun	/* Go back to host stack */
2725*4882a593Smuzhiyun	ld	r1, HSTATE_HOST_R1(r13)
2726*4882a593Smuzhiyun
2727*4882a593Smuzhiyun	/*
2728*4882a593Smuzhiyun	 * Take a nap until a decrementer or external or doobell interrupt
2729*4882a593Smuzhiyun	 * occurs, with PECE1 and PECE0 set in LPCR.
2730*4882a593Smuzhiyun	 * On POWER8, set PECEDH, and if we are ceding, also set PECEDP.
2731*4882a593Smuzhiyun	 * Also clear the runlatch bit before napping.
2732*4882a593Smuzhiyun	 */
2733*4882a593Smuzhiyunkvm_do_nap:
2734*4882a593Smuzhiyun	mfspr	r0, SPRN_CTRLF
2735*4882a593Smuzhiyun	clrrdi	r0, r0, 1
2736*4882a593Smuzhiyun	mtspr	SPRN_CTRLT, r0
2737*4882a593Smuzhiyun
2738*4882a593Smuzhiyun	li	r0,1
2739*4882a593Smuzhiyun	stb	r0,HSTATE_HWTHREAD_REQ(r13)
2740*4882a593Smuzhiyun	mfspr	r5,SPRN_LPCR
2741*4882a593Smuzhiyun	ori	r5,r5,LPCR_PECE0 | LPCR_PECE1
2742*4882a593SmuzhiyunBEGIN_FTR_SECTION
2743*4882a593Smuzhiyun	ori	r5, r5, LPCR_PECEDH
2744*4882a593Smuzhiyun	rlwimi	r5, r3, 0, LPCR_PECEDP
2745*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
2746*4882a593Smuzhiyun
2747*4882a593Smuzhiyunkvm_nap_sequence:		/* desired LPCR value in r5 */
2748*4882a593SmuzhiyunBEGIN_FTR_SECTION
2749*4882a593Smuzhiyun	/*
2750*4882a593Smuzhiyun	 * PSSCR bits:	exit criterion = 1 (wakeup based on LPCR at sreset)
2751*4882a593Smuzhiyun	 *		enable state loss = 1 (allow SMT mode switch)
2752*4882a593Smuzhiyun	 *		requested level = 0 (just stop dispatching)
2753*4882a593Smuzhiyun	 */
2754*4882a593Smuzhiyun	lis	r3, (PSSCR_EC | PSSCR_ESL)@h
2755*4882a593Smuzhiyun	/* Set LPCR_PECE_HVEE bit to enable wakeup by HV interrupts */
2756*4882a593Smuzhiyun	li	r4, LPCR_PECE_HVEE@higher
2757*4882a593Smuzhiyun	sldi	r4, r4, 32
2758*4882a593Smuzhiyun	or	r5, r5, r4
2759*4882a593SmuzhiyunFTR_SECTION_ELSE
2760*4882a593Smuzhiyun	li	r3, PNV_THREAD_NAP
2761*4882a593SmuzhiyunALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
2762*4882a593Smuzhiyun	mtspr	SPRN_LPCR,r5
2763*4882a593Smuzhiyun	isync
2764*4882a593Smuzhiyun
2765*4882a593SmuzhiyunBEGIN_FTR_SECTION
2766*4882a593Smuzhiyun	bl	isa300_idle_stop_mayloss
2767*4882a593SmuzhiyunFTR_SECTION_ELSE
2768*4882a593Smuzhiyun	bl	isa206_idle_insn_mayloss
2769*4882a593SmuzhiyunALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
2770*4882a593Smuzhiyun
2771*4882a593Smuzhiyun	mfspr	r0, SPRN_CTRLF
2772*4882a593Smuzhiyun	ori	r0, r0, 1
2773*4882a593Smuzhiyun	mtspr	SPRN_CTRLT, r0
2774*4882a593Smuzhiyun
2775*4882a593Smuzhiyun	mtspr	SPRN_SRR1, r3
2776*4882a593Smuzhiyun
2777*4882a593Smuzhiyun	li	r0, 0
2778*4882a593Smuzhiyun	stb	r0, PACA_FTRACE_ENABLED(r13)
2779*4882a593Smuzhiyun
2780*4882a593Smuzhiyun	li	r0, KVM_HWTHREAD_IN_KVM
2781*4882a593Smuzhiyun	stb	r0, HSTATE_HWTHREAD_STATE(r13)
2782*4882a593Smuzhiyun
2783*4882a593Smuzhiyun	lbz	r0, HSTATE_NAPPING(r13)
2784*4882a593Smuzhiyun	cmpwi	r0, NAPPING_CEDE
2785*4882a593Smuzhiyun	beq	kvm_end_cede
2786*4882a593Smuzhiyun	cmpwi	r0, NAPPING_NOVCPU
2787*4882a593Smuzhiyun	beq	kvm_novcpu_wakeup
2788*4882a593Smuzhiyun	cmpwi	r0, NAPPING_UNSPLIT
2789*4882a593Smuzhiyun	beq	kvm_unsplit_wakeup
2790*4882a593Smuzhiyun	twi	31,0,0 /* Nap state must not be zero */
2791*4882a593Smuzhiyun
2792*4882a593Smuzhiyun33:	mr	r4, r3
2793*4882a593Smuzhiyun	li	r3, 0
2794*4882a593Smuzhiyun	li	r12, 0
2795*4882a593Smuzhiyun	b	34f
2796*4882a593Smuzhiyun
2797*4882a593Smuzhiyunkvm_end_cede:
2798*4882a593Smuzhiyun	/* Woken by external or decrementer interrupt */
2799*4882a593Smuzhiyun
2800*4882a593Smuzhiyun	/* get vcpu pointer */
2801*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
2802*4882a593Smuzhiyun
2803*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
2804*4882a593Smuzhiyun	addi	r3, r4, VCPU_TB_RMINTR
2805*4882a593Smuzhiyun	bl	kvmhv_accumulate_time
2806*4882a593Smuzhiyun#endif
2807*4882a593Smuzhiyun
2808*4882a593Smuzhiyun#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2809*4882a593Smuzhiyun/*
2810*4882a593Smuzhiyun * Branch around the call if both CPU_FTR_TM and
2811*4882a593Smuzhiyun * CPU_FTR_P9_TM_HV_ASSIST are off.
2812*4882a593Smuzhiyun */
2813*4882a593SmuzhiyunBEGIN_FTR_SECTION
2814*4882a593Smuzhiyun	b	91f
2815*4882a593SmuzhiyunEND_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
2816*4882a593Smuzhiyun	/*
2817*4882a593Smuzhiyun	 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS (but not CR)
2818*4882a593Smuzhiyun	 */
2819*4882a593Smuzhiyun	mr      r3, r4
2820*4882a593Smuzhiyun	ld      r4, VCPU_MSR(r3)
2821*4882a593Smuzhiyun	li	r5, 0			/* don't preserve non-vol regs */
2822*4882a593Smuzhiyun	bl	kvmppc_restore_tm_hv
2823*4882a593Smuzhiyun	nop
2824*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
2825*4882a593Smuzhiyun91:
2826*4882a593Smuzhiyun#endif
2827*4882a593Smuzhiyun
2828*4882a593Smuzhiyun	/* load up FP state */
2829*4882a593Smuzhiyun	bl	kvmppc_load_fp
2830*4882a593Smuzhiyun
2831*4882a593Smuzhiyun	/* Restore guest decrementer */
2832*4882a593Smuzhiyun	ld	r3, VCPU_DEC_EXPIRES(r4)
2833*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
2834*4882a593Smuzhiyun	ld	r6, VCORE_TB_OFFSET_APPL(r5)
2835*4882a593Smuzhiyun	add	r3, r3, r6	/* convert host TB to guest TB value */
2836*4882a593Smuzhiyun	mftb	r7
2837*4882a593Smuzhiyun	subf	r3, r7, r3
2838*4882a593Smuzhiyun	mtspr	SPRN_DEC, r3
2839*4882a593Smuzhiyun
2840*4882a593Smuzhiyun	/* Load NV GPRS */
2841*4882a593Smuzhiyun	ld	r14, VCPU_GPR(R14)(r4)
2842*4882a593Smuzhiyun	ld	r15, VCPU_GPR(R15)(r4)
2843*4882a593Smuzhiyun	ld	r16, VCPU_GPR(R16)(r4)
2844*4882a593Smuzhiyun	ld	r17, VCPU_GPR(R17)(r4)
2845*4882a593Smuzhiyun	ld	r18, VCPU_GPR(R18)(r4)
2846*4882a593Smuzhiyun	ld	r19, VCPU_GPR(R19)(r4)
2847*4882a593Smuzhiyun	ld	r20, VCPU_GPR(R20)(r4)
2848*4882a593Smuzhiyun	ld	r21, VCPU_GPR(R21)(r4)
2849*4882a593Smuzhiyun	ld	r22, VCPU_GPR(R22)(r4)
2850*4882a593Smuzhiyun	ld	r23, VCPU_GPR(R23)(r4)
2851*4882a593Smuzhiyun	ld	r24, VCPU_GPR(R24)(r4)
2852*4882a593Smuzhiyun	ld	r25, VCPU_GPR(R25)(r4)
2853*4882a593Smuzhiyun	ld	r26, VCPU_GPR(R26)(r4)
2854*4882a593Smuzhiyun	ld	r27, VCPU_GPR(R27)(r4)
2855*4882a593Smuzhiyun	ld	r28, VCPU_GPR(R28)(r4)
2856*4882a593Smuzhiyun	ld	r29, VCPU_GPR(R29)(r4)
2857*4882a593Smuzhiyun	ld	r30, VCPU_GPR(R30)(r4)
2858*4882a593Smuzhiyun	ld	r31, VCPU_GPR(R31)(r4)
2859*4882a593Smuzhiyun
2860*4882a593Smuzhiyun	/* Check the wake reason in SRR1 to see why we got here */
2861*4882a593Smuzhiyun	bl	kvmppc_check_wake_reason
2862*4882a593Smuzhiyun
2863*4882a593Smuzhiyun	/*
2864*4882a593Smuzhiyun	 * Restore volatile registers since we could have called a
2865*4882a593Smuzhiyun	 * C routine in kvmppc_check_wake_reason
2866*4882a593Smuzhiyun	 *	r4 = VCPU
2867*4882a593Smuzhiyun	 * r3 tells us whether we need to return to host or not
2868*4882a593Smuzhiyun	 * WARNING: it gets checked further down:
2869*4882a593Smuzhiyun	 * should not modify r3 until this check is done.
2870*4882a593Smuzhiyun	 */
2871*4882a593Smuzhiyun	ld	r4, HSTATE_KVM_VCPU(r13)
2872*4882a593Smuzhiyun
2873*4882a593Smuzhiyun	/* clear our bit in vcore->napping_threads */
2874*4882a593Smuzhiyun34:	ld	r5,HSTATE_KVM_VCORE(r13)
2875*4882a593Smuzhiyun	lbz	r7,HSTATE_PTID(r13)
2876*4882a593Smuzhiyun	li	r0,1
2877*4882a593Smuzhiyun	sld	r0,r0,r7
2878*4882a593Smuzhiyun	addi	r6,r5,VCORE_NAPPING_THREADS
2879*4882a593Smuzhiyun32:	lwarx	r7,0,r6
2880*4882a593Smuzhiyun	andc	r7,r7,r0
2881*4882a593Smuzhiyun	stwcx.	r7,0,r6
2882*4882a593Smuzhiyun	bne	32b
2883*4882a593Smuzhiyun	li	r0,0
2884*4882a593Smuzhiyun	stb	r0,HSTATE_NAPPING(r13)
2885*4882a593Smuzhiyun
2886*4882a593Smuzhiyun	/* See if the wake reason saved in r3 means we need to exit */
2887*4882a593Smuzhiyun	stw	r12, VCPU_TRAP(r4)
2888*4882a593Smuzhiyun	mr	r9, r4
2889*4882a593Smuzhiyun	cmpdi	r3, 0
2890*4882a593Smuzhiyun	bgt	guest_exit_cont
2891*4882a593Smuzhiyun	b	maybe_reenter_guest
2892*4882a593Smuzhiyun
2893*4882a593Smuzhiyun	/* cede when already previously prodded case */
2894*4882a593Smuzhiyunkvm_cede_prodded:
2895*4882a593Smuzhiyun	li	r0,0
2896*4882a593Smuzhiyun	stb	r0,VCPU_PRODDED(r3)
2897*4882a593Smuzhiyun	sync			/* order testing prodded vs. clearing ceded */
2898*4882a593Smuzhiyun	stb	r0,VCPU_CEDED(r3)
2899*4882a593Smuzhiyun	li	r3,H_SUCCESS
2900*4882a593Smuzhiyun	blr
2901*4882a593Smuzhiyun
2902*4882a593Smuzhiyun	/* we've ceded but we want to give control to the host */
2903*4882a593Smuzhiyunkvm_cede_exit:
2904*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
2905*4882a593Smuzhiyun#ifdef CONFIG_KVM_XICS
2906*4882a593Smuzhiyun	/* are we using XIVE with single escalation? */
2907*4882a593Smuzhiyun	ld	r10, VCPU_XIVE_ESC_VADDR(r9)
2908*4882a593Smuzhiyun	cmpdi	r10, 0
2909*4882a593Smuzhiyun	beq	3f
2910*4882a593Smuzhiyun	li	r6, XIVE_ESB_SET_PQ_00
2911*4882a593Smuzhiyun	/*
2912*4882a593Smuzhiyun	 * If we still have a pending escalation, abort the cede,
2913*4882a593Smuzhiyun	 * and we must set PQ to 10 rather than 00 so that we don't
2914*4882a593Smuzhiyun	 * potentially end up with two entries for the escalation
2915*4882a593Smuzhiyun	 * interrupt in the XIVE interrupt queue.  In that case
2916*4882a593Smuzhiyun	 * we also don't want to set xive_esc_on to 1 here in
2917*4882a593Smuzhiyun	 * case we race with xive_esc_irq().
2918*4882a593Smuzhiyun	 */
2919*4882a593Smuzhiyun	lbz	r5, VCPU_XIVE_ESC_ON(r9)
2920*4882a593Smuzhiyun	cmpwi	r5, 0
2921*4882a593Smuzhiyun	beq	4f
2922*4882a593Smuzhiyun	li	r0, 0
2923*4882a593Smuzhiyun	stb	r0, VCPU_CEDED(r9)
2924*4882a593Smuzhiyun	/*
2925*4882a593Smuzhiyun	 * The escalation interrupts are special as we don't EOI them.
2926*4882a593Smuzhiyun	 * There is no need to use the load-after-store ordering offset
2927*4882a593Smuzhiyun	 * to set PQ to 10 as we won't use StoreEOI.
2928*4882a593Smuzhiyun	 */
2929*4882a593Smuzhiyun	li	r6, XIVE_ESB_SET_PQ_10
2930*4882a593Smuzhiyun	b	5f
2931*4882a593Smuzhiyun4:	li	r0, 1
2932*4882a593Smuzhiyun	stb	r0, VCPU_XIVE_ESC_ON(r9)
2933*4882a593Smuzhiyun	/* make sure store to xive_esc_on is seen before xive_esc_irq runs */
2934*4882a593Smuzhiyun	sync
2935*4882a593Smuzhiyun5:	/* Enable XIVE escalation */
2936*4882a593Smuzhiyun	mfmsr	r0
2937*4882a593Smuzhiyun	andi.	r0, r0, MSR_DR		/* in real mode? */
2938*4882a593Smuzhiyun	beq	1f
2939*4882a593Smuzhiyun	ldx	r0, r10, r6
2940*4882a593Smuzhiyun	b	2f
2941*4882a593Smuzhiyun1:	ld	r10, VCPU_XIVE_ESC_RADDR(r9)
2942*4882a593Smuzhiyun	ldcix	r0, r10, r6
2943*4882a593Smuzhiyun2:	sync
2944*4882a593Smuzhiyun#endif /* CONFIG_KVM_XICS */
2945*4882a593Smuzhiyun3:	b	guest_exit_cont
2946*4882a593Smuzhiyun
2947*4882a593Smuzhiyun	/* Try to do machine check recovery in real mode */
2948*4882a593Smuzhiyunmachine_check_realmode:
2949*4882a593Smuzhiyun	mr	r3, r9		/* get vcpu pointer */
2950*4882a593Smuzhiyun	bl	kvmppc_realmode_machine_check
2951*4882a593Smuzhiyun	nop
2952*4882a593Smuzhiyun	/* all machine checks go to virtual mode for further handling */
2953*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
2954*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_MACHINE_CHECK
2955*4882a593Smuzhiyun	b	guest_exit_cont
2956*4882a593Smuzhiyun
2957*4882a593Smuzhiyun/*
2958*4882a593Smuzhiyun * Call C code to handle a HMI in real mode.
2959*4882a593Smuzhiyun * Only the primary thread does the call, secondary threads are handled
2960*4882a593Smuzhiyun * by calling hmi_exception_realmode() after kvmppc_hv_entry returns.
2961*4882a593Smuzhiyun * r9 points to the vcpu on entry
2962*4882a593Smuzhiyun */
2963*4882a593Smuzhiyunhmi_realmode:
2964*4882a593Smuzhiyun	lbz	r0, HSTATE_PTID(r13)
2965*4882a593Smuzhiyun	cmpwi	r0, 0
2966*4882a593Smuzhiyun	bne	guest_exit_cont
2967*4882a593Smuzhiyun	bl	kvmppc_realmode_hmi_handler
2968*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
2969*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_HMI
2970*4882a593Smuzhiyun	b	guest_exit_cont
2971*4882a593Smuzhiyun
2972*4882a593Smuzhiyun/*
2973*4882a593Smuzhiyun * Check the reason we woke from nap, and take appropriate action.
2974*4882a593Smuzhiyun * Returns (in r3):
2975*4882a593Smuzhiyun *	0 if nothing needs to be done
2976*4882a593Smuzhiyun *	1 if something happened that needs to be handled by the host
2977*4882a593Smuzhiyun *	-1 if there was a guest wakeup (IPI or msgsnd)
2978*4882a593Smuzhiyun *	-2 if we handled a PCI passthrough interrupt (returned by
2979*4882a593Smuzhiyun *		kvmppc_read_intr only)
2980*4882a593Smuzhiyun *
2981*4882a593Smuzhiyun * Also sets r12 to the interrupt vector for any interrupt that needs
2982*4882a593Smuzhiyun * to be handled now by the host (0x500 for external interrupt), or zero.
2983*4882a593Smuzhiyun * Modifies all volatile registers (since it may call a C function).
2984*4882a593Smuzhiyun * This routine calls kvmppc_read_intr, a C function, if an external
2985*4882a593Smuzhiyun * interrupt is pending.
2986*4882a593Smuzhiyun */
2987*4882a593Smuzhiyunkvmppc_check_wake_reason:
2988*4882a593Smuzhiyun	mfspr	r6, SPRN_SRR1
2989*4882a593SmuzhiyunBEGIN_FTR_SECTION
2990*4882a593Smuzhiyun	rlwinm	r6, r6, 45-31, 0xf	/* extract wake reason field (P8) */
2991*4882a593SmuzhiyunFTR_SECTION_ELSE
2992*4882a593Smuzhiyun	rlwinm	r6, r6, 45-31, 0xe	/* P7 wake reason field is 3 bits */
2993*4882a593SmuzhiyunALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_207S)
2994*4882a593Smuzhiyun	cmpwi	r6, 8			/* was it an external interrupt? */
2995*4882a593Smuzhiyun	beq	7f			/* if so, see what it was */
2996*4882a593Smuzhiyun	li	r3, 0
2997*4882a593Smuzhiyun	li	r12, 0
2998*4882a593Smuzhiyun	cmpwi	r6, 6			/* was it the decrementer? */
2999*4882a593Smuzhiyun	beq	0f
3000*4882a593SmuzhiyunBEGIN_FTR_SECTION
3001*4882a593Smuzhiyun	cmpwi	r6, 5			/* privileged doorbell? */
3002*4882a593Smuzhiyun	beq	0f
3003*4882a593Smuzhiyun	cmpwi	r6, 3			/* hypervisor doorbell? */
3004*4882a593Smuzhiyun	beq	3f
3005*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
3006*4882a593Smuzhiyun	cmpwi	r6, 0xa			/* Hypervisor maintenance ? */
3007*4882a593Smuzhiyun	beq	4f
3008*4882a593Smuzhiyun	li	r3, 1			/* anything else, return 1 */
3009*4882a593Smuzhiyun0:	blr
3010*4882a593Smuzhiyun
3011*4882a593Smuzhiyun	/* hypervisor doorbell */
3012*4882a593Smuzhiyun3:	li	r12, BOOK3S_INTERRUPT_H_DOORBELL
3013*4882a593Smuzhiyun
3014*4882a593Smuzhiyun	/*
3015*4882a593Smuzhiyun	 * Clear the doorbell as we will invoke the handler
3016*4882a593Smuzhiyun	 * explicitly in the guest exit path.
3017*4882a593Smuzhiyun	 */
3018*4882a593Smuzhiyun	lis	r6, (PPC_DBELL_SERVER << (63-36))@h
3019*4882a593Smuzhiyun	PPC_MSGCLR(6)
3020*4882a593Smuzhiyun	/* see if it's a host IPI */
3021*4882a593Smuzhiyun	li	r3, 1
3022*4882a593SmuzhiyunBEGIN_FTR_SECTION
3023*4882a593Smuzhiyun	PPC_MSGSYNC
3024*4882a593Smuzhiyun	lwsync
3025*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
3026*4882a593Smuzhiyun	lbz	r0, HSTATE_HOST_IPI(r13)
3027*4882a593Smuzhiyun	cmpwi	r0, 0
3028*4882a593Smuzhiyun	bnelr
3029*4882a593Smuzhiyun	/* if not, return -1 */
3030*4882a593Smuzhiyun	li	r3, -1
3031*4882a593Smuzhiyun	blr
3032*4882a593Smuzhiyun
3033*4882a593Smuzhiyun	/* Woken up due to Hypervisor maintenance interrupt */
3034*4882a593Smuzhiyun4:	li	r12, BOOK3S_INTERRUPT_HMI
3035*4882a593Smuzhiyun	li	r3, 1
3036*4882a593Smuzhiyun	blr
3037*4882a593Smuzhiyun
3038*4882a593Smuzhiyun	/* external interrupt - create a stack frame so we can call C */
3039*4882a593Smuzhiyun7:	mflr	r0
3040*4882a593Smuzhiyun	std	r0, PPC_LR_STKOFF(r1)
3041*4882a593Smuzhiyun	stdu	r1, -PPC_MIN_STKFRM(r1)
3042*4882a593Smuzhiyun	bl	kvmppc_read_intr
3043*4882a593Smuzhiyun	nop
3044*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_EXTERNAL
3045*4882a593Smuzhiyun	cmpdi	r3, 1
3046*4882a593Smuzhiyun	ble	1f
3047*4882a593Smuzhiyun
3048*4882a593Smuzhiyun	/*
3049*4882a593Smuzhiyun	 * Return code of 2 means PCI passthrough interrupt, but
3050*4882a593Smuzhiyun	 * we need to return back to host to complete handling the
3051*4882a593Smuzhiyun	 * interrupt. Trap reason is expected in r12 by guest
3052*4882a593Smuzhiyun	 * exit code.
3053*4882a593Smuzhiyun	 */
3054*4882a593Smuzhiyun	li	r12, BOOK3S_INTERRUPT_HV_RM_HARD
3055*4882a593Smuzhiyun1:
3056*4882a593Smuzhiyun	ld	r0, PPC_MIN_STKFRM+PPC_LR_STKOFF(r1)
3057*4882a593Smuzhiyun	addi	r1, r1, PPC_MIN_STKFRM
3058*4882a593Smuzhiyun	mtlr	r0
3059*4882a593Smuzhiyun	blr
3060*4882a593Smuzhiyun
3061*4882a593Smuzhiyun/*
3062*4882a593Smuzhiyun * Save away FP, VMX and VSX registers.
3063*4882a593Smuzhiyun * r3 = vcpu pointer
3064*4882a593Smuzhiyun * N.B. r30 and r31 are volatile across this function,
3065*4882a593Smuzhiyun * thus it is not callable from C.
3066*4882a593Smuzhiyun */
3067*4882a593Smuzhiyunkvmppc_save_fp:
3068*4882a593Smuzhiyun	mflr	r30
3069*4882a593Smuzhiyun	mr	r31,r3
3070*4882a593Smuzhiyun	mfmsr	r5
3071*4882a593Smuzhiyun	ori	r8,r5,MSR_FP
3072*4882a593Smuzhiyun#ifdef CONFIG_ALTIVEC
3073*4882a593SmuzhiyunBEGIN_FTR_SECTION
3074*4882a593Smuzhiyun	oris	r8,r8,MSR_VEC@h
3075*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
3076*4882a593Smuzhiyun#endif
3077*4882a593Smuzhiyun#ifdef CONFIG_VSX
3078*4882a593SmuzhiyunBEGIN_FTR_SECTION
3079*4882a593Smuzhiyun	oris	r8,r8,MSR_VSX@h
3080*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_VSX)
3081*4882a593Smuzhiyun#endif
3082*4882a593Smuzhiyun	mtmsrd	r8
3083*4882a593Smuzhiyun	addi	r3,r3,VCPU_FPRS
3084*4882a593Smuzhiyun	bl	store_fp_state
3085*4882a593Smuzhiyun#ifdef CONFIG_ALTIVEC
3086*4882a593SmuzhiyunBEGIN_FTR_SECTION
3087*4882a593Smuzhiyun	addi	r3,r31,VCPU_VRS
3088*4882a593Smuzhiyun	bl	store_vr_state
3089*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
3090*4882a593Smuzhiyun#endif
3091*4882a593Smuzhiyun	mfspr	r6,SPRN_VRSAVE
3092*4882a593Smuzhiyun	stw	r6,VCPU_VRSAVE(r31)
3093*4882a593Smuzhiyun	mtlr	r30
3094*4882a593Smuzhiyun	blr
3095*4882a593Smuzhiyun
3096*4882a593Smuzhiyun/*
3097*4882a593Smuzhiyun * Load up FP, VMX and VSX registers
3098*4882a593Smuzhiyun * r4 = vcpu pointer
3099*4882a593Smuzhiyun * N.B. r30 and r31 are volatile across this function,
3100*4882a593Smuzhiyun * thus it is not callable from C.
3101*4882a593Smuzhiyun */
3102*4882a593Smuzhiyunkvmppc_load_fp:
3103*4882a593Smuzhiyun	mflr	r30
3104*4882a593Smuzhiyun	mr	r31,r4
3105*4882a593Smuzhiyun	mfmsr	r9
3106*4882a593Smuzhiyun	ori	r8,r9,MSR_FP
3107*4882a593Smuzhiyun#ifdef CONFIG_ALTIVEC
3108*4882a593SmuzhiyunBEGIN_FTR_SECTION
3109*4882a593Smuzhiyun	oris	r8,r8,MSR_VEC@h
3110*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
3111*4882a593Smuzhiyun#endif
3112*4882a593Smuzhiyun#ifdef CONFIG_VSX
3113*4882a593SmuzhiyunBEGIN_FTR_SECTION
3114*4882a593Smuzhiyun	oris	r8,r8,MSR_VSX@h
3115*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_VSX)
3116*4882a593Smuzhiyun#endif
3117*4882a593Smuzhiyun	mtmsrd	r8
3118*4882a593Smuzhiyun	addi	r3,r4,VCPU_FPRS
3119*4882a593Smuzhiyun	bl	load_fp_state
3120*4882a593Smuzhiyun#ifdef CONFIG_ALTIVEC
3121*4882a593SmuzhiyunBEGIN_FTR_SECTION
3122*4882a593Smuzhiyun	addi	r3,r31,VCPU_VRS
3123*4882a593Smuzhiyun	bl	load_vr_state
3124*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
3125*4882a593Smuzhiyun#endif
3126*4882a593Smuzhiyun	lwz	r7,VCPU_VRSAVE(r31)
3127*4882a593Smuzhiyun	mtspr	SPRN_VRSAVE,r7
3128*4882a593Smuzhiyun	mtlr	r30
3129*4882a593Smuzhiyun	mr	r4,r31
3130*4882a593Smuzhiyun	blr
3131*4882a593Smuzhiyun
3132*4882a593Smuzhiyun#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
3133*4882a593Smuzhiyun/*
3134*4882a593Smuzhiyun * Save transactional state and TM-related registers.
3135*4882a593Smuzhiyun * Called with r3 pointing to the vcpu struct and r4 containing
3136*4882a593Smuzhiyun * the guest MSR value.
3137*4882a593Smuzhiyun * r5 is non-zero iff non-volatile register state needs to be maintained.
3138*4882a593Smuzhiyun * If r5 == 0, this can modify all checkpointed registers, but
3139*4882a593Smuzhiyun * restores r1 and r2 before exit.
3140*4882a593Smuzhiyun */
3141*4882a593Smuzhiyun_GLOBAL_TOC(kvmppc_save_tm_hv)
3142*4882a593SmuzhiyunEXPORT_SYMBOL_GPL(kvmppc_save_tm_hv)
3143*4882a593Smuzhiyun	/* See if we need to handle fake suspend mode */
3144*4882a593SmuzhiyunBEGIN_FTR_SECTION
3145*4882a593Smuzhiyun	b	__kvmppc_save_tm
3146*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_P9_TM_HV_ASSIST)
3147*4882a593Smuzhiyun
3148*4882a593Smuzhiyun	lbz	r0, HSTATE_FAKE_SUSPEND(r13) /* Were we fake suspended? */
3149*4882a593Smuzhiyun	cmpwi	r0, 0
3150*4882a593Smuzhiyun	beq	__kvmppc_save_tm
3151*4882a593Smuzhiyun
3152*4882a593Smuzhiyun	/* The following code handles the fake_suspend = 1 case */
3153*4882a593Smuzhiyun	mflr	r0
3154*4882a593Smuzhiyun	std	r0, PPC_LR_STKOFF(r1)
3155*4882a593Smuzhiyun	stdu	r1, -TM_FRAME_SIZE(r1)
3156*4882a593Smuzhiyun
3157*4882a593Smuzhiyun	/* Turn on TM. */
3158*4882a593Smuzhiyun	mfmsr	r8
3159*4882a593Smuzhiyun	li	r0, 1
3160*4882a593Smuzhiyun	rldimi	r8, r0, MSR_TM_LG, 63-MSR_TM_LG
3161*4882a593Smuzhiyun	mtmsrd	r8
3162*4882a593Smuzhiyun
3163*4882a593Smuzhiyun	rldicl. r8, r8, 64 - MSR_TS_S_LG, 62 /* Did we actually hrfid? */
3164*4882a593Smuzhiyun	beq	4f
3165*4882a593SmuzhiyunBEGIN_FTR_SECTION
3166*4882a593Smuzhiyun	bl	pnv_power9_force_smt4_catch
3167*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
3168*4882a593Smuzhiyun	nop
3169*4882a593Smuzhiyun
3170*4882a593Smuzhiyun	/*
3171*4882a593Smuzhiyun	 * It's possible that treclaim. may modify registers, if we have lost
3172*4882a593Smuzhiyun	 * track of fake-suspend state in the guest due to it using rfscv.
3173*4882a593Smuzhiyun	 * Save and restore registers in case this occurs.
3174*4882a593Smuzhiyun	 */
3175*4882a593Smuzhiyun	mfspr	r3, SPRN_DSCR
3176*4882a593Smuzhiyun	mfspr	r4, SPRN_XER
3177*4882a593Smuzhiyun	mfspr	r5, SPRN_AMR
3178*4882a593Smuzhiyun	/* SPRN_TAR would need to be saved here if the kernel ever used it */
3179*4882a593Smuzhiyun	mfcr	r12
3180*4882a593Smuzhiyun	SAVE_NVGPRS(r1)
3181*4882a593Smuzhiyun	SAVE_GPR(2, r1)
3182*4882a593Smuzhiyun	SAVE_GPR(3, r1)
3183*4882a593Smuzhiyun	SAVE_GPR(4, r1)
3184*4882a593Smuzhiyun	SAVE_GPR(5, r1)
3185*4882a593Smuzhiyun	stw	r12, 8(r1)
3186*4882a593Smuzhiyun	std	r1, HSTATE_HOST_R1(r13)
3187*4882a593Smuzhiyun
3188*4882a593Smuzhiyun	/* We have to treclaim here because that's the only way to do S->N */
3189*4882a593Smuzhiyun	li	r3, TM_CAUSE_KVM_RESCHED
3190*4882a593Smuzhiyun	TRECLAIM(R3)
3191*4882a593Smuzhiyun
3192*4882a593Smuzhiyun	GET_PACA(r13)
3193*4882a593Smuzhiyun	ld	r1, HSTATE_HOST_R1(r13)
3194*4882a593Smuzhiyun	REST_GPR(2, r1)
3195*4882a593Smuzhiyun	REST_GPR(3, r1)
3196*4882a593Smuzhiyun	REST_GPR(4, r1)
3197*4882a593Smuzhiyun	REST_GPR(5, r1)
3198*4882a593Smuzhiyun	lwz	r12, 8(r1)
3199*4882a593Smuzhiyun	REST_NVGPRS(r1)
3200*4882a593Smuzhiyun	mtspr	SPRN_DSCR, r3
3201*4882a593Smuzhiyun	mtspr	SPRN_XER, r4
3202*4882a593Smuzhiyun	mtspr	SPRN_AMR, r5
3203*4882a593Smuzhiyun	mtcr	r12
3204*4882a593Smuzhiyun	HMT_MEDIUM
3205*4882a593Smuzhiyun
3206*4882a593Smuzhiyun	/*
3207*4882a593Smuzhiyun	 * We were in fake suspend, so we are not going to save the
3208*4882a593Smuzhiyun	 * register state as the guest checkpointed state (since
3209*4882a593Smuzhiyun	 * we already have it), therefore we can now use any volatile GPR.
3210*4882a593Smuzhiyun	 * In fact treclaim in fake suspend state doesn't modify
3211*4882a593Smuzhiyun	 * any registers.
3212*4882a593Smuzhiyun	 */
3213*4882a593Smuzhiyun
3214*4882a593SmuzhiyunBEGIN_FTR_SECTION
3215*4882a593Smuzhiyun	bl	pnv_power9_force_smt4_release
3216*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
3217*4882a593Smuzhiyun	nop
3218*4882a593Smuzhiyun
3219*4882a593Smuzhiyun4:
3220*4882a593Smuzhiyun	mfspr	r3, SPRN_PSSCR
3221*4882a593Smuzhiyun	/* PSSCR_FAKE_SUSPEND is a write-only bit, but clear it anyway */
3222*4882a593Smuzhiyun	li	r0, PSSCR_FAKE_SUSPEND
3223*4882a593Smuzhiyun	andc	r3, r3, r0
3224*4882a593Smuzhiyun	mtspr	SPRN_PSSCR, r3
3225*4882a593Smuzhiyun
3226*4882a593Smuzhiyun	/* Don't save TEXASR, use value from last exit in real suspend state */
3227*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
3228*4882a593Smuzhiyun	mfspr	r5, SPRN_TFHAR
3229*4882a593Smuzhiyun	mfspr	r6, SPRN_TFIAR
3230*4882a593Smuzhiyun	std	r5, VCPU_TFHAR(r9)
3231*4882a593Smuzhiyun	std	r6, VCPU_TFIAR(r9)
3232*4882a593Smuzhiyun
3233*4882a593Smuzhiyun	addi	r1, r1, TM_FRAME_SIZE
3234*4882a593Smuzhiyun	ld	r0, PPC_LR_STKOFF(r1)
3235*4882a593Smuzhiyun	mtlr	r0
3236*4882a593Smuzhiyun	blr
3237*4882a593Smuzhiyun
3238*4882a593Smuzhiyun/*
3239*4882a593Smuzhiyun * Restore transactional state and TM-related registers.
3240*4882a593Smuzhiyun * Called with r3 pointing to the vcpu struct
3241*4882a593Smuzhiyun * and r4 containing the guest MSR value.
3242*4882a593Smuzhiyun * r5 is non-zero iff non-volatile register state needs to be maintained.
3243*4882a593Smuzhiyun * This potentially modifies all checkpointed registers.
3244*4882a593Smuzhiyun * It restores r1 and r2 from the PACA.
3245*4882a593Smuzhiyun */
3246*4882a593Smuzhiyun_GLOBAL_TOC(kvmppc_restore_tm_hv)
3247*4882a593SmuzhiyunEXPORT_SYMBOL_GPL(kvmppc_restore_tm_hv)
3248*4882a593Smuzhiyun	/*
3249*4882a593Smuzhiyun	 * If we are doing TM emulation for the guest on a POWER9 DD2,
3250*4882a593Smuzhiyun	 * then we don't actually do a trechkpt -- we either set up
3251*4882a593Smuzhiyun	 * fake-suspend mode, or emulate a TM rollback.
3252*4882a593Smuzhiyun	 */
3253*4882a593SmuzhiyunBEGIN_FTR_SECTION
3254*4882a593Smuzhiyun	b	__kvmppc_restore_tm
3255*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_P9_TM_HV_ASSIST)
3256*4882a593Smuzhiyun	mflr	r0
3257*4882a593Smuzhiyun	std	r0, PPC_LR_STKOFF(r1)
3258*4882a593Smuzhiyun
3259*4882a593Smuzhiyun	li	r0, 0
3260*4882a593Smuzhiyun	stb	r0, HSTATE_FAKE_SUSPEND(r13)
3261*4882a593Smuzhiyun
3262*4882a593Smuzhiyun	/* Turn on TM so we can restore TM SPRs */
3263*4882a593Smuzhiyun	mfmsr	r5
3264*4882a593Smuzhiyun	li	r0, 1
3265*4882a593Smuzhiyun	rldimi	r5, r0, MSR_TM_LG, 63-MSR_TM_LG
3266*4882a593Smuzhiyun	mtmsrd	r5
3267*4882a593Smuzhiyun
3268*4882a593Smuzhiyun	/*
3269*4882a593Smuzhiyun	 * The user may change these outside of a transaction, so they must
3270*4882a593Smuzhiyun	 * always be context switched.
3271*4882a593Smuzhiyun	 */
3272*4882a593Smuzhiyun	ld	r5, VCPU_TFHAR(r3)
3273*4882a593Smuzhiyun	ld	r6, VCPU_TFIAR(r3)
3274*4882a593Smuzhiyun	ld	r7, VCPU_TEXASR(r3)
3275*4882a593Smuzhiyun	mtspr	SPRN_TFHAR, r5
3276*4882a593Smuzhiyun	mtspr	SPRN_TFIAR, r6
3277*4882a593Smuzhiyun	mtspr	SPRN_TEXASR, r7
3278*4882a593Smuzhiyun
3279*4882a593Smuzhiyun	rldicl. r5, r4, 64 - MSR_TS_S_LG, 62
3280*4882a593Smuzhiyun	beqlr		/* TM not active in guest */
3281*4882a593Smuzhiyun
3282*4882a593Smuzhiyun	/* Make sure the failure summary is set */
3283*4882a593Smuzhiyun	oris	r7, r7, (TEXASR_FS)@h
3284*4882a593Smuzhiyun	mtspr	SPRN_TEXASR, r7
3285*4882a593Smuzhiyun
3286*4882a593Smuzhiyun	cmpwi	r5, 1		/* check for suspended state */
3287*4882a593Smuzhiyun	bgt	10f
3288*4882a593Smuzhiyun	stb	r5, HSTATE_FAKE_SUSPEND(r13)
3289*4882a593Smuzhiyun	b	9f		/* and return */
3290*4882a593Smuzhiyun10:	stdu	r1, -PPC_MIN_STKFRM(r1)
3291*4882a593Smuzhiyun	/* guest is in transactional state, so simulate rollback */
3292*4882a593Smuzhiyun	bl	kvmhv_emulate_tm_rollback
3293*4882a593Smuzhiyun	nop
3294*4882a593Smuzhiyun	addi	r1, r1, PPC_MIN_STKFRM
3295*4882a593Smuzhiyun9:	ld	r0, PPC_LR_STKOFF(r1)
3296*4882a593Smuzhiyun	mtlr	r0
3297*4882a593Smuzhiyun	blr
3298*4882a593Smuzhiyun#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
3299*4882a593Smuzhiyun
3300*4882a593Smuzhiyun/*
3301*4882a593Smuzhiyun * We come here if we get any exception or interrupt while we are
3302*4882a593Smuzhiyun * executing host real mode code while in guest MMU context.
3303*4882a593Smuzhiyun * r12 is (CR << 32) | vector
3304*4882a593Smuzhiyun * r13 points to our PACA
3305*4882a593Smuzhiyun * r12 is saved in HSTATE_SCRATCH0(r13)
3306*4882a593Smuzhiyun * r9 is saved in HSTATE_SCRATCH2(r13)
3307*4882a593Smuzhiyun * r13 is saved in HSPRG1
3308*4882a593Smuzhiyun * cfar is saved in HSTATE_CFAR(r13)
3309*4882a593Smuzhiyun * ppr is saved in HSTATE_PPR(r13)
3310*4882a593Smuzhiyun */
3311*4882a593Smuzhiyunkvmppc_bad_host_intr:
3312*4882a593Smuzhiyun	/*
3313*4882a593Smuzhiyun	 * Switch to the emergency stack, but start half-way down in
3314*4882a593Smuzhiyun	 * case we were already on it.
3315*4882a593Smuzhiyun	 */
3316*4882a593Smuzhiyun	mr	r9, r1
3317*4882a593Smuzhiyun	std	r1, PACAR1(r13)
3318*4882a593Smuzhiyun	ld	r1, PACAEMERGSP(r13)
3319*4882a593Smuzhiyun	subi	r1, r1, THREAD_SIZE/2 + INT_FRAME_SIZE
3320*4882a593Smuzhiyun	std	r9, 0(r1)
3321*4882a593Smuzhiyun	std	r0, GPR0(r1)
3322*4882a593Smuzhiyun	std	r9, GPR1(r1)
3323*4882a593Smuzhiyun	std	r2, GPR2(r1)
3324*4882a593Smuzhiyun	SAVE_4GPRS(3, r1)
3325*4882a593Smuzhiyun	SAVE_2GPRS(7, r1)
3326*4882a593Smuzhiyun	srdi	r0, r12, 32
3327*4882a593Smuzhiyun	clrldi	r12, r12, 32
3328*4882a593Smuzhiyun	std	r0, _CCR(r1)
3329*4882a593Smuzhiyun	std	r12, _TRAP(r1)
3330*4882a593Smuzhiyun	andi.	r0, r12, 2
3331*4882a593Smuzhiyun	beq	1f
3332*4882a593Smuzhiyun	mfspr	r3, SPRN_HSRR0
3333*4882a593Smuzhiyun	mfspr	r4, SPRN_HSRR1
3334*4882a593Smuzhiyun	mfspr	r5, SPRN_HDAR
3335*4882a593Smuzhiyun	mfspr	r6, SPRN_HDSISR
3336*4882a593Smuzhiyun	b	2f
3337*4882a593Smuzhiyun1:	mfspr	r3, SPRN_SRR0
3338*4882a593Smuzhiyun	mfspr	r4, SPRN_SRR1
3339*4882a593Smuzhiyun	mfspr	r5, SPRN_DAR
3340*4882a593Smuzhiyun	mfspr	r6, SPRN_DSISR
3341*4882a593Smuzhiyun2:	std	r3, _NIP(r1)
3342*4882a593Smuzhiyun	std	r4, _MSR(r1)
3343*4882a593Smuzhiyun	std	r5, _DAR(r1)
3344*4882a593Smuzhiyun	std	r6, _DSISR(r1)
3345*4882a593Smuzhiyun	ld	r9, HSTATE_SCRATCH2(r13)
3346*4882a593Smuzhiyun	ld	r12, HSTATE_SCRATCH0(r13)
3347*4882a593Smuzhiyun	GET_SCRATCH0(r0)
3348*4882a593Smuzhiyun	SAVE_4GPRS(9, r1)
3349*4882a593Smuzhiyun	std	r0, GPR13(r1)
3350*4882a593Smuzhiyun	SAVE_NVGPRS(r1)
3351*4882a593Smuzhiyun	ld	r5, HSTATE_CFAR(r13)
3352*4882a593Smuzhiyun	std	r5, ORIG_GPR3(r1)
3353*4882a593Smuzhiyun	mflr	r3
3354*4882a593Smuzhiyun	mfctr	r4
3355*4882a593Smuzhiyun	mfxer	r5
3356*4882a593Smuzhiyun	lbz	r6, PACAIRQSOFTMASK(r13)
3357*4882a593Smuzhiyun	std	r3, _LINK(r1)
3358*4882a593Smuzhiyun	std	r4, _CTR(r1)
3359*4882a593Smuzhiyun	std	r5, _XER(r1)
3360*4882a593Smuzhiyun	std	r6, SOFTE(r1)
3361*4882a593Smuzhiyun	ld	r2, PACATOC(r13)
3362*4882a593Smuzhiyun	LOAD_REG_IMMEDIATE(3, 0x7265677368657265)
3363*4882a593Smuzhiyun	std	r3, STACK_FRAME_OVERHEAD-16(r1)
3364*4882a593Smuzhiyun
3365*4882a593Smuzhiyun	/*
3366*4882a593Smuzhiyun	 * On POWER9 do a minimal restore of the MMU and call C code,
3367*4882a593Smuzhiyun	 * which will print a message and panic.
3368*4882a593Smuzhiyun	 * XXX On POWER7 and POWER8, we just spin here since we don't
3369*4882a593Smuzhiyun	 * know what the other threads are doing (and we don't want to
3370*4882a593Smuzhiyun	 * coordinate with them) - but at least we now have register state
3371*4882a593Smuzhiyun	 * in memory that we might be able to look at from another CPU.
3372*4882a593Smuzhiyun	 */
3373*4882a593SmuzhiyunBEGIN_FTR_SECTION
3374*4882a593Smuzhiyun	b	.
3375*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
3376*4882a593Smuzhiyun	ld	r9, HSTATE_KVM_VCPU(r13)
3377*4882a593Smuzhiyun	ld	r10, VCPU_KVM(r9)
3378*4882a593Smuzhiyun
3379*4882a593Smuzhiyun	li	r0, 0
3380*4882a593Smuzhiyun	mtspr	SPRN_AMR, r0
3381*4882a593Smuzhiyun	mtspr	SPRN_IAMR, r0
3382*4882a593Smuzhiyun	mtspr	SPRN_CIABR, r0
3383*4882a593Smuzhiyun	mtspr	SPRN_DAWRX0, r0
3384*4882a593Smuzhiyun
3385*4882a593SmuzhiyunBEGIN_MMU_FTR_SECTION
3386*4882a593Smuzhiyun	b	4f
3387*4882a593SmuzhiyunEND_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
3388*4882a593Smuzhiyun
3389*4882a593Smuzhiyun	slbmte	r0, r0
3390*4882a593Smuzhiyun	slbia
3391*4882a593Smuzhiyun	ptesync
3392*4882a593Smuzhiyun	ld	r8, PACA_SLBSHADOWPTR(r13)
3393*4882a593Smuzhiyun	.rept	SLB_NUM_BOLTED
3394*4882a593Smuzhiyun	li	r3, SLBSHADOW_SAVEAREA
3395*4882a593Smuzhiyun	LDX_BE	r5, r8, r3
3396*4882a593Smuzhiyun	addi	r3, r3, 8
3397*4882a593Smuzhiyun	LDX_BE	r6, r8, r3
3398*4882a593Smuzhiyun	andis.	r7, r5, SLB_ESID_V@h
3399*4882a593Smuzhiyun	beq	3f
3400*4882a593Smuzhiyun	slbmte	r6, r5
3401*4882a593Smuzhiyun3:	addi	r8, r8, 16
3402*4882a593Smuzhiyun	.endr
3403*4882a593Smuzhiyun
3404*4882a593Smuzhiyun4:	lwz	r7, KVM_HOST_LPID(r10)
3405*4882a593Smuzhiyun	mtspr	SPRN_LPID, r7
3406*4882a593Smuzhiyun	mtspr	SPRN_PID, r0
3407*4882a593Smuzhiyun	ld	r8, KVM_HOST_LPCR(r10)
3408*4882a593Smuzhiyun	mtspr	SPRN_LPCR, r8
3409*4882a593Smuzhiyun	isync
3410*4882a593Smuzhiyun	li	r0, KVM_GUEST_MODE_NONE
3411*4882a593Smuzhiyun	stb	r0, HSTATE_IN_GUEST(r13)
3412*4882a593Smuzhiyun
3413*4882a593Smuzhiyun	/*
3414*4882a593Smuzhiyun	 * Turn on the MMU and jump to C code
3415*4882a593Smuzhiyun	 */
3416*4882a593Smuzhiyun	bcl	20, 31, .+4
3417*4882a593Smuzhiyun5:	mflr	r3
3418*4882a593Smuzhiyun	addi	r3, r3, 9f - 5b
3419*4882a593Smuzhiyun	li	r4, -1
3420*4882a593Smuzhiyun	rldimi	r3, r4, 62, 0	/* ensure 0xc000000000000000 bits are set */
3421*4882a593Smuzhiyun	ld	r4, PACAKMSR(r13)
3422*4882a593Smuzhiyun	mtspr	SPRN_SRR0, r3
3423*4882a593Smuzhiyun	mtspr	SPRN_SRR1, r4
3424*4882a593Smuzhiyun	RFI_TO_KERNEL
3425*4882a593Smuzhiyun9:	addi	r3, r1, STACK_FRAME_OVERHEAD
3426*4882a593Smuzhiyun	bl	kvmppc_bad_interrupt
3427*4882a593Smuzhiyun	b	9b
3428*4882a593Smuzhiyun
3429*4882a593Smuzhiyun/*
3430*4882a593Smuzhiyun * This mimics the MSR transition on IRQ delivery.  The new guest MSR is taken
3431*4882a593Smuzhiyun * from VCPU_INTR_MSR and is modified based on the required TM state changes.
3432*4882a593Smuzhiyun *   r11 has the guest MSR value (in/out)
3433*4882a593Smuzhiyun *   r9 has a vcpu pointer (in)
3434*4882a593Smuzhiyun *   r0 is used as a scratch register
3435*4882a593Smuzhiyun */
3436*4882a593Smuzhiyunkvmppc_msr_interrupt:
3437*4882a593Smuzhiyun	rldicl	r0, r11, 64 - MSR_TS_S_LG, 62
3438*4882a593Smuzhiyun	cmpwi	r0, 2 /* Check if we are in transactional state..  */
3439*4882a593Smuzhiyun	ld	r11, VCPU_INTR_MSR(r9)
3440*4882a593Smuzhiyun	bne	1f
3441*4882a593Smuzhiyun	/* ... if transactional, change to suspended */
3442*4882a593Smuzhiyun	li	r0, 1
3443*4882a593Smuzhiyun1:	rldimi	r11, r0, MSR_TS_S_LG, 63 - MSR_TS_T_LG
3444*4882a593Smuzhiyun	blr
3445*4882a593Smuzhiyun
3446*4882a593Smuzhiyun/*
3447*4882a593Smuzhiyun * Load up guest PMU state.  R3 points to the vcpu struct.
3448*4882a593Smuzhiyun */
3449*4882a593Smuzhiyun_GLOBAL(kvmhv_load_guest_pmu)
3450*4882a593SmuzhiyunEXPORT_SYMBOL_GPL(kvmhv_load_guest_pmu)
3451*4882a593Smuzhiyun	mr	r4, r3
3452*4882a593Smuzhiyun	mflr	r0
3453*4882a593Smuzhiyun	li	r3, 1
3454*4882a593Smuzhiyun	sldi	r3, r3, 31		/* MMCR0_FC (freeze counters) bit */
3455*4882a593Smuzhiyun	mtspr	SPRN_MMCR0, r3		/* freeze all counters, disable ints */
3456*4882a593Smuzhiyun	isync
3457*4882a593SmuzhiyunBEGIN_FTR_SECTION
3458*4882a593Smuzhiyun	ld	r3, VCPU_MMCR(r4)
3459*4882a593Smuzhiyun	andi.	r5, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO
3460*4882a593Smuzhiyun	cmpwi	r5, MMCR0_PMAO
3461*4882a593Smuzhiyun	beql	kvmppc_fix_pmao
3462*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG)
3463*4882a593Smuzhiyun	lwz	r3, VCPU_PMC(r4)	/* always load up guest PMU registers */
3464*4882a593Smuzhiyun	lwz	r5, VCPU_PMC + 4(r4)	/* to prevent information leak */
3465*4882a593Smuzhiyun	lwz	r6, VCPU_PMC + 8(r4)
3466*4882a593Smuzhiyun	lwz	r7, VCPU_PMC + 12(r4)
3467*4882a593Smuzhiyun	lwz	r8, VCPU_PMC + 16(r4)
3468*4882a593Smuzhiyun	lwz	r9, VCPU_PMC + 20(r4)
3469*4882a593Smuzhiyun	mtspr	SPRN_PMC1, r3
3470*4882a593Smuzhiyun	mtspr	SPRN_PMC2, r5
3471*4882a593Smuzhiyun	mtspr	SPRN_PMC3, r6
3472*4882a593Smuzhiyun	mtspr	SPRN_PMC4, r7
3473*4882a593Smuzhiyun	mtspr	SPRN_PMC5, r8
3474*4882a593Smuzhiyun	mtspr	SPRN_PMC6, r9
3475*4882a593Smuzhiyun	ld	r3, VCPU_MMCR(r4)
3476*4882a593Smuzhiyun	ld	r5, VCPU_MMCR + 8(r4)
3477*4882a593Smuzhiyun	ld	r6, VCPU_MMCRA(r4)
3478*4882a593Smuzhiyun	ld	r7, VCPU_SIAR(r4)
3479*4882a593Smuzhiyun	ld	r8, VCPU_SDAR(r4)
3480*4882a593Smuzhiyun	mtspr	SPRN_MMCR1, r5
3481*4882a593Smuzhiyun	mtspr	SPRN_MMCRA, r6
3482*4882a593Smuzhiyun	mtspr	SPRN_SIAR, r7
3483*4882a593Smuzhiyun	mtspr	SPRN_SDAR, r8
3484*4882a593SmuzhiyunBEGIN_FTR_SECTION
3485*4882a593Smuzhiyun	ld      r5, VCPU_MMCR + 24(r4)
3486*4882a593Smuzhiyun	ld      r6, VCPU_SIER + 8(r4)
3487*4882a593Smuzhiyun	ld      r7, VCPU_SIER + 16(r4)
3488*4882a593Smuzhiyun	mtspr   SPRN_MMCR3, r5
3489*4882a593Smuzhiyun	mtspr   SPRN_SIER2, r6
3490*4882a593Smuzhiyun	mtspr   SPRN_SIER3, r7
3491*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_31)
3492*4882a593SmuzhiyunBEGIN_FTR_SECTION
3493*4882a593Smuzhiyun	ld	r5, VCPU_MMCR + 16(r4)
3494*4882a593Smuzhiyun	ld	r6, VCPU_SIER(r4)
3495*4882a593Smuzhiyun	mtspr	SPRN_MMCR2, r5
3496*4882a593Smuzhiyun	mtspr	SPRN_SIER, r6
3497*4882a593SmuzhiyunBEGIN_FTR_SECTION_NESTED(96)
3498*4882a593Smuzhiyun	lwz	r7, VCPU_PMC + 24(r4)
3499*4882a593Smuzhiyun	lwz	r8, VCPU_PMC + 28(r4)
3500*4882a593Smuzhiyun	ld	r9, VCPU_MMCRS(r4)
3501*4882a593Smuzhiyun	mtspr	SPRN_SPMC1, r7
3502*4882a593Smuzhiyun	mtspr	SPRN_SPMC2, r8
3503*4882a593Smuzhiyun	mtspr	SPRN_MMCRS, r9
3504*4882a593SmuzhiyunEND_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96)
3505*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
3506*4882a593Smuzhiyun	mtspr	SPRN_MMCR0, r3
3507*4882a593Smuzhiyun	isync
3508*4882a593Smuzhiyun	mtlr	r0
3509*4882a593Smuzhiyun	blr
3510*4882a593Smuzhiyun
3511*4882a593Smuzhiyun/*
3512*4882a593Smuzhiyun * Reload host PMU state saved in the PACA by kvmhv_save_host_pmu.
3513*4882a593Smuzhiyun */
3514*4882a593Smuzhiyun_GLOBAL(kvmhv_load_host_pmu)
3515*4882a593SmuzhiyunEXPORT_SYMBOL_GPL(kvmhv_load_host_pmu)
3516*4882a593Smuzhiyun	mflr	r0
3517*4882a593Smuzhiyun	lbz	r4, PACA_PMCINUSE(r13) /* is the host using the PMU? */
3518*4882a593Smuzhiyun	cmpwi	r4, 0
3519*4882a593Smuzhiyun	beq	23f			/* skip if not */
3520*4882a593SmuzhiyunBEGIN_FTR_SECTION
3521*4882a593Smuzhiyun	ld	r3, HSTATE_MMCR0(r13)
3522*4882a593Smuzhiyun	andi.	r4, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO
3523*4882a593Smuzhiyun	cmpwi	r4, MMCR0_PMAO
3524*4882a593Smuzhiyun	beql	kvmppc_fix_pmao
3525*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG)
3526*4882a593Smuzhiyun	lwz	r3, HSTATE_PMC1(r13)
3527*4882a593Smuzhiyun	lwz	r4, HSTATE_PMC2(r13)
3528*4882a593Smuzhiyun	lwz	r5, HSTATE_PMC3(r13)
3529*4882a593Smuzhiyun	lwz	r6, HSTATE_PMC4(r13)
3530*4882a593Smuzhiyun	lwz	r8, HSTATE_PMC5(r13)
3531*4882a593Smuzhiyun	lwz	r9, HSTATE_PMC6(r13)
3532*4882a593Smuzhiyun	mtspr	SPRN_PMC1, r3
3533*4882a593Smuzhiyun	mtspr	SPRN_PMC2, r4
3534*4882a593Smuzhiyun	mtspr	SPRN_PMC3, r5
3535*4882a593Smuzhiyun	mtspr	SPRN_PMC4, r6
3536*4882a593Smuzhiyun	mtspr	SPRN_PMC5, r8
3537*4882a593Smuzhiyun	mtspr	SPRN_PMC6, r9
3538*4882a593Smuzhiyun	ld	r3, HSTATE_MMCR0(r13)
3539*4882a593Smuzhiyun	ld	r4, HSTATE_MMCR1(r13)
3540*4882a593Smuzhiyun	ld	r5, HSTATE_MMCRA(r13)
3541*4882a593Smuzhiyun	ld	r6, HSTATE_SIAR(r13)
3542*4882a593Smuzhiyun	ld	r7, HSTATE_SDAR(r13)
3543*4882a593Smuzhiyun	mtspr	SPRN_MMCR1, r4
3544*4882a593Smuzhiyun	mtspr	SPRN_MMCRA, r5
3545*4882a593Smuzhiyun	mtspr	SPRN_SIAR, r6
3546*4882a593Smuzhiyun	mtspr	SPRN_SDAR, r7
3547*4882a593SmuzhiyunBEGIN_FTR_SECTION
3548*4882a593Smuzhiyun	ld	r8, HSTATE_MMCR2(r13)
3549*4882a593Smuzhiyun	ld	r9, HSTATE_SIER(r13)
3550*4882a593Smuzhiyun	mtspr	SPRN_MMCR2, r8
3551*4882a593Smuzhiyun	mtspr	SPRN_SIER, r9
3552*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
3553*4882a593SmuzhiyunBEGIN_FTR_SECTION
3554*4882a593Smuzhiyun	ld      r5, HSTATE_MMCR3(r13)
3555*4882a593Smuzhiyun	ld      r6, HSTATE_SIER2(r13)
3556*4882a593Smuzhiyun	ld      r7, HSTATE_SIER3(r13)
3557*4882a593Smuzhiyun	mtspr   SPRN_MMCR3, r5
3558*4882a593Smuzhiyun	mtspr   SPRN_SIER2, r6
3559*4882a593Smuzhiyun	mtspr   SPRN_SIER3, r7
3560*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_31)
3561*4882a593Smuzhiyun	mtspr	SPRN_MMCR0, r3
3562*4882a593Smuzhiyun	isync
3563*4882a593Smuzhiyun	mtlr	r0
3564*4882a593Smuzhiyun23:	blr
3565*4882a593Smuzhiyun
3566*4882a593Smuzhiyun/*
3567*4882a593Smuzhiyun * Save guest PMU state into the vcpu struct.
3568*4882a593Smuzhiyun * r3 = vcpu, r4 = full save flag (PMU in use flag set in VPA)
3569*4882a593Smuzhiyun */
3570*4882a593Smuzhiyun_GLOBAL(kvmhv_save_guest_pmu)
3571*4882a593SmuzhiyunEXPORT_SYMBOL_GPL(kvmhv_save_guest_pmu)
3572*4882a593Smuzhiyun	mr	r9, r3
3573*4882a593Smuzhiyun	mr	r8, r4
3574*4882a593SmuzhiyunBEGIN_FTR_SECTION
3575*4882a593Smuzhiyun	/*
3576*4882a593Smuzhiyun	 * POWER8 seems to have a hardware bug where setting
3577*4882a593Smuzhiyun	 * MMCR0[PMAE] along with MMCR0[PMC1CE] and/or MMCR0[PMCjCE]
3578*4882a593Smuzhiyun	 * when some counters are already negative doesn't seem
3579*4882a593Smuzhiyun	 * to cause a performance monitor alert (and hence interrupt).
3580*4882a593Smuzhiyun	 * The effect of this is that when saving the PMU state,
3581*4882a593Smuzhiyun	 * if there is no PMU alert pending when we read MMCR0
3582*4882a593Smuzhiyun	 * before freezing the counters, but one becomes pending
3583*4882a593Smuzhiyun	 * before we read the counters, we lose it.
3584*4882a593Smuzhiyun	 * To work around this, we need a way to freeze the counters
3585*4882a593Smuzhiyun	 * before reading MMCR0.  Normally, freezing the counters
3586*4882a593Smuzhiyun	 * is done by writing MMCR0 (to set MMCR0[FC]) which
3587*4882a593Smuzhiyun	 * unavoidably writes MMCR0[PMA0] as well.  On POWER8,
3588*4882a593Smuzhiyun	 * we can also freeze the counters using MMCR2, by writing
3589*4882a593Smuzhiyun	 * 1s to all the counter freeze condition bits (there are
3590*4882a593Smuzhiyun	 * 9 bits each for 6 counters).
3591*4882a593Smuzhiyun	 */
3592*4882a593Smuzhiyun	li	r3, -1			/* set all freeze bits */
3593*4882a593Smuzhiyun	clrrdi	r3, r3, 10
3594*4882a593Smuzhiyun	mfspr	r10, SPRN_MMCR2
3595*4882a593Smuzhiyun	mtspr	SPRN_MMCR2, r3
3596*4882a593Smuzhiyun	isync
3597*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
3598*4882a593Smuzhiyun	li	r3, 1
3599*4882a593Smuzhiyun	sldi	r3, r3, 31		/* MMCR0_FC (freeze counters) bit */
3600*4882a593Smuzhiyun	mfspr	r4, SPRN_MMCR0		/* save MMCR0 */
3601*4882a593Smuzhiyun	mtspr	SPRN_MMCR0, r3		/* freeze all counters, disable ints */
3602*4882a593Smuzhiyun	mfspr	r6, SPRN_MMCRA
3603*4882a593Smuzhiyun	/* Clear MMCRA in order to disable SDAR updates */
3604*4882a593Smuzhiyun	li	r7, 0
3605*4882a593Smuzhiyun	mtspr	SPRN_MMCRA, r7
3606*4882a593Smuzhiyun	isync
3607*4882a593Smuzhiyun	cmpwi	r8, 0			/* did they ask for PMU stuff to be saved? */
3608*4882a593Smuzhiyun	bne	21f
3609*4882a593Smuzhiyun	std	r3, VCPU_MMCR(r9)	/* if not, set saved MMCR0 to FC */
3610*4882a593Smuzhiyun	b	22f
3611*4882a593Smuzhiyun21:	mfspr	r5, SPRN_MMCR1
3612*4882a593Smuzhiyun	mfspr	r7, SPRN_SIAR
3613*4882a593Smuzhiyun	mfspr	r8, SPRN_SDAR
3614*4882a593Smuzhiyun	std	r4, VCPU_MMCR(r9)
3615*4882a593Smuzhiyun	std	r5, VCPU_MMCR + 8(r9)
3616*4882a593Smuzhiyun	std	r6, VCPU_MMCRA(r9)
3617*4882a593SmuzhiyunBEGIN_FTR_SECTION
3618*4882a593Smuzhiyun	std	r10, VCPU_MMCR + 16(r9)
3619*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
3620*4882a593SmuzhiyunBEGIN_FTR_SECTION
3621*4882a593Smuzhiyun	mfspr   r5, SPRN_MMCR3
3622*4882a593Smuzhiyun	mfspr   r6, SPRN_SIER2
3623*4882a593Smuzhiyun	mfspr   r7, SPRN_SIER3
3624*4882a593Smuzhiyun	std     r5, VCPU_MMCR + 24(r9)
3625*4882a593Smuzhiyun	std     r6, VCPU_SIER + 8(r9)
3626*4882a593Smuzhiyun	std     r7, VCPU_SIER + 16(r9)
3627*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_31)
3628*4882a593Smuzhiyun	std	r7, VCPU_SIAR(r9)
3629*4882a593Smuzhiyun	std	r8, VCPU_SDAR(r9)
3630*4882a593Smuzhiyun	mfspr	r3, SPRN_PMC1
3631*4882a593Smuzhiyun	mfspr	r4, SPRN_PMC2
3632*4882a593Smuzhiyun	mfspr	r5, SPRN_PMC3
3633*4882a593Smuzhiyun	mfspr	r6, SPRN_PMC4
3634*4882a593Smuzhiyun	mfspr	r7, SPRN_PMC5
3635*4882a593Smuzhiyun	mfspr	r8, SPRN_PMC6
3636*4882a593Smuzhiyun	stw	r3, VCPU_PMC(r9)
3637*4882a593Smuzhiyun	stw	r4, VCPU_PMC + 4(r9)
3638*4882a593Smuzhiyun	stw	r5, VCPU_PMC + 8(r9)
3639*4882a593Smuzhiyun	stw	r6, VCPU_PMC + 12(r9)
3640*4882a593Smuzhiyun	stw	r7, VCPU_PMC + 16(r9)
3641*4882a593Smuzhiyun	stw	r8, VCPU_PMC + 20(r9)
3642*4882a593SmuzhiyunBEGIN_FTR_SECTION
3643*4882a593Smuzhiyun	mfspr	r5, SPRN_SIER
3644*4882a593Smuzhiyun	std	r5, VCPU_SIER(r9)
3645*4882a593SmuzhiyunBEGIN_FTR_SECTION_NESTED(96)
3646*4882a593Smuzhiyun	mfspr	r6, SPRN_SPMC1
3647*4882a593Smuzhiyun	mfspr	r7, SPRN_SPMC2
3648*4882a593Smuzhiyun	mfspr	r8, SPRN_MMCRS
3649*4882a593Smuzhiyun	stw	r6, VCPU_PMC + 24(r9)
3650*4882a593Smuzhiyun	stw	r7, VCPU_PMC + 28(r9)
3651*4882a593Smuzhiyun	std	r8, VCPU_MMCRS(r9)
3652*4882a593Smuzhiyun	lis	r4, 0x8000
3653*4882a593Smuzhiyun	mtspr	SPRN_MMCRS, r4
3654*4882a593SmuzhiyunEND_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96)
3655*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
3656*4882a593Smuzhiyun22:	blr
3657*4882a593Smuzhiyun
3658*4882a593Smuzhiyun/*
3659*4882a593Smuzhiyun * This works around a hardware bug on POWER8E processors, where
3660*4882a593Smuzhiyun * writing a 1 to the MMCR0[PMAO] bit doesn't generate a
3661*4882a593Smuzhiyun * performance monitor interrupt.  Instead, when we need to have
3662*4882a593Smuzhiyun * an interrupt pending, we have to arrange for a counter to overflow.
3663*4882a593Smuzhiyun */
3664*4882a593Smuzhiyunkvmppc_fix_pmao:
3665*4882a593Smuzhiyun	li	r3, 0
3666*4882a593Smuzhiyun	mtspr	SPRN_MMCR2, r3
3667*4882a593Smuzhiyun	lis	r3, (MMCR0_PMXE | MMCR0_FCECE)@h
3668*4882a593Smuzhiyun	ori	r3, r3, MMCR0_PMCjCE | MMCR0_C56RUN
3669*4882a593Smuzhiyun	mtspr	SPRN_MMCR0, r3
3670*4882a593Smuzhiyun	lis	r3, 0x7fff
3671*4882a593Smuzhiyun	ori	r3, r3, 0xffff
3672*4882a593Smuzhiyun	mtspr	SPRN_PMC6, r3
3673*4882a593Smuzhiyun	isync
3674*4882a593Smuzhiyun	blr
3675*4882a593Smuzhiyun
3676*4882a593Smuzhiyun#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
3677*4882a593Smuzhiyun/*
3678*4882a593Smuzhiyun * Start timing an activity
3679*4882a593Smuzhiyun * r3 = pointer to time accumulation struct, r4 = vcpu
3680*4882a593Smuzhiyun */
3681*4882a593Smuzhiyunkvmhv_start_timing:
3682*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
3683*4882a593Smuzhiyun	ld	r6, VCORE_TB_OFFSET_APPL(r5)
3684*4882a593Smuzhiyun	mftb	r5
3685*4882a593Smuzhiyun	subf	r5, r6, r5	/* subtract current timebase offset */
3686*4882a593Smuzhiyun	std	r3, VCPU_CUR_ACTIVITY(r4)
3687*4882a593Smuzhiyun	std	r5, VCPU_ACTIVITY_START(r4)
3688*4882a593Smuzhiyun	blr
3689*4882a593Smuzhiyun
3690*4882a593Smuzhiyun/*
3691*4882a593Smuzhiyun * Accumulate time to one activity and start another.
3692*4882a593Smuzhiyun * r3 = pointer to new time accumulation struct, r4 = vcpu
3693*4882a593Smuzhiyun */
3694*4882a593Smuzhiyunkvmhv_accumulate_time:
3695*4882a593Smuzhiyun	ld	r5, HSTATE_KVM_VCORE(r13)
3696*4882a593Smuzhiyun	ld	r8, VCORE_TB_OFFSET_APPL(r5)
3697*4882a593Smuzhiyun	ld	r5, VCPU_CUR_ACTIVITY(r4)
3698*4882a593Smuzhiyun	ld	r6, VCPU_ACTIVITY_START(r4)
3699*4882a593Smuzhiyun	std	r3, VCPU_CUR_ACTIVITY(r4)
3700*4882a593Smuzhiyun	mftb	r7
3701*4882a593Smuzhiyun	subf	r7, r8, r7	/* subtract current timebase offset */
3702*4882a593Smuzhiyun	std	r7, VCPU_ACTIVITY_START(r4)
3703*4882a593Smuzhiyun	cmpdi	r5, 0
3704*4882a593Smuzhiyun	beqlr
3705*4882a593Smuzhiyun	subf	r3, r6, r7
3706*4882a593Smuzhiyun	ld	r8, TAS_SEQCOUNT(r5)
3707*4882a593Smuzhiyun	cmpdi	r8, 0
3708*4882a593Smuzhiyun	addi	r8, r8, 1
3709*4882a593Smuzhiyun	std	r8, TAS_SEQCOUNT(r5)
3710*4882a593Smuzhiyun	lwsync
3711*4882a593Smuzhiyun	ld	r7, TAS_TOTAL(r5)
3712*4882a593Smuzhiyun	add	r7, r7, r3
3713*4882a593Smuzhiyun	std	r7, TAS_TOTAL(r5)
3714*4882a593Smuzhiyun	ld	r6, TAS_MIN(r5)
3715*4882a593Smuzhiyun	ld	r7, TAS_MAX(r5)
3716*4882a593Smuzhiyun	beq	3f
3717*4882a593Smuzhiyun	cmpd	r3, r6
3718*4882a593Smuzhiyun	bge	1f
3719*4882a593Smuzhiyun3:	std	r3, TAS_MIN(r5)
3720*4882a593Smuzhiyun1:	cmpd	r3, r7
3721*4882a593Smuzhiyun	ble	2f
3722*4882a593Smuzhiyun	std	r3, TAS_MAX(r5)
3723*4882a593Smuzhiyun2:	lwsync
3724*4882a593Smuzhiyun	addi	r8, r8, 1
3725*4882a593Smuzhiyun	std	r8, TAS_SEQCOUNT(r5)
3726*4882a593Smuzhiyun	blr
3727*4882a593Smuzhiyun#endif
3728