KVM: irq ack notification
Based on a patch from: Ben-Ami Yassour <benami@il.ibm.com> which was based on a patch from: Amit Shah <amit.shah@qumranet.com> Notify IRQ acking on PIC/APIC emulation. The previous patch missed two things: - Edge triggered interrupts on IOAPIC - PIC reset with IRR/ISR set should be equivalent to ack (LAPIC probably needs something similar). Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> CC: Amit Shah <amit.shah@qumranet.com> CC: Ben-Ami Yassour <benami@il.ibm.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
This commit is contained in:
committed by
Avi Kivity
parent
564f15378f
commit
f52447261b
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "ioapic.h"
|
||||
#include "lapic.h"
|
||||
#include "irq.h"
|
||||
|
||||
#if 0
|
||||
#define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg)
|
||||
@@ -285,26 +286,31 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
|
||||
}
|
||||
}
|
||||
|
||||
static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi)
|
||||
static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
|
||||
int trigger_mode)
|
||||
{
|
||||
union ioapic_redir_entry *ent;
|
||||
|
||||
ent = &ioapic->redirtbl[gsi];
|
||||
ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
|
||||
|
||||
ent->fields.remote_irr = 0;
|
||||
if (!ent->fields.mask && (ioapic->irr & (1 << gsi)))
|
||||
ioapic_service(ioapic, gsi);
|
||||
kvm_notify_acked_irq(ioapic->kvm, gsi);
|
||||
|
||||
if (trigger_mode == IOAPIC_LEVEL_TRIG) {
|
||||
ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
|
||||
ent->fields.remote_irr = 0;
|
||||
if (!ent->fields.mask && (ioapic->irr & (1 << gsi)))
|
||||
ioapic_service(ioapic, gsi);
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector)
|
||||
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode)
|
||||
{
|
||||
struct kvm_ioapic *ioapic = kvm->arch.vioapic;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IOAPIC_NUM_PINS; i++)
|
||||
if (ioapic->redirtbl[i].fields.vector == vector)
|
||||
__kvm_ioapic_update_eoi(ioapic, i);
|
||||
__kvm_ioapic_update_eoi(ioapic, i, trigger_mode);
|
||||
}
|
||||
|
||||
static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr,
|
||||
|
||||
@@ -58,6 +58,7 @@ struct kvm_ioapic {
|
||||
} redirtbl[IOAPIC_NUM_PINS];
|
||||
struct kvm_io_device dev;
|
||||
struct kvm *kvm;
|
||||
void (*ack_notifier)(void *opaque, int irq);
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -87,7 +88,7 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
|
||||
|
||||
struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
|
||||
unsigned long bitmap);
|
||||
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector);
|
||||
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
|
||||
int kvm_ioapic_init(struct kvm *kvm);
|
||||
void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
|
||||
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
|
||||
|
||||
Reference in New Issue
Block a user