kvm: ioapic: Lazy update IOAPIC EOI
In-kernel IOAPIC does not receive EOI with AMD SVM AVIC since the processor accelerate write to APIC EOI register and does not trap if the interrupt is edge-triggered. Workaround this by lazy check for pending APIC EOI at the time when setting new IOPIC irq, and update IOAPIC EOI if no pending APIC EOI. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
1ec2405c7c
commit
f458d039db
|
@ -49,6 +49,11 @@
|
|||
static int ioapic_service(struct kvm_ioapic *vioapic, int irq,
|
||||
bool line_status);
|
||||
|
||||
static void kvm_ioapic_update_eoi_one(struct kvm_vcpu *vcpu,
|
||||
struct kvm_ioapic *ioapic,
|
||||
int trigger_mode,
|
||||
int pin);
|
||||
|
||||
static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
|
||||
unsigned long addr,
|
||||
unsigned long length)
|
||||
|
@ -177,6 +182,31 @@ static bool rtc_irq_check_coalesced(struct kvm_ioapic *ioapic)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void ioapic_lazy_update_eoi(struct kvm_ioapic *ioapic, int irq)
|
||||
{
|
||||
int i;
|
||||
struct kvm_vcpu *vcpu;
|
||||
union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
|
||||
|
||||
kvm_for_each_vcpu(i, vcpu, ioapic->kvm) {
|
||||
if (!kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
|
||||
entry->fields.dest_id,
|
||||
entry->fields.dest_mode) ||
|
||||
kvm_apic_pending_eoi(vcpu, entry->fields.vector))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If no longer has pending EOI in LAPICs, update
|
||||
* EOI for this vetor.
|
||||
*/
|
||||
rtc_irq_eoi(ioapic, vcpu, entry->fields.vector);
|
||||
kvm_ioapic_update_eoi_one(vcpu, ioapic,
|
||||
entry->fields.trig_mode,
|
||||
irq);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
|
||||
int irq_level, bool line_status)
|
||||
{
|
||||
|
@ -194,6 +224,15 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* AMD SVM AVIC accelerate EOI write and do not trap,
|
||||
* in-kernel IOAPIC will not be able to receive the EOI.
|
||||
* In this case, we do lazy update of the pending EOI when
|
||||
* trying to set IOAPIC irq.
|
||||
*/
|
||||
if (kvm_apicv_activated(ioapic->kvm))
|
||||
ioapic_lazy_update_eoi(ioapic, irq);
|
||||
|
||||
/*
|
||||
* Return 0 for coalesced interrupts; for edge-triggered interrupts,
|
||||
* this only happens if a previous edge has not been delivered due
|
||||
|
|
Loading…
Reference in New Issue