Revision 2c17449b target-i386/svm_helper.c
b/target-i386/svm_helper.c | ||
---|---|---|
105 | 105 |
unsigned int flags; |
106 | 106 |
|
107 | 107 |
sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector)); |
108 |
sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base)); |
|
108 |
sc->base = ldq_phys(cs->as, addr + offsetof(struct vmcb_seg, base));
|
|
109 | 109 |
sc->limit = ldl_phys(cs->as, addr + offsetof(struct vmcb_seg, limit)); |
110 | 110 |
flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib)); |
111 | 111 |
sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12); |
... | ... | |
178 | 178 |
|
179 | 179 |
/* load the interception bitmaps so we do not need to access the |
180 | 180 |
vmcb in svm mode */ |
181 |
env->intercept = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
181 |
env->intercept = ldq_phys(cs->as, env->vm_vmcb + offsetof(struct vmcb,
|
|
182 | 182 |
control.intercept)); |
183 | 183 |
env->intercept_cr_read = lduw_phys(env->vm_vmcb + |
184 | 184 |
offsetof(struct vmcb, |
... | ... | |
200 | 200 |
/* enable intercepts */ |
201 | 201 |
env->hflags |= HF_SVMI_MASK; |
202 | 202 |
|
203 |
env->tsc_offset = ldq_phys(env->vm_vmcb + |
|
203 |
env->tsc_offset = ldq_phys(cs->as, env->vm_vmcb +
|
|
204 | 204 |
offsetof(struct vmcb, control.tsc_offset)); |
205 | 205 |
|
206 |
env->gdt.base = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
206 |
env->gdt.base = ldq_phys(cs->as, env->vm_vmcb + offsetof(struct vmcb,
|
|
207 | 207 |
save.gdtr.base)); |
208 | 208 |
env->gdt.limit = ldl_phys(cs->as, env->vm_vmcb + offsetof(struct vmcb, |
209 | 209 |
save.gdtr.limit)); |
210 | 210 |
|
211 |
env->idt.base = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
211 |
env->idt.base = ldq_phys(cs->as, env->vm_vmcb + offsetof(struct vmcb,
|
|
212 | 212 |
save.idtr.base)); |
213 | 213 |
env->idt.limit = ldl_phys(cs->as, env->vm_vmcb + offsetof(struct vmcb, |
214 | 214 |
save.idtr.limit)); |
... | ... | |
216 | 216 |
/* clear exit_info_2 so we behave like the real hardware */ |
217 | 217 |
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0); |
218 | 218 |
|
219 |
cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
219 |
cpu_x86_update_cr0(env, ldq_phys(cs->as, |
|
220 |
env->vm_vmcb + offsetof(struct vmcb, |
|
220 | 221 |
save.cr0))); |
221 |
cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
222 |
cpu_x86_update_cr4(env, ldq_phys(cs->as, |
|
223 |
env->vm_vmcb + offsetof(struct vmcb, |
|
222 | 224 |
save.cr4))); |
223 |
cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
225 |
cpu_x86_update_cr3(env, ldq_phys(cs->as, |
|
226 |
env->vm_vmcb + offsetof(struct vmcb, |
|
224 | 227 |
save.cr3))); |
225 |
env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2)); |
|
228 |
env->cr[2] = ldq_phys(cs->as, |
|
229 |
env->vm_vmcb + offsetof(struct vmcb, save.cr2)); |
|
226 | 230 |
int_ctl = ldl_phys(cs->as, |
227 | 231 |
env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)); |
228 | 232 |
env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK); |
... | ... | |
235 | 239 |
} |
236 | 240 |
|
237 | 241 |
cpu_load_efer(env, |
238 |
ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer))); |
|
242 |
ldq_phys(cs->as, |
|
243 |
env->vm_vmcb + offsetof(struct vmcb, save.efer))); |
|
239 | 244 |
env->eflags = 0; |
240 |
cpu_load_eflags(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
245 |
cpu_load_eflags(env, ldq_phys(cs->as, |
|
246 |
env->vm_vmcb + offsetof(struct vmcb, |
|
241 | 247 |
save.rflags)), |
242 | 248 |
~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
243 | 249 |
CC_OP = CC_OP_EFLAGS; |
... | ... | |
251 | 257 |
svm_load_seg_cache(env, env->vm_vmcb + offsetof(struct vmcb, save.ds), |
252 | 258 |
R_DS); |
253 | 259 |
|
254 |
env->eip = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip)); |
|
255 |
|
|
256 |
env->regs[R_ESP] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp)); |
|
257 |
env->regs[R_EAX] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax)); |
|
258 |
env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7)); |
|
259 |
env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6)); |
|
260 |
cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
260 |
env->eip = ldq_phys(cs->as, |
|
261 |
env->vm_vmcb + offsetof(struct vmcb, save.rip)); |
|
262 |
|
|
263 |
env->regs[R_ESP] = ldq_phys(cs->as, |
|
264 |
env->vm_vmcb + offsetof(struct vmcb, save.rsp)); |
|
265 |
env->regs[R_EAX] = ldq_phys(cs->as, |
|
266 |
env->vm_vmcb + offsetof(struct vmcb, save.rax)); |
|
267 |
env->dr[7] = ldq_phys(cs->as, |
|
268 |
env->vm_vmcb + offsetof(struct vmcb, save.dr7)); |
|
269 |
env->dr[6] = ldq_phys(cs->as, |
|
270 |
env->vm_vmcb + offsetof(struct vmcb, save.dr6)); |
|
271 |
cpu_x86_set_cpl(env, ldub_phys(cs->as, |
|
272 |
env->vm_vmcb + offsetof(struct vmcb, |
|
261 | 273 |
save.cpl))); |
262 | 274 |
|
263 | 275 |
/* FIXME: guest state consistency checks */ |
264 | 276 |
|
265 |
switch (ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) { |
|
277 |
switch (ldub_phys(cs->as, |
|
278 |
env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) { |
|
266 | 279 |
case TLB_CONTROL_DO_NOTHING: |
267 | 280 |
break; |
268 | 281 |
case TLB_CONTROL_FLUSH_ALL_ASID: |
... | ... | |
339 | 352 |
|
340 | 353 |
void helper_vmload(CPUX86State *env, int aflag) |
341 | 354 |
{ |
355 |
CPUState *cs = ENV_GET_CPU(env); |
|
342 | 356 |
target_ulong addr; |
343 | 357 |
|
344 | 358 |
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0); |
... | ... | |
351 | 365 |
|
352 | 366 |
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx |
353 | 367 |
"\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", |
354 |
addr, ldq_phys(addr + offsetof(struct vmcb, |
|
368 |
addr, ldq_phys(cs->as, addr + offsetof(struct vmcb,
|
|
355 | 369 |
save.fs.base)), |
356 | 370 |
env->segs[R_FS].base); |
357 | 371 |
|
... | ... | |
361 | 375 |
svm_load_seg(env, addr + offsetof(struct vmcb, save.ldtr), &env->ldt); |
362 | 376 |
|
363 | 377 |
#ifdef TARGET_X86_64 |
364 |
env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, |
|
378 |
env->kernelgsbase = ldq_phys(cs->as, addr + offsetof(struct vmcb,
|
|
365 | 379 |
save.kernel_gs_base)); |
366 |
env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar)); |
|
367 |
env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar)); |
|
368 |
env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask)); |
|
380 |
env->lstar = ldq_phys(cs->as, addr + offsetof(struct vmcb, save.lstar));
|
|
381 |
env->cstar = ldq_phys(cs->as, addr + offsetof(struct vmcb, save.cstar));
|
|
382 |
env->fmask = ldq_phys(cs->as, addr + offsetof(struct vmcb, save.sfmask));
|
|
369 | 383 |
#endif |
370 |
env->star = ldq_phys(addr + offsetof(struct vmcb, save.star)); |
|
371 |
env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs)); |
|
372 |
env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, |
|
384 |
env->star = ldq_phys(cs->as, addr + offsetof(struct vmcb, save.star)); |
|
385 |
env->sysenter_cs = ldq_phys(cs->as, |
|
386 |
addr + offsetof(struct vmcb, save.sysenter_cs)); |
|
387 |
env->sysenter_esp = ldq_phys(cs->as, addr + offsetof(struct vmcb, |
|
373 | 388 |
save.sysenter_esp)); |
374 |
env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, |
|
389 |
env->sysenter_eip = ldq_phys(cs->as, addr + offsetof(struct vmcb,
|
|
375 | 390 |
save.sysenter_eip)); |
376 | 391 |
} |
377 | 392 |
|
378 | 393 |
void helper_vmsave(CPUX86State *env, int aflag) |
379 | 394 |
{ |
395 |
CPUState *cs = ENV_GET_CPU(env); |
|
380 | 396 |
target_ulong addr; |
381 | 397 |
|
382 | 398 |
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0); |
... | ... | |
389 | 405 |
|
390 | 406 |
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmsave! " TARGET_FMT_lx |
391 | 407 |
"\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", |
392 |
addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), |
|
408 |
addr, ldq_phys(cs->as, |
|
409 |
addr + offsetof(struct vmcb, save.fs.base)), |
|
393 | 410 |
env->segs[R_FS].base); |
394 | 411 |
|
395 | 412 |
svm_save_seg(env, addr + offsetof(struct vmcb, save.fs), |
... | ... | |
455 | 472 |
void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type, |
456 | 473 |
uint64_t param) |
457 | 474 |
{ |
475 |
CPUState *cs = ENV_GET_CPU(env); |
|
476 |
|
|
458 | 477 |
if (likely(!(env->hflags & HF_SVMI_MASK))) { |
459 | 478 |
return; |
460 | 479 |
} |
... | ... | |
487 | 506 |
case SVM_EXIT_MSR: |
488 | 507 |
if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) { |
489 | 508 |
/* FIXME: this should be read in at vmrun (faster this way?) */ |
490 |
uint64_t addr = ldq_phys(env->vm_vmcb + |
|
509 |
uint64_t addr = ldq_phys(cs->as, env->vm_vmcb +
|
|
491 | 510 |
offsetof(struct vmcb, |
492 | 511 |
control.msrpm_base_pa)); |
493 | 512 |
uint32_t t0, t1; |
... | ... | |
513 | 532 |
t1 = 0; |
514 | 533 |
break; |
515 | 534 |
} |
516 |
if (ldub_phys(addr + t1) & ((1 << param) << t0)) { |
|
535 |
if (ldub_phys(cs->as, addr + t1) & ((1 << param) << t0)) {
|
|
517 | 536 |
helper_vmexit(env, type, param); |
518 | 537 |
} |
519 | 538 |
} |
... | ... | |
535 | 554 |
void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param, |
536 | 555 |
uint32_t next_eip_addend) |
537 | 556 |
{ |
557 |
CPUState *cs = ENV_GET_CPU(env); |
|
538 | 558 |
if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) { |
539 | 559 |
/* FIXME: this should be read in at vmrun (faster this way?) */ |
540 |
uint64_t addr = ldq_phys(env->vm_vmcb + |
|
560 |
uint64_t addr = ldq_phys(cs->as, env->vm_vmcb +
|
|
541 | 561 |
offsetof(struct vmcb, control.iopm_base_pa)); |
542 | 562 |
uint16_t mask = (1 << ((param >> 4) & 7)) - 1; |
543 | 563 |
|
... | ... | |
559 | 579 |
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016" |
560 | 580 |
PRIx64 ", " TARGET_FMT_lx ")!\n", |
561 | 581 |
exit_code, exit_info_1, |
562 |
ldq_phys(env->vm_vmcb + offsetof(struct vmcb, |
|
582 |
ldq_phys(cs->as, env->vm_vmcb + offsetof(struct vmcb,
|
|
563 | 583 |
control.exit_info_2)), |
564 | 584 |
env->eip); |
565 | 585 |
|
... | ... | |
625 | 645 |
cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; |
626 | 646 |
env->tsc_offset = 0; |
627 | 647 |
|
628 |
env->gdt.base = ldq_phys(env->vm_hsave + offsetof(struct vmcb, |
|
648 |
env->gdt.base = ldq_phys(cs->as, env->vm_hsave + offsetof(struct vmcb,
|
|
629 | 649 |
save.gdtr.base)); |
630 | 650 |
env->gdt.limit = ldl_phys(cs->as, env->vm_hsave + offsetof(struct vmcb, |
631 | 651 |
save.gdtr.limit)); |
632 | 652 |
|
633 |
env->idt.base = ldq_phys(env->vm_hsave + offsetof(struct vmcb, |
|
653 |
env->idt.base = ldq_phys(cs->as, env->vm_hsave + offsetof(struct vmcb,
|
|
634 | 654 |
save.idtr.base)); |
635 | 655 |
env->idt.limit = ldl_phys(cs->as, env->vm_hsave + offsetof(struct vmcb, |
636 | 656 |
save.idtr.limit)); |
637 | 657 |
|
638 |
cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, |
|
658 |
cpu_x86_update_cr0(env, ldq_phys(cs->as, |
|
659 |
env->vm_hsave + offsetof(struct vmcb, |
|
639 | 660 |
save.cr0)) | |
640 | 661 |
CR0_PE_MASK); |
641 |
cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, |
|
662 |
cpu_x86_update_cr4(env, ldq_phys(cs->as, |
|
663 |
env->vm_hsave + offsetof(struct vmcb, |
|
642 | 664 |
save.cr4))); |
643 |
cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, |
|
665 |
cpu_x86_update_cr3(env, ldq_phys(cs->as, |
|
666 |
env->vm_hsave + offsetof(struct vmcb, |
|
644 | 667 |
save.cr3))); |
645 | 668 |
/* we need to set the efer after the crs so the hidden flags get |
646 | 669 |
set properly */ |
647 |
cpu_load_efer(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, |
|
670 |
cpu_load_efer(env, ldq_phys(cs->as, env->vm_hsave + offsetof(struct vmcb,
|
|
648 | 671 |
save.efer))); |
649 | 672 |
env->eflags = 0; |
650 |
cpu_load_eflags(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, |
|
673 |
cpu_load_eflags(env, ldq_phys(cs->as, |
|
674 |
env->vm_hsave + offsetof(struct vmcb, |
|
651 | 675 |
save.rflags)), |
652 | 676 |
~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
653 | 677 |
CC_OP = CC_OP_EFLAGS; |
... | ... | |
661 | 685 |
svm_load_seg_cache(env, env->vm_hsave + offsetof(struct vmcb, save.ds), |
662 | 686 |
R_DS); |
663 | 687 |
|
664 |
env->eip = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip)); |
|
665 |
env->regs[R_ESP] = ldq_phys(env->vm_hsave + |
|
688 |
env->eip = ldq_phys(cs->as, |
|
689 |
env->vm_hsave + offsetof(struct vmcb, save.rip)); |
|
690 |
env->regs[R_ESP] = ldq_phys(cs->as, env->vm_hsave + |
|
666 | 691 |
offsetof(struct vmcb, save.rsp)); |
667 |
env->regs[R_EAX] = ldq_phys(env->vm_hsave + |
|
692 |
env->regs[R_EAX] = ldq_phys(cs->as, env->vm_hsave +
|
|
668 | 693 |
offsetof(struct vmcb, save.rax)); |
669 | 694 |
|
670 |
env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6)); |
|
671 |
env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7)); |
|
695 |
env->dr[6] = ldq_phys(cs->as, |
|
696 |
env->vm_hsave + offsetof(struct vmcb, save.dr6)); |
|
697 |
env->dr[7] = ldq_phys(cs->as, |
|
698 |
env->vm_hsave + offsetof(struct vmcb, save.dr7)); |
|
672 | 699 |
|
673 | 700 |
/* other setups */ |
674 | 701 |
cpu_x86_set_cpl(env, 0); |
Also available in: Unified diff