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 | #ifdef CONFIG_BOOKE |
196 | |
197 | /* also used for wrteei 1 */ |
198 | .global kvm_emulate_wrtee |
199 | kvm_emulate_wrtee: |
200 | |
201 | SCRATCH_SAVE |
202 | |
203 | /* Fetch old MSR in r31 */ |
204 | LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) |
205 | |
206 | /* Insert new MSR[EE] */ |
207 | kvm_emulate_wrtee_reg: |
208 | ori r30, r0, 0 |
209 | rlwimi r31, r30, 0, MSR_EE |
210 | |
211 | /* |
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. |
215 | */ |
216 | andi. r30, r30, MSR_EE |
217 | |
218 | /* Put MSR into magic page because we don't call wrtee */ |
219 | STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) |
220 | |
221 | beq no_wrtee |
222 | |
223 | /* Check if we have to fetch an interrupt */ |
224 | lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0) |
225 | cmpwi r30, 0 |
226 | bne do_wrtee |
227 | |
228 | no_wrtee: |
229 | SCRATCH_RESTORE |
230 | |
231 | /* Go back to caller */ |
232 | kvm_emulate_wrtee_branch: |
233 | b . |
234 | |
235 | do_wrtee: |
236 | SCRATCH_RESTORE |
237 | |
238 | /* Just fire off the wrtee if it's critical */ |
239 | kvm_emulate_wrtee_orig_ins: |
240 | wrtee r0 |
241 | |
242 | b kvm_emulate_wrtee_branch |
243 | |
244 | kvm_emulate_wrtee_end: |
245 | |
246 | .global kvm_emulate_wrtee_branch_offs |
247 | kvm_emulate_wrtee_branch_offs: |
248 | .long (kvm_emulate_wrtee_branch - kvm_emulate_wrtee) / 4 |
249 | |
250 | .global kvm_emulate_wrtee_reg_offs |
251 | kvm_emulate_wrtee_reg_offs: |
252 | .long (kvm_emulate_wrtee_reg - kvm_emulate_wrtee) / 4 |
253 | |
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 |
257 | |
258 | .global kvm_emulate_wrtee_len |
259 | kvm_emulate_wrtee_len: |
260 | .long (kvm_emulate_wrtee_end - kvm_emulate_wrtee) / 4 |
261 | |
262 | .global kvm_emulate_wrteei_0 |
263 | kvm_emulate_wrteei_0: |
264 | SCRATCH_SAVE |
265 | |
266 | /* Fetch old MSR in r31 */ |
267 | LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) |
268 | |
269 | /* Remove MSR_EE from old MSR */ |
270 | rlwinm r31, r31, 0, ~MSR_EE |
271 | |
272 | /* Write new MSR value back */ |
273 | STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) |
274 | |
275 | SCRATCH_RESTORE |
276 | |
277 | /* Go back to caller */ |
278 | kvm_emulate_wrteei_0_branch: |
279 | b . |
280 | kvm_emulate_wrteei_0_end: |
281 | |
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 |
285 | |
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 |
289 | |
290 | #endif /* CONFIG_BOOKE */ |
291 | |
292 | #ifdef CONFIG_PPC_BOOK3S_32 |
293 | |
294 | .global kvm_emulate_mtsrin |
295 | kvm_emulate_mtsrin: |
296 | |
297 | SCRATCH_SAVE |
298 | |
299 | LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) |
300 | andi. r31, r31, MSR_DR | MSR_IR |
301 | beq kvm_emulate_mtsrin_reg1 |
302 | |
303 | SCRATCH_RESTORE |
304 | |
305 | kvm_emulate_mtsrin_orig_ins: |
306 | nop |
307 | b kvm_emulate_mtsrin_branch |
308 | |
309 | kvm_emulate_mtsrin_reg1: |
310 | /* rX >> 26 */ |
311 | rlwinm r30,r0,6,26,29 |
312 | |
313 | kvm_emulate_mtsrin_reg2: |
314 | stw r0, (KVM_MAGIC_PAGE + KVM_MAGIC_SR)(r30) |
315 | |
316 | SCRATCH_RESTORE |
317 | |
318 | /* Go back to caller */ |
319 | kvm_emulate_mtsrin_branch: |
320 | b . |
321 | kvm_emulate_mtsrin_end: |
322 | |
323 | .global kvm_emulate_mtsrin_branch_offs |
324 | kvm_emulate_mtsrin_branch_offs: |
325 | .long (kvm_emulate_mtsrin_branch - kvm_emulate_mtsrin) / 4 |
326 | |
327 | .global kvm_emulate_mtsrin_reg1_offs |
328 | kvm_emulate_mtsrin_reg1_offs: |
329 | .long (kvm_emulate_mtsrin_reg1 - kvm_emulate_mtsrin) / 4 |
330 | |
331 | .global kvm_emulate_mtsrin_reg2_offs |
332 | kvm_emulate_mtsrin_reg2_offs: |
333 | .long (kvm_emulate_mtsrin_reg2 - kvm_emulate_mtsrin) / 4 |
334 | |
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 |
338 | |
339 | .global kvm_emulate_mtsrin_len |
340 | kvm_emulate_mtsrin_len: |
341 | .long (kvm_emulate_mtsrin_end - kvm_emulate_mtsrin) / 4 |
342 | |
343 | #endif /* CONFIG_PPC_BOOK3S_32 */ |
344 | |
345 | .balign 4 |
346 | .global kvm_tmp |
347 | kvm_tmp: |
348 | .space (64 * 1024) |
349 | |
350 | .global kvm_tmp_end |
351 | kvm_tmp_end: |
352 | |
353 | .global kvm_template_end |
354 | kvm_template_end: |
355 | |