WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] IRQ injection changes for HVM PCI passthr

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] IRQ injection changes for HVM PCI passthru.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 26 Sep 2007 03:40:36 -0700
Delivery-date: Wed, 26 Sep 2007 03:42:58 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1190128159 -3600
# Node ID b7eb2bb9b6251c0533bac7361218c398ad3e8cbf
# Parent  b594583d6e44346d91233bd7b9a6ea0eab648802
IRQ injection changes for HVM PCI passthru.
Signed-off-by: Allen Kay <allen.m.kay@xxxxxxxxx>
Signed-off-by: Guy Zana <guy@xxxxxxxxxxxx>
---
 xen/arch/x86/hvm/irq.c                 |    4 -
 xen/arch/x86/hvm/vioapic.c             |    4 +
 xen/arch/x86/hvm/vmx/Makefile          |    2 
 xen/arch/x86/hvm/vmx/intr.c            |   21 +++++++++
 xen/arch/x86/hvm/vmx/vtd/dmar.c        |   20 ++++++--
 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c |   12 +++--
 xen/arch/x86/hvm/vmx/vtd/io.c          |   76 ++++++++++++++++-----------------
 xen/arch/x86/hvm/vmx/vtd/msi.h         |    1 
 xen/arch/x86/hvm/vpic.c                |    8 ++-
 xen/arch/x86/io_apic.c                 |   76 +++++++++++++++++++++++++++++++--
 xen/include/asm-x86/hvm/irq.h          |    4 +
 xen/include/xen/irq.h                  |    7 ---
 12 files changed, 175 insertions(+), 60 deletions(-)

diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/irq.c    Tue Sep 18 16:09:19 2007 +0100
@@ -26,7 +26,7 @@
 #include <asm/hvm/domain.h>
 #include <asm/hvm/support.h>
 
-static void __hvm_pci_intx_assert(
+void __hvm_pci_intx_assert(
     struct domain *d, unsigned int device, unsigned int intx)
 {
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
@@ -59,7 +59,7 @@ void hvm_pci_intx_assert(
     spin_unlock(&d->arch.hvm_domain.irq_lock);
 }
 
-static void __hvm_pci_intx_deassert(
+void __hvm_pci_intx_deassert(
     struct domain *d, unsigned int device, unsigned int intx)
 {
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/vioapic.c        Tue Sep 18 16:09:19 2007 +0100
@@ -458,6 +458,10 @@ void vioapic_update_EOI(struct domain *d
     ent = &vioapic->redirtbl[gsi];
 
     ent->fields.remote_irr = 0;
+
+    if ( vtd_enabled )
+        hvm_dpci_eoi(gsi, ent);
+
     if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
          !ent->fields.mask &&
          hvm_irq->gsi_assert_count[gsi] )
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/vmx/Makefile
--- a/xen/arch/x86/hvm/vmx/Makefile     Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/Makefile     Tue Sep 18 16:09:19 2007 +0100
@@ -1,3 +1,5 @@ subdir-$(x86_32) += x86_32
+subdir-y += vtd
+
 subdir-$(x86_32) += x86_32
 subdir-$(x86_64) += x86_64
 
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c       Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/intr.c       Tue Sep 18 16:09:19 2007 +0100
@@ -138,6 +138,23 @@ static void update_tpr_threshold(
     __vmwrite(TPR_THRESHOLD, threshold);
 }
 
+static void vmx_dirq_assist(struct domain *d)
+{
+    unsigned int irq;
+    uint32_t device, intx;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+    for ( irq = find_first_bit(hvm_irq->dirq_mask, NR_IRQS);
+          irq < NR_IRQS;
+          irq = find_next_bit(hvm_irq->dirq_mask, NR_IRQS, irq + 1) )
+    {
+        test_and_clear_bit(irq, &hvm_irq->dirq_mask);
+        device = hvm_irq->mirq[irq].device;
+        intx = hvm_irq->mirq[irq].intx;
+        hvm_pci_intx_assert(d, device, intx);
+    }
+}
+
 asmlinkage void vmx_intr_assist(void)
 {
     int intr_vector;
@@ -147,6 +164,10 @@ asmlinkage void vmx_intr_assist(void)
 
     /* Crank the handle on interrupt state. */
     pt_update_irq(v);
+
+    if ( vtd_enabled && (v->vcpu_id == 0) )
+        vmx_dirq_assist(v->domain);
+  
     hvm_set_callback_irq_level();
 
     do {
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/vmx/vtd/dmar.c
--- a/xen/arch/x86/hvm/vmx/vtd/dmar.c   Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vtd/dmar.c   Tue Sep 18 16:09:19 2007 +0100
@@ -30,6 +30,10 @@
 #include "pci-direct.h"
 #include "pci_regs.h"
 
+#define VTDPREFIX
+int vtd_enabled;
+boolean_param("vtd", vtd_enabled);
+
 #undef PREFIX
 #define PREFIX VTDPREFIX "ACPI DMAR:"
 #define DEBUG
@@ -484,11 +488,19 @@ acpi_parse_dmar(unsigned long phys_addr,
 
 int acpi_dmar_init(void)
 {
+    extern int ioapic_ack_new;
+
     acpi_table_parse(ACPI_DMAR, acpi_parse_dmar);
+
     if (list_empty(&acpi_drhd_units)) {
         printk(KERN_ERR PREFIX "No DMAR devices found\n");
+        vtd_enabled = 0;
         return -ENODEV;
-    } else
-        vtd_enabled = 1;
-    return 0;
-}
+    }
+
+    /* Use fake-vector style of IOAPIC acknowledgement. */
+    if (vtd_enabled)
+        ioapic_ack_new = 0;
+
+    return 0;
+}
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
--- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c    Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c    Tue Sep 18 16:09:19 2007 +0100
@@ -34,10 +34,16 @@
 #include "pci_regs.h"
 #include "msi.h"
 
+#define VTDPREFIX
+static inline int request_irq(int vector, void *func,
+                              int flags, char *name, void *data)
+{
+    return -ENOSYS;
+}
+
 extern void print_iommu_regs(struct acpi_drhd_unit *drhd);
 extern void print_vtd_entries(struct domain *d, int bus, int devfn,
                        unsigned long gmfn);
-extern void (*interrupt[])(void);
 
 #define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */
 
@@ -831,7 +837,6 @@ int iommu_set_interrupt(struct iommu *io
 int iommu_set_interrupt(struct iommu *iommu)
 {
     int vector, ret;
-    unsigned long flags;
 
     vector = assign_irq_vector(AUTO_ASSIGN);
     vector_to_iommu[vector] = iommu;
@@ -845,10 +850,7 @@ int iommu_set_interrupt(struct iommu *io
         return -EINVAL;
     }
 
-    spin_lock_irqsave(&irq_desc[vector].lock, flags);
     irq_desc[vector].handler = &dma_msi_type;
-    spin_unlock_irqrestore(&irq_desc[vector].lock, flags);
-    set_intr_gate(vector, interrupt[vector]);
     ret = request_irq(vector, iommu_page_fault, 0, "dmar", iommu);
     if (ret)
         gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: can't request irq\n");
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/vmx/vtd/io.c
--- a/xen/arch/x86/hvm/vmx/vtd/io.c     Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vtd/io.c     Tue Sep 18 16:09:19 2007 +0100
@@ -50,33 +50,31 @@ int hvm_do_IRQ_dpci(struct domain *d, un
     uint32_t link, isa_irq;
     struct hvm_irq *hvm_irq;
 
-    if (!vtd_enabled || (d == dom0))
+    if ( !vtd_enabled || (d == dom0) ||
+         !d->arch.hvm_domain.irq.mirq[mirq].valid )
         return 0;
 
-    if (d->arch.hvm_domain.irq.mirq[mirq].valid)
+    device = d->arch.hvm_domain.irq.mirq[mirq].device;
+    intx = d->arch.hvm_domain.irq.mirq[mirq].intx;
+    link = hvm_pci_intx_link(device, intx);
+    hvm_irq = &d->arch.hvm_domain.irq;
+    isa_irq = hvm_irq->pci_link.route[link];
+
+    if ( !d->arch.hvm_domain.irq.girq[isa_irq].valid )
     {
-        device = d->arch.hvm_domain.irq.mirq[mirq].device;
-        intx = d->arch.hvm_domain.irq.mirq[mirq].intx;
-        link = hvm_pci_intx_link(device, intx);
-        hvm_irq = &d->arch.hvm_domain.irq;
-        isa_irq = hvm_irq->pci_link.route[link];
+        d->arch.hvm_domain.irq.girq[isa_irq].valid = 1;
+        d->arch.hvm_domain.irq.girq[isa_irq].device = device;
+        d->arch.hvm_domain.irq.girq[isa_irq].intx = intx;
+        d->arch.hvm_domain.irq.girq[isa_irq].machine_gsi = mirq;
+    }
 
-        if ( !d->arch.hvm_domain.irq.girq[isa_irq].valid )
-        {
-            d->arch.hvm_domain.irq.girq[isa_irq].valid = 1;
-            d->arch.hvm_domain.irq.girq[isa_irq].device = device;
-            d->arch.hvm_domain.irq.girq[isa_irq].intx = intx;
-            d->arch.hvm_domain.irq.girq[isa_irq].machine_gsi = mirq;
-        }
+    if ( !test_and_set_bit(mirq, d->arch.hvm_domain.irq.dirq_mask) )
+    {
+        vcpu_kick(d->vcpu[0]);
+        return 1;
+    }
 
-        if ( !test_and_set_bit(mirq, d->arch.hvm_domain.irq.dirq_mask) )
-        {
-            vcpu_kick(d->vcpu[0]);
-            return 1;
-        }
-        else
-            dprintk(XENLOG_INFO, "Want to pending mirq, but failed\n");
-    }
+    dprintk(XENLOG_INFO, "mirq already pending\n");
     return 0;
 }
 
@@ -86,18 +84,21 @@ void hvm_dpci_eoi(unsigned int guest_gsi
     uint32_t device, intx, machine_gsi;
     irq_desc_t *desc;
 
-    if (d->arch.hvm_domain.irq.girq[guest_gsi].valid)
+    ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock));
+
+    if ( !vtd_enabled || !d->arch.hvm_domain.irq.girq[guest_gsi].valid )
+        return;
+
+    device = d->arch.hvm_domain.irq.girq[guest_gsi].device;
+    intx = d->arch.hvm_domain.irq.girq[guest_gsi].intx;
+    machine_gsi = d->arch.hvm_domain.irq.girq[guest_gsi].machine_gsi;
+    gdprintk(XENLOG_INFO, "hvm_dpci_eoi:: device %x intx %x\n",
+             device, intx);
+    __hvm_pci_intx_deassert(d, device, intx);
+    if ( (ent == NULL) || (ent->fields.mask == 0) )
     {
-        device = d->arch.hvm_domain.irq.girq[guest_gsi].device;
-        intx = d->arch.hvm_domain.irq.girq[guest_gsi].intx;
-        machine_gsi = d->arch.hvm_domain.irq.girq[guest_gsi].machine_gsi;
-        gdprintk(XENLOG_INFO, "hvm_dpci_eoi:: device %x intx %x\n",
-            device, intx);
-        hvm_pci_intx_deassert(d, device, intx);
-        if ( (ent == NULL) || (ent && ent->fields.mask == 0) ) {
-            desc = &irq_desc[irq_to_vector(machine_gsi)];
-            desc->handler->end(irq_to_vector(machine_gsi));
-        }
+        desc = &irq_desc[irq_to_vector(machine_gsi)];
+        desc->handler->end(irq_to_vector(machine_gsi));
     }
 }
 
@@ -107,14 +108,13 @@ int release_devices(struct domain *d)
     uint32_t i;
     int ret = 0;
 
-    if (!vtd_enabled)
+    if ( !vtd_enabled )
         return ret;
 
-    /* unbind irq */
-    for (i = 0; i < NR_IRQS; i++) {
-        if (hd->irq.mirq[i].valid)
+    for ( i = 0; i < NR_IRQS; i++ )
+        if ( hd->irq.mirq[i].valid )
             ret = pirq_guest_unbind(d, i);
-    }
+
     iommu_domain_teardown(d);
     return ret;
 }
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/vmx/vtd/msi.h
--- a/xen/arch/x86/hvm/vmx/vtd/msi.h    Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vtd/msi.h    Tue Sep 18 16:09:19 2007 +0100
@@ -17,7 +17,6 @@
 #define NR_HP_RESERVED_VECTORS         20
 
 extern int vector_irq[NR_VECTORS];
-extern void (*interrupt[NR_IRQS])(void);
 extern int pci_vector_resources(int last, int nr_released);
 
 /*
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c   Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/hvm/vpic.c   Tue Sep 18 16:09:19 2007 +0100
@@ -182,8 +182,7 @@ static void vpic_ioport_write(
 
     vpic_lock(vpic);
 
-    addr &= 1;
-    if ( addr == 0 )
+    if ( (addr & 1) == 0 )
     {
         if ( val & 0x10 )
         {
@@ -250,6 +249,11 @@ static void vpic_ioport_write(
                 vpic->isr &= ~(1 << irq);
                 if ( cmd == 7 )
                     vpic->priority_add = (irq + 1) & 7;
+                if ( vtd_enabled )
+                {
+                    irq |= ((addr & 0xa0) == 0xa0) ? 8 : 0;
+                    hvm_dpci_eoi(hvm_isa_irq_to_gsi(irq), NULL);
+                }
                 break;
             case 6: /* Set Priority                */
                 vpic->priority_add = (val + 1) & 7;
diff -r b594583d6e44 -r b7eb2bb9b625 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/arch/x86/io_apic.c    Tue Sep 18 16:09:19 2007 +0100
@@ -182,6 +182,68 @@ static void __modify_IO_APIC_irq (unsign
             break;
         entry = irq_2_pin + entry->next;
     }
+}
+
+static int real_vector[MAX_IRQ_SOURCES];
+static int fake_vector=-1;
+
+/*
+ * Following 2 functions are used to workaround spurious interrupt
+ * problem related to mask/unmask of interrupts.  Instead we program
+ * an unused vector in the IOAPIC before issueing EOI to LAPIC.
+ */
+static void write_fake_IO_APIC_vector (unsigned int irq)
+{
+    struct irq_pin_list *entry = irq_2_pin + irq;
+    unsigned int pin, reg;
+    unsigned long flags;
+
+    spin_lock_irqsave(&ioapic_lock, flags);
+    for (;;) {
+        pin = entry->pin;
+        if (pin == -1)
+            break;
+        reg = io_apic_read(entry->apic, 0x10 + pin*2);
+        real_vector[irq] = reg & 0xff;
+        reg &= ~0xff;
+
+        if (fake_vector == -1)
+            fake_vector = assign_irq_vector(MAX_IRQ_SOURCES-1);
+
+        reg |= fake_vector;
+        io_apic_write(entry->apic, 0x10 + pin*2, reg);
+
+        if (!entry->next)
+            break;
+        entry = irq_2_pin + entry->next;
+    }
+    spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+static void restore_real_IO_APIC_vector (unsigned int irq)
+{
+    struct irq_pin_list *entry = irq_2_pin + irq;
+    unsigned int pin, reg;
+    unsigned long flags;
+
+    spin_lock_irqsave(&ioapic_lock, flags);
+    for (;;) {
+        pin = entry->pin;
+        if (pin == -1)
+            break;
+
+        reg = io_apic_read(entry->apic, 0x10 + pin*2);
+        reg &= ~0xff;
+        reg |= real_vector[irq];
+        io_apic_write(entry->apic, 0x10 + pin*2, reg);
+        mb();
+        *(IO_APIC_BASE(entry->apic) + 0x10) = reg & 0xff;
+
+        if (!entry->next)
+            break;
+        entry = irq_2_pin + entry->next;
+    }
+    spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 /* mask = 1 */
@@ -1356,7 +1418,11 @@ static void mask_and_ack_level_ioapic_ir
     if ( ioapic_ack_new )
         return;
 
-    mask_IO_APIC_irq(irq);
+    if ( vtd_enabled )
+        write_fake_IO_APIC_vector(irq);
+    else
+        mask_IO_APIC_irq(irq);
+
 /*
  * It appears there is an erratum which affects at least version 0x11
  * of I/O APIC (that's the 82093AA and cores integrated into various
@@ -1398,8 +1464,12 @@ static void end_level_ioapic_irq (unsign
 
     if ( !ioapic_ack_new )
     {
-        if ( !(irq_desc[IO_APIC_VECTOR(irq)].status & IRQ_DISABLED) )
-            unmask_IO_APIC_irq(irq);
+        if ( !(irq_desc[IO_APIC_VECTOR(irq)].status & IRQ_DISABLED) ) {
+            if ( vtd_enabled )
+                restore_real_IO_APIC_vector(irq);
+            else
+                unmask_IO_APIC_irq(irq);
+        }
         return;
     }
 
diff -r b594583d6e44 -r b7eb2bb9b625 xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h     Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/include/asm-x86/hvm/irq.h     Tue Sep 18 16:09:19 2007 +0100
@@ -114,7 +114,11 @@ struct hvm_irq {
 #define hvm_isa_irq_to_gsi(isa_irq) ((isa_irq) ? : 2)
 
 /* Modify state of a PCI INTx wire. */
+void __hvm_pci_intx_assert(
+    struct domain *d, unsigned int device, unsigned int intx);
 void hvm_pci_intx_assert(
+    struct domain *d, unsigned int device, unsigned int intx);
+void __hvm_pci_intx_deassert(
     struct domain *d, unsigned int device, unsigned int intx);
 void hvm_pci_intx_deassert(
     struct domain *d, unsigned int device, unsigned int intx);
diff -r b594583d6e44 -r b7eb2bb9b625 xen/include/xen/irq.h
--- a/xen/include/xen/irq.h     Tue Sep 18 15:11:39 2007 +0100
+++ b/xen/include/xen/irq.h     Tue Sep 18 16:09:19 2007 +0100
@@ -64,9 +64,6 @@ extern irq_desc_t irq_desc[NR_IRQS];
 
 extern int setup_irq(unsigned int, struct irqaction *);
 extern void free_irq(unsigned int);
-extern int request_irq(unsigned int irq,
-               void (*handler)(int, void *, struct cpu_user_regs *),
-               unsigned long irqflags, const char * devname, void *dev_id);
 
 extern hw_irq_controller no_irq_type;
 extern void no_action(int cpl, void *dev_id, struct cpu_user_regs *regs);
@@ -80,11 +77,11 @@ extern int pirq_guest_unbind(struct doma
 
 static inline void set_native_irq_info(int irq, cpumask_t mask)
 {
-       irq_desc[irq].affinity = mask;
+    irq_desc[irq].affinity = mask;
 }
 
 static inline void set_irq_info(int irq, cpumask_t mask)
 {
-       set_native_irq_info(irq, mask);
+    set_native_irq_info(irq, mask);
 }
 #endif /* __XEN_IRQ_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] IRQ injection changes for HVM PCI passthru., Xen patchbot-unstable <=