aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-08-27 16:46:17 -0400
committerMarcelo Tosatti <mtosatti@redhat.com>2012-08-27 17:38:55 -0400
commitdd856efafe6097a5c9104725c2bca74430423db8 (patch)
treed074a16680f3a39798f372e16426476aa7f6e1df /arch/x86/kvm/x86.c
parent66a03505a7fcc70187319ef2318832f4d3c451a6 (diff)
KVM: x86 emulator: access GPRs on demand
Instead of populating the entire register file, read in registers as they are accessed, and write back only the modified ones. This saves a VMREAD and VMWRITE on Intel (for rsp, since it is not usually used during emulation), and a two 128-byte copies for the registers. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c45
1 files changed, 18 insertions, 27 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 42bbf4187d20..e00050ce7a6a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4313,7 +4313,19 @@ static void emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
4313 kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx); 4313 kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx);
4314} 4314}
4315 4315
4316static ulong emulator_read_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg)
4317{
4318 return kvm_register_read(emul_to_vcpu(ctxt), reg);
4319}
4320
4321static void emulator_write_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg, ulong val)
4322{
4323 kvm_register_write(emul_to_vcpu(ctxt), reg, val);
4324}
4325
4316static struct x86_emulate_ops emulate_ops = { 4326static struct x86_emulate_ops emulate_ops = {
4327 .read_gpr = emulator_read_gpr,
4328 .write_gpr = emulator_write_gpr,
4317 .read_std = kvm_read_guest_virt_system, 4329 .read_std = kvm_read_guest_virt_system,
4318 .write_std = kvm_write_guest_virt_system, 4330 .write_std = kvm_write_guest_virt_system,
4319 .fetch = kvm_fetch_guest_virt, 4331 .fetch = kvm_fetch_guest_virt,
@@ -4348,14 +4360,6 @@ static struct x86_emulate_ops emulate_ops = {
4348 .get_cpuid = emulator_get_cpuid, 4360 .get_cpuid = emulator_get_cpuid,
4349}; 4361};
4350 4362
4351static void cache_all_regs(struct kvm_vcpu *vcpu)
4352{
4353 kvm_register_read(vcpu, VCPU_REGS_RAX);
4354 kvm_register_read(vcpu, VCPU_REGS_RSP);
4355 kvm_register_read(vcpu, VCPU_REGS_RIP);
4356 vcpu->arch.regs_dirty = ~0;
4357}
4358
4359static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask) 4363static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
4360{ 4364{
4361 u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(vcpu, mask); 4365 u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(vcpu, mask);
@@ -4382,12 +4386,10 @@ static void inject_emulated_exception(struct kvm_vcpu *vcpu)
4382 kvm_queue_exception(vcpu, ctxt->exception.vector); 4386 kvm_queue_exception(vcpu, ctxt->exception.vector);
4383} 4387}
4384 4388
4385static void init_decode_cache(struct x86_emulate_ctxt *ctxt, 4389static void init_decode_cache(struct x86_emulate_ctxt *ctxt)
4386 const unsigned long *regs)
4387{ 4390{
4388 memset(&ctxt->twobyte, 0, 4391 memset(&ctxt->twobyte, 0,
4389 (void *)&ctxt->regs - (void *)&ctxt->twobyte); 4392 (void *)&ctxt->_regs - (void *)&ctxt->twobyte);
4390 memcpy(ctxt->regs, regs, sizeof(ctxt->regs));
4391 4393
4392 ctxt->fetch.start = 0; 4394 ctxt->fetch.start = 0;
4393 ctxt->fetch.end = 0; 4395 ctxt->fetch.end = 0;
@@ -4402,14 +4404,6 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
4402 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt; 4404 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
4403 int cs_db, cs_l; 4405 int cs_db, cs_l;
4404 4406
4405 /*
4406 * TODO: fix emulate.c to use guest_read/write_register
4407 * instead of direct ->regs accesses, can save hundred cycles
4408 * on Intel for instructions that don't read/change RSP, for
4409 * for example.
4410 */
4411 cache_all_regs(vcpu);
4412
4413 kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); 4407 kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
4414 4408
4415 ctxt->eflags = kvm_get_rflags(vcpu); 4409 ctxt->eflags = kvm_get_rflags(vcpu);
@@ -4421,7 +4415,7 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
4421 X86EMUL_MODE_PROT16; 4415 X86EMUL_MODE_PROT16;
4422 ctxt->guest_mode = is_guest_mode(vcpu); 4416 ctxt->guest_mode = is_guest_mode(vcpu);
4423 4417
4424 init_decode_cache(ctxt, vcpu->arch.regs); 4418 init_decode_cache(ctxt);
4425 vcpu->arch.emulate_regs_need_sync_from_vcpu = false; 4419 vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
4426} 4420}
4427 4421
@@ -4441,7 +4435,6 @@ int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip)
4441 return EMULATE_FAIL; 4435 return EMULATE_FAIL;
4442 4436
4443 ctxt->eip = ctxt->_eip; 4437 ctxt->eip = ctxt->_eip;
4444 memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
4445 kvm_rip_write(vcpu, ctxt->eip); 4438 kvm_rip_write(vcpu, ctxt->eip);
4446 kvm_set_rflags(vcpu, ctxt->eflags); 4439 kvm_set_rflags(vcpu, ctxt->eflags);
4447 4440
@@ -4599,7 +4592,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
4599 changes registers values during IO operation */ 4592 changes registers values during IO operation */
4600 if (vcpu->arch.emulate_regs_need_sync_from_vcpu) { 4593 if (vcpu->arch.emulate_regs_need_sync_from_vcpu) {
4601 vcpu->arch.emulate_regs_need_sync_from_vcpu = false; 4594 vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
4602 memcpy(ctxt->regs, vcpu->arch.regs, sizeof ctxt->regs); 4595 emulator_invalidate_register_cache(ctxt);
4603 } 4596 }
4604 4597
4605restart: 4598restart:
@@ -4637,7 +4630,6 @@ restart:
4637 toggle_interruptibility(vcpu, ctxt->interruptibility); 4630 toggle_interruptibility(vcpu, ctxt->interruptibility);
4638 kvm_set_rflags(vcpu, ctxt->eflags); 4631 kvm_set_rflags(vcpu, ctxt->eflags);
4639 kvm_make_request(KVM_REQ_EVENT, vcpu); 4632 kvm_make_request(KVM_REQ_EVENT, vcpu);
4640 memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
4641 vcpu->arch.emulate_regs_need_sync_to_vcpu = false; 4633 vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
4642 kvm_rip_write(vcpu, ctxt->eip); 4634 kvm_rip_write(vcpu, ctxt->eip);
4643 } else 4635 } else
@@ -5591,8 +5583,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
5591 * that usually, but some bad designed PV devices (vmware 5583 * that usually, but some bad designed PV devices (vmware
5592 * backdoor interface) need this to work 5584 * backdoor interface) need this to work
5593 */ 5585 */
5594 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt; 5586 emulator_writeback_register_cache(&vcpu->arch.emulate_ctxt);
5595 memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
5596 vcpu->arch.emulate_regs_need_sync_to_vcpu = false; 5587 vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
5597 } 5588 }
5598 regs->rax = kvm_register_read(vcpu, VCPU_REGS_RAX); 5589 regs->rax = kvm_register_read(vcpu, VCPU_REGS_RAX);
@@ -5723,6 +5714,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
5723{ 5714{
5724 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt; 5715 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
5725 int ret; 5716 int ret;
5717 unsigned reg;
5726 5718
5727 init_emulate_ctxt(vcpu); 5719 init_emulate_ctxt(vcpu);
5728 5720
@@ -5732,7 +5724,6 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
5732 if (ret) 5724 if (ret)
5733 return EMULATE_FAIL; 5725 return EMULATE_FAIL;
5734 5726
5735 memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
5736 kvm_rip_write(vcpu, ctxt->eip); 5727 kvm_rip_write(vcpu, ctxt->eip);
5737 kvm_set_rflags(vcpu, ctxt->eflags); 5728 kvm_set_rflags(vcpu, ctxt->eflags);
5738 kvm_make_request(KVM_REQ_EVENT, vcpu); 5729 kvm_make_request(KVM_REQ_EVENT, vcpu);