master
c 930 lines 34.2 KB
Raw
1 /*
2 * x86 SVM helpers (system only)
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "qemu/osdep.h"
21 #include "qemu/log.h"
22 #include "cpu.h"
23 #include "exec/helper-proto.h"
24 #include "exec/cputlb.h"
25 #include "accel/tcg/cpu-ldst.h"
26 #include "accel/tcg/cpu-loop.h"
27 #include "tcg/helper-tcg.h"
28
29 /* Secure Virtual Machine helpers */
30
31 static void svm_save_seg(CPUX86State *env, int mmu_idx, hwaddr addr,
32 const SegmentCache *sc)
33 {
34 cpu_stw_le_mmuidx_ra(env, addr + offsetof(struct vmcb_seg, selector),
35 sc->selector, mmu_idx, 0);
36 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb_seg, base),
37 sc->base, mmu_idx, 0);
38 cpu_stl_le_mmuidx_ra(env, addr + offsetof(struct vmcb_seg, limit),
39 sc->limit, mmu_idx, 0);
40 cpu_stw_le_mmuidx_ra(env, addr + offsetof(struct vmcb_seg, attrib),
41 ((sc->flags >> 8) & 0xff)
42 | ((sc->flags >> 12) & 0x0f00),
43 mmu_idx, 0);
44 }
45
46 /*
47 * VMRUN and VMLOAD canonicalizes (i.e., sign-extend to bit 63) all base
48 * addresses in the segment registers that have been loaded.
49 */
50 static inline void svm_canonicalization(CPUX86State *env, target_ulong *seg_base)
51 {
52 uint16_t shift_amt = 64 - cpu_x86_virtual_addr_width(env);
53 *seg_base = (((int64_t) *seg_base) << shift_amt) >> shift_amt;
54 }
55
56 static void svm_load_seg(CPUX86State *env, int mmu_idx, hwaddr addr,
57 SegmentCache *sc)
58 {
59 unsigned int flags;
60
61 sc->selector =
62 cpu_lduw_le_mmuidx_ra(env, addr + offsetof(struct vmcb_seg, selector),
63 mmu_idx, 0);
64 sc->base =
65 cpu_ldq_le_mmuidx_ra(env, addr + offsetof(struct vmcb_seg, base),
66 mmu_idx, 0);
67 sc->limit =
68 cpu_ldl_le_mmuidx_ra(env, addr + offsetof(struct vmcb_seg, limit),
69 mmu_idx, 0);
70 flags =
71 cpu_lduw_le_mmuidx_ra(env, addr + offsetof(struct vmcb_seg, attrib),
72 mmu_idx, 0);
73 sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
74
75 svm_canonicalization(env, &sc->base);
76 }
77
78 static void svm_load_seg_cache(CPUX86State *env, int mmu_idx,
79 hwaddr addr, int seg_reg)
80 {
81 SegmentCache sc;
82
83 svm_load_seg(env, mmu_idx, addr, &sc);
84 cpu_x86_load_seg_cache(env, seg_reg, sc.selector,
85 sc.base, sc.limit, sc.flags);
86 }
87
88 static inline bool is_efer_invalid_state (CPUX86State *env)
89 {
90 if (!(env->efer & MSR_EFER_SVME)) {
91 return true;
92 }
93
94 if (env->efer & MSR_EFER_RESERVED) {
95 return true;
96 }
97
98 if ((env->efer & (MSR_EFER_LMA | MSR_EFER_LME)) &&
99 !(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
100 return true;
101 }
102
103 if ((env->efer & MSR_EFER_LME) && (env->cr[0] & CR0_PG_MASK)
104 && !(env->cr[4] & CR4_PAE_MASK)) {
105 return true;
106 }
107
108 if ((env->efer & MSR_EFER_LME) && (env->cr[0] & CR0_PG_MASK)
109 && !(env->cr[0] & CR0_PE_MASK)) {
110 return true;
111 }
112
113 if ((env->efer & MSR_EFER_LME) && (env->cr[0] & CR0_PG_MASK)
114 && (env->cr[4] & CR4_PAE_MASK)
115 && (env->segs[R_CS].flags & DESC_L_MASK)
116 && (env->segs[R_CS].flags & DESC_B_MASK)) {
117 return true;
118 }
119
120 return false;
121 }
122
123 static inline bool virtual_gif_enabled(CPUX86State *env)
124 {
125 if (likely(env->hflags & HF_GUEST_MASK)) {
126 return (env->features[FEAT_SVM] & CPUID_SVM_VGIF)
127 && (env->int_ctl & V_GIF_ENABLED_MASK);
128 }
129 return false;
130 }
131
132 static inline bool virtual_vm_load_save_enabled(CPUX86State *env, uint64_t exit_code, uintptr_t retaddr)
133 {
134 uint64_t lbr_ctl;
135
136 if (likely(env->hflags & HF_GUEST_MASK)) {
137 if (likely(!(env->hflags2 & HF2_NPT_MASK)) || !(env->efer & MSR_EFER_LMA)) {
138 cpu_vmexit(env, exit_code, 0, retaddr);
139 }
140
141 lbr_ctl = x86_ldl_phys(env_cpu(env), env->vm_vmcb + offsetof(struct vmcb,
142 control.lbr_ctl));
143 return (env->features[FEAT_SVM] & CPUID_SVM_V_VMSAVE_VMLOAD)
144 && (lbr_ctl & V_VMLOAD_VMSAVE_ENABLED_MASK);
145
146 }
147
148 return false;
149 }
150
151 static inline bool virtual_gif_set(CPUX86State *env)
152 {
153 return !virtual_gif_enabled(env) || (env->int_ctl & V_GIF_MASK);
154 }
155
156 void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
157 {
158 CPUState *cs = env_cpu(env);
159 X86CPU *cpu = env_archcpu(env);
160 target_ulong addr;
161 uint64_t nested_ctl;
162 uint32_t event_inj;
163 uint32_t asid;
164 uint64_t new_cr0;
165 uint64_t new_cr3;
166 uint64_t new_cr4;
167 uint64_t new_dr6;
168 uint64_t new_dr7;
169
170 if (aflag == 2) {
171 addr = env->regs[R_EAX];
172 } else {
173 addr = (uint32_t)env->regs[R_EAX];
174 }
175
176 /* Exceptions are checked before the intercept. */
177 if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
178 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
179 }
180
181 cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
182
183 qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
184
185 env->vm_vmcb = addr;
186
187 /* save the current CPU state in the hsave page */
188 x86_stq_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.gdtr.base),
189 env->gdt.base);
190 x86_stl_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit),
191 env->gdt.limit);
192
193 x86_stq_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.idtr.base),
194 env->idt.base);
195 x86_stl_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.idtr.limit),
196 env->idt.limit);
197
198 x86_stq_phys(cs,
199 env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
200 x86_stq_phys(cs,
201 env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
202 x86_stq_phys(cs,
203 env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
204 x86_stq_phys(cs,
205 env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
206 x86_stq_phys(cs,
207 env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
208 x86_stq_phys(cs,
209 env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
210
211 x86_stq_phys(cs,
212 env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
213 x86_stq_phys(cs,
214 env->vm_hsave + offsetof(struct vmcb, save.rflags),
215 cpu_compute_eflags(env));
216
217 svm_save_seg(env, MMU_PHYS_IDX,
218 env->vm_hsave + offsetof(struct vmcb, save.es),
219 &env->segs[R_ES]);
220 svm_save_seg(env, MMU_PHYS_IDX,
221 env->vm_hsave + offsetof(struct vmcb, save.cs),
222 &env->segs[R_CS]);
223 svm_save_seg(env, MMU_PHYS_IDX,
224 env->vm_hsave + offsetof(struct vmcb, save.ss),
225 &env->segs[R_SS]);
226 svm_save_seg(env, MMU_PHYS_IDX,
227 env->vm_hsave + offsetof(struct vmcb, save.ds),
228 &env->segs[R_DS]);
229
230 x86_stq_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.rip),
231 env->eip + next_eip_addend);
232 x86_stq_phys(cs,
233 env->vm_hsave + offsetof(struct vmcb, save.rsp), env->regs[R_ESP]);
234 x86_stq_phys(cs,
235 env->vm_hsave + offsetof(struct vmcb, save.rax), env->regs[R_EAX]);
236
237 /* load the interception bitmaps so we do not need to access the
238 vmcb in svm mode */
239 env->intercept = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
240 control.intercept));
241 env->intercept_cr_read = x86_lduw_phys(cs, env->vm_vmcb +
242 offsetof(struct vmcb,
243 control.intercept_cr_read));
244 env->intercept_cr_write = x86_lduw_phys(cs, env->vm_vmcb +
245 offsetof(struct vmcb,
246 control.intercept_cr_write));
247 env->intercept_dr_read = x86_lduw_phys(cs, env->vm_vmcb +
248 offsetof(struct vmcb,
249 control.intercept_dr_read));
250 env->intercept_dr_write = x86_lduw_phys(cs, env->vm_vmcb +
251 offsetof(struct vmcb,
252 control.intercept_dr_write));
253 env->intercept_exceptions = x86_ldl_phys(cs, env->vm_vmcb +
254 offsetof(struct vmcb,
255 control.intercept_exceptions
256 ));
257
258 env->hflags &= ~HF_INHIBIT_IRQ_MASK;
259 if (x86_ldl_phys(cs, env->vm_vmcb +
260 offsetof(struct vmcb, control.int_state)) &
261 SVM_INTERRUPT_SHADOW_MASK) {
262 env->hflags |= HF_INHIBIT_IRQ_MASK;
263 }
264
265 nested_ctl = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
266 control.nested_ctl));
267 asid = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
268 control.asid));
269
270 uint64_t msrpm_base_pa = x86_ldq_phys(cs, env->vm_vmcb +
271 offsetof(struct vmcb,
272 control.msrpm_base_pa));
273 uint64_t iopm_base_pa = x86_ldq_phys(cs, env->vm_vmcb +
274 offsetof(struct vmcb, control.iopm_base_pa));
275
276 if ((msrpm_base_pa & ~0xfff) >= (1ull << cpu->phys_bits) - SVM_MSRPM_SIZE) {
277 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
278 }
279
280 if ((iopm_base_pa & ~0xfff) >= (1ull << cpu->phys_bits) - SVM_IOPM_SIZE) {
281 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
282 }
283
284 env->nested_pg_mode = 0;
285
286 if (!cpu_svm_has_intercept(env, SVM_EXIT_VMRUN)) {
287 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
288 }
289 if (asid == 0) {
290 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
291 }
292
293 if (nested_ctl & SVM_NPT_ENABLED) {
294 env->nested_cr3 = x86_ldq_phys(cs,
295 env->vm_vmcb + offsetof(struct vmcb,
296 control.nested_cr3));
297 env->hflags2 |= HF2_NPT_MASK;
298
299 env->nested_pg_mode = get_pg_mode(env) & PG_MODE_SVM_MASK;
300
301 tlb_flush_by_mmuidx(cs, 1 << MMU_NESTED_IDX);
302 }
303
304 /* enable intercepts */
305 env->hflags |= HF_GUEST_MASK;
306
307 env->tsc_offset = x86_ldq_phys(cs, env->vm_vmcb +
308 offsetof(struct vmcb, control.tsc_offset));
309
310 new_cr0 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cr0));
311 if (new_cr0 & SVM_CR0_RESERVED_MASK) {
312 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
313 }
314 if ((new_cr0 & CR0_NW_MASK) && !(new_cr0 & CR0_CD_MASK)) {
315 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
316 }
317 new_cr3 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cr3));
318 if ((env->efer & MSR_EFER_LMA) &&
319 (new_cr3 & ((~0ULL) << cpu->phys_bits))) {
320 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
321 }
322 new_cr4 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cr4));
323 if (new_cr4 & cr4_reserved_bits(env)) {
324 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
325 }
326 /* clear exit_info_2 so we behave like the real hardware */
327 x86_stq_phys(cs,
328 env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
329
330 cpu_x86_update_cr0(env, new_cr0);
331 cpu_x86_update_cr4(env, new_cr4);
332 cpu_x86_update_cr3(env, new_cr3);
333 env->cr[2] = x86_ldq_phys(cs,
334 env->vm_vmcb + offsetof(struct vmcb, save.cr2));
335 env->int_ctl = x86_ldl_phys(cs,
336 env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
337 env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
338 if (env->int_ctl & V_INTR_MASKING_MASK) {
339 env->hflags2 |= HF2_VINTR_MASK;
340 if (env->eflags & IF_MASK) {
341 env->hflags2 |= HF2_HIF_MASK;
342 }
343 }
344
345 cpu_load_efer(env,
346 x86_ldq_phys(cs,
347 env->vm_vmcb + offsetof(struct vmcb, save.efer)));
348 env->eflags = 0;
349 cpu_load_eflags(env, x86_ldq_phys(cs,
350 env->vm_vmcb + offsetof(struct vmcb,
351 save.rflags)),
352 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
353
354 svm_load_seg_cache(env, MMU_PHYS_IDX,
355 env->vm_vmcb + offsetof(struct vmcb, save.es), R_ES);
356 svm_load_seg_cache(env, MMU_PHYS_IDX,
357 env->vm_vmcb + offsetof(struct vmcb, save.cs), R_CS);
358 svm_load_seg_cache(env, MMU_PHYS_IDX,
359 env->vm_vmcb + offsetof(struct vmcb, save.ss), R_SS);
360 svm_load_seg_cache(env, MMU_PHYS_IDX,
361 env->vm_vmcb + offsetof(struct vmcb, save.ds), R_DS);
362 svm_load_seg(env, MMU_PHYS_IDX,
363 env->vm_vmcb + offsetof(struct vmcb, save.idtr), &env->idt);
364 svm_load_seg(env, MMU_PHYS_IDX,
365 env->vm_vmcb + offsetof(struct vmcb, save.gdtr), &env->gdt);
366
367 env->eip = x86_ldq_phys(cs,
368 env->vm_vmcb + offsetof(struct vmcb, save.rip));
369
370 env->regs[R_ESP] = x86_ldq_phys(cs,
371 env->vm_vmcb + offsetof(struct vmcb, save.rsp));
372 env->regs[R_EAX] = x86_ldq_phys(cs,
373 env->vm_vmcb + offsetof(struct vmcb, save.rax));
374
375 new_dr7 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.dr7));
376 new_dr6 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.dr6));
377
378 #ifdef TARGET_X86_64
379 if (new_dr7 & DR_RESERVED_MASK) {
380 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
381 }
382 if (new_dr6 & DR_RESERVED_MASK) {
383 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
384 }
385 #endif
386
387 cpu_x86_update_dr7(env, new_dr7);
388 env->dr[6] = new_dr6;
389
390 if (is_efer_invalid_state(env)) {
391 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
392 }
393
394 switch (x86_ldub_phys(cs,
395 env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
396 case TLB_CONTROL_DO_NOTHING:
397 break;
398 case TLB_CONTROL_FLUSH_ALL_ASID:
399 /* FIXME: this is not 100% correct but should work for now */
400 tlb_flush(cs);
401 break;
402 }
403
404 env->hflags2 |= HF2_GIF_MASK;
405
406 if (ctl_has_irq(env)) {
407 cpu_set_interrupt(cs, CPU_INTERRUPT_VIRQ);
408 }
409
410 if (virtual_gif_set(env)) {
411 env->hflags2 |= HF2_VGIF_MASK;
412 }
413
414 /* maybe we need to inject an event */
415 event_inj = x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
416 control.event_inj));
417 if (event_inj & SVM_EVTINJ_VALID) {
418 uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
419 uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
420 uint32_t event_inj_err = x86_ldl_phys(cs, env->vm_vmcb +
421 offsetof(struct vmcb,
422 control.event_inj_err));
423
424 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
425 /* FIXME: need to implement valid_err */
426 switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
427 case SVM_EVTINJ_TYPE_INTR:
428 cs->exception_index = vector;
429 env->error_code = event_inj_err;
430 env->exception_is_int = 0;
431 env->exception_next_eip = -1;
432 qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
433 /* XXX: is it always correct? */
434 do_interrupt_x86_hardirq(env, vector, 1);
435 break;
436 case SVM_EVTINJ_TYPE_NMI:
437 cs->exception_index = EXCP02_NMI;
438 env->error_code = event_inj_err;
439 env->exception_is_int = 0;
440 env->exception_next_eip = env->eip;
441 qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
442 cpu_loop_exit(cs);
443 break;
444 case SVM_EVTINJ_TYPE_EXEPT:
445 if (vector == EXCP02_NMI || vector >= 31) {
446 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
447 }
448 cs->exception_index = vector;
449 env->error_code = event_inj_err;
450 env->exception_is_int = 0;
451 env->exception_next_eip = -1;
452 qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
453 cpu_loop_exit(cs);
454 break;
455 case SVM_EVTINJ_TYPE_SOFT:
456 cs->exception_index = vector;
457 env->error_code = event_inj_err;
458 env->exception_is_int = 1;
459 env->exception_next_eip = env->eip;
460 qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
461 cpu_loop_exit(cs);
462 break;
463 default:
464 cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
465 break;
466 }
467 qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", cs->exception_index,
468 env->error_code);
469 }
470 }
471
472 void helper_vmmcall(CPUX86State *env)
473 {
474 cpu_svm_check_intercept_param(env, SVM_EXIT_VMMCALL, 0, GETPC());
475 raise_exception(env, EXCP06_ILLOP);
476 }
477
478 void helper_vmload(CPUX86State *env, int aflag)
479 {
480 int mmu_idx = MMU_PHYS_IDX;
481 target_ulong addr;
482
483 if (aflag == 2) {
484 addr = env->regs[R_EAX];
485 } else {
486 addr = (uint32_t)env->regs[R_EAX];
487 }
488
489 /* Exceptions are checked before the intercept. */
490 if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
491 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
492 }
493
494 cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
495
496 if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMLOAD, GETPC())) {
497 mmu_idx = MMU_NESTED_IDX;
498 }
499
500 svm_load_seg_cache(env, mmu_idx,
501 addr + offsetof(struct vmcb, save.fs), R_FS);
502 svm_load_seg_cache(env, mmu_idx,
503 addr + offsetof(struct vmcb, save.gs), R_GS);
504 svm_load_seg(env, mmu_idx,
505 addr + offsetof(struct vmcb, save.tr), &env->tr);
506 svm_load_seg(env, mmu_idx,
507 addr + offsetof(struct vmcb, save.ldtr), &env->ldt);
508
509 #ifdef TARGET_X86_64
510 env->kernelgsbase =
511 cpu_ldq_le_mmuidx_ra(env,
512 addr + offsetof(struct vmcb, save.kernel_gs_base),
513 mmu_idx, 0);
514 env->lstar =
515 cpu_ldq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.lstar),
516 mmu_idx, 0);
517 env->cstar =
518 cpu_ldq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.cstar),
519 mmu_idx, 0);
520 env->fmask =
521 cpu_ldq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.sfmask),
522 mmu_idx, 0);
523 svm_canonicalization(env, &env->kernelgsbase);
524 #endif
525 env->star =
526 cpu_ldq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.star),
527 mmu_idx, 0);
528 env->sysenter_cs =
529 cpu_ldq_le_mmuidx_ra(env,
530 addr + offsetof(struct vmcb, save.sysenter_cs),
531 mmu_idx, 0);
532 env->sysenter_esp =
533 cpu_ldq_le_mmuidx_ra(env,
534 addr + offsetof(struct vmcb, save.sysenter_esp),
535 mmu_idx, 0);
536 env->sysenter_eip =
537 cpu_ldq_le_mmuidx_ra(env,
538 addr + offsetof(struct vmcb, save.sysenter_eip),
539 mmu_idx, 0);
540 }
541
542 void helper_vmsave(CPUX86State *env, int aflag)
543 {
544 int mmu_idx = MMU_PHYS_IDX;
545 target_ulong addr;
546
547 if (aflag == 2) {
548 addr = env->regs[R_EAX];
549 } else {
550 addr = (uint32_t)env->regs[R_EAX];
551 }
552
553 /* Exceptions are checked before the intercept. */
554 if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
555 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
556 }
557
558 cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
559
560 if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMSAVE, GETPC())) {
561 mmu_idx = MMU_NESTED_IDX;
562 }
563
564 svm_save_seg(env, mmu_idx, addr + offsetof(struct vmcb, save.fs),
565 &env->segs[R_FS]);
566 svm_save_seg(env, mmu_idx, addr + offsetof(struct vmcb, save.gs),
567 &env->segs[R_GS]);
568 svm_save_seg(env, mmu_idx, addr + offsetof(struct vmcb, save.tr),
569 &env->tr);
570 svm_save_seg(env, mmu_idx, addr + offsetof(struct vmcb, save.ldtr),
571 &env->ldt);
572
573 #ifdef TARGET_X86_64
574 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.kernel_gs_base),
575 env->kernelgsbase, mmu_idx, 0);
576 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.lstar),
577 env->lstar, mmu_idx, 0);
578 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.cstar),
579 env->cstar, mmu_idx, 0);
580 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.sfmask),
581 env->fmask, mmu_idx, 0);
582 #endif
583 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.star),
584 env->star, mmu_idx, 0);
585 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.sysenter_cs),
586 env->sysenter_cs, mmu_idx, 0);
587 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.sysenter_esp),
588 env->sysenter_esp, mmu_idx, 0);
589 cpu_stq_le_mmuidx_ra(env, addr + offsetof(struct vmcb, save.sysenter_eip),
590 env->sysenter_eip, mmu_idx, 0);
591 }
592
593 void helper_stgi(CPUX86State *env)
594 {
595 cpu_svm_check_intercept_param(env, SVM_EXIT_STGI, 0, GETPC());
596
597 if (virtual_gif_enabled(env)) {
598 env->int_ctl |= V_GIF_MASK;
599 env->hflags2 |= HF2_VGIF_MASK;
600 } else {
601 env->hflags2 |= HF2_GIF_MASK;
602 }
603 }
604
605 void helper_clgi(CPUX86State *env)
606 {
607 cpu_svm_check_intercept_param(env, SVM_EXIT_CLGI, 0, GETPC());
608
609 if (virtual_gif_enabled(env)) {
610 env->int_ctl &= ~V_GIF_MASK;
611 env->hflags2 &= ~HF2_VGIF_MASK;
612 } else {
613 env->hflags2 &= ~HF2_GIF_MASK;
614 }
615 }
616
617 bool cpu_svm_has_intercept(CPUX86State *env, uint32_t type)
618 {
619 switch (type) {
620 case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
621 if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
622 return true;
623 }
624 break;
625 case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
626 if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
627 return true;
628 }
629 break;
630 case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
631 if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
632 return true;
633 }
634 break;
635 case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
636 if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
637 return true;
638 }
639 break;
640 case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
641 if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
642 return true;
643 }
644 break;
645 default:
646 if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
647 return true;
648 }
649 break;
650 }
651 return false;
652 }
653
654 void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
655 uint64_t param, uintptr_t retaddr)
656 {
657 CPUState *cs = env_cpu(env);
658
659 if (likely(!(env->hflags & HF_GUEST_MASK))) {
660 return;
661 }
662
663 if (!cpu_svm_has_intercept(env, type)) {
664 return;
665 }
666
667 if (type == SVM_EXIT_MSR) {
668 /* FIXME: this should be read in at vmrun (faster this way?) */
669 uint64_t addr = x86_ldq_phys(cs, env->vm_vmcb +
670 offsetof(struct vmcb,
671 control.msrpm_base_pa));
672 uint32_t t0, t1;
673
674 switch ((uint32_t)env->regs[R_ECX]) {
675 case 0 ... 0x1fff:
676 t0 = (env->regs[R_ECX] * 2) % 8;
677 t1 = (env->regs[R_ECX] * 2) / 8;
678 break;
679 case 0xc0000000 ... 0xc0001fff:
680 t0 = (8192 + env->regs[R_ECX] - 0xc0000000) * 2;
681 t1 = (t0 / 8);
682 t0 %= 8;
683 break;
684 case 0xc0010000 ... 0xc0011fff:
685 t0 = (16384 + env->regs[R_ECX] - 0xc0010000) * 2;
686 t1 = (t0 / 8);
687 t0 %= 8;
688 break;
689 default:
690 cpu_vmexit(env, type, param, retaddr);
691 t0 = 0;
692 t1 = 0;
693 break;
694 }
695 if (x86_ldub_phys(cs, addr + t1) & ((1 << param) << t0)) {
696 cpu_vmexit(env, type, param, retaddr);
697 }
698 return;
699 }
700
701 cpu_vmexit(env, type, param, retaddr);
702 }
703
704 void helper_svm_check_intercept(CPUX86State *env, uint32_t type)
705 {
706 cpu_svm_check_intercept_param(env, type, 0, GETPC());
707 }
708
709 void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
710 uint32_t next_eip_addend)
711 {
712 CPUState *cs = env_cpu(env);
713
714 if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
715 /* FIXME: this should be read in at vmrun (faster this way?) */
716 uint64_t addr = x86_ldq_phys(cs, env->vm_vmcb +
717 offsetof(struct vmcb, control.iopm_base_pa));
718 uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
719
720 if (x86_lduw_phys(cs, addr + port / 8) & (mask << (port & 7))) {
721 /* next env->eip */
722 x86_stq_phys(cs,
723 env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
724 env->eip + next_eip_addend);
725 cpu_vmexit(env, SVM_EXIT_IOIO, param | (port << 16), GETPC());
726 }
727 }
728 }
729
730 void cpu_vmexit(CPUX86State *env, uint64_t exit_code, uint64_t exit_info_1,
731 uintptr_t retaddr)
732 {
733 CPUState *cs = env_cpu(env);
734
735 cpu_restore_state(cs, retaddr);
736
737 qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
738 PRIx64 ", " TARGET_FMT_lx ")!\n",
739 (uint32_t)exit_code, exit_info_1,
740 x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
741 control.exit_info_2)),
742 env->eip);
743
744 cs->exception_index = EXCP_VMEXIT;
745 x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_code),
746 exit_code);
747
748 x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
749 control.exit_info_1), exit_info_1);
750
751 /* remove any pending exception */
752 env->old_exception = -1;
753 cpu_loop_exit(cs);
754 }
755
756 void do_vmexit(CPUX86State *env)
757 {
758 CPUState *cs = env_cpu(env);
759
760 if (env->hflags & HF_INHIBIT_IRQ_MASK) {
761 x86_stl_phys(cs,
762 env->vm_vmcb + offsetof(struct vmcb, control.int_state),
763 SVM_INTERRUPT_SHADOW_MASK);
764 env->hflags &= ~HF_INHIBIT_IRQ_MASK;
765 } else {
766 x86_stl_phys(cs,
767 env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
768 }
769 env->hflags2 &= ~HF2_NPT_MASK;
770 tlb_flush_by_mmuidx(cs, 1 << MMU_NESTED_IDX);
771
772 /* Save the VM state in the vmcb */
773 svm_save_seg(env, MMU_PHYS_IDX,
774 env->vm_vmcb + offsetof(struct vmcb, save.es),
775 &env->segs[R_ES]);
776 svm_save_seg(env, MMU_PHYS_IDX,
777 env->vm_vmcb + offsetof(struct vmcb, save.cs),
778 &env->segs[R_CS]);
779 svm_save_seg(env, MMU_PHYS_IDX,
780 env->vm_vmcb + offsetof(struct vmcb, save.ss),
781 &env->segs[R_SS]);
782 svm_save_seg(env, MMU_PHYS_IDX,
783 env->vm_vmcb + offsetof(struct vmcb, save.ds),
784 &env->segs[R_DS]);
785
786 x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base),
787 env->gdt.base);
788 x86_stl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit),
789 env->gdt.limit);
790
791 x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.idtr.base),
792 env->idt.base);
793 x86_stl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit),
794 env->idt.limit);
795
796 x86_stq_phys(cs,
797 env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
798 x86_stq_phys(cs,
799 env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
800 x86_stq_phys(cs,
801 env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
802 x86_stq_phys(cs,
803 env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
804 x86_stq_phys(cs,
805 env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
806 x86_stl_phys(cs,
807 env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), env->int_ctl);
808
809 x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.rflags),
810 cpu_compute_eflags(env));
811 x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.rip),
812 env->eip);
813 x86_stq_phys(cs,
814 env->vm_vmcb + offsetof(struct vmcb, save.rsp), env->regs[R_ESP]);
815 x86_stq_phys(cs,
816 env->vm_vmcb + offsetof(struct vmcb, save.rax), env->regs[R_EAX]);
817 x86_stq_phys(cs,
818 env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
819 x86_stq_phys(cs,
820 env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
821 x86_stb_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cpl),
822 env->hflags & HF_CPL_MASK);
823
824 /* Reload the host state from vm_hsave */
825 env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
826 env->hflags &= ~HF_GUEST_MASK;
827 env->intercept = 0;
828 env->intercept_exceptions = 0;
829
830 /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
831 cpu_reset_interrupt(cs, CPU_INTERRUPT_VIRQ);
832 env->int_ctl = 0;
833
834 /* Clears the TSC_OFFSET inside the processor. */
835 env->tsc_offset = 0;
836
837 env->gdt.base = x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb,
838 save.gdtr.base));
839 env->gdt.limit = x86_ldl_phys(cs, env->vm_hsave + offsetof(struct vmcb,
840 save.gdtr.limit));
841
842 env->idt.base = x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb,
843 save.idtr.base));
844 env->idt.limit = x86_ldl_phys(cs, env->vm_hsave + offsetof(struct vmcb,
845 save.idtr.limit));
846
847 cpu_x86_update_cr0(env, x86_ldq_phys(cs,
848 env->vm_hsave + offsetof(struct vmcb,
849 save.cr0)) |
850 CR0_PE_MASK);
851 cpu_x86_update_cr4(env, x86_ldq_phys(cs,
852 env->vm_hsave + offsetof(struct vmcb,
853 save.cr4)));
854
855 /*
856 * Resets the current ASID register to zero (host ASID; TLB flush).
857 *
858 * If the host is in PAE mode, the processor reloads the host's PDPEs
859 * from the page table indicated the host's CR3. FIXME: If the PDPEs
860 * contain illegal state, the processor causes a shutdown (QEMU does
861 * not implement PDPTRs).
862 */
863 cpu_x86_update_cr3(env, x86_ldq_phys(cs,
864 env->vm_hsave + offsetof(struct vmcb,
865 save.cr3)));
866 /* we need to set the efer after the crs so the hidden flags get
867 set properly */
868 cpu_load_efer(env, x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb,
869 save.efer)));
870
871 /* Completion of the VMRUN instruction clears the host EFLAGS.RF bit. */
872 env->eflags = 0;
873 cpu_load_eflags(env, x86_ldq_phys(cs,
874 env->vm_hsave + offsetof(struct vmcb,
875 save.rflags)),
876 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK |
877 RF_MASK | VM_MASK));
878
879 svm_load_seg_cache(env, MMU_PHYS_IDX,
880 env->vm_hsave + offsetof(struct vmcb, save.es), R_ES);
881 svm_load_seg_cache(env, MMU_PHYS_IDX,
882 env->vm_hsave + offsetof(struct vmcb, save.cs), R_CS);
883 svm_load_seg_cache(env, MMU_PHYS_IDX,
884 env->vm_hsave + offsetof(struct vmcb, save.ss), R_SS);
885 svm_load_seg_cache(env, MMU_PHYS_IDX,
886 env->vm_hsave + offsetof(struct vmcb, save.ds), R_DS);
887
888 env->eip = x86_ldq_phys(cs,
889 env->vm_hsave + offsetof(struct vmcb, save.rip));
890 env->regs[R_ESP] = x86_ldq_phys(cs, env->vm_hsave +
891 offsetof(struct vmcb, save.rsp));
892 env->regs[R_EAX] = x86_ldq_phys(cs, env->vm_hsave +
893 offsetof(struct vmcb, save.rax));
894
895 env->dr[6] = x86_ldq_phys(cs,
896 env->vm_hsave + offsetof(struct vmcb, save.dr6));
897
898 /* Disables all breakpoints in the host DR7 register. */
899 cpu_x86_update_dr7(env,
900 x86_ldq_phys(cs,
901 env->vm_hsave + offsetof(struct vmcb, save.dr7)) & ~0xff);
902
903 /* other setups */
904 x86_stl_phys(cs,
905 env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info),
906 x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
907 control.event_inj)));
908 x86_stl_phys(cs,
909 env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err),
910 x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
911 control.event_inj_err)));
912 x86_stl_phys(cs,
913 env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 0);
914
915 env->hflags2 &= ~HF2_GIF_MASK;
916 env->hflags2 &= ~HF2_VGIF_MASK;
917
918
919 /* FIXME: Checks the reloaded host state for consistency. */
920
921 /*
922 * EFLAGS.TF causes a #DB trap after the VMRUN completes on the host
923 * side (i.e., after the #VMEXIT from the guest). Since we're running
924 * in the main loop, call do_interrupt_all directly.
925 */
926 if ((env->eflags & TF_MASK) != 0) {
927 env->dr[6] |= DR6_BS;
928 do_interrupt_all(X86_CPU(cs), EXCP01_DB, 0, 0, env->eip, 0);
929 }
930 }