]> asedeno.scripts.mit.edu Git - linux.git/blob - arch/powerpc/kernel/kvm_emul.S
Merge tag 'dev_groups_all_drivers' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / arch / powerpc / kernel / kvm_emul.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  *
4  * Copyright SUSE Linux Products GmbH 2010
5  * Copyright 2010-2011 Freescale Semiconductor, Inc.
6  *
7  * Authors: Alexander Graf <agraf@suse.de>
8  */
9
10 #include <asm/ppc_asm.h>
11 #include <asm/kvm_asm.h>
12 #include <asm/reg.h>
13 #include <asm/page.h>
14 #include <asm/asm-offsets.h>
15 #include <asm/asm-compat.h>
16
17 #define KVM_MAGIC_PAGE          (-4096)
18
19 #ifdef CONFIG_64BIT
20 #define LL64(reg, offs, reg2)   ld      reg, (offs)(reg2)
21 #define STL64(reg, offs, reg2)  std     reg, (offs)(reg2)
22 #else
23 #define LL64(reg, offs, reg2)   lwz     reg, (offs + 4)(reg2)
24 #define STL64(reg, offs, reg2)  stw     reg, (offs + 4)(reg2)
25 #endif
26
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);              \
31                                                                         \
32         /* Save state */                                                \
33         PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0);          \
34         PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0);          \
35         mfcr    r31;                                                    \
36         stw     r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);
37
38 #define SCRATCH_RESTORE                                                 \
39         /* Restore state */                                             \
40         PPC_LL  r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0);          \
41         lwz     r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);          \
42         mtcr    r30;                                                    \
43         PPC_LL  r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0);          \
44                                                                         \
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);
48
49 .global kvm_template_start
50 kvm_template_start:
51
52 .global kvm_emulate_mtmsrd
53 kvm_emulate_mtmsrd:
54
55         SCRATCH_SAVE
56
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
61         and     r31, r31, r30
62
63         /* OR the register's (MSR_EE|MSR_RI) on MSR */
64 kvm_emulate_mtmsrd_reg:
65         ori     r30, r0, 0
66         andi.   r30, r30, (MSR_EE|MSR_RI)
67         or      r31, r31, r30
68
69         /* Put MSR back into magic page */
70         STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
71
72         /* Check if we have to fetch an interrupt */
73         lwz     r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
74         cmpwi   r31, 0
75         beq+    no_check
76
77         /* Check if we may trigger an interrupt */
78         andi.   r30, r30, MSR_EE
79         beq     no_check
80
81         SCRATCH_RESTORE
82
83         /* Nag hypervisor */
84 kvm_emulate_mtmsrd_orig_ins:
85         tlbsync
86
87         b       kvm_emulate_mtmsrd_branch
88
89 no_check:
90
91         SCRATCH_RESTORE
92
93         /* Go back to caller */
94 kvm_emulate_mtmsrd_branch:
95         b       .
96 kvm_emulate_mtmsrd_end:
97
98 .global kvm_emulate_mtmsrd_branch_offs
99 kvm_emulate_mtmsrd_branch_offs:
100         .long (kvm_emulate_mtmsrd_branch - kvm_emulate_mtmsrd) / 4
101
102 .global kvm_emulate_mtmsrd_reg_offs
103 kvm_emulate_mtmsrd_reg_offs:
104         .long (kvm_emulate_mtmsrd_reg - kvm_emulate_mtmsrd) / 4
105
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
109
110 .global kvm_emulate_mtmsrd_len
111 kvm_emulate_mtmsrd_len:
112         .long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4
113
114
115 #define MSR_SAFE_BITS (MSR_EE | MSR_RI)
116 #define MSR_CRITICAL_BITS ~MSR_SAFE_BITS
117
118 .global kvm_emulate_mtmsr
119 kvm_emulate_mtmsr:
120
121         SCRATCH_SAVE
122
123         /* Fetch old MSR in r31 */
124         LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
125
126         /* Find the changed bits between old and new MSR */
127 kvm_emulate_mtmsr_reg1:
128         ori     r30, r0, 0
129         xor     r31, r30, r31
130
131         /* Check if we need to really do mtmsr */
132         LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS)
133         and.    r31, r31, r30
134
135         /* No critical bits changed? Maybe we can stay in the guest. */
136         beq     maybe_stay_in_guest
137
138 do_mtmsr:
139
140         SCRATCH_RESTORE
141
142         /* Just fire off the mtmsr if it's critical */
143 kvm_emulate_mtmsr_orig_ins:
144         mtmsr   r0
145
146         b       kvm_emulate_mtmsr_branch
147
148 maybe_stay_in_guest:
149
150         /* Get the target register in r30 */
151 kvm_emulate_mtmsr_reg2:
152         ori     r30, r0, 0
153
154         /* Put MSR into magic page because we don't call mtmsr */
155         STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
156
157         /* Check if we have to fetch an interrupt */
158         lwz     r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
159         cmpwi   r31, 0
160         beq+    no_mtmsr
161
162         /* Check if we may trigger an interrupt */
163         andi.   r31, r30, MSR_EE
164         bne     do_mtmsr
165
166 no_mtmsr:
167
168         SCRATCH_RESTORE
169
170         /* Go back to caller */
171 kvm_emulate_mtmsr_branch:
172         b       .
173 kvm_emulate_mtmsr_end:
174
175 .global kvm_emulate_mtmsr_branch_offs
176 kvm_emulate_mtmsr_branch_offs:
177         .long (kvm_emulate_mtmsr_branch - kvm_emulate_mtmsr) / 4
178
179 .global kvm_emulate_mtmsr_reg1_offs
180 kvm_emulate_mtmsr_reg1_offs:
181         .long (kvm_emulate_mtmsr_reg1 - kvm_emulate_mtmsr) / 4
182
183 .global kvm_emulate_mtmsr_reg2_offs
184 kvm_emulate_mtmsr_reg2_offs:
185         .long (kvm_emulate_mtmsr_reg2 - kvm_emulate_mtmsr) / 4
186
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
190
191 .global kvm_emulate_mtmsr_len
192 kvm_emulate_mtmsr_len:
193         .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
194
195 /* also used for wrteei 1 */
196 .global kvm_emulate_wrtee
197 kvm_emulate_wrtee:
198
199         SCRATCH_SAVE
200
201         /* Fetch old MSR in r31 */
202         LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
203
204         /* Insert new MSR[EE] */
205 kvm_emulate_wrtee_reg:
206         ori     r30, r0, 0
207         rlwimi  r31, r30, 0, MSR_EE
208
209         /*
210          * If MSR[EE] is now set, check for a pending interrupt.
211          * We could skip this if MSR[EE] was already on, but that
212          * should be rare, so don't bother.
213          */
214         andi.   r30, r30, MSR_EE
215
216         /* Put MSR into magic page because we don't call wrtee */
217         STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
218
219         beq     no_wrtee
220
221         /* Check if we have to fetch an interrupt */
222         lwz     r30, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
223         cmpwi   r30, 0
224         bne     do_wrtee
225
226 no_wrtee:
227         SCRATCH_RESTORE
228
229         /* Go back to caller */
230 kvm_emulate_wrtee_branch:
231         b       .
232
233 do_wrtee:
234         SCRATCH_RESTORE
235
236         /* Just fire off the wrtee if it's critical */
237 kvm_emulate_wrtee_orig_ins:
238         wrtee   r0
239
240         b       kvm_emulate_wrtee_branch
241
242 kvm_emulate_wrtee_end:
243
244 .global kvm_emulate_wrtee_branch_offs
245 kvm_emulate_wrtee_branch_offs:
246         .long (kvm_emulate_wrtee_branch - kvm_emulate_wrtee) / 4
247
248 .global kvm_emulate_wrtee_reg_offs
249 kvm_emulate_wrtee_reg_offs:
250         .long (kvm_emulate_wrtee_reg - kvm_emulate_wrtee) / 4
251
252 .global kvm_emulate_wrtee_orig_ins_offs
253 kvm_emulate_wrtee_orig_ins_offs:
254         .long (kvm_emulate_wrtee_orig_ins - kvm_emulate_wrtee) / 4
255
256 .global kvm_emulate_wrtee_len
257 kvm_emulate_wrtee_len:
258         .long (kvm_emulate_wrtee_end - kvm_emulate_wrtee) / 4
259
260 .global kvm_emulate_wrteei_0
261 kvm_emulate_wrteei_0:
262         SCRATCH_SAVE
263
264         /* Fetch old MSR in r31 */
265         LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
266
267         /* Remove MSR_EE from old MSR */
268         rlwinm  r31, r31, 0, ~MSR_EE
269
270         /* Write new MSR value back */
271         STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
272
273         SCRATCH_RESTORE
274
275         /* Go back to caller */
276 kvm_emulate_wrteei_0_branch:
277         b       .
278 kvm_emulate_wrteei_0_end:
279
280 .global kvm_emulate_wrteei_0_branch_offs
281 kvm_emulate_wrteei_0_branch_offs:
282         .long (kvm_emulate_wrteei_0_branch - kvm_emulate_wrteei_0) / 4
283
284 .global kvm_emulate_wrteei_0_len
285 kvm_emulate_wrteei_0_len:
286         .long (kvm_emulate_wrteei_0_end - kvm_emulate_wrteei_0) / 4
287
288 .global kvm_emulate_mtsrin
289 kvm_emulate_mtsrin:
290
291         SCRATCH_SAVE
292
293         LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
294         andi.   r31, r31, MSR_DR | MSR_IR
295         beq     kvm_emulate_mtsrin_reg1
296
297         SCRATCH_RESTORE
298
299 kvm_emulate_mtsrin_orig_ins:
300         nop
301         b       kvm_emulate_mtsrin_branch
302
303 kvm_emulate_mtsrin_reg1:
304         /* rX >> 26 */
305         rlwinm  r30,r0,6,26,29
306
307 kvm_emulate_mtsrin_reg2:
308         stw     r0, (KVM_MAGIC_PAGE + KVM_MAGIC_SR)(r30)
309
310         SCRATCH_RESTORE
311
312         /* Go back to caller */
313 kvm_emulate_mtsrin_branch:
314         b       .
315 kvm_emulate_mtsrin_end:
316
317 .global kvm_emulate_mtsrin_branch_offs
318 kvm_emulate_mtsrin_branch_offs:
319         .long (kvm_emulate_mtsrin_branch - kvm_emulate_mtsrin) / 4
320
321 .global kvm_emulate_mtsrin_reg1_offs
322 kvm_emulate_mtsrin_reg1_offs:
323         .long (kvm_emulate_mtsrin_reg1 - kvm_emulate_mtsrin) / 4
324
325 .global kvm_emulate_mtsrin_reg2_offs
326 kvm_emulate_mtsrin_reg2_offs:
327         .long (kvm_emulate_mtsrin_reg2 - kvm_emulate_mtsrin) / 4
328
329 .global kvm_emulate_mtsrin_orig_ins_offs
330 kvm_emulate_mtsrin_orig_ins_offs:
331         .long (kvm_emulate_mtsrin_orig_ins - kvm_emulate_mtsrin) / 4
332
333 .global kvm_emulate_mtsrin_len
334 kvm_emulate_mtsrin_len:
335         .long (kvm_emulate_mtsrin_end - kvm_emulate_mtsrin) / 4
336
337 .global kvm_template_end
338 kvm_template_end: