1f3601156SNicholas Piggin/* SPDX-License-Identifier: GPL-2.0-only */
2f3601156SNicholas Piggin#include <asm/asm-offsets.h>
3f3601156SNicholas Piggin#include <asm/cache.h>
4f33e0702SNicholas Piggin#include <asm/exception-64s.h>
5f3601156SNicholas Piggin#include <asm/kvm_asm.h>
6f3601156SNicholas Piggin#include <asm/kvm_book3s_asm.h>
7f3601156SNicholas Piggin#include <asm/ppc_asm.h>
8f3601156SNicholas Piggin#include <asm/reg.h>
9f3601156SNicholas Piggin
10f3601156SNicholas Piggin/*
1131c67cfeSNicholas Piggin * These are branched to from interrupt handlers in exception-64s.S which set
12f3601156SNicholas Piggin * IKVM_REAL or IKVM_VIRT, if HSTATE_IN_GUEST was found to be non-zero.
13f3601156SNicholas Piggin */
1431c67cfeSNicholas Piggin.global	kvmppc_hcall
1531c67cfeSNicholas Piggin.balign IFETCH_ALIGN_BYTES
1631c67cfeSNicholas Pigginkvmppc_hcall:
1704ece7b6SNicholas Piggin	/*
1804ece7b6SNicholas Piggin	 * This is a hcall, so register convention is as
1904ece7b6SNicholas Piggin	 * Documentation/powerpc/papr_hcalls.rst, with these additions:
2004ece7b6SNicholas Piggin	 * R13		= PACA
2104ece7b6SNicholas Piggin	 * guest R13 saved in SPRN_SCRATCH0
2204ece7b6SNicholas Piggin	 * R10		= free
2304ece7b6SNicholas Piggin	 * guest r10 saved in PACA_EXGEN
2404ece7b6SNicholas Piggin	 *
2504ece7b6SNicholas Piggin	 * This may also be a syscall from PR-KVM userspace that is to be
2604ece7b6SNicholas Piggin	 * reflected to the PR guest kernel, so registers may be set up for
2704ece7b6SNicholas Piggin	 * a system call rather than hcall. We don't currently clobber
2804ece7b6SNicholas Piggin	 * anything here, but the 0xc00 handler has already clobbered CTR
2904ece7b6SNicholas Piggin	 * and CR0, so PR-KVM can not support a guest kernel that preserves
3004ece7b6SNicholas Piggin	 * those registers across its system calls.
3104ece7b6SNicholas Piggin	 */
3204ece7b6SNicholas Piggin	 /*
3304ece7b6SNicholas Piggin	  * Save the PPR (on systems that support it) before changing to
3404ece7b6SNicholas Piggin	  * HMT_MEDIUM. That allows the KVM code to save that value into the
3504ece7b6SNicholas Piggin	  * guest state (it is the guest's PPR value).
3604ece7b6SNicholas Piggin	  */
3704ece7b6SNicholas PigginBEGIN_FTR_SECTION
3804ece7b6SNicholas Piggin	mfspr	r10,SPRN_PPR
3904ece7b6SNicholas Piggin	std	r10,HSTATE_PPR(r13)
4004ece7b6SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
4104ece7b6SNicholas Piggin	HMT_MEDIUM
4204ece7b6SNicholas Piggin	mfcr	r10
4304ece7b6SNicholas Piggin	std	r12,HSTATE_SCRATCH0(r13)
4404ece7b6SNicholas Piggin	sldi	r12,r10,32
4504ece7b6SNicholas Piggin	ori	r12,r12,0xc00
4604ece7b6SNicholas Piggin	ld	r10,PACA_EXGEN+EX_R10(r13)
47*69fdd674SNicholas Piggin	b	do_kvm_interrupt
4831c67cfeSNicholas Piggin
49*69fdd674SNicholas Piggin/*
50*69fdd674SNicholas Piggin * KVM interrupt entry occurs after GEN_INT_ENTRY runs, and follows that
51*69fdd674SNicholas Piggin * call convention:
52*69fdd674SNicholas Piggin *
53*69fdd674SNicholas Piggin * guest R9-R13, CTR, CFAR, PPR saved in PACA EX_xxx save area
54*69fdd674SNicholas Piggin * guest (H)DAR, (H)DSISR are also in the save area for relevant interrupts
55*69fdd674SNicholas Piggin * guest R13 also saved in SCRATCH0
56*69fdd674SNicholas Piggin * R13		= PACA
57*69fdd674SNicholas Piggin * R11		= (H)SRR0
58*69fdd674SNicholas Piggin * R12		= (H)SRR1
59*69fdd674SNicholas Piggin * R9		= guest CR
60*69fdd674SNicholas Piggin * PPR is set to medium
61*69fdd674SNicholas Piggin *
62*69fdd674SNicholas Piggin * With the addition for KVM:
63*69fdd674SNicholas Piggin * R10		= trap vector
64*69fdd674SNicholas Piggin */
65f3601156SNicholas Piggin.global	kvmppc_interrupt
66f3601156SNicholas Piggin.balign IFETCH_ALIGN_BYTES
67f3601156SNicholas Pigginkvmppc_interrupt:
68*69fdd674SNicholas Piggin	li	r11,PACA_EXGEN
69*69fdd674SNicholas Piggin	cmpdi	r10,0x200
70*69fdd674SNicholas Piggin	bgt+	1f
71*69fdd674SNicholas Piggin	li	r11,PACA_EXMC
72*69fdd674SNicholas Piggin	beq	1f
73*69fdd674SNicholas Piggin	li	r11,PACA_EXNMI
74*69fdd674SNicholas Piggin1:	add	r11,r11,r13
75*69fdd674SNicholas Piggin
76*69fdd674SNicholas PigginBEGIN_FTR_SECTION
77*69fdd674SNicholas Piggin	ld	r12,EX_CFAR(r11)
78*69fdd674SNicholas Piggin	std	r12,HSTATE_CFAR(r13)
79*69fdd674SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_CFAR)
80*69fdd674SNicholas Piggin	ld	r12,EX_CTR(r11)
81*69fdd674SNicholas Piggin	mtctr	r12
82*69fdd674SNicholas PigginBEGIN_FTR_SECTION
83*69fdd674SNicholas Piggin	ld	r12,EX_PPR(r11)
84*69fdd674SNicholas Piggin	std	r12,HSTATE_PPR(r13)
85*69fdd674SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
86*69fdd674SNicholas Piggin	ld	r12,EX_R12(r11)
87*69fdd674SNicholas Piggin	std	r12,HSTATE_SCRATCH0(r13)
88*69fdd674SNicholas Piggin	sldi	r12,r9,32
89*69fdd674SNicholas Piggin	or	r12,r12,r10
90*69fdd674SNicholas Piggin	ld	r9,EX_R9(r11)
91*69fdd674SNicholas Piggin	ld	r10,EX_R10(r11)
92*69fdd674SNicholas Piggin	ld	r11,EX_R11(r11)
93*69fdd674SNicholas Piggin
94*69fdd674SNicholas Piggindo_kvm_interrupt:
95f3601156SNicholas Piggin	/*
96*69fdd674SNicholas Piggin	 * Hcalls and other interrupts come here after normalising register
97*69fdd674SNicholas Piggin	 * contents and save locations:
98*69fdd674SNicholas Piggin	 *
99f3601156SNicholas Piggin	 * R12		= (guest CR << 32) | interrupt vector
100f3601156SNicholas Piggin	 * R13		= PACA
101*69fdd674SNicholas Piggin	 * guest R12 saved in shadow HSTATE_SCRATCH0
102f3601156SNicholas Piggin	 * guest R13 saved in SPRN_SCRATCH0
103f3601156SNicholas Piggin	 */
104f3601156SNicholas Piggin	std	r9,HSTATE_SCRATCH2(r13)
105f3601156SNicholas Piggin	lbz	r9,HSTATE_IN_GUEST(r13)
106f33e0702SNicholas Piggin	cmpwi	r9,KVM_GUEST_MODE_SKIP
107f33e0702SNicholas Piggin	beq-	.Lmaybe_skip
108f33e0702SNicholas Piggin.Lno_skip:
109f33e0702SNicholas Piggin#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
110f3601156SNicholas Piggin	cmpwi	r9,KVM_GUEST_MODE_HOST_HV
111f3601156SNicholas Piggin	beq	kvmppc_bad_host_intr
112f3601156SNicholas Piggin#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
113f3601156SNicholas Piggin	cmpwi	r9,KVM_GUEST_MODE_GUEST
114f3601156SNicholas Piggin	ld	r9,HSTATE_SCRATCH2(r13)
115f3601156SNicholas Piggin	beq	kvmppc_interrupt_pr
116f3601156SNicholas Piggin#endif
117f3601156SNicholas Piggin	b	kvmppc_interrupt_hv
118f3601156SNicholas Piggin#else
119f33e0702SNicholas Piggin	ld	r9,HSTATE_SCRATCH2(r13)
120f3601156SNicholas Piggin	b	kvmppc_interrupt_pr
121f3601156SNicholas Piggin#endif
122f33e0702SNicholas Piggin
123f33e0702SNicholas Piggin/*
124f33e0702SNicholas Piggin * "Skip" interrupts are part of a trick KVM uses a with hash guests to load
125f33e0702SNicholas Piggin * the faulting instruction in guest memory from the the hypervisor without
126f33e0702SNicholas Piggin * walking page tables.
127f33e0702SNicholas Piggin *
128f33e0702SNicholas Piggin * When the guest takes a fault that requires the hypervisor to load the
129f33e0702SNicholas Piggin * instruction (e.g., MMIO emulation), KVM is running in real-mode with HV=1
130f33e0702SNicholas Piggin * and the guest MMU context loaded. It sets KVM_GUEST_MODE_SKIP, and sets
131f33e0702SNicholas Piggin * MSR[DR]=1 while leaving MSR[IR]=0, so it continues to fetch HV instructions
132f33e0702SNicholas Piggin * but loads and stores will access the guest context. This is used to load
133f33e0702SNicholas Piggin * the faulting instruction using the faulting guest effective address.
134f33e0702SNicholas Piggin *
135f33e0702SNicholas Piggin * However the guest context may not be able to translate, or it may cause a
136f33e0702SNicholas Piggin * machine check or other issue, which results in a fault in the host
137f33e0702SNicholas Piggin * (even with KVM-HV).
138f33e0702SNicholas Piggin *
139f33e0702SNicholas Piggin * These faults come here because KVM_GUEST_MODE_SKIP was set, so if they
140f33e0702SNicholas Piggin * are (or are likely) caused by that load, the instruction is skipped by
141f33e0702SNicholas Piggin * just returning with the PC advanced +4, where it is noticed the load did
142f33e0702SNicholas Piggin * not execute and it goes to the slow path which walks the page tables to
143f33e0702SNicholas Piggin * read guest memory.
144f33e0702SNicholas Piggin */
145f33e0702SNicholas Piggin.Lmaybe_skip:
146f33e0702SNicholas Piggin	cmpwi	r12,BOOK3S_INTERRUPT_MACHINE_CHECK
147f33e0702SNicholas Piggin	beq	1f
148f33e0702SNicholas Piggin	cmpwi	r12,BOOK3S_INTERRUPT_DATA_STORAGE
149f33e0702SNicholas Piggin	beq	1f
150f33e0702SNicholas Piggin	cmpwi	r12,BOOK3S_INTERRUPT_DATA_SEGMENT
151f33e0702SNicholas Piggin	beq	1f
152f33e0702SNicholas Piggin#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
153f33e0702SNicholas Piggin	/* HSRR interrupts get 2 added to interrupt number */
154f33e0702SNicholas Piggin	cmpwi	r12,BOOK3S_INTERRUPT_H_DATA_STORAGE | 0x2
155f33e0702SNicholas Piggin	beq	2f
156f33e0702SNicholas Piggin#endif
157f33e0702SNicholas Piggin	b	.Lno_skip
158f33e0702SNicholas Piggin1:	mfspr	r9,SPRN_SRR0
159f33e0702SNicholas Piggin	addi	r9,r9,4
160f33e0702SNicholas Piggin	mtspr	SPRN_SRR0,r9
161f33e0702SNicholas Piggin	ld	r12,HSTATE_SCRATCH0(r13)
162f33e0702SNicholas Piggin	ld	r9,HSTATE_SCRATCH2(r13)
163f33e0702SNicholas Piggin	GET_SCRATCH0(r13)
164f33e0702SNicholas Piggin	RFI_TO_KERNEL
165f33e0702SNicholas Piggin#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
166f33e0702SNicholas Piggin2:	mfspr	r9,SPRN_HSRR0
167f33e0702SNicholas Piggin	addi	r9,r9,4
168f33e0702SNicholas Piggin	mtspr	SPRN_HSRR0,r9
169f33e0702SNicholas Piggin	ld	r12,HSTATE_SCRATCH0(r13)
170f33e0702SNicholas Piggin	ld	r9,HSTATE_SCRATCH2(r13)
171f33e0702SNicholas Piggin	GET_SCRATCH0(r13)
172f33e0702SNicholas Piggin	HRFI_TO_KERNEL
173f33e0702SNicholas Piggin#endif
174