1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * Copyright SUSE Linux Products GmbH 2010
5 * Copyright 2010-2011 Freescale Semiconductor, Inc.
7 * Authors: Alexander Graf <agraf@suse.de>
10 #include <asm/ppc_asm.h>
11 #include <asm/kvm_asm.h>
14 #include <asm/asm-offsets.h>
15 #include <asm/asm-compat.h>
17 #define KVM_MAGIC_PAGE (-4096)
20 #define LL64(reg, offs, reg2) ld reg, (offs)(reg2)
21 #define STL64(reg, offs, reg2) std reg, (offs)(reg2)
23 #define LL64(reg, offs, reg2) lwz reg, (offs + 4)(reg2)
24 #define STL64(reg, offs, reg2) stw reg, (offs + 4)(reg2)
27 #define SCRATCH_SAVE \
28 /* Enable critical section. We are critical if \
29 shared->critical == r1 */ \
30 STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); \
33 PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \
34 PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \
36 stw r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);
38 #define SCRATCH_RESTORE \
40 PPC_LL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \
41 lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); \
43 PPC_LL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \
45 /* Disable critical section. We are critical if \
46 shared->critical == r1 and r2 is always != r1 */ \
47 STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
49 .global kvm_template_start
52 .global kvm_emulate_mtmsrd
57 /* Put MSR & ~(MSR_EE|MSR_RI) in r31 */
58 LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
59 lis r30, (~(MSR_EE | MSR_RI))@h
60 ori r30, r30, (~(MSR_EE | MSR_RI))@l
63 /* OR the register's (MSR_EE|MSR_RI) on MSR */
64 kvm_emulate_mtmsrd_reg:
66 andi. r30, r30, (MSR_EE|MSR_RI)
69 /* Put MSR back into magic page */
70 STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
72 /* Check if we have to fetch an interrupt */
73 lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
77 /* Check if we may trigger an interrupt */
78 andi. r30, r30, MSR_EE
84 kvm_emulate_mtmsrd_orig_ins:
87 b kvm_emulate_mtmsrd_branch
93 /* Go back to caller */
94 kvm_emulate_mtmsrd_branch:
96 kvm_emulate_mtmsrd_end:
98 .global kvm_emulate_mtmsrd_branch_offs
99 kvm_emulate_mtmsrd_branch_offs:
100 .long (kvm_emulate_mtmsrd_branch - kvm_emulate_mtmsrd) / 4
102 .global kvm_emulate_mtmsrd_reg_offs
103 kvm_emulate_mtmsrd_reg_offs:
104 .long (kvm_emulate_mtmsrd_reg - kvm_emulate_mtmsrd) / 4
106 .global kvm_emulate_mtmsrd_orig_ins_offs
107 kvm_emulate_mtmsrd_orig_ins_offs:
108 .long (kvm_emulate_mtmsrd_orig_ins - kvm_emulate_mtmsrd) / 4
110 .global kvm_emulate_mtmsrd_len
111 kvm_emulate_mtmsrd_len:
112 .long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4
115 #define MSR_SAFE_BITS (MSR_EE | MSR_RI)
116 #define MSR_CRITICAL_BITS ~MSR_SAFE_BITS
118 .global kvm_emulate_mtmsr
123 /* Fetch old MSR in r31 */
124 LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
126 /* Find the changed bits between old and new MSR */
127 kvm_emulate_mtmsr_reg1:
131 /* Check if we need to really do mtmsr */
132 LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS)
135 /* No critical bits changed? Maybe we can stay in the guest. */
136 beq maybe_stay_in_guest
142 /* Just fire off the mtmsr if it's critical */
143 kvm_emulate_mtmsr_orig_ins:
146 b kvm_emulate_mtmsr_branch
150 /* Get the target register in r30 */
151 kvm_emulate_mtmsr_reg2:
154 /* Put MSR into magic page because we don't call mtmsr */
155 STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
157 /* Check if we have to fetch an interrupt */
158 lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
162 /* Check if we may trigger an interrupt */
163 andi. r31, r30, MSR_EE
170 /* Go back to caller */
171 kvm_emulate_mtmsr_branch:
173 kvm_emulate_mtmsr_end:
175 .global kvm_emulate_mtmsr_branch_offs
176 kvm_emulate_mtmsr_branch_offs:
177 .long (kvm_emulate_mtmsr_branch - kvm_emulate_mtmsr) / 4
179 .global kvm_emulate_mtmsr_reg1_offs
180 kvm_emulate_mtmsr_reg1_offs:
181 .long (kvm_emulate_mtmsr_reg1 - kvm_emulate_mtmsr) / 4
183 .global kvm_emulate_mtmsr_reg2_offs
184 kvm_emulate_mtmsr_reg2_offs:
185 .long (kvm_emulate_mtmsr_reg2 - kvm_emulate_mtmsr) / 4
187 .global kvm_emulate_mtmsr_orig_ins_offs
188 kvm_emulate_mtmsr_orig_ins_offs:
189 .long (kvm_emulate_mtmsr_orig_ins - kvm_emulate_mtmsr) / 4
191 .global kvm_emulate_mtmsr_len
192 kvm_emulate_mtmsr_len:
193 .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
197 /* also used for wrteei 1 */
198 .global kvm_emulate_wrtee
203 /* Fetch old MSR in r31 */
204 LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
206 /* Insert new MSR[EE] */
207 kvm_emulate_wrtee_reg:
209 rlwimi r31, r30, 0, MSR_EE
212 * If MSR[EE] is now set, check for a pending interrupt.
213 * We could skip this if MSR[EE] was already on, but that
214 * should be rare, so don't bother.
216 andi. r30, r30, MSR_EE
218 /* Put MSR into magic page because we don't call wrtee */
219 STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
223 /* Check if we have to fetch an interrupt */
224 lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
231 /* Go back to caller */
232 kvm_emulate_wrtee_branch:
238 /* Just fire off the wrtee if it's critical */
239 kvm_emulate_wrtee_orig_ins:
242 b kvm_emulate_wrtee_branch
244 kvm_emulate_wrtee_end:
246 .global kvm_emulate_wrtee_branch_offs
247 kvm_emulate_wrtee_branch_offs:
248 .long (kvm_emulate_wrtee_branch - kvm_emulate_wrtee) / 4
250 .global kvm_emulate_wrtee_reg_offs
251 kvm_emulate_wrtee_reg_offs:
252 .long (kvm_emulate_wrtee_reg - kvm_emulate_wrtee) / 4
254 .global kvm_emulate_wrtee_orig_ins_offs
255 kvm_emulate_wrtee_orig_ins_offs:
256 .long (kvm_emulate_wrtee_orig_ins - kvm_emulate_wrtee) / 4
258 .global kvm_emulate_wrtee_len
259 kvm_emulate_wrtee_len:
260 .long (kvm_emulate_wrtee_end - kvm_emulate_wrtee) / 4
262 .global kvm_emulate_wrteei_0
263 kvm_emulate_wrteei_0:
266 /* Fetch old MSR in r31 */
267 LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
269 /* Remove MSR_EE from old MSR */
270 rlwinm r31, r31, 0, ~MSR_EE
272 /* Write new MSR value back */
273 STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
277 /* Go back to caller */
278 kvm_emulate_wrteei_0_branch:
280 kvm_emulate_wrteei_0_end:
282 .global kvm_emulate_wrteei_0_branch_offs
283 kvm_emulate_wrteei_0_branch_offs:
284 .long (kvm_emulate_wrteei_0_branch - kvm_emulate_wrteei_0) / 4
286 .global kvm_emulate_wrteei_0_len
287 kvm_emulate_wrteei_0_len:
288 .long (kvm_emulate_wrteei_0_end - kvm_emulate_wrteei_0) / 4
290 #endif /* CONFIG_BOOKE */
292 #ifdef CONFIG_PPC_BOOK3S_32
294 .global kvm_emulate_mtsrin
299 LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
300 andi. r31, r31, MSR_DR | MSR_IR
301 beq kvm_emulate_mtsrin_reg1
305 kvm_emulate_mtsrin_orig_ins:
307 b kvm_emulate_mtsrin_branch
309 kvm_emulate_mtsrin_reg1:
311 rlwinm r30,r0,6,26,29
313 kvm_emulate_mtsrin_reg2:
314 stw r0, (KVM_MAGIC_PAGE + KVM_MAGIC_SR)(r30)
318 /* Go back to caller */
319 kvm_emulate_mtsrin_branch:
321 kvm_emulate_mtsrin_end:
323 .global kvm_emulate_mtsrin_branch_offs
324 kvm_emulate_mtsrin_branch_offs:
325 .long (kvm_emulate_mtsrin_branch - kvm_emulate_mtsrin) / 4
327 .global kvm_emulate_mtsrin_reg1_offs
328 kvm_emulate_mtsrin_reg1_offs:
329 .long (kvm_emulate_mtsrin_reg1 - kvm_emulate_mtsrin) / 4
331 .global kvm_emulate_mtsrin_reg2_offs
332 kvm_emulate_mtsrin_reg2_offs:
333 .long (kvm_emulate_mtsrin_reg2 - kvm_emulate_mtsrin) / 4
335 .global kvm_emulate_mtsrin_orig_ins_offs
336 kvm_emulate_mtsrin_orig_ins_offs:
337 .long (kvm_emulate_mtsrin_orig_ins - kvm_emulate_mtsrin) / 4
339 .global kvm_emulate_mtsrin_len
340 kvm_emulate_mtsrin_len:
341 .long (kvm_emulate_mtsrin_end - kvm_emulate_mtsrin) / 4
343 #endif /* CONFIG_PPC_BOOK3S_32 */
353 .global kvm_template_end