@@ -241,8 +241,8 @@ int pit_has_pending_timer(struct kvm_vcpu *vcpu)
static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
{
- struct kvm_kpit_state *ps = container_of(kian, struct kvm_kpit_state,
- irq_ack_notifier);
+ struct kvm_kpit_state *ps = kian->priv;
+
raw_spin_lock(&ps->inject_lock);
if (atomic_dec_return(&ps->pit_timer.pending) < 0)
atomic_inc(&ps->pit_timer.pending);
@@ -636,6 +636,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
pit_state->irq_ack_notifier.gsi = 0;
pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq;
+ pit_state->irq_ack_notifier.priv = &pit->pit_state;
kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
pit_state->pit_timer.reinject = true;
mutex_unlock(&pit->pit_state.lock);
@@ -404,6 +404,7 @@ struct kvm_irq_ack_notifier {
struct hlist_node link;
unsigned gsi;
void (*irq_acked)(struct kvm_irq_ack_notifier *kian);
+ void *priv;
};
#define KVM_ASSIGNED_MSIX_PENDING 0x1
@@ -121,8 +121,7 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
if (kian->gsi == -1)
return;
- dev = container_of(kian, struct kvm_assigned_dev_kernel,
- ack_notifier);
+ dev = kian->priv;
kvm_set_irq(dev->kvm, dev->irq_source_id, dev->guest_irq, 0);
@@ -563,6 +562,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
match->irq_source_id = -1;
match->kvm = kvm;
match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq;
+ match->ack_notifier.priv = match;
INIT_WORK(&match->interrupt_work,
kvm_assigned_dev_interrupt_work_handler);
@@ -175,11 +175,14 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level)
return ret;
}
+#define MAX_ACK_NOTIFIER_PER_GSI 4
+
void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
{
struct kvm_irq_ack_notifier *kian;
+ struct kvm_irq_ack_notifier acks[MAX_ACK_NOTIFIER_PER_GSI];
struct hlist_node *n;
- int gsi;
+ int gsi, i, acks_nr = 0;
trace_kvm_ack_irq(irqchip, pin);
@@ -188,9 +191,15 @@ void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
if (gsi != -1)
hlist_for_each_entry_rcu(kian, n, &kvm->irq_ack_notifier_list,
link)
- if (kian->gsi == gsi)
- kian->irq_acked(kian);
+ if (kian->gsi == gsi) {
+ if (acks_nr == MAX_ACK_NOTIFIER_PER_GSI)
+ break;
+ acks[acks_nr++] = *kian;
+ }
rcu_read_unlock();
+
+ for (i = 0; i < acks_nr; i++)
+ acks[i].irq_acked(&acks[i]);
}
void kvm_register_irq_ack_notifier(struct kvm *kvm,