Re: [PATCH v2 12/15] kvm: i8254: Check LAPIC EOI pending when injecting irq on SVM AVIC

From: Suthikulpanit, Suravee
Date: Mon Aug 26 2019 - 16:46:24 EST


Alex,

On 8/19/2019 5:42 AM, Alexander Graf wrote:
>
>
> OnÂ15.08.19Â18:25,ÂSuthikulpanit,ÂSuraveeÂwrote:
>> ACKÂnotifiersÂdon'tÂworkÂwithÂAMDÂSVMÂw/ÂAVICÂwhenÂtheÂPITÂinterrupt
>> isÂdeliveredÂasÂedge-triggeredÂfixedÂinterruptÂsinceÂAMDÂprocessors
>> cannotÂexitÂonÂEOIÂforÂtheseÂinterrupts.
>>
>> AddÂcodeÂtoÂcheckÂLAPICÂpendingÂEOIÂbeforeÂinjectingÂanyÂpendingÂPIT
>> interruptÂonÂAMDÂSVMÂwhenÂAVICÂisÂactivated.
>>
>> Signed-off-by:ÂSuraveeÂSuthikulpanit <suravee.suthikulpanit@xxxxxxx>
>> ---
>> ÂÂarch/x86/kvm/i8254.cÂ|Â31Â+++++++++++++++++++++++++------
>> ÂÂ1ÂfileÂchanged,Â25Âinsertions(+),Â6Âdeletions(-)
>>
>> diffÂ--gitÂa/arch/x86/kvm/i8254.cÂb/arch/x86/kvm/i8254.c
>> indexÂ4a6dc54..31c4a9bÂ100644
>> ---Âa/arch/x86/kvm/i8254.c
>> +++Âb/arch/x86/kvm/i8254.c
>> @@Â-34,10Â+34,12Â@@
>> ÂÂ#includeÂ<linux/kvm_host.h>
>> ÂÂ#includeÂ<linux/slab.h>
>> +#includeÂ<asm/virtext.h>
>> ÂÂ#includeÂ"ioapic.h"
>> ÂÂ#includeÂ"irq.h"
>> ÂÂ#includeÂ"i8254.h"
>> +#includeÂ"lapic.h"
>> ÂÂ#includeÂ"x86.h"
>> ÂÂ#ifndefÂCONFIG_X86_64
>> @@Â-236,6Â+238,12Â@@ÂstaticÂvoidÂdestroy_pit_timer(structÂkvm_pitÂ*pit)
>> ÂÂÂÂÂÂkthread_flush_work(&pit->expired);
>> ÂÂ}
>> +staticÂinlineÂvoidÂkvm_pit_reset_reinject(structÂkvm_pitÂ*pit)
>> +{
>> +ÂÂÂÂatomic_set(&pit->pit_state.pending,Â0);
>> +ÂÂÂÂatomic_set(&pit->pit_state.irq_ack,Â1);
>> +}
>> +
>> ÂÂstaticÂvoidÂpit_do_work(structÂkthread_workÂ*work)
>> ÂÂ{
>> ÂÂÂÂÂÂstructÂkvm_pitÂ*pitÂ=Âcontainer_of(work,ÂstructÂkvm_pit,Âexpired);
>> @@Â-244,6Â+252,23Â@@ÂstaticÂvoidÂpit_do_work(structÂkthread_workÂ*work)
>> ÂÂÂÂÂÂintÂi;
>> ÂÂÂÂÂÂstructÂkvm_kpit_stateÂ*psÂ=Â&pit->pit_state;
>> +ÂÂÂÂ/*
>> +ÂÂÂÂÂ*ÂSince,ÂAMDÂSVMÂAVICÂacceleratesÂwriteÂaccessÂtoÂAPICÂEOI
>> +ÂÂÂÂÂ*ÂregisterÂforÂedge-triggerÂinterrupts.ÂPITÂwillÂnotÂbeÂable
>> +ÂÂÂÂÂ*ÂtoÂreceiveÂtheÂIRQÂACKÂnotifierÂandÂwillÂalwaysÂbeÂzero.
>> +ÂÂÂÂÂ*ÂTherefore,ÂweÂcheckÂifÂanyÂLAPICÂEOIÂpendingÂforÂvectorÂ0
>> +ÂÂÂÂÂ*ÂandÂresetÂirq_ackÂifÂnoÂpending.
>> +ÂÂÂÂÂ*/
>> +ÂÂÂÂifÂ(cpu_has_svm(NULL)Â&&Âkvm->arch.apicv_stateÂ==ÂAPICV_ACTIVATED)Â{
>> +ÂÂÂÂÂÂÂÂintÂeoiÂ=Â0;
>> +
>> +ÂÂÂÂÂÂÂÂkvm_for_each_vcpu(i,Âvcpu,Âkvm)
>> +ÂÂÂÂÂÂÂÂÂÂÂÂifÂ(kvm_apic_pending_eoi(vcpu,Â0))
>> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂeoi++;
>> +ÂÂÂÂÂÂÂÂifÂ(!eoi)
>> +ÂÂÂÂÂÂÂÂÂÂÂÂkvm_pit_reset_reinject(pit);
>
> InÂwhichÂcaseÂwouldÂeoiÂbeÂ!=Â0ÂwhenÂAPIC-VÂisÂactive?

That would be the case when guest has not processed and/or still processing the interrupt.
Once the guest writes to APIC EOI register for edge-triggered interrupt for vector 0,
and the AVIC hardware accelerated the access by clearing the highest priority ISR bit,
then the eoi should be zero.

Suravee