xref: /openbmc/linux/arch/powerpc/kernel/kvm_emul.S (revision 976e3645923bdd2fe7893aae33fd7a21098bfb28)
1d94d71cbSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
2d17051cbSAlexander Graf/*
3d17051cbSAlexander Graf *
4d17051cbSAlexander Graf * Copyright SUSE Linux Products GmbH 2010
5940b45ecSScott Wood * Copyright 2010-2011 Freescale Semiconductor, Inc.
6d17051cbSAlexander Graf *
7d17051cbSAlexander Graf * Authors: Alexander Graf <agraf@suse.de>
8d17051cbSAlexander Graf */
9d17051cbSAlexander Graf
10d17051cbSAlexander Graf#include <asm/ppc_asm.h>
11d17051cbSAlexander Graf#include <asm/kvm_asm.h>
12d17051cbSAlexander Graf#include <asm/reg.h>
13d17051cbSAlexander Graf#include <asm/page.h>
14d17051cbSAlexander Graf#include <asm/asm-offsets.h>
15ec0c464cSChristophe Leroy#include <asm/asm-compat.h>
16d17051cbSAlexander Graf
17d17051cbSAlexander Graf#define KVM_MAGIC_PAGE		(-4096)
1892234722SAlexander Graf
1992234722SAlexander Graf#ifdef CONFIG_64BIT
2092234722SAlexander Graf#define LL64(reg, offs, reg2)	ld	reg, (offs)(reg2)
2192234722SAlexander Graf#define STL64(reg, offs, reg2)	std	reg, (offs)(reg2)
2292234722SAlexander Graf#else
2392234722SAlexander Graf#define LL64(reg, offs, reg2)	lwz	reg, (offs + 4)(reg2)
2492234722SAlexander Graf#define STL64(reg, offs, reg2)	stw	reg, (offs + 4)(reg2)
2592234722SAlexander Graf#endif
2692234722SAlexander Graf
2792234722SAlexander Graf#define SCRATCH_SAVE							\
2892234722SAlexander Graf	/* Enable critical section. We are critical if			\
2992234722SAlexander Graf	   shared->critical == r1 */					\
3092234722SAlexander Graf	STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);		\
3192234722SAlexander Graf									\
3292234722SAlexander Graf	/* Save state */						\
3392234722SAlexander Graf	PPC_STL	r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0);		\
3492234722SAlexander Graf	PPC_STL	r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0);		\
3592234722SAlexander Graf	mfcr	r31;							\
3692234722SAlexander Graf	stw	r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);
3792234722SAlexander Graf
3892234722SAlexander Graf#define SCRATCH_RESTORE							\
3992234722SAlexander Graf	/* Restore state */						\
4092234722SAlexander Graf	PPC_LL	r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0);		\
4192234722SAlexander Graf	lwz	r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);		\
4292234722SAlexander Graf	mtcr	r30;							\
4392234722SAlexander Graf	PPC_LL	r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0);		\
4492234722SAlexander Graf									\
4592234722SAlexander Graf	/* Disable critical section. We are critical if			\
4692234722SAlexander Graf	   shared->critical == r1 and r2 is always != r1 */		\
4792234722SAlexander Graf	STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
48819a63dcSAlexander Graf
49befdc0a6SLiu Yu-B13201.global kvm_template_start
50befdc0a6SLiu Yu-B13201kvm_template_start:
51befdc0a6SLiu Yu-B13201
52819a63dcSAlexander Graf.global kvm_emulate_mtmsrd
53819a63dcSAlexander Grafkvm_emulate_mtmsrd:
54819a63dcSAlexander Graf
55819a63dcSAlexander Graf	SCRATCH_SAVE
56819a63dcSAlexander Graf
57819a63dcSAlexander Graf	/* Put MSR & ~(MSR_EE|MSR_RI) in r31 */
58819a63dcSAlexander Graf	LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
59819a63dcSAlexander Graf	lis	r30, (~(MSR_EE | MSR_RI))@h
60819a63dcSAlexander Graf	ori	r30, r30, (~(MSR_EE | MSR_RI))@l
61819a63dcSAlexander Graf	and	r31, r31, r30
62819a63dcSAlexander Graf
63819a63dcSAlexander Graf	/* OR the register's (MSR_EE|MSR_RI) on MSR */
64819a63dcSAlexander Grafkvm_emulate_mtmsrd_reg:
65df08bd10SAlexander Graf	ori	r30, r0, 0
66df08bd10SAlexander Graf	andi.	r30, r30, (MSR_EE|MSR_RI)
67819a63dcSAlexander Graf	or	r31, r31, r30
68819a63dcSAlexander Graf
69819a63dcSAlexander Graf	/* Put MSR back into magic page */
70819a63dcSAlexander Graf	STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
71819a63dcSAlexander Graf
72819a63dcSAlexander Graf	/* Check if we have to fetch an interrupt */
73819a63dcSAlexander Graf	lwz	r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
74819a63dcSAlexander Graf	cmpwi	r31, 0
75819a63dcSAlexander Graf	beq+	no_check
76819a63dcSAlexander Graf
77819a63dcSAlexander Graf	/* Check if we may trigger an interrupt */
78819a63dcSAlexander Graf	andi.	r30, r30, MSR_EE
79819a63dcSAlexander Graf	beq	no_check
80819a63dcSAlexander Graf
81819a63dcSAlexander Graf	SCRATCH_RESTORE
82819a63dcSAlexander Graf
83819a63dcSAlexander Graf	/* Nag hypervisor */
84df08bd10SAlexander Grafkvm_emulate_mtmsrd_orig_ins:
85819a63dcSAlexander Graf	tlbsync
86819a63dcSAlexander Graf
87819a63dcSAlexander Graf	b	kvm_emulate_mtmsrd_branch
88819a63dcSAlexander Graf
89819a63dcSAlexander Grafno_check:
90819a63dcSAlexander Graf
91819a63dcSAlexander Graf	SCRATCH_RESTORE
92819a63dcSAlexander Graf
93819a63dcSAlexander Graf	/* Go back to caller */
94819a63dcSAlexander Grafkvm_emulate_mtmsrd_branch:
95819a63dcSAlexander Graf	b	.
96819a63dcSAlexander Grafkvm_emulate_mtmsrd_end:
97819a63dcSAlexander Graf
98819a63dcSAlexander Graf.global kvm_emulate_mtmsrd_branch_offs
99819a63dcSAlexander Grafkvm_emulate_mtmsrd_branch_offs:
100819a63dcSAlexander Graf	.long (kvm_emulate_mtmsrd_branch - kvm_emulate_mtmsrd) / 4
101819a63dcSAlexander Graf
102819a63dcSAlexander Graf.global kvm_emulate_mtmsrd_reg_offs
103819a63dcSAlexander Grafkvm_emulate_mtmsrd_reg_offs:
104819a63dcSAlexander Graf	.long (kvm_emulate_mtmsrd_reg - kvm_emulate_mtmsrd) / 4
105819a63dcSAlexander Graf
106df08bd10SAlexander Graf.global kvm_emulate_mtmsrd_orig_ins_offs
107df08bd10SAlexander Grafkvm_emulate_mtmsrd_orig_ins_offs:
108df08bd10SAlexander Graf	.long (kvm_emulate_mtmsrd_orig_ins - kvm_emulate_mtmsrd) / 4
109df08bd10SAlexander Graf
110819a63dcSAlexander Graf.global kvm_emulate_mtmsrd_len
111819a63dcSAlexander Grafkvm_emulate_mtmsrd_len:
112819a63dcSAlexander Graf	.long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4
11378109277SAlexander Graf
11478109277SAlexander Graf
115d35b1075SBharat Bhushan#define MSR_SAFE_BITS (MSR_EE | MSR_RI)
11678109277SAlexander Graf#define MSR_CRITICAL_BITS ~MSR_SAFE_BITS
11778109277SAlexander Graf
11878109277SAlexander Graf.global kvm_emulate_mtmsr
11978109277SAlexander Grafkvm_emulate_mtmsr:
12078109277SAlexander Graf
12178109277SAlexander Graf	SCRATCH_SAVE
12278109277SAlexander Graf
12378109277SAlexander Graf	/* Fetch old MSR in r31 */
12478109277SAlexander Graf	LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
12578109277SAlexander Graf
12678109277SAlexander Graf	/* Find the changed bits between old and new MSR */
12778109277SAlexander Grafkvm_emulate_mtmsr_reg1:
128512ba59eSAlexander Graf	ori	r30, r0, 0
129512ba59eSAlexander Graf	xor	r31, r30, r31
13078109277SAlexander Graf
13178109277SAlexander Graf	/* Check if we need to really do mtmsr */
13278109277SAlexander Graf	LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS)
13378109277SAlexander Graf	and.	r31, r31, r30
13478109277SAlexander Graf
13578109277SAlexander Graf	/* No critical bits changed? Maybe we can stay in the guest. */
13678109277SAlexander Graf	beq	maybe_stay_in_guest
13778109277SAlexander Graf
13878109277SAlexander Grafdo_mtmsr:
13978109277SAlexander Graf
14078109277SAlexander Graf	SCRATCH_RESTORE
14178109277SAlexander Graf
14278109277SAlexander Graf	/* Just fire off the mtmsr if it's critical */
14378109277SAlexander Grafkvm_emulate_mtmsr_orig_ins:
14478109277SAlexander Graf	mtmsr	r0
14578109277SAlexander Graf
14678109277SAlexander Graf	b	kvm_emulate_mtmsr_branch
14778109277SAlexander Graf
14878109277SAlexander Grafmaybe_stay_in_guest:
14978109277SAlexander Graf
150512ba59eSAlexander Graf	/* Get the target register in r30 */
151512ba59eSAlexander Grafkvm_emulate_mtmsr_reg2:
152512ba59eSAlexander Graf	ori	r30, r0, 0
153512ba59eSAlexander Graf
154f9208427SBharat Bhushan	/* Put MSR into magic page because we don't call mtmsr */
155f9208427SBharat Bhushan	STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
156f9208427SBharat Bhushan
15778109277SAlexander Graf	/* Check if we have to fetch an interrupt */
15878109277SAlexander Graf	lwz	r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
15978109277SAlexander Graf	cmpwi	r31, 0
16078109277SAlexander Graf	beq+	no_mtmsr
16178109277SAlexander Graf
16278109277SAlexander Graf	/* Check if we may trigger an interrupt */
163512ba59eSAlexander Graf	andi.	r31, r30, MSR_EE
164f9208427SBharat Bhushan	bne	do_mtmsr
16578109277SAlexander Graf
16678109277SAlexander Grafno_mtmsr:
16778109277SAlexander Graf
16878109277SAlexander Graf	SCRATCH_RESTORE
16978109277SAlexander Graf
17078109277SAlexander Graf	/* Go back to caller */
17178109277SAlexander Grafkvm_emulate_mtmsr_branch:
17278109277SAlexander Graf	b	.
17378109277SAlexander Grafkvm_emulate_mtmsr_end:
17478109277SAlexander Graf
17578109277SAlexander Graf.global kvm_emulate_mtmsr_branch_offs
17678109277SAlexander Grafkvm_emulate_mtmsr_branch_offs:
17778109277SAlexander Graf	.long (kvm_emulate_mtmsr_branch - kvm_emulate_mtmsr) / 4
17878109277SAlexander Graf
17978109277SAlexander Graf.global kvm_emulate_mtmsr_reg1_offs
18078109277SAlexander Grafkvm_emulate_mtmsr_reg1_offs:
18178109277SAlexander Graf	.long (kvm_emulate_mtmsr_reg1 - kvm_emulate_mtmsr) / 4
18278109277SAlexander Graf
18378109277SAlexander Graf.global kvm_emulate_mtmsr_reg2_offs
18478109277SAlexander Grafkvm_emulate_mtmsr_reg2_offs:
18578109277SAlexander Graf	.long (kvm_emulate_mtmsr_reg2 - kvm_emulate_mtmsr) / 4
18678109277SAlexander Graf
18778109277SAlexander Graf.global kvm_emulate_mtmsr_orig_ins_offs
18878109277SAlexander Grafkvm_emulate_mtmsr_orig_ins_offs:
18978109277SAlexander Graf	.long (kvm_emulate_mtmsr_orig_ins - kvm_emulate_mtmsr) / 4
19078109277SAlexander Graf
19178109277SAlexander Graf.global kvm_emulate_mtmsr_len
19278109277SAlexander Grafkvm_emulate_mtmsr_len:
19378109277SAlexander Graf	.long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
194644bfa01SAlexander Graf
195*caff52dcSMichael Ellerman#ifdef CONFIG_BOOKE
196*caff52dcSMichael Ellerman
197940b45ecSScott Wood/* also used for wrteei 1 */
198940b45ecSScott Wood.global kvm_emulate_wrtee
199940b45ecSScott Woodkvm_emulate_wrtee:
200644bfa01SAlexander Graf
201644bfa01SAlexander Graf	SCRATCH_SAVE
202644bfa01SAlexander Graf
203644bfa01SAlexander Graf	/* Fetch old MSR in r31 */
204644bfa01SAlexander Graf	LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
205644bfa01SAlexander Graf
206940b45ecSScott Wood	/* Insert new MSR[EE] */
207940b45ecSScott Woodkvm_emulate_wrtee_reg:
208940b45ecSScott Wood	ori	r30, r0, 0
209940b45ecSScott Wood	rlwimi	r31, r30, 0, MSR_EE
210644bfa01SAlexander Graf
211940b45ecSScott Wood	/*
212940b45ecSScott Wood	 * If MSR[EE] is now set, check for a pending interrupt.
213940b45ecSScott Wood	 * We could skip this if MSR[EE] was already on, but that
214940b45ecSScott Wood	 * should be rare, so don't bother.
215940b45ecSScott Wood	 */
216940b45ecSScott Wood	andi.	r30, r30, MSR_EE
217940b45ecSScott Wood
218940b45ecSScott Wood	/* Put MSR into magic page because we don't call wrtee */
219940b45ecSScott Wood	STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
220940b45ecSScott Wood
221940b45ecSScott Wood	beq	no_wrtee
222940b45ecSScott Wood
223940b45ecSScott Wood	/* Check if we have to fetch an interrupt */
224940b45ecSScott Wood	lwz	r30, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
225940b45ecSScott Wood	cmpwi	r30, 0
226940b45ecSScott Wood	bne	do_wrtee
227940b45ecSScott Wood
228940b45ecSScott Woodno_wrtee:
229940b45ecSScott Wood	SCRATCH_RESTORE
230940b45ecSScott Wood
231940b45ecSScott Wood	/* Go back to caller */
232940b45ecSScott Woodkvm_emulate_wrtee_branch:
233940b45ecSScott Wood	b	.
234940b45ecSScott Wood
235940b45ecSScott Wooddo_wrtee:
236940b45ecSScott Wood	SCRATCH_RESTORE
237940b45ecSScott Wood
238940b45ecSScott Wood	/* Just fire off the wrtee if it's critical */
239940b45ecSScott Woodkvm_emulate_wrtee_orig_ins:
240940b45ecSScott Wood	wrtee	r0
241940b45ecSScott Wood
242940b45ecSScott Wood	b	kvm_emulate_wrtee_branch
243940b45ecSScott Wood
244940b45ecSScott Woodkvm_emulate_wrtee_end:
245940b45ecSScott Wood
246940b45ecSScott Wood.global kvm_emulate_wrtee_branch_offs
247940b45ecSScott Woodkvm_emulate_wrtee_branch_offs:
248940b45ecSScott Wood	.long (kvm_emulate_wrtee_branch - kvm_emulate_wrtee) / 4
249940b45ecSScott Wood
250940b45ecSScott Wood.global kvm_emulate_wrtee_reg_offs
251940b45ecSScott Woodkvm_emulate_wrtee_reg_offs:
252940b45ecSScott Wood	.long (kvm_emulate_wrtee_reg - kvm_emulate_wrtee) / 4
253940b45ecSScott Wood
254940b45ecSScott Wood.global kvm_emulate_wrtee_orig_ins_offs
255940b45ecSScott Woodkvm_emulate_wrtee_orig_ins_offs:
256940b45ecSScott Wood	.long (kvm_emulate_wrtee_orig_ins - kvm_emulate_wrtee) / 4
257940b45ecSScott Wood
258940b45ecSScott Wood.global kvm_emulate_wrtee_len
259940b45ecSScott Woodkvm_emulate_wrtee_len:
260940b45ecSScott Wood	.long (kvm_emulate_wrtee_end - kvm_emulate_wrtee) / 4
261940b45ecSScott Wood
262940b45ecSScott Wood.global kvm_emulate_wrteei_0
263940b45ecSScott Woodkvm_emulate_wrteei_0:
264940b45ecSScott Wood	SCRATCH_SAVE
265940b45ecSScott Wood
266940b45ecSScott Wood	/* Fetch old MSR in r31 */
267940b45ecSScott Wood	LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
268940b45ecSScott Wood
269940b45ecSScott Wood	/* Remove MSR_EE from old MSR */
270940b45ecSScott Wood	rlwinm	r31, r31, 0, ~MSR_EE
271644bfa01SAlexander Graf
272644bfa01SAlexander Graf	/* Write new MSR value back */
273644bfa01SAlexander Graf	STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
274644bfa01SAlexander Graf
275644bfa01SAlexander Graf	SCRATCH_RESTORE
276644bfa01SAlexander Graf
277644bfa01SAlexander Graf	/* Go back to caller */
278940b45ecSScott Woodkvm_emulate_wrteei_0_branch:
279644bfa01SAlexander Graf	b	.
280940b45ecSScott Woodkvm_emulate_wrteei_0_end:
281644bfa01SAlexander Graf
282940b45ecSScott Wood.global kvm_emulate_wrteei_0_branch_offs
283940b45ecSScott Woodkvm_emulate_wrteei_0_branch_offs:
284940b45ecSScott Wood	.long (kvm_emulate_wrteei_0_branch - kvm_emulate_wrteei_0) / 4
285644bfa01SAlexander Graf
286940b45ecSScott Wood.global kvm_emulate_wrteei_0_len
287940b45ecSScott Woodkvm_emulate_wrteei_0_len:
288940b45ecSScott Wood	.long (kvm_emulate_wrteei_0_end - kvm_emulate_wrteei_0) / 4
289cbe487faSAlexander Graf
290*caff52dcSMichael Ellerman#endif /* CONFIG_BOOKE */
291*caff52dcSMichael Ellerman
292*caff52dcSMichael Ellerman#ifdef CONFIG_PPC_BOOK3S_32
293*caff52dcSMichael Ellerman
294cbe487faSAlexander Graf.global kvm_emulate_mtsrin
295cbe487faSAlexander Grafkvm_emulate_mtsrin:
296cbe487faSAlexander Graf
297cbe487faSAlexander Graf	SCRATCH_SAVE
298cbe487faSAlexander Graf
299cbe487faSAlexander Graf	LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
300cbe487faSAlexander Graf	andi.	r31, r31, MSR_DR | MSR_IR
301cbe487faSAlexander Graf	beq	kvm_emulate_mtsrin_reg1
302cbe487faSAlexander Graf
303cbe487faSAlexander Graf	SCRATCH_RESTORE
304cbe487faSAlexander Graf
305cbe487faSAlexander Grafkvm_emulate_mtsrin_orig_ins:
306cbe487faSAlexander Graf	nop
307cbe487faSAlexander Graf	b	kvm_emulate_mtsrin_branch
308cbe487faSAlexander Graf
309cbe487faSAlexander Grafkvm_emulate_mtsrin_reg1:
310cbe487faSAlexander Graf	/* rX >> 26 */
311cbe487faSAlexander Graf	rlwinm  r30,r0,6,26,29
312cbe487faSAlexander Graf
313cbe487faSAlexander Grafkvm_emulate_mtsrin_reg2:
314cbe487faSAlexander Graf	stw	r0, (KVM_MAGIC_PAGE + KVM_MAGIC_SR)(r30)
315cbe487faSAlexander Graf
316cbe487faSAlexander Graf	SCRATCH_RESTORE
317cbe487faSAlexander Graf
318cbe487faSAlexander Graf	/* Go back to caller */
319cbe487faSAlexander Grafkvm_emulate_mtsrin_branch:
320cbe487faSAlexander Graf	b	.
321cbe487faSAlexander Grafkvm_emulate_mtsrin_end:
322cbe487faSAlexander Graf
323cbe487faSAlexander Graf.global kvm_emulate_mtsrin_branch_offs
324cbe487faSAlexander Grafkvm_emulate_mtsrin_branch_offs:
325cbe487faSAlexander Graf	.long (kvm_emulate_mtsrin_branch - kvm_emulate_mtsrin) / 4
326cbe487faSAlexander Graf
327cbe487faSAlexander Graf.global kvm_emulate_mtsrin_reg1_offs
328cbe487faSAlexander Grafkvm_emulate_mtsrin_reg1_offs:
329cbe487faSAlexander Graf	.long (kvm_emulate_mtsrin_reg1 - kvm_emulate_mtsrin) / 4
330cbe487faSAlexander Graf
331cbe487faSAlexander Graf.global kvm_emulate_mtsrin_reg2_offs
332cbe487faSAlexander Grafkvm_emulate_mtsrin_reg2_offs:
333cbe487faSAlexander Graf	.long (kvm_emulate_mtsrin_reg2 - kvm_emulate_mtsrin) / 4
334cbe487faSAlexander Graf
335cbe487faSAlexander Graf.global kvm_emulate_mtsrin_orig_ins_offs
336cbe487faSAlexander Grafkvm_emulate_mtsrin_orig_ins_offs:
337cbe487faSAlexander Graf	.long (kvm_emulate_mtsrin_orig_ins - kvm_emulate_mtsrin) / 4
338cbe487faSAlexander Graf
339cbe487faSAlexander Graf.global kvm_emulate_mtsrin_len
340cbe487faSAlexander Grafkvm_emulate_mtsrin_len:
341cbe487faSAlexander Graf	.long (kvm_emulate_mtsrin_end - kvm_emulate_mtsrin) / 4
342befdc0a6SLiu Yu-B13201
343*caff52dcSMichael Ellerman#endif /* CONFIG_PPC_BOOK3S_32 */
344*caff52dcSMichael Ellerman
3450cb0837fSMichael Ellerman	.balign 4
3460cb0837fSMichael Ellerman	.global kvm_tmp
3470cb0837fSMichael Ellermankvm_tmp:
3480cb0837fSMichael Ellerman	.space	(64 * 1024)
3490cb0837fSMichael Ellerman
3500cb0837fSMichael Ellerman.global kvm_tmp_end
3510cb0837fSMichael Ellermankvm_tmp_end:
3520cb0837fSMichael Ellerman
353befdc0a6SLiu Yu-B13201.global kvm_template_end
354befdc0a6SLiu Yu-B13201kvm_template_end:
355