RE: [PATCH] KVM: APIC: avoid instruction emulation for EOI writes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> From: Avi Kivity [mailto:avi@xxxxxxxxxx]
> Sent: Monday, August 29, 2011 3:24 PM
> 
> On 08/29/2011 09:09 AM, Tian, Kevin wrote:
> >
> >   static int handle_apic_access(struct kvm_vcpu *vcpu)
> >   {
> > +	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
> > +	int access_type, offset;
> > +
> > +	access_type = (exit_qualification>>  12)&  0xf;
> > +	offset = exit_qualification&  0xfff;
> > +	/*
> > +	 * Sane guest uses MOV instead of string operations to
> > +	 * write EOI, with written value not cared. So make a
> > +	 * short-circuit here by avoiding heavy instruction
> > +	 * emulation.
> > +	 */
> > +	if ((access_type == 1)&&  (offset == APIC_EOI)) {
> 
> Please replace this 1 with a #define.
> 

updated.

--

    KVM: APIC: avoid instruction emulation for EOI writes
    
    Instruction emulation for EOI writes can be skipped, since sane
    guest simply uses MOV instead of string operations. This is a nice
    improvement when guest doesn't support x2apic or hyper-V EOI
    support.
    
    a single VM bandwidth is observed with ~8% bandwidth improvement
    (7.4Gbps->8Gbps), by saving ~5% cycles from EOI emulation.
    
    Signed-off-by: Kevin Tian <kevin.tian@xxxxxxxxx>
    <Based on earlier work from>:
    Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>
    Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx>

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 57dcbd4..933187e 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -864,6 +864,15 @@ static int apic_mmio_write(struct kvm_io_device *this,
 	return 0;
 }
 
+void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic)
+		apic_set_eoi(vcpu->arch.apic);
+}
+EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
+
 void kvm_free_lapic(struct kvm_vcpu *vcpu)
 {
 	if (!vcpu->arch.apic)
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 52c9e6b..8287243 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -26,6 +26,7 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu);
 void kvm_lapic_reset(struct kvm_vcpu *vcpu);
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
+void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
 u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
 void kvm_apic_set_version(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 5e8d411..34c094f 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4538,8 +4538,25 @@ static int handle_xsetbv(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
+#define APIC_ACCESS_TYPE_W 1 /* Linear write access during inst execution */
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
+	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+	int access_type, offset;
+
+	access_type = (exit_qualification >> 12) & 0xf;
+	offset = exit_qualification & 0xfff;
+	/*
+	 * Sane guest uses MOV instead of string operations to
+	 * write EOI, with written value not cared. So make a
+	 * short-circuit here by avoiding heavy instruction 
+	 * emulation.
+	 */
+	if ((access_type == APIC_ACCESS_TYPE_W) && (offset == APIC_EOI)) {
+		kvm_lapic_set_eoi(vcpu);
+		skip_emulated_instruction(vcpu);
+		return 1;
+	}
 	return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 }

Thanks
Kevin

Attachment: 20110829_kvm_eoi_opt.patch
Description: 20110829_kvm_eoi_opt.patch


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux