diff -urp kvm_kmod/include/linux/kvm_host.h kvm_kmod_new//include/linux/kvm_host.h
--- kvm_kmod/include/linux/kvm_host.h	2014-03-10 14:08:28.000000000 +0000
+++ kvm_kmod_new//include/linux/kvm_host.h	2014-03-26 15:07:48.000000000 +0000
@@ -337,6 +337,12 @@ struct kvm {
 
 	struct mutex irq_lock;
 #ifdef CONFIG_HAVE_KVM_IRQCHIP
+	struct task_struct *kthread;
+	wait_queue_head_t wq;
+	struct mutex irq_routing_lock;
+	struct kvm_irq_routing to_update_routing;
+	struct kvm_irq_routing_entry *to_update_entries;
+	atomic_t have_new;
 	/*
 	 * Update side is protected by irq_lock and,
 	 * if configured, irqfds.lock.
diff -urp kvm_kmod/x86/assigned-dev.c kvm_kmod_new//x86/assigned-dev.c
--- kvm_kmod/x86/assigned-dev.c	2014-03-10 14:08:28.000000000 +0000
+++ kvm_kmod_new//x86/assigned-dev.c	2014-03-26 15:22:33.000000000 +0000
@@ -1056,12 +1056,23 @@ long kvm_vm_ioctl_assigned_device(struct
 		r = -EFAULT;
 		urouting = argp;
 		if (copy_from_user(entries, urouting->entries,
-				   routing.nr * sizeof(*entries)))
-			goto out_free_irq_routing;
-		r = kvm_set_irq_routing(kvm, entries, routing.nr,
-					routing.flags);
-	out_free_irq_routing:
-		vfree(entries);
+				   routing.nr * sizeof(*entries))) {
+			vfree(entries);
+			break;
+		}
+
+		mutex_lock(&kvm->irq_routing_lock);
+		if (kvm->to_update_entries) {
+			vfree(kvm->to_update_entries);
+			kvm->to_update_entries = NULL;
+		}
+		kvm->to_update_routing = routing;
+		kvm->to_update_entries = entries;
+		atomic_set(&kvm->have_new, 1);
+		mutex_unlock(&kvm->irq_routing_lock);
+
+		wake_up(&kvm->wq);
+		r = 0;  /* parameter validity or memory alloc avalibity should be checked before return */
 		break;
 	}
 #endif /* KVM_CAP_IRQ_ROUTING */
diff -urp kvm_kmod/x86/kvm_main.c kvm_kmod_new//x86/kvm_main.c
--- kvm_kmod/x86/kvm_main.c	2014-03-10 14:08:28.000000000 +0000
+++ kvm_kmod_new//x86/kvm_main.c	2014-03-26 15:27:02.000000000 +0000
@@ -83,6 +83,7 @@
 #include <linux/slab.h>
 #include <linux/sort.h>
 #include <linux/bsearch.h>
+#include <linux/kthread.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -501,6 +502,49 @@ static void kvm_init_memslots_id(struct
 		slots->id_to_index[i] = slots->memslots[i].id = i;
 }
 
+static int do_irq_routing_table_update(struct kvm *kvm)
+{
+	struct kvm_irq_routing_entry *entries;
+	unsigned nr;
+	unsigned flags;
+
+	mutex_lock(&kvm->irq_routing_lock);
+	BUG_ON(!kvm->to_update_entries);
+
+	nr = kvm->to_update_routing.nr;
+	flags = kvm->to_update_routing.flags;
+	entries = vmalloc(nr * sizeof(*entries));
+	if (!entries) {
+		mutex_unlock(&kvm->irq_routing_lock);
+	        return 0;
+	}
+       /* this memcpy can be eliminated by doing set in mutex_lock and doing synchronize_rcu outside */
+	memcpy(entries, kvm->to_update_entries, nr * sizeof(*entries));
+
+	atomic_set(&kvm->have_new, 0);
+	mutex_unlock(&kvm->irq_routing_lock);
+
+	kvm_set_irq_routing(kvm, entries, nr, flags);
+
+	return 0;
+}
+
+static int do_irq_routing_rcu(void *data)
+{
+	struct kvm *kvm = (struct kvm *)data;
+
+	while (1) {
+		wait_event_interruptible(kvm->wq,
+			atomic_read(&kvm->have_new) || kthread_should_stop());
+
+		if (kthread_should_stop())
+			break;
+
+		do_irq_routing_table_update(kvm);
+	}
+
+	return 0;
+}
+
 static struct kvm *kvm_create_vm(unsigned long type)
 {
 	int r, i;
@@ -529,6 +573,12 @@ static struct kvm *kvm_create_vm(unsigne
 	kvm_init_memslots_id(kvm);
 	if (init_srcu_struct(&kvm->srcu))
 		goto out_err_nosrcu;
+
+	atomic_set(&kvm->have_new, 0);
+	init_waitqueue_head(&kvm->wq);
+	mutex_init(&kvm->irq_routing_lock);
+	kvm->kthread = kthread_run(do_irq_routing_rcu, kvm, "irq_routing");
+
 	for (i = 0; i < KVM_NR_BUSES; i++) {
 		kvm->buses[i] = kzalloc(sizeof(struct kvm_io_bus),
 					GFP_KERNEL);
@@ -635,6 +685,11 @@ static void kvm_destroy_vm(struct kvm *k
 	list_del(&kvm->vm_list);
 	raw_spin_unlock(&kvm_lock);
 	kvm_free_irq_routing(kvm);
+
+	kthread_stop(kvm->kthread);
+	if (kvm->to_update_entries)
+		vfree(kvm->to_update_entries);
+
 	for (i = 0; i < KVM_NR_BUSES; i++)
 		kvm_io_bus_destroy(kvm->buses[i]);
 	kvm_coalesced_mmio_free(kvm);
