From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marcelo Tosatti Subject: RFC: cache_regs in kvm_emulate_pio Date: Thu, 19 Jun 2008 20:31:23 -0300 Message-ID: <20080619233123.GA24183@dmt.cnet> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: kvm-devel To: Avi Kivity Return-path: Received: from mx1.redhat.com ([66.187.233.31]:52815 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753679AbYFSXbk (ORCPT ); Thu, 19 Jun 2008 19:31:40 -0400 Content-Disposition: inline Sender: kvm-owner@vger.kernel.org List-ID: Hi, >>From my understanding the ->cache_regs call on kvm_emulate_pio() is necessary only on AMD, where vcpu->arch.regs[RAX] is not copied during exit in svm_vcpu_load(). On both architectures, the remaining general purpose registers are saved on exit. The following patch saves 100 cycles out of both light and heavy exits on Intel (if correct, kvm_emulate_hypercall and complete_pio could also benefit, thus saving 200 cycles for in-kernel devices). BTW, the decache_regs(vcpu) call at the end of complete_pio() could also be a noop on Intel from what I can tell ? diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 238e8f3..6f247cc 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -709,6 +709,13 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu) rdtscll(vcpu->arch.host_tsc); } +static void svm_cache_rax(struct kvm_vcpu *vcpu) +{ + struct vcpu_svm *svm = to_svm(vcpu); + + vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax; +} + static void svm_cache_regs(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -1949,6 +1956,7 @@ static struct kvm_x86_ops svm_x86_ops = { .set_gdt = svm_set_gdt, .get_dr = svm_get_dr, .set_dr = svm_set_dr, + .cache_rax = svm_cache_rax, .cache_regs = svm_cache_regs, .decache_regs = svm_decache_regs, .get_rflags = svm_get_rflags, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 6e4278d..0d9a148 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -932,6 +932,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) } /* + * vcpu->arch.regs[RAX] already loaded by vmx_vcpu_run(). + */ +static void vcpu_load_rax(struct kvm_vcpu *vcpu) +{ +} + +/* * Sync the rsp and rip registers into the vcpu structure. This allows * registers to be accessed by indexing vcpu->arch.regs. */ @@ -3213,6 +3220,7 @@ static struct kvm_x86_ops vmx_x86_ops = { .set_idt = vmx_set_idt, .get_gdt = vmx_get_gdt, .set_gdt = vmx_set_gdt, + .cache_rax = vcpu_load_rax, .cache_regs = vcpu_load_rsp_rip, .decache_regs = vcpu_put_rsp_rip, .get_rflags = vmx_get_rflags, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 26b051b..6111946 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2302,7 +2302,7 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, KVMTRACE_2D(IO_WRITE, vcpu, vcpu->run->io.port, (u32)size, handler); - kvm_x86_ops->cache_regs(vcpu); + kvm_x86_ops->cache_rax(vcpu); memcpy(vcpu->arch.pio_data, &vcpu->arch.regs[VCPU_REGS_RAX], 4); kvm_x86_ops->skip_emulated_instruction(vcpu); diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 851184d..95a0736 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -410,6 +410,7 @@ struct kvm_x86_ops { unsigned long (*get_dr)(struct kvm_vcpu *vcpu, int dr); void (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value, int *exception); + void (*cache_rax)(struct kvm_vcpu *vcpu); void (*cache_regs)(struct kvm_vcpu *vcpu); void (*decache_regs)(struct kvm_vcpu *vcpu); unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);