aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-05-13 08:02:13 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-07-11 03:14:04 -0400
commit44583cba9188b29b20ceeefe8ae23ad19e26d9a4 (patch)
tree5c5566b5d4398cfccc3dc88194dcc6571ffbdebd /arch/x86/kvm
parent719d5a9b2487e0562f178f61e323c3dc18a8b200 (diff)
KVM: x86: use kvm_read_guest_page for emulator accesses
Emulator accesses are always done a page at a time, either by the emulator itself (for fetches) or because we need to query the MMU for address translations. Speed up these accesses by using kvm_read_guest_page and, in the case of fetches, by inlining kvm_read_guest_virt_helper and dropping the loop around kvm_read_guest_page. This final tweak saves 30-100 more clock cycles (4-10%), bringing the count (as measured by kvm-unit-tests) down to 720-1100 clock cycles on a Sandy Bridge Xeon host, compared to 2300-3200 before the whole series and 925-1700 after the first two low-hanging fruit changes. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/x86.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 905edf8557e7..f750b69ca443 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4085,7 +4085,8 @@ static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
4085 4085
4086 if (gpa == UNMAPPED_GVA) 4086 if (gpa == UNMAPPED_GVA)
4087 return X86EMUL_PROPAGATE_FAULT; 4087 return X86EMUL_PROPAGATE_FAULT;
4088 ret = kvm_read_guest(vcpu->kvm, gpa, data, toread); 4088 ret = kvm_read_guest_page(vcpu->kvm, gpa >> PAGE_SHIFT, data,
4089 offset, toread);
4089 if (ret < 0) { 4090 if (ret < 0) {
4090 r = X86EMUL_IO_NEEDED; 4091 r = X86EMUL_IO_NEEDED;
4091 goto out; 4092 goto out;
@@ -4106,10 +4107,24 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt,
4106{ 4107{
4107 struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); 4108 struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
4108 u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; 4109 u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
4110 unsigned offset;
4111 int ret;
4109 4112
4110 return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 4113 /* Inline kvm_read_guest_virt_helper for speed. */
4111 access | PFERR_FETCH_MASK, 4114 gpa_t gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, addr, access|PFERR_FETCH_MASK,
4112 exception); 4115 exception);
4116 if (unlikely(gpa == UNMAPPED_GVA))
4117 return X86EMUL_PROPAGATE_FAULT;
4118
4119 offset = addr & (PAGE_SIZE-1);
4120 if (WARN_ON(offset + bytes > PAGE_SIZE))
4121 bytes = (unsigned)PAGE_SIZE - offset;
4122 ret = kvm_read_guest_page(vcpu->kvm, gpa >> PAGE_SHIFT, val,
4123 offset, bytes);
4124 if (unlikely(ret < 0))
4125 return X86EMUL_IO_NEEDED;
4126
4127 return X86EMUL_CONTINUE;
4113} 4128}
4114 4129
4115int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt, 4130int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,