Maxim Levitsky <mlevitsk@xxxxxxxxxx> writes: > On Mon, 2021-07-19 at 09:47 +0200, Vitaly Kuznetsov wrote: >> Maxim Levitsky <mlevitsk@xxxxxxxxxx> writes: >> >> > On Tue, 2021-07-13 at 17:20 +0300, Maxim Levitsky wrote: >> > > From: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> >> > > >> > > APICV_INHIBIT_REASON_HYPERV is currently unconditionally forced upon >> > > SynIC activation as SynIC's AutoEOI is incompatible with APICv/AVIC. It is, >> > > however, possible to track whether the feature was actually used by the >> > > guest and only inhibit APICv/AVIC when needed. >> > > >> > > TLFS suggests a dedicated 'HV_DEPRECATING_AEOI_RECOMMENDED' flag to let >> > > Windows know that AutoEOI feature should be avoided. While it's up to >> > > KVM userspace to set the flag, KVM can help a bit by exposing global >> > > APICv/AVIC enablement: in case APICv/AVIC usage is impossible, AutoEOI >> > > is still preferred. >> > > Maxim: >> > > - added SRCU lock drop around call to kvm_request_apicv_update >> > > - always set HV_DEPRECATING_AEOI_RECOMMENDED in kvm_get_hv_cpuid, >> > > since this feature can be used regardless of AVIC >> > > >> > > Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> >> > > Signed-off-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx> >> > > --- >> > > arch/x86/include/asm/kvm_host.h | 3 +++ >> > > arch/x86/kvm/hyperv.c | 34 +++++++++++++++++++++++++++------ >> > > 2 files changed, 31 insertions(+), 6 deletions(-) >> > > >> > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h >> > > index e11d64aa0bcd..f900dca58af8 100644 >> > > --- a/arch/x86/include/asm/kvm_host.h >> > > +++ b/arch/x86/include/asm/kvm_host.h >> > > @@ -956,6 +956,9 @@ struct kvm_hv { >> > > /* How many vCPUs have VP index != vCPU index */ >> > > atomic_t num_mismatched_vp_indexes; >> > > >> > > + /* How many SynICs use 'AutoEOI' feature */ >> > > + atomic_t synic_auto_eoi_used; >> > > + >> > > struct hv_partition_assist_pg *hv_pa_pg; >> > > struct kvm_hv_syndbg hv_syndbg; >> > > }; >> > > diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c >> > > index b07592ca92f0..6bf47a583d0e 100644 >> > > --- a/arch/x86/kvm/hyperv.c >> > > +++ b/arch/x86/kvm/hyperv.c >> > > @@ -85,9 +85,22 @@ static bool synic_has_vector_auto_eoi(struct kvm_vcpu_hv_synic *synic, >> > > return false; >> > > } >> > > >> > > + >> > > +static void synic_toggle_avic(struct kvm_vcpu *vcpu, bool activate) >> > > +{ >> > > + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); >> > > + kvm_request_apicv_update(vcpu->kvm, activate, >> > > + APICV_INHIBIT_REASON_HYPERV); >> > > + vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); >> > > +} >> > >> > Well turns out that this patch still doesn't work (on this >> > weekend I found out that all my AVIC enabled VMs hang on reboot). >> > >> > I finally found out what prompted me back then to make srcu lock drop >> > in synic_update_vector conditional on whether the write was done >> > by the host. >> > >> > Turns out that while KVM_SET_MSRS does take the kvm->srcu lock, >> > it stores the returned srcu index in a local variable and not >> > in vcpu->srcu_idx, thus the lock drop in synic_toggle_avic >> > doesn't work. >> > >> > So it is likely that I have seen it not work, and blamed >> > KVM_SET_MSRS for not taking the srcu lock which was a wrong assumption. >> > >> > I am more inclined to fix this by just tracking if we hold the srcu >> > lock on each VCPU manually, just as we track the srcu index anyway, >> > and then kvm_request_apicv_update can use this to drop the srcu >> > lock when needed. >> > >> >> Would it be possible to use some magic value in 'vcpu->srcu_idx' and not >> introduce a new 'srcu_ls_locked' flag? > > Well, currently the returned index value from srcu_read_lock is opaque > (and we have two SRCU implementations and both I think return small positive numbers, > but I haven't studied them in depth). > > We can ask the people that maintain SRCU to reserve a number (like -1) > or so. > I probably first add the 'srcu_is_locked' thought and then as a follow up patch > remove it if they agree. > Ah, OK. BTW, I've just discovered srcu_read_lock_held() which sounds like the function we need but unfortunately it is not. -- Vitaly