On Mon, Jun 11, 2012 at 02:19:22PM +0300, Michael S. Tsirkin wrote: > We do not want a potential broadcast to all VCPUs to run in > a host IRQ handler. Implement an API that sends an MSI > interrupt but only if it's safe from interrupt context, > that is if it is a unicast. > We will still iterate over all vcpus, we may as well deliver to them. Or you want to avoid a lot of vcpu kicks? > Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx> > --- > include/linux/kvm_host.h | 2 ++ > virt/kvm/irq_comm.c | 37 ++++++++++++++++++++++++++++++++----- > 2 files changed, 34 insertions(+), 5 deletions(-) > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index c446435..ddb476a 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -618,6 +618,8 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic, > int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level); > int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm, > int irq_source_id, int level); > +int kvm_set_msi_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry, > + struct kvm *kvm); > void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin); > void kvm_register_irq_ack_notifier(struct kvm *kvm, > struct kvm_irq_ack_notifier *kian); > diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c > index 5afb431..3395e03 100644 > --- a/virt/kvm/irq_comm.c > +++ b/virt/kvm/irq_comm.c > @@ -114,13 +114,20 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, > return r; > } > > -int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, > - struct kvm *kvm, int irq_source_id, int level) > +static bool kvm_msi_is_multicast(unsigned dest, int dest_mode) > { > - struct kvm_lapic_irq irq; > + if (dest_mode == 0) > + /* Physical mode. */ > + return dest == 0xff; > + else > + /* Logical mode. */ > + return dest & (dest - 1); > +} > > - if (!level) > - return -1; > +static int __kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, > + struct kvm *kvm, bool noblock) > +{ > + struct kvm_lapic_irq irq; > > trace_kvm_msi_set_irq(e->msi.address_lo, e->msi.data); > > @@ -134,10 +141,30 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, > irq.level = 1; > irq.shorthand = 0; > > + /* Multicast MSI doesn't really block but might take a long time. */ > + if (unlikely(noblock && kvm_msi_is_multicast(irq.dest_id, > + irq.delivery_mode))) delivery_mode? Should be dest_mode. But you probably need to check that delivery_mode is not ExtINT either. > + return -EWOULDBLOCK; > + > /* TODO Deal with RH bit of MSI message address */ > return kvm_irq_delivery_to_apic(kvm, NULL, &irq); > } > > +int kvm_set_msi_inatomic(struct kvm_kernel_irq_routing_entry *e, > + struct kvm *kvm) > +{ > + return __kvm_set_msi(e, kvm, true); > +} > + > +int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, > + struct kvm *kvm, int irq_source_id, int level) > +{ > + if (unlikely(!level)) > + return -1; > + > + return __kvm_set_msi(e, kvm, false); > +} > + > int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi) > { > struct kvm_kernel_irq_routing_entry route; > -- > MST > > -- > 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