|
@@ -97,6 +97,14 @@ static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic)
|
|
|
bitmap_zero(ioapic->rtc_status.dest_map, KVM_MAX_VCPUS);
|
|
|
}
|
|
|
|
|
|
+static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic);
|
|
|
+
|
|
|
+static void rtc_status_pending_eoi_check_valid(struct kvm_ioapic *ioapic)
|
|
|
+{
|
|
|
+ if (WARN_ON(ioapic->rtc_status.pending_eoi < 0))
|
|
|
+ kvm_rtc_eoi_tracking_restore_all(ioapic);
|
|
|
+}
|
|
|
+
|
|
|
static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
|
|
|
{
|
|
|
bool new_val, old_val;
|
|
@@ -120,9 +128,8 @@ static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
|
|
|
} else {
|
|
|
__clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map);
|
|
|
ioapic->rtc_status.pending_eoi--;
|
|
|
+ rtc_status_pending_eoi_check_valid(ioapic);
|
|
|
}
|
|
|
-
|
|
|
- WARN_ON(ioapic->rtc_status.pending_eoi < 0);
|
|
|
}
|
|
|
|
|
|
void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
|
|
@@ -149,10 +156,10 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic)
|
|
|
|
|
|
static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu)
|
|
|
{
|
|
|
- if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map))
|
|
|
+ if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map)) {
|
|
|
--ioapic->rtc_status.pending_eoi;
|
|
|
-
|
|
|
- WARN_ON(ioapic->rtc_status.pending_eoi < 0);
|
|
|
+ rtc_status_pending_eoi_check_valid(ioapic);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static bool rtc_irq_check_coalesced(struct kvm_ioapic *ioapic)
|
|
@@ -353,6 +360,12 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
|
|
|
ioapic->irr &= ~(1 << irq);
|
|
|
|
|
|
if (irq == RTC_GSI && line_status) {
|
|
|
+ /*
|
|
|
+ * pending_eoi cannot ever become negative (see
|
|
|
+ * rtc_status_pending_eoi_check_valid) and the caller
|
|
|
+ * ensures that it is only called if it is >= zero, namely
|
|
|
+ * if rtc_irq_check_coalesced returns false).
|
|
|
+ */
|
|
|
BUG_ON(ioapic->rtc_status.pending_eoi != 0);
|
|
|
ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
|
|
|
ioapic->rtc_status.dest_map);
|