Re: AVIC related warning in enable_irq_window

From: Suravee Suthikulpanit
Date: Mon May 04 2020 - 06:38:14 EST


Paolo / Maxim,

On 5/4/20 4:25 PM, Paolo Bonzini wrote:
On 04/05/20 11:13, Maxim Levitsky wrote:
On Mon, 2020-05-04 at 15:46 +0700, Suravee Suthikulpanit wrote:
Paolo / Maxim,

On 5/2/20 11:42 PM, Paolo Bonzini wrote:
On 02/05/20 15:58, Maxim Levitsky wrote:
The AVIC is disabled by svm_toggle_avic_for_irq_window, which calls
kvm_request_apicv_update, which broadcasts the KVM_REQ_APICV_UPDATE vcpu request,
however it doesn't broadcast it to CPU on which now we are running, which seems OK,
because the code that handles that broadcast runs on each VCPU entry, thus
when this CPU will enter guest mode it will notice and disable the AVIC.

However later in svm_enable_vintr, there is test 'WARN_ON(kvm_vcpu_apicv_active(&svm->vcpu));'
which is still true on current CPU because of the above.

Good point! We can just remove the WARN_ON I think. Can you send a patch?

Instead, as an alternative to remove the WARN_ON(), would it be better to just explicitly
calling kvm_vcpu_update_apicv(vcpu) to update the apicv_active flag right after
kvm_request_apicv_update()?

This should work IMHO, other that the fact kvm_vcpu_update_apicv will be called again,
when this vcpu is entered since the KVM_REQ_APICV_UPDATE will still be pending on it.
It shoudn't be a problem, and we can even add a check to do nothing when it is called
while avic is already in target enable state.

I thought about that but I think it's a bit confusing. If we want to
keep the WARN_ON, Maxim can add an equivalent one to svm_vcpu_run, which
is even better because the invariant is clearer.

WARN_ON((vmcb->control.int_ctl & (AVIC_ENABLE_MASK | V_IRQ_MASK))
== (AVIC_ENABLE_MASK | V_IRQ_MASK));

Paolo


Quick update. I tried your suggestion as following, and it's showing the warning still.
I'll look further into this.

arch/x86/kvm/svm/svm.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 2f379ba..142c4b9 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1368,9 +1368,6 @@ static inline void svm_enable_vintr(struct vcpu_svm *svm)
{
struct vmcb_control_area *control;

- /* The following fields are ignored when AVIC is enabled */
- WARN_ON(kvm_vcpu_apicv_active(&svm->vcpu));
-
/*
* This is just a dummy VINTR to actually cause a vmexit to happen.
* Actual injection of virtual interrupts happens through EVENTINJ.
@@ -3322,6 +3319,11 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
vcpu->arch.apic->lapic_timer.timer_advance_ns)
kvm_wait_lapic_expire(vcpu);

+//SURAVEE
+ WARN_ON((svm->vmcb->control.int_ctl &
+ (AVIC_ENABLE_MASK | V_IRQ_MASK))
+ == (AVIC_ENABLE_MASK | V_IRQ_MASK));
+

Suravee