|
@@ -206,6 +206,8 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
|
|
|
|
|
|
old_irr = ioapic->irr;
|
|
|
ioapic->irr |= mask;
|
|
|
+ if (edge)
|
|
|
+ ioapic->irr_delivered &= ~mask;
|
|
|
if ((edge && old_irr == ioapic->irr) ||
|
|
|
(!edge && entry.fields.remote_irr)) {
|
|
|
ret = 0;
|
|
@@ -349,7 +351,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
|
|
|
irqe.shorthand = 0;
|
|
|
|
|
|
if (irqe.trig_mode == IOAPIC_EDGE_TRIG)
|
|
|
- ioapic->irr &= ~(1 << irq);
|
|
|
+ ioapic->irr_delivered |= 1 << irq;
|
|
|
|
|
|
if (irq == RTC_GSI && line_status) {
|
|
|
/*
|
|
@@ -597,6 +599,7 @@ static void kvm_ioapic_reset(struct kvm_ioapic *ioapic)
|
|
|
ioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS;
|
|
|
ioapic->ioregsel = 0;
|
|
|
ioapic->irr = 0;
|
|
|
+ ioapic->irr_delivered = 0;
|
|
|
ioapic->id = 0;
|
|
|
memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS);
|
|
|
rtc_irq_eoi_tracking_reset(ioapic);
|
|
@@ -654,6 +657,7 @@ int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
|
|
|
|
|
|
spin_lock(&ioapic->lock);
|
|
|
memcpy(state, ioapic, sizeof(struct kvm_ioapic_state));
|
|
|
+ state->irr &= ~ioapic->irr_delivered;
|
|
|
spin_unlock(&ioapic->lock);
|
|
|
return 0;
|
|
|
}
|
|
@@ -667,6 +671,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
|
|
|
spin_lock(&ioapic->lock);
|
|
|
memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
|
|
|
ioapic->irr = 0;
|
|
|
+ ioapic->irr_delivered = 0;
|
|
|
update_handled_vectors(ioapic);
|
|
|
kvm_vcpu_request_scan_ioapic(kvm);
|
|
|
kvm_ioapic_inject_all(ioapic, state->irr);
|