int kvm_irq_map_gsi(struct kvm *kvm, struct kvm_kernel_irq_routing_entry *entries, int gsi)
{ struct kvm_irq_routing_table *irq_rt; struct kvm_kernel_irq_routing_entry *e; int n = 0;
/* *Returnvalue: *<0Interruptwasignored(maskedornotdeliveredforotherreasons) *=0Interruptwascoalesced(previousirqisstillpending) *>0NumberofCPUsinterruptwasdeliveredto
*/ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, bool line_status)
{ struct kvm_kernel_irq_routing_entry irq_set[KVM_NR_IRQCHIPS]; int ret = -1, i, idx;
trace_kvm_set_irq(irq, level, irq_source_id);
/* Not possible to detect if the guest uses the PIC or the *IOAPIC.Sosetthebitinboth.Theguestwillignore *writestotheunusedone.
*/
idx = srcu_read_lock(&kvm->irq_srcu);
i = kvm_irq_map_gsi(kvm, irq_set, irq);
srcu_read_unlock(&kvm->irq_srcu, idx);
while (i--) { int r;
r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level,
line_status); if (r < 0) continue;
ret = r + ((ret < 0) ? 0 : ret);
}
return ret;
}
staticvoid free_irq_routing_table(struct kvm_irq_routing_table *rt)
{ int i;
if (!rt) return;
for (i = 0; i < rt->nr_rt_entries; ++i) { struct kvm_kernel_irq_routing_entry *e; struct hlist_node *n;
hlist_for_each_entry_safe(e, n, &rt->map[i], link) {
hlist_del(&e->link);
kfree(e);
}
}
kfree(rt);
}
void kvm_free_irq_routing(struct kvm *kvm)
{ /* Called only during vm destruction. Nobody can use the pointer
at this stage */ struct kvm_irq_routing_table *rt = rcu_access_pointer(kvm->irq_routing);
free_irq_routing_table(rt);
}
int kvm_set_irq_routing(struct kvm *kvm, conststruct kvm_irq_routing_entry *ue, unsigned nr, unsigned flags)
{ struct kvm_irq_routing_table *new, *old; struct kvm_kernel_irq_routing_entry *e;
u32 i, j, nr_rt_entries = 0; int r;
for (i = 0; i < nr; ++i) { if (ue[i].gsi >= KVM_MAX_IRQ_ROUTES) return -EINVAL;
nr_rt_entries = max(nr_rt_entries, ue[i].gsi);
}
nr_rt_entries += 1;
new = kzalloc(struct_size(new, map, nr_rt_entries), GFP_KERNEL_ACCOUNT); if (!new) return -ENOMEM;
new->nr_rt_entries = nr_rt_entries; for (i = 0; i < KVM_NR_IRQCHIPS; i++) for (j = 0; j < KVM_IRQCHIP_NUM_PINS; j++) new->chip[i][j] = -1;
for (i = 0; i < nr; ++i) {
r = -ENOMEM;
e = kzalloc(sizeof(*e), GFP_KERNEL_ACCOUNT); if (!e) goto out;
r = -EINVAL; switch (ue->type) { case KVM_IRQ_ROUTING_MSI: if (ue->flags & ~KVM_MSI_VALID_DEVID) goto free_entry; break; default: if (ue->flags) goto free_entry; break;
}
r = setup_routing_entry(kvm, new, e, ue); if (r) goto free_entry;
++ue;
}
mutex_lock(&kvm->irq_lock);
old = rcu_dereference_protected(kvm->irq_routing, 1);
rcu_assign_pointer(kvm->irq_routing, new);
kvm_irq_routing_update(kvm);
kvm_arch_irq_routing_update(kvm);
mutex_unlock(&kvm->irq_lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.