kvm: fast-path msi injection with irqfd
PATCH 1/1 kvm: fast-path msi injection with irqfd
Store irq routing table pointer in the irqfd object, and use that to inject MSI directly without bouncing out to a kernel thread.
While we touch this structure, rearrange irqfd fields to make fastpath better packed for better cache utilization.
This also adds some comments about locking rules and rcu usage in code.
Some notes on the design:
- Use pointer into the rt instead of copying an entry,
to make it possible to use rcu, thus side-stepping locking complexities. We also save some memory this way.
- Old workqueue code is still used for level irqs.
I don't think we DTRT with level anyway, however,
it seems easier to keep the code around as
it has been thought through and debugged, and fix level later than rip out and re-instate it later.
---
OK, this seems to work fine for me. Tested with virtio-net in guest with and without vhost-net. Pls review/apply if appropriate.
include/linux/kvm_host.h | 16 ++++++++ virt/kvm/eventfd.c | 91 ++++++++++++++++++++++++++++++++++++++++------ virt/kvm/irq_comm.c | 7 ++-- 3 files changed, 99 insertions(+), 15 deletions(-)
include/linux/kvm_host.h +16 -0
@@ -16,6 +16,7 @@#include <linux/mm.h> #include <linux/preempt.h> #include <linux/msi.h> +#include <linux/rcupdate.h> #include <asm/signal.h> #include <linux/kvm.h>
@@ -206,6 +207,10 @@ struct kvm {struct mutex irq_lock;#ifdef CONFIG_HAVE_KVM_IRQCHIP +/* +* Update side is protected by irq_lock and, +* if configured, irqfds.lock. +*/ struct kvm_irq_routing_table __rcu *irq_routing;struct hlist_head mask_notifier_list;struct hlist_head irq_ack_notifier_list;
@@ -462,6 +467,8 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic, unsigned long *deliver_bitmask);#endif 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);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);
@@ -603,17 +610,26 @@ static inline void kvm_free_irq_routing(struct kvm *kvm) {}void kvm_eventfd_init (struct kvm *kvm);int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags);void kvm_irqfd_release (struct kvm *kvm); +void kvm_irq_routing_update (struct kvm *,struct kvm_irq_routing_table *);int kvm_ioeventfd (struct kvm *kvm,struct kvm_ioeventfd *args);#else static inline void kvm_eventfd_init (struct kvm *kvm) {} +static inline int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags) {return -EINVAL ; }static inline void kvm_irqfd_release (struct kvm *kvm) {} + +static inline void kvm_irq_routing_update (struct kvm *kvm, +struct kvm_irq_routing_table *irq_rt) +{ +rcu_assign_pointer (kvm->irq_routing, irq_rt); +} +static inline int kvm_ioeventfd (struct kvm *kvm,struct kvm_ioeventfd *args) {return -ENOSYS ;
virt/kvm/eventfd.c +79 -12
136 lines not on this page · raw message
virt/kvm/irq_comm.c +4 -3
@@ -114,8 +114,8 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,return r; } -static int kvm_set_msi (struct kvm_kernel_irq_routing_entry *e, -struct kvm *kvm,int irq_source_id,int level) +int kvm_set_msi (struct kvm_kernel_irq_routing_entry *e, +struct kvm *kvm,int irq_source_id,int level) {struct kvm_lapic_irq irq;
@@ -409,8 +409,9 @@ int kvm_set_irq_routing(struct kvm *kvm,mutex_lock (&kvm->irq_lock); old = kvm->irq_routing; -rcu_assign_pointer (kvm->irq_routing, new); +kvm_irq_routing_update (kvm, new);mutex_unlock (&kvm->irq_lock); +synchronize_rcu (); new = old;
Signature · 1 line
1.7.3.2.91.g446ac
Quoted 19 lines · Michael S. Tsirkin
Store irq routing table pointer in the irqfd object, and use that to inject MSI directly without bouncing out to a kernel thread.
While we touch this structure, rearrange irqfd fields to make fastpath better packed for better cache utilization.
This also adds some comments about locking rules and rcu usage in code.
Some notes on the design:
- Use pointer into the rt instead of copying an entry,
to make it possible to use rcu, thus side-stepping locking complexities. We also save some memory this way.
- Old workqueue code is still used for level irqs.
I don't think we DTRT with level anyway, however,
it seems easier to keep the code around as
it has been thought through and debugged, and fix level later than rip out and re-instate it later.
Quoted 5 lines
Signed-off-by Michael S. Tsirkin <[email protected]>---
OK, this seems to work fine for me. Tested with virtio-net in guest with and without vhost-net. Pls review/apply if appropriate.
Gregory Haskins
Acked-byQuoted 1 line
Quoted 1 line
Quoted 1 line
On 11/19/2010 at 10:54 AM, in message <[email protected]>,
Quoted 20 lines · Marcelo Tosatti
Quoted 19 lines · Michael S. Tsirkin
Store irq routing table pointer in the irqfd object, and use that to inject MSI directly without bouncing out to a kernel thread.
While we touch this structure, rearrange irqfd fields to make fastpath better packed for better cache utilization.
This also adds some comments about locking rules and rcu usage in code.
Some notes on the design:
- Use pointer into the rt instead of copying an entry,
to make it possible to use rcu, thus side-stepping locking complexities. We also save some memory this way.
- Old workqueue code is still used for level irqs.
I don't think we DTRT with level anyway, however,
it seems easier to keep the code around as
it has been thought through and debugged, and fix level later than rip out and re-instate it later.
Quoted 7 lines
Quoted 5 lines
Signed-off-by Michael S. Tsirkin <[email protected]>---
OK, this seems to work fine for me. Tested with virtio-net in guest with and without vhost-net. Pls review/apply if appropriate.
Acked-by Marcelo Tosatti <[email protected]>
Avi Kivity
AppliedQuoted 9 lines · Michael S. Tsirkin
Store irq routing table pointer in the irqfd object, and use that to inject MSI directly without bouncing out to a kernel thread.
While we touch this structure, rearrange irqfd fields to make fastpath better packed for better cache utilization.
This also adds some comments about locking rules and rcu usage in code.
Quoted 10 lines
Some notes on the design:
- Use pointer into the rt instead of copying an entry,
to make it possible to use rcu, thus side-stepping locking complexities. We also save some memory this way.
- Old workqueue code is still used for level irqs.
I don't think we DTRT with level anyway, however,
it seems easier to keep the code around as
it has been thought through and debugged, and fix level later than rip out and re-instate it later.
Applied, thanks.
Signature · 1 line
error compiling committee.c: too many arguments to function