diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-05-13 08:02:13 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-07-11 03:14:04 -0400 |
commit | 44583cba9188b29b20ceeefe8ae23ad19e26d9a4 (patch) | |
tree | 5c5566b5d4398cfccc3dc88194dcc6571ffbdebd /arch/x86/kvm | |
parent | 719d5a9b2487e0562f178f61e323c3dc18a8b200 (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.c | 23 |
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 | ||
4115 | int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt, | 4130 | int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt, |