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

[Xen-changelog] [xen-unstable] vtd: Dynamically allocate IRQ-tracking structures, only for those



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1191340747 -3600
# Node ID c2871913c5c2c09e54169ce86af73ec1314554d9
# Parent  e1b574bc36b5068baf0053da32f8ca11a907625a
vtd: Dynamically allocate IRQ-tracking structures, only for those
domains that actually have PCI-passthru devices. Greatly reduces size
of 'struct domain'.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/intr.c   |   21 ++++++----
 xen/arch/x86/hvm/vmx/vtd/io.c |   83 ++++++++++++++++++++++++++----------------
 xen/include/asm-x86/hvm/irq.h |   16 +++++---
 3 files changed, 74 insertions(+), 46 deletions(-)

diff -r e1b574bc36b5 -r c2871913c5c2 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c       Tue Oct 02 16:28:58 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/intr.c       Tue Oct 02 16:59:07 2007 +0100
@@ -107,19 +107,23 @@ static void enable_intr_window(struct vc
     }
 }
 
-static void vmx_dirq_assist(struct domain *d)
+static void vmx_dirq_assist(struct vcpu *v)
 {
     unsigned int irq;
     uint32_t device, intx;
-    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct domain *d = v->domain;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
 
-    for ( irq = find_first_bit(hvm_irq->dirq_mask, NR_IRQS);
+    if ( !vtd_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) )
+        return;
+
+    for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS);
           irq < NR_IRQS;
-          irq = find_next_bit(hvm_irq->dirq_mask, NR_IRQS, irq + 1) )
+          irq = find_next_bit(hvm_irq_dpci->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;
+        test_and_clear_bit(irq, &hvm_irq_dpci->dirq_mask);
+        device = hvm_irq_dpci->mirq[irq].device;
+        intx = hvm_irq_dpci->mirq[irq].intx;
         hvm_pci_intx_assert(d, device, intx);
     }
 }
@@ -134,8 +138,7 @@ 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);
+    vmx_dirq_assist(v);
   
     hvm_set_callback_irq_level();
 
diff -r e1b574bc36b5 -r c2871913c5c2 xen/arch/x86/hvm/vmx/vtd/io.c
--- a/xen/arch/x86/hvm/vmx/vtd/io.c     Tue Oct 02 16:28:58 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vtd/io.c     Tue Oct 02 16:59:07 2007 +0100
@@ -46,27 +46,41 @@
 #include <public/domctl.h>
 
 int pt_irq_create_bind_vtd(
-    struct domain *d,
-    xen_domctl_bind_pt_irq_t * pt_irq_bind)
+    struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
 {
-    struct hvm_domain *hd = &d->arch.hvm_domain;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     uint32_t machine_gsi, guest_gsi;
     uint32_t device, intx;
+
+    if ( hvm_irq_dpci == NULL )
+    {
+        hvm_irq_dpci = xmalloc(struct hvm_irq_dpci);
+        if ( hvm_irq_dpci == NULL )
+            return -ENOMEM;
+
+        memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci));
+
+        if ( cmpxchg((unsigned long *)&d->arch.hvm_domain.irq.dpci,
+                     0, (unsigned long)hvm_irq_dpci) != 0 )
+            xfree(hvm_irq_dpci);
+
+        hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    }
 
     machine_gsi = pt_irq_bind->machine_irq;
     device = pt_irq_bind->u.pci.device;
     intx = pt_irq_bind->u.pci.intx;
     guest_gsi = hvm_pci_intx_gsi(device, intx);
 
-    hd->irq.mirq[machine_gsi].valid = 1;
-    hd->irq.mirq[machine_gsi].device = device;
-    hd->irq.mirq[machine_gsi].intx = intx;
-    hd->irq.mirq[machine_gsi].guest_gsi = guest_gsi;
+    hvm_irq_dpci->mirq[machine_gsi].valid = 1;
+    hvm_irq_dpci->mirq[machine_gsi].device = device;
+    hvm_irq_dpci->mirq[machine_gsi].intx = intx;
+    hvm_irq_dpci->mirq[machine_gsi].guest_gsi = guest_gsi;
 
-    hd->irq.girq[guest_gsi].valid = 1;
-    hd->irq.girq[guest_gsi].device = device;
-    hd->irq.girq[guest_gsi].intx = intx;
-    hd->irq.girq[guest_gsi].machine_gsi = machine_gsi;
+    hvm_irq_dpci->girq[guest_gsi].valid = 1;
+    hvm_irq_dpci->girq[guest_gsi].device = device;
+    hvm_irq_dpci->girq[guest_gsi].intx = intx;
+    hvm_irq_dpci->girq[guest_gsi].machine_gsi = machine_gsi;
 
     /* Deal with gsi for legacy devices */
     pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE);
@@ -76,31 +90,31 @@ int pt_irq_create_bind_vtd(
 
     return 0;
 }
+
 int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
 {
     uint32_t device, intx;
     uint32_t link, isa_irq;
-    struct hvm_irq *hvm_irq;
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
 
-    if ( !vtd_enabled || (d == dom0) ||
-         !d->arch.hvm_domain.irq.mirq[mirq].valid )
+    if ( !vtd_enabled || (d == dom0) || (hvm_irq->dpci == NULL) ||
+         !hvm_irq->dpci->mirq[mirq].valid )
         return 0;
 
-    device = d->arch.hvm_domain.irq.mirq[mirq].device;
-    intx = d->arch.hvm_domain.irq.mirq[mirq].intx;
+    device = hvm_irq->dpci->mirq[mirq].device;
+    intx = hvm_irq->dpci->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 )
+    if ( !hvm_irq->dpci->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;
+        hvm_irq->dpci->girq[isa_irq].valid = 1;
+        hvm_irq->dpci->girq[isa_irq].device = device;
+        hvm_irq->dpci->girq[isa_irq].intx = intx;
+        hvm_irq->dpci->girq[isa_irq].machine_gsi = mirq;
     }
 
-    if ( !test_and_set_bit(mirq, d->arch.hvm_domain.irq.dirq_mask) )
+    if ( !test_and_set_bit(mirq, hvm_irq->dpci->dirq_mask) )
     {
         vcpu_kick(d->vcpu[0]);
         return 1;
@@ -113,17 +127,19 @@ void hvm_dpci_eoi(unsigned int guest_gsi
 void hvm_dpci_eoi(unsigned int guest_gsi, union vioapic_redir_entry *ent)
 {
     struct domain *d = current->domain;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     uint32_t device, intx, machine_gsi;
     irq_desc_t *desc;
 
     ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock));
 
-    if ( !vtd_enabled || !d->arch.hvm_domain.irq.girq[guest_gsi].valid )
+    if ( !vtd_enabled || (hvm_irq_dpci == NULL) ||
+         !hvm_irq_dpci->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;
+    device = hvm_irq_dpci->girq[guest_gsi].device;
+    intx = hvm_irq_dpci->girq[guest_gsi].intx;
+    machine_gsi = hvm_irq_dpci->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);
@@ -136,15 +152,20 @@ void hvm_dpci_eoi(unsigned int guest_gsi
 
 void iommu_domain_destroy(struct domain *d)
 {
-    struct hvm_domain *hd = &d->arch.hvm_domain;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     uint32_t i;
 
     if ( !vtd_enabled )
         return;
 
-    for ( i = 0; i < NR_IRQS; i++ )
-        if ( hd->irq.mirq[i].valid )
-            pirq_guest_unbind(d, i);
+    if ( hvm_irq_dpci != NULL )
+    {
+        for ( i = 0; i < NR_IRQS; i++ )
+            if ( hvm_irq_dpci->mirq[i].valid )
+                pirq_guest_unbind(d, i);
+        d->arch.hvm_domain.irq.dpci = NULL;
+        xfree(hvm_irq_dpci);
+    }
 
     iommu_domain_teardown(d);
 }
diff -r e1b574bc36b5 -r c2871913c5c2 xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h     Tue Oct 02 16:28:58 2007 +0100
+++ b/xen/include/asm-x86/hvm/irq.h     Tue Oct 02 16:59:07 2007 +0100
@@ -29,7 +29,7 @@
 #include <asm/hvm/vioapic.h>
 #include <public/hvm/save.h>
 
-struct hvm_irq_mapping {
+struct hvm_irq_dpci_mapping {
     uint8_t valid;
     uint8_t device;
     uint8_t intx;
@@ -37,6 +37,14 @@ struct hvm_irq_mapping {
         uint8_t guest_gsi;
         uint8_t machine_gsi;
     };
+};
+
+struct hvm_irq_dpci {
+    /* Machine IRQ to guest device/intx mapping. */
+    struct hvm_irq_dpci_mapping mirq[NR_IRQS];
+    /* Guest IRQ to guest device/intx mapping. */
+    struct hvm_irq_dpci_mapping girq[NR_IRQS];
+    DECLARE_BITMAP(dirq_mask, NR_IRQS);
 };
 
 struct hvm_irq {
@@ -99,11 +107,7 @@ struct hvm_irq {
     /* Last VCPU that was delivered a LowestPrio interrupt. */
     u8 round_robin_prev_vcpu;
 
-    /* machine irq to guest device/intx mapping */
-    struct hvm_irq_mapping mirq[NR_IRQS];
-    /* guest irq to guest device/intx mapping */
-    struct hvm_irq_mapping girq[NR_IRQS];
-    DECLARE_BITMAP(dirq_mask, NR_IRQS);
+    struct hvm_irq_dpci *dpci;
 };
 
 #define hvm_pci_intx_gsi(dev, intx)  \

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.