On Tue, Sep 17, 2013 at 07:18:40PM +1000, Paul Mackerras wrote: > This implements a simple way to express the case of IRQ routing where > there is one in-kernel PIC and the system interrupts (GSIs) are routed > 1-1 to the corresponding pins of the PIC. This is expressed by having > kvm->irq_routing == NULL with a skeleton irq routing entry in the new > kvm->default_irq_route field. > > This provides a convenient way to provide backwards compatibility when > adding IRQ routing capability to an existing in-kernel PIC, such as the > XICS emulation on powerpc. > Why not create simple 1-1 irq routing table? It will take a little bit more memory, but there will be no need for kvm->irq_routing == NULL special handling. > Signed-off-by: Paul Mackerras <paulus@xxxxxxxxx> > --- > include/linux/kvm_host.h | 1 + > virt/kvm/eventfd.c | 4 ++++ > virt/kvm/irqchip.c | 23 ++++++++++++++++++++--- > 3 files changed, 25 insertions(+), 3 deletions(-) > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 749bdb1..609f587 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -394,6 +394,7 @@ struct kvm { > * if configured, irqfds.lock. > */ > struct kvm_irq_routing_table __rcu *irq_routing; > + struct kvm_kernel_irq_routing_entry default_irq_route; > struct hlist_head mask_notifier_list; > struct hlist_head irq_ack_notifier_list; > #endif > diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c > index abe4d60..7010cb3 100644 > --- a/virt/kvm/eventfd.c > +++ b/virt/kvm/eventfd.c > @@ -272,6 +272,10 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd, > { > struct kvm_kernel_irq_routing_entry *e; > > + if (!irq_rt) { > + rcu_assign_pointer(irqfd->irq_entry, NULL); > + return; > + } > if (irqfd->gsi >= irq_rt->nr_rt_entries) { > rcu_assign_pointer(irqfd->irq_entry, NULL); > return; > diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c > index 20dc9e4..ebc2941 100644 > --- a/virt/kvm/irqchip.c > +++ b/virt/kvm/irqchip.c > @@ -30,13 +30,24 @@ > #include <trace/events/kvm.h> > #include "irq.h" > > +static inline int pin_to_gsi(struct kvm *kvm, unsigned irqchip, unsigned pin) > +{ > + struct kvm_irq_routing_table *rt; > + int gsi = pin; > + > + rt = rcu_dereference(kvm->irq_routing); > + if (rt) > + gsi = rt->chip[irqchip][pin]; > + return gsi; > +} > + > bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) > { > struct kvm_irq_ack_notifier *kian; > int gsi; > > rcu_read_lock(); > - gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; > + gsi = pin_to_gsi(kvm, irqchip, pin); > if (gsi != -1) > hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, > link) > @@ -59,7 +70,7 @@ void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) > trace_kvm_ack_irq(irqchip, pin); > > rcu_read_lock(); > - gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; > + gsi = pin_to_gsi(kvm, irqchip, pin); > if (gsi != -1) > hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, > link) > @@ -126,7 +137,13 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, > */ > rcu_read_lock(); > irq_rt = rcu_dereference(kvm->irq_routing); > - if (irq < irq_rt->nr_rt_entries) > + if (!irq_rt) { > + if (kvm->default_irq_route.set) { > + irq_set[i] = kvm->default_irq_route; > + irq_set[i].gsi = irq; > + irq_set[i++].irqchip.pin = irq; > + } > + } else if (irq < irq_rt->nr_rt_entries) > hlist_for_each_entry(e, &irq_rt->map[irq], link) > irq_set[i++] = *e; > rcu_read_unlock(); > -- > 1.8.4.rc3 > > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html