Re: [PATCH 2/4] KVM: Introduce a callback routine for IOAPIC ack handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2008-07-07 at 13:08 +0300, Avi Kivity wrote:
> Amit Shah wrote:
> > This will be useful for acking irqs of assigned devices
> >
> >   
> 
> And also for improving time drift tracking.
> 
> Please make this more generic by having a list of callbacks.  There 
> could also be just one list, rather than one for the ioapic and one for 
> the pic as implemented now.
> 
> It may also make sense to filter the irq number before calling the 
> callback rather than relying on the callback to ignore uninteresting irqs.
> 
Avi,

Did you mean something like the patch below?
How should we protect list accesses, should it be a new lock or an existing one?

Regards,
Ben

>From 102013bdd75e8141027e461ae5834138f561a3c3 Mon Sep 17 00:00:00 2001
From: Ben-Ami Yassour <benami@xxxxxxxxxx>
Date: Tue, 8 Jul 2008 13:30:01 +0300
Subject: [PATCH] KVM: interrupt ack notifier list

API to get notification when a guest acks an interrupt.

Signed-off-by: Ben-Ami Yassour <benami@xxxxxxxxxx>
---
 arch/x86/kvm/i8259.c       |    4 ++-
 arch/x86/kvm/irq.c         |    2 +-
 arch/x86/kvm/irq.h         |    2 +-
 arch/x86/kvm/x86.c         |   84 ++++++++++++++++++++++++++++++++++++++++++++
 include/asm-x86/kvm_host.h |   10 +++++
 5 files changed, 99 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 5857f59..9160343 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -151,9 +151,10 @@ static inline void pic_intack(struct kvm_kpic_state *s, int irq)
 		s->irr &= ~(1 << irq);
 }
 
-int kvm_pic_read_irq(struct kvm_pic *s)
+int kvm_pic_read_irq(struct kvm *kvm)
 {
 	int irq, irq2, intno;
+	struct kvm_pic *s = pic_irqchip(kvm);
 
 	irq = pic_get_irq(&s->pics[0]);
 	if (irq >= 0) {
@@ -178,6 +179,7 @@ int kvm_pic_read_irq(struct kvm_pic *s)
 		irq = 7;
 		intno = s->pics[0].irq_base + irq;
 	}
+	notify_interrupt_ack(kvm, irq);
 	pic_update_irq(s);
 
 	return intno;
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index 76d736b..cf29c02 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -72,7 +72,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
 		if (kvm_apic_accept_pic_intr(v)) {
 			s = pic_irqchip(v->kvm);
 			s->output = 0;		/* PIC */
-			vector = kvm_pic_read_irq(s);
+			vector = kvm_pic_read_irq(v->kvm);
 		}
 	}
 	return vector;
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 2a15be2..7657654 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -65,7 +65,7 @@ struct kvm_pic {
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm);
 void kvm_pic_set_irq(void *opaque, int irq, int level);
-int kvm_pic_read_irq(struct kvm_pic *s);
+int kvm_pic_read_irq(struct kvm *kvm);
 void kvm_pic_update_irq(struct kvm_pic *s);
 
 static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5a83c3b..6d33f00 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -199,6 +199,88 @@ static void __queue_exception(struct kvm_vcpu *vcpu)
 				     vcpu->arch.exception.error_code);
 }
 
+void notify_interrupt_ack(struct kvm *kvm, int irq)
+{
+	struct list_head *ptr;
+	struct interrupt_ack_notifier *notifier;
+
+	list_for_each(ptr, &kvm->arch.interrupt_ack_notifier) {
+		notifier = list_entry(ptr, struct interrupt_ack_notifier, list);
+		if (irq == notifier->irq)
+			notifier->callback(notifier->opaque, irq);
+	}
+}
+
+static int
+register_interrupt_ack_notifier(struct kvm *kvm,
+				int irq,
+				void (*callback)(void *opaque, int irq),
+				void *opaque)
+{
+	struct interrupt_ack_notifier *notifier;
+	
+	notifier = kzalloc(sizeof(struct interrupt_ack_notifier), GFP_KERNEL);
+	if (notifier == NULL) {
+		printk(KERN_INFO "%s: Couldn't allocate memory\n", __func__);
+		return -ENOMEM;
+	}
+	
+	notifier->callback = callback;
+	notifier->opaque = opaque;
+	notifier->irq = irq;
+	list_add(&notifier->list, &kvm->arch.interrupt_ack_notifier);
+
+	return 0;
+}
+
+static struct interrupt_ack_notifier *
+find_interrupt_ack_notifier(struct kvm *kvm,
+			    int irq,
+			    void (*callback)(void *opaque, int irq),
+			    void *opaque)
+{
+	struct list_head *ptr;
+	struct interrupt_ack_notifier *notifier;
+
+	list_for_each(ptr, &kvm->arch.interrupt_ack_notifier) {
+		notifier = list_entry(ptr, struct interrupt_ack_notifier, list);
+		if ((irq == notifier->irq) &&
+		    (callback == notifier->callback) &&
+		    (opaque == notifier->opaque)) {
+			return notifier;
+		}
+	}
+	return NULL;
+}
+
+static void
+unregister_interrupt_ack_notifier(struct kvm *kvm,
+					     int irq,
+					     void (*callback)(void *opaque, int irq),
+					     void *opaque)
+{
+	struct interrupt_ack_notifier *notifier;
+
+	notifier = find_interrupt_ack_notifier(kvm, irq, callback, opaque);
+	if (notifier) {
+		list_del(&notifier->list);
+		kfree(notifier);
+	}
+}
+
+static void free_interrupt_ack_notifier_list(struct kvm *kvm)
+{
+	struct list_head *ptr, *ptr2;
+	struct interrupt_ack_notifier *notifier;
+
+	list_for_each_safe(ptr, ptr2, &kvm->arch.interrupt_ack_notifier) {
+		notifier = list_entry(ptr,
+				      struct interrupt_ack_notifier, list);
+		list_del(&notifier->list);
+		kfree(notifier);
+	}
+}
+
 /*
  * Load the pae pdptrs.  Return true is they are all valid.
  */
@@ -3946,6 +4028,7 @@ struct  kvm *kvm_arch_create_vm(void)
 		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
+	INIT_LIST_HEAD(&kvm->arch.interrupt_ack_notifier);
 
 	return kvm;
 }
@@ -3981,6 +4064,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 	kvm_free_pit(kvm);
 	kfree(kvm->arch.vpic);
 	kfree(kvm->arch.vioapic);
+	free_interrupt_ack_notifier_list(kvm);
 	kvm_free_vcpus(kvm);
 	kvm_free_physmem(kvm);
 	if (kvm->arch.apic_access_page)
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
index 9391e57..fe35b15 100644
--- a/include/asm-x86/kvm_host.h
+++ b/include/asm-x86/kvm_host.h
@@ -302,6 +302,13 @@ struct kvm_vcpu_arch {
 	u64 mtrr[0x100];
 };
 
+struct interrupt_ack_notifier {
+	struct list_head list;
+	int irq;
+	void (*callback)(void *opaque, int irq);
+	void *opaque;
+};
+
 struct kvm_mem_alias {
 	gfn_t base_gfn;
 	unsigned long npages;
@@ -339,6 +346,7 @@ struct kvm_arch{
 	struct dmar_domain *intel_iommu_domain;
 	struct kvm_pic *vpic;
 	struct kvm_ioapic *vioapic;
+	struct list_head interrupt_ack_notifier;	
 	struct kvm_pit *vpit;
 
 	int round_robin_prev_vcpu;
@@ -582,6 +590,8 @@ void kvm_enable_tdp(void);
 int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
 int complete_pio(struct kvm_vcpu *vcpu);
 
+void notify_interrupt_ack(struct kvm *kvm, int irq);
+
 static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
 {
 	struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT);
-- 
1.5.5.1



_______________________________________________
Virtualization mailing list
Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/virtualization

[Index of Archives]     [KVM Development]     [Libvirt Development]     [Libvirt Users]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux