[Oops, outlook even didn't notice that last mail don't have subject then send 
it out...]

>From eab008da232cd9cc09dd8071bd15796c8e46f6bd Mon Sep 17 00:00:00 2001
From: Sheng Yang <[EMAIL PROTECTED]>
Date: Thu, 2 Oct 2008 14:21:06 +0800
Subject: [PATCH 2/2] KVM: Implement OR logic on guest shared IRQ line

Now IOAPIC and PIC treat every kvm_set_irq() as from one separate interrupt
source, so implement OR logic base on this.

Notice that the every caller should ensure that it would call kvm_set_irq()
only when the interrupt state of source is changing (also means call
kvm_set_irq() in pair).

Signed-off-by: Sheng Yang <[EMAIL PROTECTED]>
---
 arch/x86/kvm/i8259.c |   12 +++++++++++-
 arch/x86/kvm/irq.c   |    6 +++++-
 arch/x86/kvm/irq.h   |    1 +
 arch/x86/kvm/x86.c   |    3 ---
 virt/kvm/ioapic.c    |    9 +++++++++
 virt/kvm/ioapic.h    |    1 +
 6 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 17e41e1..d2b05be 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -142,9 +142,19 @@ void kvm_pic_update_irq(struct kvm_pic *s)
 void kvm_pic_set_irq(void *opaque, int irq, int level)
 {
        struct kvm_pic *s = opaque;
+       struct kvm_kpic_state *entry;

+       entry = &s->pics[irq >> 3];
        if (irq >= 0 && irq < PIC_NUM_PINS) {
-               pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
+               /* OR logic on level trig for sharing interrupt */
+               if (entry->elcr) {
+                       s->irq_counts[irq] += (level == 1 ? 1 : -1);
+                       ASSERT(s->irq_counts[irq] >= 0);
+                       if (s->irq_counts[irq] != 0)
+                               level = 1;
+               }
+
+               pic_set_irq1(entry, irq & 7, level);
                pic_update_irq(s);
        }
 }
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index 8c1b9c5..8999d9d 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -100,7 +100,11 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
        __kvm_migrate_pit_timer(vcpu);
 }

-/* This should be called with the kvm->lock mutex held */
+/*
+ * The caller of kvm_set_irq() should hold kvm->lock mutex, and ensure
+ * that kvm_set_irq() was called in pair when asserting and deasserting with
+ * level trig interrupt source for the same irq.
+ */
 void kvm_set_irq(struct kvm *kvm, int irq, int level)
 {
        /* Not possible to detect if the guest uses the PIC or the
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 9f157c9..ef9e828 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -60,6 +60,7 @@ struct kvm_kpic_state {

 struct kvm_pic {
        struct kvm_kpic_state pics[2]; /* 0 is master pic, 1 is slave pic */
+       int irq_counts[PIC_NUM_PINS];
        irq_request_func *irq_request;
        void *irq_request_opaque;
        int output;             /* intr from master PIC */
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e685d48..71a0f81 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -144,9 +144,6 @@ static void kvm_assigned_dev_interrupt_work_handler(struct 
work_struct *work)
        kvm_put_kvm(assigned_dev->kvm);
 }

-/* FIXME: Implement the OR logic needed to make shared interrupts on
- * this line behave properly
- */
 static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
 {
        struct kvm_assigned_dev_kernel *assigned_dev =
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index c8f939c..d9526e0 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -275,6 +275,15 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int 
irq, int level)

        if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
                entry = ioapic->redirtbl[irq];
+
+               /* OR logic on level trig for sharing interrupt */
+               if (entry.fields.trig_mode == 1) {
+                       ioapic->irq_counts[irq] += (level == 1 ? 1 : -1);
+                       ASSERT(ioapic->irq_counts[irq] >= 0);
+                       if (ioapic->irq_counts[irq] != 0)
+                               level = 1;
+               }
+
                level ^= entry.fields.polarity;
                if (!level)
                        ioapic->irr &= ~mask;
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index b52732f..6ed7dc7 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -56,6 +56,7 @@ struct kvm_ioapic {
                        u8 dest_id;
                } fields;
        } redirtbl[IOAPIC_NUM_PINS];
+       int irq_counts[IOAPIC_NUM_PINS];
        struct kvm_io_device dev;
        struct kvm *kvm;
        void (*ack_notifier)(void *opaque, int irq);
--
1.5.3

Attachment: 0002-KVM-Implement-OR-logic-on-guest-shared-IRQ-line.patch
Description: 0002-KVM-Implement-OR-logic-on-guest-shared-IRQ-line.patch

Reply via email to