aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2011-03-31 06:06:41 -0400
committerAvi Kivity <avi@redhat.com>2011-05-11 07:57:08 -0400
commit7ae441eac521b2006c9f03c4f2a23582c07fd76d (patch)
treede57202d5fefed3a7bff36c8ac688bd1fc86f5b8 /arch/x86/kvm
parent618ff15de19109af126b33d90d7eaec27e61c691 (diff)
KVM: emulator: do not needlesly sync registers from emulator ctxt to vcpu
Currently we sync registers back and forth before/after exiting to userspace for IO, but during IO device model shouldn't need to read/write the registers, so we can as well skip those sync points. The only exaception is broken vmware backdor interface. The new code sync registers content during IO only if registers are read from/written to by userspace in the middle of the IO operation and this almost never happens in practise. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/x86.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 1d5a7f418795..3416a3473849 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4420,6 +4420,7 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
4420 vcpu->arch.emulate_ctxt.guest_mode = is_guest_mode(vcpu); 4420 vcpu->arch.emulate_ctxt.guest_mode = is_guest_mode(vcpu);
4421 memset(c, 0, sizeof(struct decode_cache)); 4421 memset(c, 0, sizeof(struct decode_cache));
4422 memcpy(c->regs, vcpu->arch.regs, sizeof c->regs); 4422 memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
4423 vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
4423} 4424}
4424 4425
4425int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq) 4426int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq)
@@ -4502,6 +4503,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
4502{ 4503{
4503 int r; 4504 int r;
4504 struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode; 4505 struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
4506 bool writeback = true;
4505 4507
4506 kvm_clear_exception_queue(vcpu); 4508 kvm_clear_exception_queue(vcpu);
4507 vcpu->arch.mmio_fault_cr2 = cr2; 4509 vcpu->arch.mmio_fault_cr2 = cr2;
@@ -4542,9 +4544,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
4542 return EMULATE_DONE; 4544 return EMULATE_DONE;
4543 } 4545 }
4544 4546
4545 /* this is needed for vmware backdor interface to work since it 4547 /* this is needed for vmware backdoor interface to work since it
4546 changes registers values during IO operation */ 4548 changes registers values during IO operation */
4547 memcpy(c->regs, vcpu->arch.regs, sizeof c->regs); 4549 if (vcpu->arch.emulate_regs_need_sync_from_vcpu) {
4550 vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
4551 memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
4552 }
4548 4553
4549restart: 4554restart:
4550 r = x86_emulate_insn(&vcpu->arch.emulate_ctxt); 4555 r = x86_emulate_insn(&vcpu->arch.emulate_ctxt);
@@ -4565,19 +4570,28 @@ restart:
4565 } else if (vcpu->arch.pio.count) { 4570 } else if (vcpu->arch.pio.count) {
4566 if (!vcpu->arch.pio.in) 4571 if (!vcpu->arch.pio.in)
4567 vcpu->arch.pio.count = 0; 4572 vcpu->arch.pio.count = 0;
4573 else
4574 writeback = false;
4568 r = EMULATE_DO_MMIO; 4575 r = EMULATE_DO_MMIO;
4569 } else if (vcpu->mmio_needed) 4576 } else if (vcpu->mmio_needed) {
4577 if (!vcpu->mmio_is_write)
4578 writeback = false;
4570 r = EMULATE_DO_MMIO; 4579 r = EMULATE_DO_MMIO;
4571 else if (r == EMULATION_RESTART) 4580 } else if (r == EMULATION_RESTART)
4572 goto restart; 4581 goto restart;
4573 else 4582 else
4574 r = EMULATE_DONE; 4583 r = EMULATE_DONE;
4575 4584
4576 toggle_interruptibility(vcpu, vcpu->arch.emulate_ctxt.interruptibility); 4585 if (writeback) {
4577 kvm_set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags); 4586 toggle_interruptibility(vcpu,
4578 kvm_make_request(KVM_REQ_EVENT, vcpu); 4587 vcpu->arch.emulate_ctxt.interruptibility);
4579 memcpy(vcpu->arch.regs, c->regs, sizeof c->regs); 4588 kvm_set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
4580 kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip); 4589 kvm_make_request(KVM_REQ_EVENT, vcpu);
4590 memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
4591 vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
4592 kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
4593 } else
4594 vcpu->arch.emulate_regs_need_sync_to_vcpu = true;
4581 4595
4582 return r; 4596 return r;
4583} 4597}
@@ -5587,6 +5601,18 @@ out:
5587 5601
5588int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 5602int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
5589{ 5603{
5604 if (vcpu->arch.emulate_regs_need_sync_to_vcpu) {
5605 /*
5606 * We are here if userspace calls get_regs() in the middle of
5607 * instruction emulation. Registers state needs to be copied
5608 * back from emulation context to vcpu. Usrapace shouldn't do
5609 * that usually, but some bad designed PV devices (vmware
5610 * backdoor interface) need this to work
5611 */
5612 struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
5613 memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
5614 vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
5615 }
5590 regs->rax = kvm_register_read(vcpu, VCPU_REGS_RAX); 5616 regs->rax = kvm_register_read(vcpu, VCPU_REGS_RAX);
5591 regs->rbx = kvm_register_read(vcpu, VCPU_REGS_RBX); 5617 regs->rbx = kvm_register_read(vcpu, VCPU_REGS_RBX);
5592 regs->rcx = kvm_register_read(vcpu, VCPU_REGS_RCX); 5618 regs->rcx = kvm_register_read(vcpu, VCPU_REGS_RCX);
@@ -5614,6 +5640,9 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
5614 5640
5615int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 5641int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
5616{ 5642{
5643 vcpu->arch.emulate_regs_need_sync_from_vcpu = true;
5644 vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
5645
5617 kvm_register_write(vcpu, VCPU_REGS_RAX, regs->rax); 5646 kvm_register_write(vcpu, VCPU_REGS_RAX, regs->rax);
5618 kvm_register_write(vcpu, VCPU_REGS_RBX, regs->rbx); 5647 kvm_register_write(vcpu, VCPU_REGS_RBX, regs->rbx);
5619 kvm_register_write(vcpu, VCPU_REGS_RCX, regs->rcx); 5648 kvm_register_write(vcpu, VCPU_REGS_RCX, regs->rcx);