public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: wzj <zijie.wei@linux.alibaba.com>
To: "Huang, Kai" <kai.huang@intel.com>,
	seanjc@google.com, bp@alien8.de, dave.hansen@linux.intel.com,
	hpa@zytor.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	mingo@redhat.com, pbonzini@redhat.com, tglx@linutronix.de,
	x86@kernel.org, xuyun_xy.xy@linux.alibaba.com,
	zijie.wei@linux.alibaba.com
Subject: Re: [PATCH v3] KVM: x86: ioapic: Optimize EOI handling to reduce unnecessary VM exits
Date: Mon, 3 Mar 2025 13:01:10 +0800	[thread overview]
Message-ID: <f7636788-4fa2-4fa6-afe6-a8fa2edb72ab@linux.alibaba.com> (raw)
In-Reply-To: <9553f84e3a4533278e06938a4693991cf23cdfc3.camel@intel.com>



On 2025/2/28 20:25, Huang, Kai wrote:
> On Fri, 2025-02-28 at 10:15 +0800, weizijie wrote:
>> Address performance issues caused by a vector being reused by a
>> non-IOAPIC source.
> 
> I saw your reply in v2.  Thanks.
> 
> Some minor comments below, which may be just nits for Sean/Paolo, so feel free
> to add:
> 
> Reviewed-by: Kai Huang <kai.huang@intel.com>
> 
>>
>> Commit 0fc5a36dd6b3
>> ("KVM: x86: ioapic: Fix level-triggered EOI and IOAPIC reconfigure race")
>> addressed the issues related to EOI and IOAPIC reconfiguration races.
>> However, it has introduced some performance concerns:
>>
>> Configuring IOAPIC interrupts while an interrupt request (IRQ) is
>> already in service can unintentionally trigger a VM exit for other
>> interrupts that normally do not require one, due to the settings of
>> `ioapic_handled_vectors`. If the IOAPIC is not reconfigured during
>> runtime, this issue persists, continuing to adversely affect
>> performance.
> 
> 
> So in short:
> 
>    The "rare case" mentioned in db2bdcbbbd32 and 0fc5a36dd6b3 is actually
>    not that rare and can actually happen in the good behaved guest.
> 
> The above commit message isn't very clear to me, though.  How about below?
> 
> Configuring IOAPIC routed interrupts triggers KVM to rescan all vCPU's
> ioapic_handled_vectors which is used to control which vectors need to trigger
> EOI-induced VMEXITs.  If any interrupt is already in service on some vCPU using
> some vector when the IOAPIC is being rescanned, the vector is set to vCPU's
> ioapic_handled_vectors.  If the vector is then reused by other interrupts, each
> of them will cause a VMEXIT even it is unnecessary.  W/o further IOAPIC rescan,
> the vector remains set, and this issue persists, impacting guest's interrupt
> performance.
> 
> Both commit
> 
>    db2bdcbbbd32 (KVM: x86: fix edge EOI and IOAPIC reconfig race)
> 
> and commit
> 
>    0fc5a36dd6b3 (KVM: x86: ioapic: Fix level-triggered EOI and IOAPIC reconfigure
> race)
> 
> mentioned this issue, but it was considered as "rare" thus was not addressed.
> However in real environment this issue can actually happen in a well-behaved
> guest.
> 

Thank you very much for your suggestions on the comment modifications.
I will apply it to this patch.

>>
>> Simple Fix Proposal:
>> A straightforward solution is to record highest in-service IRQ that
>> is pending at the time of the last scan. Then, upon the next guest
>> exit, do a full KVM_REQ_SCAN_IOAPIC. This ensures that a re-scan of
>> the ioapic occurs only when the recorded vector is EOI'd, and
>> subsequently, the extra bit in the eoi_exit_bitmap are cleared,
> 			  ^
> 			  bits
> 

Thank you for the correction.

>> avoiding unnecessary VM exits.
>>
>> Co-developed-by: xuyun <xuyun_xy.xy@linux.alibaba.com>
>> Signed-off-by: xuyun <xuyun_xy.xy@linux.alibaba.com>
>> Signed-off-by: weizijie <zijie.wei@linux.alibaba.com>
>> ---
>>   arch/x86/include/asm/kvm_host.h |  1 +
>>   arch/x86/kvm/ioapic.c           | 10 ++++++++--
>>   arch/x86/kvm/irq_comm.c         |  9 +++++++--
>>   arch/x86/kvm/lapic.c            | 10 ++++++++++
>>   4 files changed, 26 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
>> index 0b7af5902ff7..8c50e7b4a96f 100644
>> --- a/arch/x86/include/asm/kvm_host.h
>> +++ b/arch/x86/include/asm/kvm_host.h
>> @@ -1062,6 +1062,7 @@ struct kvm_vcpu_arch {
>>   #if IS_ENABLED(CONFIG_HYPERV)
>>   	hpa_t hv_root_tdp;
>>   #endif
>> +	u8 last_pending_vector;
>>   };
>>   
>>   struct kvm_lpage_info {
>> diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c
>> index 995eb5054360..40252a800897 100644
>> --- a/arch/x86/kvm/ioapic.c
>> +++ b/arch/x86/kvm/ioapic.c
>> @@ -297,10 +297,16 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, ulong *ioapic_handled_vectors)
>>   			u16 dm = kvm_lapic_irq_dest_mode(!!e->fields.dest_mode);
>>   
>>   			if (kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
>> -						e->fields.dest_id, dm) ||
>> -			    kvm_apic_pending_eoi(vcpu, e->fields.vector))
>> +						e->fields.dest_id, dm))
>>   				__set_bit(e->fields.vector,
>>   					  ioapic_handled_vectors);
>> +			else if (kvm_apic_pending_eoi(vcpu, e->fields.vector)) {
>> +				__set_bit(e->fields.vector,
>> +					  ioapic_handled_vectors);
>> +				vcpu->arch.last_pending_vector = e->fields.vector >
>> +					vcpu->arch.last_pending_vector ? e->fields.vector :
>> +					vcpu->arch.last_pending_vector;
>> +			}
>>   		}
>>   	}
>>   	spin_unlock(&ioapic->lock);
>> diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
>> index 8136695f7b96..1d23c52576e1 100644
>> --- a/arch/x86/kvm/irq_comm.c
>> +++ b/arch/x86/kvm/irq_comm.c
>> @@ -426,9 +426,14 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
>>   
>>   			if (irq.trig_mode &&
>>   			    (kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
>> -						 irq.dest_id, irq.dest_mode) ||
>> -			     kvm_apic_pending_eoi(vcpu, irq.vector)))
>> +						 irq.dest_id, irq.dest_mode)))
>>   				__set_bit(irq.vector, ioapic_handled_vectors);
>> +			else if (kvm_apic_pending_eoi(vcpu, irq.vector)) {
>> +				__set_bit(irq.vector, ioapic_handled_vectors);
>> +				vcpu->arch.last_pending_vector = irq.vector >
>> +					vcpu->arch.last_pending_vector ? irq.vector :
>> +					vcpu->arch.last_pending_vector;
>> +			}
>>   		}
>>   	}
>>   	srcu_read_unlock(&kvm->irq_srcu, idx);
>> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
>> index a009c94c26c2..5d62ea5f1503 100644
>> --- a/arch/x86/kvm/lapic.c
>> +++ b/arch/x86/kvm/lapic.c
>> @@ -1466,6 +1466,16 @@ static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector)
>>   	if (!kvm_ioapic_handles_vector(apic, vector))
>>   		return;
>>   
>> +	/*
>> +	 * When there are instances where ioapic_handled_vectors is
>> +	 * set due to pending interrupts, clean up the record and do
>> +	 * a full KVM_REQ_SCAN_IOAPIC.
>> +	 */
> 
> How about also add below to the comment?
> 
> 	This ensures the vector is cleared in the vCPU's ioapic_handled_vectors
> 	if the vector is reused by non-IOAPIC interrupts,  avoiding unnecessary
> 	EOI-induced VMEXITs for that vector.
> 

This additional information seems to make it easier to understand. Thank 
you very much.

>> +	if (apic->vcpu->arch.last_pending_vector == vector) {
>> +		apic->vcpu->arch.last_pending_vector = 0;
>> +		kvm_make_request(KVM_REQ_SCAN_IOAPIC, apic->vcpu);
>> +	}
>> +
>>   	/* Request a KVM exit to inform the userspace IOAPIC. */
>>   	if (irqchip_split(apic->vcpu->kvm)) {
>>   		apic->vcpu->arch.pending_ioapic_eoi = vector;
> 


  reply	other threads:[~2025-03-03  5:01 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-21  6:50 [PATCH] KVM: x86: ioapic: Optimize EOI handling to reduce unnecessary VM exits weizijie
2024-12-17 23:04 ` Sean Christopherson
2024-12-22  9:01   ` [PATCH v2] " weizijie
2024-12-27  7:30   ` [PATCH] " wzj
2025-02-11 19:45     ` Sean Christopherson
2025-02-25  6:42       ` [PATCH Resend] " weizijie
2025-02-26 22:44         ` Huang, Kai
2025-02-27 12:16           ` wzj
2025-02-28  2:15 ` [PATCH v3] " weizijie
2025-02-28 12:25   ` Huang, Kai
2025-03-03  5:01     ` wzj [this message]
2025-03-03  5:22 ` [PATCH v4] " weizijie
2025-03-03 17:55   ` Sean Christopherson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f7636788-4fa2-4fa6-afe6-a8fa2edb72ab@linux.alibaba.com \
    --to=zijie.wei@linux.alibaba.com \
    --cc=9553f84e3a4533278e06938a4693991cf23cdfc3.camel@intel.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=kai.huang@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    --cc=xuyun_xy.xy@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox