/* * Return value: * < 0 Interrupt was ignored (masked or not delivered for other reasons) * = 0 Interrupt was coalesced (previous irq is still pending) * > 0 Number of CPUs interrupt was delivered to */ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level) { struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS]; int ret = -1, i = 0; struct kvm_irq_routing_table *irq_rt; struct hlist_node *n; trace_kvm_set_irq(irq, level, irq_source_id); /* Not possible to detect if the guest uses the PIC or the * IOAPIC. So set the bit in both. The guest will ignore * writes to the unused one. */ rcu_read_lock(); irq_rt = rcu_dereference(kvm->irq_routing); if (irq < irq_rt->nr_rt_entries) hlist_for_each_entry(e, n, &irq_rt->map[irq], link) irq_set[i++] = *e; rcu_read_unlock(); while(i--) { int r; r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level); if (r < 0) continue; ret = r + ((ret < 0) ? 0 : ret); } return ret; }
/* * Deliver an IRQ in an atomic context if we can, or return a failure, * user can retry in a process context. * Return value: * -EWOULDBLOCK - Can't deliver in atomic context: retry in a process context. * Other values - No need to retry. */ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level) { struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; struct kvm_kernel_irq_routing_entry *e; int ret = -EINVAL; int idx; trace_kvm_set_irq(irq, level, irq_source_id); /* * Injection into either PIC or IOAPIC might need to scan all CPUs, * which would need to be retried from thread context; when same GSI * is connected to both PIC and IOAPIC, we'd have to report a * partial failure here. * Since there's no easy way to do this, we only support injecting MSI * which is limited to 1:1 GSI mapping. */ idx = srcu_read_lock(&kvm->irq_srcu); if (kvm_irq_map_gsi(kvm, entries, irq) > 0) { e = &entries[0]; if (likely(e->type == KVM_IRQ_ROUTING_MSI)) ret = kvm_set_msi_inatomic(e, kvm); else ret = -EWOULDBLOCK; } srcu_read_unlock(&kvm->irq_srcu, idx); return ret; }
/* This should be called with the kvm->irq_lock mutex held * Return value: * < 0 Interrupt was ignored (masked or not delivered for other reasons) * = 0 Interrupt was coalesced (previous irq is still pending) * > 0 Number of CPUs interrupt was delivered to */ int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) { struct kvm_kernel_irq_routing_entry *e; unsigned long *irq_state, sig_level; int ret = -1; trace_kvm_set_irq(irq, level, irq_source_id); WARN_ON(!mutex_is_locked(&kvm->irq_lock)); if (irq < KVM_IOAPIC_NUM_PINS) { irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; /* Logical OR for level trig interrupt */ if (level) set_bit(irq_source_id, irq_state); else clear_bit(irq_source_id, irq_state); sig_level = !!(*irq_state); } else if (!level) return ret; else /* Deal with MSI/MSI-X */ sig_level = 1; /* Not possible to detect if the guest uses the PIC or the * IOAPIC. So set the bit in both. The guest will ignore * writes to the unused one. */ list_for_each_entry(e, &kvm->irq_routing, link) if (e->gsi == irq) { int r = e->set(e, kvm, sig_level); if (r < 0) continue; ret = r + ((ret < 0) ? 0 : ret); } return ret; }